OpenACC acc_on_device: Fix logic error introduced in an earlier change.
[official-gcc.git] / gcc / omp-low.c
blob1395f241edd4ccafd94b1af5fbb466a368aa5131
1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2014 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "tree.h"
30 #include "stringpool.h"
31 #include "stor-layout.h"
32 #include "rtl.h"
33 #include "predict.h"
34 #include "vec.h"
35 #include "hashtab.h"
36 #include "hash-set.h"
37 #include "machmode.h"
38 #include "hard-reg-set.h"
39 #include "input.h"
40 #include "function.h"
41 #include "dominance.h"
42 #include "cfg.h"
43 #include "cfganal.h"
44 #include "basic-block.h"
45 #include "tree-ssa-alias.h"
46 #include "internal-fn.h"
47 #include "gimple-fold.h"
48 #include "gimple-expr.h"
49 #include "is-a.h"
50 #include "gimple.h"
51 #include "gimplify.h"
52 #include "gimple-iterator.h"
53 #include "gimplify-me.h"
54 #include "gimple-walk.h"
55 #include "tree-iterator.h"
56 #include "tree-inline.h"
57 #include "langhooks.h"
58 #include "diagnostic-core.h"
59 #include "gimple-ssa.h"
60 #include "hash-map.h"
61 #include "plugin-api.h"
62 #include "ipa-ref.h"
63 #include "cgraph.h"
64 #include "tree-cfg.h"
65 #include "tree-phinodes.h"
66 #include "ssa-iterators.h"
67 #include "tree-ssanames.h"
68 #include "tree-into-ssa.h"
69 #include "expr.h"
70 #include "tree-dfa.h"
71 #include "tree-ssa.h"
72 #include "flags.h"
73 #include "expr.h"
74 #include "tree-pass.h"
75 #include "except.h"
76 #include "splay-tree.h"
77 #include "insn-codes.h"
78 #include "optabs.h"
79 #include "cfgloop.h"
80 #include "target.h"
81 #include "common/common-target.h"
82 #include "omp-low.h"
83 #include "gimple-low.h"
84 #include "tree-cfgcleanup.h"
85 #include "pretty-print.h"
86 #include "alloc-pool.h"
87 #include "ipa-prop.h"
88 #include "tree-nested.h"
89 #include "tree-eh.h"
90 #include "cilk.h"
91 #include "context.h"
92 #include "lto-section-names.h"
93 #include "gomp-constants.h"
96 /* Lowering of OMP parallel and workshare constructs proceeds in two
97 phases. The first phase scans the function looking for OMP statements
98 and then for variables that must be replaced to satisfy data sharing
99 clauses. The second phase expands code for the constructs, as well as
100 re-gimplifying things when variables have been replaced with complex
101 expressions.
103 Final code generation is done by pass_expand_omp. The flowgraph is
104 scanned for regions which are then moved to a new
105 function, to be invoked by the thread library, or offloaded. */
107 /* OMP region information. Every parallel and workshare
108 directive is enclosed between two markers, the OMP_* directive
109 and a corresponding OMP_RETURN statement. */
111 struct omp_region
113 /* The enclosing region. */
114 struct omp_region *outer;
116 /* First child region. */
117 struct omp_region *inner;
119 /* Next peer region. */
120 struct omp_region *next;
122 /* Block containing the omp directive as its last stmt. */
123 basic_block entry;
125 /* Block containing the OMP_RETURN as its last stmt. */
126 basic_block exit;
128 /* Block containing the OMP_CONTINUE as its last stmt. */
129 basic_block cont;
131 /* If this is a combined parallel+workshare region, this is a list
132 of additional arguments needed by the combined parallel+workshare
133 library call. */
134 vec<tree, va_gc> *ws_args;
136 /* The code for the omp directive of this region. */
137 enum gimple_code type;
139 /* Schedule kind, only used for OMP_FOR type regions. */
140 enum omp_clause_schedule_kind sched_kind;
142 /* True if this is a combined parallel+workshare region. */
143 bool is_combined_parallel;
146 /* Levels of parallelism as defined by OpenACC. Increasing numbers
147 correspond to deeper loop nesting levels. */
148 #define MASK_GANG 1
149 #define MASK_WORKER 2
150 #define MASK_VECTOR 4
152 /* Context structure. Used to store information about each parallel
153 directive in the code. */
155 typedef struct omp_context
157 /* This field must be at the beginning, as we do "inheritance": Some
158 callback functions for tree-inline.c (e.g., omp_copy_decl)
159 receive a copy_body_data pointer that is up-casted to an
160 omp_context pointer. */
161 copy_body_data cb;
163 /* The tree of contexts corresponding to the encountered constructs. */
164 struct omp_context *outer;
165 gimple stmt;
167 /* Map variables to fields in a structure that allows communication
168 between sending and receiving threads. */
169 splay_tree field_map;
170 tree record_type;
171 tree sender_decl;
172 tree receiver_decl;
174 /* These are used just by task contexts, if task firstprivate fn is
175 needed. srecord_type is used to communicate from the thread
176 that encountered the task construct to task firstprivate fn,
177 record_type is allocated by GOMP_task, initialized by task firstprivate
178 fn and passed to the task body fn. */
179 splay_tree sfield_map;
180 tree srecord_type;
182 /* A chain of variables to add to the top-level block surrounding the
183 construct. In the case of a parallel, this is in the child function. */
184 tree block_vars;
186 /* A map of reduction pointer variables. For accelerators, each
187 reduction variable is replaced with an array. Each thread, in turn,
188 is assigned to a slot on that array. */
189 splay_tree reduction_map;
191 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
192 barriers should jump to during omplower pass. */
193 tree cancel_label;
195 /* What to do with variables with implicitly determined sharing
196 attributes. */
197 enum omp_clause_default_kind default_kind;
199 /* Nesting depth of this context. Used to beautify error messages re
200 invalid gotos. The outermost ctx is depth 1, with depth 0 being
201 reserved for the main body of the function. */
202 int depth;
204 /* True if this parallel directive is nested within another. */
205 bool is_nested;
207 /* True if this construct can be cancelled. */
208 bool cancellable;
210 /* For OpenACC loops, a mask of gang, worker and vector used at
211 levels below this one. */
212 int gwv_below;
213 /* For OpenACC loops, a mask of gang, worker and vector used at
214 this level and above. For parallel and kernels clauses, a mask
215 indicating which of num_gangs/num_workers/num_vectors was used. */
216 int gwv_this;
217 } omp_context;
219 /* A structure holding the elements of:
220 for (V = N1; V cond N2; V += STEP) [...] */
222 struct omp_for_data_loop
224 tree v, n1, n2, step;
225 enum tree_code cond_code;
228 /* A structure describing the main elements of a parallel loop. */
230 struct omp_for_data
232 struct omp_for_data_loop loop;
233 tree chunk_size;
234 gomp_for *for_stmt;
235 tree pre, iter_type;
236 int collapse;
237 bool have_nowait, have_ordered;
238 enum omp_clause_schedule_kind sched_kind;
239 struct omp_for_data_loop *loops;
243 static splay_tree all_contexts;
244 static int taskreg_nesting_level;
245 static int target_nesting_level;
246 static struct omp_region *root_omp_region;
247 static bitmap task_shared_vars;
248 static vec<omp_context *> taskreg_contexts;
250 static void scan_omp (gimple_seq *, omp_context *);
251 static tree scan_omp_1_op (tree *, int *, void *);
253 #define WALK_SUBSTMTS \
254 case GIMPLE_BIND: \
255 case GIMPLE_TRY: \
256 case GIMPLE_CATCH: \
257 case GIMPLE_EH_FILTER: \
258 case GIMPLE_TRANSACTION: \
259 /* The sub-statements for these should be walked. */ \
260 *handled_ops_p = false; \
261 break;
263 /* Helper function to get the name of the array containing the partial
264 reductions for OpenACC reductions. */
265 static const char *
266 oacc_get_reduction_array_id (tree node)
268 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
269 int len = strlen ("OACC") + strlen (id);
270 char *temp_name = XALLOCAVEC (char, len + 1);
271 snprintf (temp_name, len + 1, "OACC%s", id);
272 return IDENTIFIER_POINTER (get_identifier (temp_name));
275 /* Determine the number of threads OpenACC threads used to determine the
276 size of the array of partial reductions. Currently, this is num_gangs
277 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
278 because it is independed of the device used. */
280 static tree
281 oacc_max_threads (omp_context *ctx)
283 tree nthreads, vector_length, gangs, clauses;
285 gangs = fold_convert (sizetype, integer_one_node);
286 vector_length = gangs;
288 /* The reduction clause may be nested inside a loop directive.
289 Scan for the innermost vector_length clause. */
290 for (omp_context *oc = ctx; oc; oc = oc->outer)
292 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
293 || (gimple_omp_target_kind (oc->stmt)
294 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
295 continue;
297 clauses = gimple_omp_target_clauses (oc->stmt);
299 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
300 if (vector_length)
301 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
302 sizetype,
303 OMP_CLAUSE_VECTOR_LENGTH_EXPR
304 (vector_length));
305 else
306 vector_length = fold_convert (sizetype, integer_one_node);
308 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
309 if (gangs)
310 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
311 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
312 else
313 gangs = fold_convert (sizetype, integer_one_node);
315 break;
318 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
320 return nthreads;
323 /* Holds offload tables with decls. */
324 vec<tree, va_gc> *offload_funcs, *offload_vars;
326 /* Holds a decl for __OFFLOAD_TABLE__. */
327 static GTY(()) tree offload_symbol_decl;
329 /* Get the __OFFLOAD_TABLE__ symbol. */
330 static tree
331 get_offload_symbol_decl (void)
333 if (!offload_symbol_decl)
335 tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
336 get_identifier ("__OFFLOAD_TABLE__"),
337 ptr_type_node);
338 TREE_ADDRESSABLE (decl) = 1;
339 TREE_PUBLIC (decl) = 1;
340 DECL_EXTERNAL (decl) = 1;
341 DECL_WEAK (decl) = 1;
342 DECL_ATTRIBUTES (decl)
343 = tree_cons (get_identifier ("weak"),
344 NULL_TREE, DECL_ATTRIBUTES (decl));
345 offload_symbol_decl = decl;
347 return offload_symbol_decl;
350 /* Convenience function for calling scan_omp_1_op on tree operands. */
352 static inline tree
353 scan_omp_op (tree *tp, omp_context *ctx)
355 struct walk_stmt_info wi;
357 memset (&wi, 0, sizeof (wi));
358 wi.info = ctx;
359 wi.want_locations = true;
361 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
364 static void lower_omp (gimple_seq *, omp_context *);
365 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
366 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
368 /* Find an OMP clause of type KIND within CLAUSES. */
370 tree
371 find_omp_clause (tree clauses, enum omp_clause_code kind)
373 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
374 if (OMP_CLAUSE_CODE (clauses) == kind)
375 return clauses;
377 return NULL_TREE;
380 /* Return true if CTX is for an omp parallel. */
382 static inline bool
383 is_parallel_ctx (omp_context *ctx)
385 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
389 /* Return true if CTX is for an omp task. */
391 static inline bool
392 is_task_ctx (omp_context *ctx)
394 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
398 /* Return true if CTX is for an omp parallel or omp task. */
400 static inline bool
401 is_taskreg_ctx (omp_context *ctx)
403 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
404 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
408 /* Return true if REGION is a combined parallel+workshare region. */
410 static inline bool
411 is_combined_parallel (struct omp_region *region)
413 return region->is_combined_parallel;
417 /* Extract the header elements of parallel loop FOR_STMT and store
418 them into *FD. */
420 static void
421 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
422 struct omp_for_data_loop *loops)
424 tree t, var, *collapse_iter, *collapse_count;
425 tree count = NULL_TREE, iter_type = long_integer_type_node;
426 struct omp_for_data_loop *loop;
427 int i;
428 struct omp_for_data_loop dummy_loop;
429 location_t loc = gimple_location (for_stmt);
430 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
431 bool distribute = gimple_omp_for_kind (for_stmt)
432 == GF_OMP_FOR_KIND_DISTRIBUTE;
434 fd->for_stmt = for_stmt;
435 fd->pre = NULL;
436 fd->collapse = gimple_omp_for_collapse (for_stmt);
437 if (fd->collapse > 1)
438 fd->loops = loops;
439 else
440 fd->loops = &fd->loop;
442 fd->have_nowait = distribute || simd;
443 fd->have_ordered = false;
444 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
445 fd->chunk_size = NULL_TREE;
446 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
447 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
448 collapse_iter = NULL;
449 collapse_count = NULL;
451 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
452 switch (OMP_CLAUSE_CODE (t))
454 case OMP_CLAUSE_NOWAIT:
455 fd->have_nowait = true;
456 break;
457 case OMP_CLAUSE_ORDERED:
458 fd->have_ordered = true;
459 break;
460 case OMP_CLAUSE_SCHEDULE:
461 gcc_assert (!distribute);
462 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
463 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
464 break;
465 case OMP_CLAUSE_DIST_SCHEDULE:
466 gcc_assert (distribute);
467 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
468 break;
469 case OMP_CLAUSE_COLLAPSE:
470 if (fd->collapse > 1)
472 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
473 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
475 break;
476 default:
477 break;
480 /* FIXME: for now map schedule(auto) to schedule(static).
481 There should be analysis to determine whether all iterations
482 are approximately the same amount of work (then schedule(static)
483 is best) or if it varies (then schedule(dynamic,N) is better). */
484 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
486 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
487 gcc_assert (fd->chunk_size == NULL);
489 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
490 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
491 gcc_assert (fd->chunk_size == NULL);
492 else if (fd->chunk_size == NULL)
494 /* We only need to compute a default chunk size for ordered
495 static loops and dynamic loops. */
496 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
497 || fd->have_ordered)
498 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
499 ? integer_zero_node : integer_one_node;
502 for (i = 0; i < fd->collapse; i++)
504 if (fd->collapse == 1)
505 loop = &fd->loop;
506 else if (loops != NULL)
507 loop = loops + i;
508 else
509 loop = &dummy_loop;
511 loop->v = gimple_omp_for_index (for_stmt, i);
512 gcc_assert (SSA_VAR_P (loop->v));
513 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
514 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
515 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
516 loop->n1 = gimple_omp_for_initial (for_stmt, i);
518 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
519 loop->n2 = gimple_omp_for_final (for_stmt, i);
520 switch (loop->cond_code)
522 case LT_EXPR:
523 case GT_EXPR:
524 break;
525 case NE_EXPR:
526 gcc_assert (gimple_omp_for_kind (for_stmt)
527 == GF_OMP_FOR_KIND_CILKSIMD
528 || (gimple_omp_for_kind (for_stmt)
529 == GF_OMP_FOR_KIND_CILKFOR));
530 break;
531 case LE_EXPR:
532 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
533 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
534 else
535 loop->n2 = fold_build2_loc (loc,
536 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
537 build_int_cst (TREE_TYPE (loop->n2), 1));
538 loop->cond_code = LT_EXPR;
539 break;
540 case GE_EXPR:
541 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
542 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
543 else
544 loop->n2 = fold_build2_loc (loc,
545 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
546 build_int_cst (TREE_TYPE (loop->n2), 1));
547 loop->cond_code = GT_EXPR;
548 break;
549 default:
550 gcc_unreachable ();
553 t = gimple_omp_for_incr (for_stmt, i);
554 gcc_assert (TREE_OPERAND (t, 0) == var);
555 switch (TREE_CODE (t))
557 case PLUS_EXPR:
558 loop->step = TREE_OPERAND (t, 1);
559 break;
560 case POINTER_PLUS_EXPR:
561 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
562 break;
563 case MINUS_EXPR:
564 loop->step = TREE_OPERAND (t, 1);
565 loop->step = fold_build1_loc (loc,
566 NEGATE_EXPR, TREE_TYPE (loop->step),
567 loop->step);
568 break;
569 default:
570 gcc_unreachable ();
573 if (simd
574 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
575 && !fd->have_ordered))
577 if (fd->collapse == 1)
578 iter_type = TREE_TYPE (loop->v);
579 else if (i == 0
580 || TYPE_PRECISION (iter_type)
581 < TYPE_PRECISION (TREE_TYPE (loop->v)))
582 iter_type
583 = build_nonstandard_integer_type
584 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
586 else if (iter_type != long_long_unsigned_type_node)
588 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
589 iter_type = long_long_unsigned_type_node;
590 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
591 && TYPE_PRECISION (TREE_TYPE (loop->v))
592 >= TYPE_PRECISION (iter_type))
594 tree n;
596 if (loop->cond_code == LT_EXPR)
597 n = fold_build2_loc (loc,
598 PLUS_EXPR, TREE_TYPE (loop->v),
599 loop->n2, loop->step);
600 else
601 n = loop->n1;
602 if (TREE_CODE (n) != INTEGER_CST
603 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
604 iter_type = long_long_unsigned_type_node;
606 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
607 > TYPE_PRECISION (iter_type))
609 tree n1, n2;
611 if (loop->cond_code == LT_EXPR)
613 n1 = loop->n1;
614 n2 = fold_build2_loc (loc,
615 PLUS_EXPR, TREE_TYPE (loop->v),
616 loop->n2, loop->step);
618 else
620 n1 = fold_build2_loc (loc,
621 MINUS_EXPR, TREE_TYPE (loop->v),
622 loop->n2, loop->step);
623 n2 = loop->n1;
625 if (TREE_CODE (n1) != INTEGER_CST
626 || TREE_CODE (n2) != INTEGER_CST
627 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
628 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
629 iter_type = long_long_unsigned_type_node;
633 if (collapse_count && *collapse_count == NULL)
635 t = fold_binary (loop->cond_code, boolean_type_node,
636 fold_convert (TREE_TYPE (loop->v), loop->n1),
637 fold_convert (TREE_TYPE (loop->v), loop->n2));
638 if (t && integer_zerop (t))
639 count = build_zero_cst (long_long_unsigned_type_node);
640 else if ((i == 0 || count != NULL_TREE)
641 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
642 && TREE_CONSTANT (loop->n1)
643 && TREE_CONSTANT (loop->n2)
644 && TREE_CODE (loop->step) == INTEGER_CST)
646 tree itype = TREE_TYPE (loop->v);
648 if (POINTER_TYPE_P (itype))
649 itype = signed_type_for (itype);
650 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
651 t = fold_build2_loc (loc,
652 PLUS_EXPR, itype,
653 fold_convert_loc (loc, itype, loop->step), t);
654 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
655 fold_convert_loc (loc, itype, loop->n2));
656 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
657 fold_convert_loc (loc, itype, loop->n1));
658 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
659 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
660 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
661 fold_build1_loc (loc, NEGATE_EXPR, itype,
662 fold_convert_loc (loc, itype,
663 loop->step)));
664 else
665 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
666 fold_convert_loc (loc, itype, loop->step));
667 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
668 if (count != NULL_TREE)
669 count = fold_build2_loc (loc,
670 MULT_EXPR, long_long_unsigned_type_node,
671 count, t);
672 else
673 count = t;
674 if (TREE_CODE (count) != INTEGER_CST)
675 count = NULL_TREE;
677 else if (count && !integer_zerop (count))
678 count = NULL_TREE;
682 if (count
683 && !simd
684 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
685 || fd->have_ordered))
687 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
688 iter_type = long_long_unsigned_type_node;
689 else
690 iter_type = long_integer_type_node;
692 else if (collapse_iter && *collapse_iter != NULL)
693 iter_type = TREE_TYPE (*collapse_iter);
694 fd->iter_type = iter_type;
695 if (collapse_iter && *collapse_iter == NULL)
696 *collapse_iter = create_tmp_var (iter_type, ".iter");
697 if (collapse_count && *collapse_count == NULL)
699 if (count)
700 *collapse_count = fold_convert_loc (loc, iter_type, count);
701 else
702 *collapse_count = create_tmp_var (iter_type, ".count");
705 if (fd->collapse > 1)
707 fd->loop.v = *collapse_iter;
708 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
709 fd->loop.n2 = *collapse_count;
710 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
711 fd->loop.cond_code = LT_EXPR;
714 /* For OpenACC loops, force a chunk size of one, as this avoids the default
715 scheduling where several subsequent iterations are being executed by the
716 same thread. */
717 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
719 gcc_assert (fd->chunk_size == NULL_TREE);
720 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
725 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
726 is the immediate dominator of PAR_ENTRY_BB, return true if there
727 are no data dependencies that would prevent expanding the parallel
728 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
730 When expanding a combined parallel+workshare region, the call to
731 the child function may need additional arguments in the case of
732 GIMPLE_OMP_FOR regions. In some cases, these arguments are
733 computed out of variables passed in from the parent to the child
734 via 'struct .omp_data_s'. For instance:
736 #pragma omp parallel for schedule (guided, i * 4)
737 for (j ...)
739 Is lowered into:
741 # BLOCK 2 (PAR_ENTRY_BB)
742 .omp_data_o.i = i;
743 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
745 # BLOCK 3 (WS_ENTRY_BB)
746 .omp_data_i = &.omp_data_o;
747 D.1667 = .omp_data_i->i;
748 D.1598 = D.1667 * 4;
749 #pragma omp for schedule (guided, D.1598)
751 When we outline the parallel region, the call to the child function
752 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
753 that value is computed *after* the call site. So, in principle we
754 cannot do the transformation.
756 To see whether the code in WS_ENTRY_BB blocks the combined
757 parallel+workshare call, we collect all the variables used in the
758 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
759 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
760 call.
762 FIXME. If we had the SSA form built at this point, we could merely
763 hoist the code in block 3 into block 2 and be done with it. But at
764 this point we don't have dataflow information and though we could
765 hack something up here, it is really not worth the aggravation. */
767 static bool
768 workshare_safe_to_combine_p (basic_block ws_entry_bb)
770 struct omp_for_data fd;
771 gimple ws_stmt = last_stmt (ws_entry_bb);
773 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
774 return true;
776 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
778 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
780 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
781 return false;
782 if (fd.iter_type != long_integer_type_node)
783 return false;
785 /* FIXME. We give up too easily here. If any of these arguments
786 are not constants, they will likely involve variables that have
787 been mapped into fields of .omp_data_s for sharing with the child
788 function. With appropriate data flow, it would be possible to
789 see through this. */
790 if (!is_gimple_min_invariant (fd.loop.n1)
791 || !is_gimple_min_invariant (fd.loop.n2)
792 || !is_gimple_min_invariant (fd.loop.step)
793 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
794 return false;
796 return true;
800 /* Collect additional arguments needed to emit a combined
801 parallel+workshare call. WS_STMT is the workshare directive being
802 expanded. */
804 static vec<tree, va_gc> *
805 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
807 tree t;
808 location_t loc = gimple_location (ws_stmt);
809 vec<tree, va_gc> *ws_args;
811 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
813 struct omp_for_data fd;
814 tree n1, n2;
816 extract_omp_for_data (for_stmt, &fd, NULL);
817 n1 = fd.loop.n1;
818 n2 = fd.loop.n2;
820 if (gimple_omp_for_combined_into_p (for_stmt))
822 tree innerc
823 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
824 OMP_CLAUSE__LOOPTEMP_);
825 gcc_assert (innerc);
826 n1 = OMP_CLAUSE_DECL (innerc);
827 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
828 OMP_CLAUSE__LOOPTEMP_);
829 gcc_assert (innerc);
830 n2 = OMP_CLAUSE_DECL (innerc);
833 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
835 t = fold_convert_loc (loc, long_integer_type_node, n1);
836 ws_args->quick_push (t);
838 t = fold_convert_loc (loc, long_integer_type_node, n2);
839 ws_args->quick_push (t);
841 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
842 ws_args->quick_push (t);
844 if (fd.chunk_size)
846 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
847 ws_args->quick_push (t);
850 return ws_args;
852 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
854 /* Number of sections is equal to the number of edges from the
855 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
856 the exit of the sections region. */
857 basic_block bb = single_succ (gimple_bb (ws_stmt));
858 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
859 vec_alloc (ws_args, 1);
860 ws_args->quick_push (t);
861 return ws_args;
864 gcc_unreachable ();
868 /* Discover whether REGION is a combined parallel+workshare region. */
870 static void
871 determine_parallel_type (struct omp_region *region)
873 basic_block par_entry_bb, par_exit_bb;
874 basic_block ws_entry_bb, ws_exit_bb;
876 if (region == NULL || region->inner == NULL
877 || region->exit == NULL || region->inner->exit == NULL
878 || region->inner->cont == NULL)
879 return;
881 /* We only support parallel+for and parallel+sections. */
882 if (region->type != GIMPLE_OMP_PARALLEL
883 || (region->inner->type != GIMPLE_OMP_FOR
884 && region->inner->type != GIMPLE_OMP_SECTIONS))
885 return;
887 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
888 WS_EXIT_BB -> PAR_EXIT_BB. */
889 par_entry_bb = region->entry;
890 par_exit_bb = region->exit;
891 ws_entry_bb = region->inner->entry;
892 ws_exit_bb = region->inner->exit;
894 if (single_succ (par_entry_bb) == ws_entry_bb
895 && single_succ (ws_exit_bb) == par_exit_bb
896 && workshare_safe_to_combine_p (ws_entry_bb)
897 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
898 || (last_and_only_stmt (ws_entry_bb)
899 && last_and_only_stmt (par_exit_bb))))
901 gimple par_stmt = last_stmt (par_entry_bb);
902 gimple ws_stmt = last_stmt (ws_entry_bb);
904 if (region->inner->type == GIMPLE_OMP_FOR)
906 /* If this is a combined parallel loop, we need to determine
907 whether or not to use the combined library calls. There
908 are two cases where we do not apply the transformation:
909 static loops and any kind of ordered loop. In the first
910 case, we already open code the loop so there is no need
911 to do anything else. In the latter case, the combined
912 parallel loop call would still need extra synchronization
913 to implement ordered semantics, so there would not be any
914 gain in using the combined call. */
915 tree clauses = gimple_omp_for_clauses (ws_stmt);
916 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
917 if (c == NULL
918 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
919 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
921 region->is_combined_parallel = false;
922 region->inner->is_combined_parallel = false;
923 return;
927 region->is_combined_parallel = true;
928 region->inner->is_combined_parallel = true;
929 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
934 /* Return true if EXPR is variable sized. */
936 static inline bool
937 is_variable_sized (const_tree expr)
939 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
942 /* Return true if DECL is a reference type. */
944 static inline bool
945 is_reference (tree decl)
947 return lang_hooks.decls.omp_privatize_by_reference (decl);
950 /* Return the type of a decl. If the decl is reference type,
951 return its base type. */
952 static inline tree
953 get_base_type (tree decl)
955 tree type = TREE_TYPE (decl);
956 if (is_reference (decl))
957 type = TREE_TYPE (type);
958 return type;
961 /* Lookup variables. The "maybe" form
962 allows for the variable form to not have been entered, otherwise we
963 assert that the variable must have been entered. */
965 static inline tree
966 lookup_decl (tree var, omp_context *ctx)
968 tree *n = ctx->cb.decl_map->get (var);
969 return *n;
972 static inline tree
973 maybe_lookup_decl (const_tree var, omp_context *ctx)
975 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
976 return n ? *n : NULL_TREE;
979 static inline tree
980 lookup_field (tree var, omp_context *ctx)
982 splay_tree_node n;
983 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
984 return (tree) n->value;
987 static inline tree
988 lookup_sfield (tree var, omp_context *ctx)
990 splay_tree_node n;
991 n = splay_tree_lookup (ctx->sfield_map
992 ? ctx->sfield_map : ctx->field_map,
993 (splay_tree_key) var);
994 return (tree) n->value;
997 static inline tree
998 maybe_lookup_field (tree var, omp_context *ctx)
1000 splay_tree_node n;
1001 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1002 return n ? (tree) n->value : NULL_TREE;
1005 static inline tree
1006 lookup_oacc_reduction (const char *id, omp_context *ctx)
1008 splay_tree_node n;
1009 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
1010 return (tree) n->value;
1013 static inline tree
1014 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
1016 splay_tree_node n = NULL;
1017 if (ctx->reduction_map)
1018 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
1019 return n ? (tree) n->value : NULL_TREE;
1022 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1023 the parallel context if DECL is to be shared. */
1025 static bool
1026 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1028 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1029 return true;
1031 /* We can only use copy-in/copy-out semantics for shared variables
1032 when we know the value is not accessible from an outer scope. */
1033 if (shared_ctx)
1035 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1037 /* ??? Trivially accessible from anywhere. But why would we even
1038 be passing an address in this case? Should we simply assert
1039 this to be false, or should we have a cleanup pass that removes
1040 these from the list of mappings? */
1041 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1042 return true;
1044 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1045 without analyzing the expression whether or not its location
1046 is accessible to anyone else. In the case of nested parallel
1047 regions it certainly may be. */
1048 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1049 return true;
1051 /* Do not use copy-in/copy-out for variables that have their
1052 address taken. */
1053 if (TREE_ADDRESSABLE (decl))
1054 return true;
1056 /* lower_send_shared_vars only uses copy-in, but not copy-out
1057 for these. */
1058 if (TREE_READONLY (decl)
1059 || ((TREE_CODE (decl) == RESULT_DECL
1060 || TREE_CODE (decl) == PARM_DECL)
1061 && DECL_BY_REFERENCE (decl)))
1062 return false;
1064 /* Disallow copy-in/out in nested parallel if
1065 decl is shared in outer parallel, otherwise
1066 each thread could store the shared variable
1067 in its own copy-in location, making the
1068 variable no longer really shared. */
1069 if (shared_ctx->is_nested)
1071 omp_context *up;
1073 for (up = shared_ctx->outer; up; up = up->outer)
1074 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1075 break;
1077 if (up)
1079 tree c;
1081 for (c = gimple_omp_taskreg_clauses (up->stmt);
1082 c; c = OMP_CLAUSE_CHAIN (c))
1083 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1084 && OMP_CLAUSE_DECL (c) == decl)
1085 break;
1087 if (c)
1088 goto maybe_mark_addressable_and_ret;
1092 /* For tasks avoid using copy-in/out. As tasks can be
1093 deferred or executed in different thread, when GOMP_task
1094 returns, the task hasn't necessarily terminated. */
1095 if (is_task_ctx (shared_ctx))
1097 tree outer;
1098 maybe_mark_addressable_and_ret:
1099 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1100 if (is_gimple_reg (outer))
1102 /* Taking address of OUTER in lower_send_shared_vars
1103 might need regimplification of everything that uses the
1104 variable. */
1105 if (!task_shared_vars)
1106 task_shared_vars = BITMAP_ALLOC (NULL);
1107 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1108 TREE_ADDRESSABLE (outer) = 1;
1110 return true;
1114 return false;
1117 /* Construct a new automatic decl similar to VAR. */
1119 static tree
1120 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1122 tree copy = copy_var_decl (var, name, type);
1124 DECL_CONTEXT (copy) = current_function_decl;
1125 DECL_CHAIN (copy) = ctx->block_vars;
1126 ctx->block_vars = copy;
1128 return copy;
1131 static tree
1132 omp_copy_decl_1 (tree var, omp_context *ctx)
1134 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1137 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1138 as appropriate. */
1139 static tree
1140 omp_build_component_ref (tree obj, tree field)
1142 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1143 if (TREE_THIS_VOLATILE (field))
1144 TREE_THIS_VOLATILE (ret) |= 1;
1145 if (TREE_READONLY (field))
1146 TREE_READONLY (ret) |= 1;
1147 return ret;
1150 /* Build tree nodes to access the field for VAR on the receiver side. */
1152 static tree
1153 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1155 tree x, field = lookup_field (var, ctx);
1157 /* If the receiver record type was remapped in the child function,
1158 remap the field into the new record type. */
1159 x = maybe_lookup_field (field, ctx);
1160 if (x != NULL)
1161 field = x;
1163 x = build_simple_mem_ref (ctx->receiver_decl);
1164 x = omp_build_component_ref (x, field);
1165 if (by_ref)
1166 x = build_simple_mem_ref (x);
1168 return x;
1171 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1172 of a parallel, this is a component reference; for workshare constructs
1173 this is some variable. */
1175 static tree
1176 build_outer_var_ref (tree var, omp_context *ctx)
1178 tree x;
1180 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1181 x = var;
1182 else if (is_variable_sized (var))
1184 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1185 x = build_outer_var_ref (x, ctx);
1186 x = build_simple_mem_ref (x);
1188 else if (is_taskreg_ctx (ctx))
1190 bool by_ref = use_pointer_for_field (var, NULL);
1191 x = build_receiver_ref (var, by_ref, ctx);
1193 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1194 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1196 /* #pragma omp simd isn't a worksharing construct, and can reference even
1197 private vars in its linear etc. clauses. */
1198 x = NULL_TREE;
1199 if (ctx->outer && is_taskreg_ctx (ctx))
1200 x = lookup_decl (var, ctx->outer);
1201 else if (ctx->outer)
1202 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1203 if (x == NULL_TREE)
1204 x = var;
1206 else if (ctx->outer)
1207 x = lookup_decl (var, ctx->outer);
1208 else if (is_reference (var))
1209 /* This can happen with orphaned constructs. If var is reference, it is
1210 possible it is shared and as such valid. */
1211 x = var;
1212 else
1213 gcc_unreachable ();
1215 if (is_reference (var))
1216 x = build_simple_mem_ref (x);
1218 return x;
1221 /* Build tree nodes to access the field for VAR on the sender side. */
1223 static tree
1224 build_sender_ref (tree var, omp_context *ctx)
1226 tree field = lookup_sfield (var, ctx);
1227 return omp_build_component_ref (ctx->sender_decl, field);
1230 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1232 static void
1233 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1235 tree field, type, sfield = NULL_TREE;
1237 gcc_assert ((mask & 1) == 0
1238 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1239 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1240 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1241 gcc_assert ((mask & 3) == 3
1242 || !is_gimple_omp_oacc (ctx->stmt));
1244 type = TREE_TYPE (var);
1245 if (mask & 4)
1247 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1248 type = build_pointer_type (build_pointer_type (type));
1250 else if (by_ref)
1251 type = build_pointer_type (type);
1252 else if ((mask & 3) == 1 && is_reference (var))
1253 type = TREE_TYPE (type);
1255 field = build_decl (DECL_SOURCE_LOCATION (var),
1256 FIELD_DECL, DECL_NAME (var), type);
1258 /* Remember what variable this field was created for. This does have a
1259 side effect of making dwarf2out ignore this member, so for helpful
1260 debugging we clear it later in delete_omp_context. */
1261 DECL_ABSTRACT_ORIGIN (field) = var;
1262 if (type == TREE_TYPE (var))
1264 DECL_ALIGN (field) = DECL_ALIGN (var);
1265 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1266 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1268 else
1269 DECL_ALIGN (field) = TYPE_ALIGN (type);
1271 if ((mask & 3) == 3)
1273 insert_field_into_struct (ctx->record_type, field);
1274 if (ctx->srecord_type)
1276 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1277 FIELD_DECL, DECL_NAME (var), type);
1278 DECL_ABSTRACT_ORIGIN (sfield) = var;
1279 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1280 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1281 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1282 insert_field_into_struct (ctx->srecord_type, sfield);
1285 else
1287 if (ctx->srecord_type == NULL_TREE)
1289 tree t;
1291 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1292 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1293 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1295 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1296 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1297 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1298 insert_field_into_struct (ctx->srecord_type, sfield);
1299 splay_tree_insert (ctx->sfield_map,
1300 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1301 (splay_tree_value) sfield);
1304 sfield = field;
1305 insert_field_into_struct ((mask & 1) ? ctx->record_type
1306 : ctx->srecord_type, field);
1309 if (mask & 1)
1310 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1311 (splay_tree_value) field);
1312 if ((mask & 2) && ctx->sfield_map)
1313 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1314 (splay_tree_value) sfield);
1317 static tree
1318 install_var_local (tree var, omp_context *ctx)
1320 tree new_var = omp_copy_decl_1 (var, ctx);
1321 insert_decl_map (&ctx->cb, var, new_var);
1322 return new_var;
1325 /* Adjust the replacement for DECL in CTX for the new context. This means
1326 copying the DECL_VALUE_EXPR, and fixing up the type. */
1328 static void
1329 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1331 tree new_decl, size;
1333 new_decl = lookup_decl (decl, ctx);
1335 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1337 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1338 && DECL_HAS_VALUE_EXPR_P (decl))
1340 tree ve = DECL_VALUE_EXPR (decl);
1341 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1342 SET_DECL_VALUE_EXPR (new_decl, ve);
1343 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1346 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1348 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1349 if (size == error_mark_node)
1350 size = TYPE_SIZE (TREE_TYPE (new_decl));
1351 DECL_SIZE (new_decl) = size;
1353 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1354 if (size == error_mark_node)
1355 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1356 DECL_SIZE_UNIT (new_decl) = size;
1360 /* The callback for remap_decl. Search all containing contexts for a
1361 mapping of the variable; this avoids having to duplicate the splay
1362 tree ahead of time. We know a mapping doesn't already exist in the
1363 given context. Create new mappings to implement default semantics. */
1365 static tree
1366 omp_copy_decl (tree var, copy_body_data *cb)
1368 omp_context *ctx = (omp_context *) cb;
1369 tree new_var;
1371 if (TREE_CODE (var) == LABEL_DECL)
1373 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1374 DECL_CONTEXT (new_var) = current_function_decl;
1375 insert_decl_map (&ctx->cb, var, new_var);
1376 return new_var;
1379 while (!is_taskreg_ctx (ctx))
1381 ctx = ctx->outer;
1382 if (ctx == NULL)
1383 return var;
1384 new_var = maybe_lookup_decl (var, ctx);
1385 if (new_var)
1386 return new_var;
1389 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1390 return var;
1392 return error_mark_node;
1396 /* Debugging dumps for parallel regions. */
1397 void dump_omp_region (FILE *, struct omp_region *, int);
1398 void debug_omp_region (struct omp_region *);
1399 void debug_all_omp_regions (void);
1401 /* Dump the parallel region tree rooted at REGION. */
1403 void
1404 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1406 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1407 gimple_code_name[region->type]);
1409 if (region->inner)
1410 dump_omp_region (file, region->inner, indent + 4);
1412 if (region->cont)
1414 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1415 region->cont->index);
1418 if (region->exit)
1419 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1420 region->exit->index);
1421 else
1422 fprintf (file, "%*s[no exit marker]\n", indent, "");
1424 if (region->next)
1425 dump_omp_region (file, region->next, indent);
1428 DEBUG_FUNCTION void
1429 debug_omp_region (struct omp_region *region)
1431 dump_omp_region (stderr, region, 0);
1434 DEBUG_FUNCTION void
1435 debug_all_omp_regions (void)
1437 dump_omp_region (stderr, root_omp_region, 0);
1441 /* Create a new parallel region starting at STMT inside region PARENT. */
1443 static struct omp_region *
1444 new_omp_region (basic_block bb, enum gimple_code type,
1445 struct omp_region *parent)
1447 struct omp_region *region = XCNEW (struct omp_region);
1449 region->outer = parent;
1450 region->entry = bb;
1451 region->type = type;
1453 if (parent)
1455 /* This is a nested region. Add it to the list of inner
1456 regions in PARENT. */
1457 region->next = parent->inner;
1458 parent->inner = region;
1460 else
1462 /* This is a toplevel region. Add it to the list of toplevel
1463 regions in ROOT_OMP_REGION. */
1464 region->next = root_omp_region;
1465 root_omp_region = region;
1468 return region;
1471 /* Release the memory associated with the region tree rooted at REGION. */
1473 static void
1474 free_omp_region_1 (struct omp_region *region)
1476 struct omp_region *i, *n;
1478 for (i = region->inner; i ; i = n)
1480 n = i->next;
1481 free_omp_region_1 (i);
1484 free (region);
1487 /* Release the memory for the entire omp region tree. */
1489 void
1490 free_omp_regions (void)
1492 struct omp_region *r, *n;
1493 for (r = root_omp_region; r ; r = n)
1495 n = r->next;
1496 free_omp_region_1 (r);
1498 root_omp_region = NULL;
1502 /* Create a new context, with OUTER_CTX being the surrounding context. */
1504 static omp_context *
1505 new_omp_context (gimple stmt, omp_context *outer_ctx)
1507 omp_context *ctx = XCNEW (omp_context);
1509 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1510 (splay_tree_value) ctx);
1511 ctx->stmt = stmt;
1513 if (outer_ctx)
1515 ctx->outer = outer_ctx;
1516 ctx->cb = outer_ctx->cb;
1517 ctx->cb.block = NULL;
1518 ctx->depth = outer_ctx->depth + 1;
1519 ctx->reduction_map = outer_ctx->reduction_map;
1521 else
1523 ctx->cb.src_fn = current_function_decl;
1524 ctx->cb.dst_fn = current_function_decl;
1525 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1526 gcc_checking_assert (ctx->cb.src_node);
1527 ctx->cb.dst_node = ctx->cb.src_node;
1528 ctx->cb.src_cfun = cfun;
1529 ctx->cb.copy_decl = omp_copy_decl;
1530 ctx->cb.eh_lp_nr = 0;
1531 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1532 ctx->depth = 1;
1535 ctx->cb.decl_map = new hash_map<tree, tree>;
1537 return ctx;
1540 static gimple_seq maybe_catch_exception (gimple_seq);
1542 /* Finalize task copyfn. */
1544 static void
1545 finalize_task_copyfn (gomp_task *task_stmt)
1547 struct function *child_cfun;
1548 tree child_fn;
1549 gimple_seq seq = NULL, new_seq;
1550 gbind *bind;
1552 child_fn = gimple_omp_task_copy_fn (task_stmt);
1553 if (child_fn == NULL_TREE)
1554 return;
1556 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1557 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1559 push_cfun (child_cfun);
1560 bind = gimplify_body (child_fn, false);
1561 gimple_seq_add_stmt (&seq, bind);
1562 new_seq = maybe_catch_exception (seq);
1563 if (new_seq != seq)
1565 bind = gimple_build_bind (NULL, new_seq, NULL);
1566 seq = NULL;
1567 gimple_seq_add_stmt (&seq, bind);
1569 gimple_set_body (child_fn, seq);
1570 pop_cfun ();
1572 /* Inform the callgraph about the new function. */
1573 cgraph_node::add_new_function (child_fn, false);
1576 /* Destroy a omp_context data structures. Called through the splay tree
1577 value delete callback. */
1579 static void
1580 delete_omp_context (splay_tree_value value)
1582 omp_context *ctx = (omp_context *) value;
1584 delete ctx->cb.decl_map;
1586 if (ctx->field_map)
1587 splay_tree_delete (ctx->field_map);
1588 if (ctx->sfield_map)
1589 splay_tree_delete (ctx->sfield_map);
1590 if (ctx->reduction_map
1591 /* Shared over several omp_contexts. */
1592 && (ctx->outer == NULL
1593 || ctx->reduction_map != ctx->outer->reduction_map))
1594 splay_tree_delete (ctx->reduction_map);
1596 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1597 it produces corrupt debug information. */
1598 if (ctx->record_type)
1600 tree t;
1601 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1602 DECL_ABSTRACT_ORIGIN (t) = NULL;
1604 if (ctx->srecord_type)
1606 tree t;
1607 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1608 DECL_ABSTRACT_ORIGIN (t) = NULL;
1611 if (is_task_ctx (ctx))
1612 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1614 XDELETE (ctx);
1617 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1618 context. */
1620 static void
1621 fixup_child_record_type (omp_context *ctx)
1623 tree f, type = ctx->record_type;
1625 /* ??? It isn't sufficient to just call remap_type here, because
1626 variably_modified_type_p doesn't work the way we expect for
1627 record types. Testing each field for whether it needs remapping
1628 and creating a new record by hand works, however. */
1629 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1630 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1631 break;
1632 if (f)
1634 tree name, new_fields = NULL;
1636 type = lang_hooks.types.make_type (RECORD_TYPE);
1637 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1638 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1639 TYPE_DECL, name, type);
1640 TYPE_NAME (type) = name;
1642 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1644 tree new_f = copy_node (f);
1645 DECL_CONTEXT (new_f) = type;
1646 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1647 DECL_CHAIN (new_f) = new_fields;
1648 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1649 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1650 &ctx->cb, NULL);
1651 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1652 &ctx->cb, NULL);
1653 new_fields = new_f;
1655 /* Arrange to be able to look up the receiver field
1656 given the sender field. */
1657 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1658 (splay_tree_value) new_f);
1660 TYPE_FIELDS (type) = nreverse (new_fields);
1661 layout_type (type);
1664 TREE_TYPE (ctx->receiver_decl)
1665 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1668 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1669 specified by CLAUSES. */
1671 static void
1672 scan_sharing_clauses (tree clauses, omp_context *ctx)
1674 tree c, decl;
1675 bool scan_array_reductions = false;
1677 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1679 bool by_ref;
1681 switch (OMP_CLAUSE_CODE (c))
1683 case OMP_CLAUSE_PRIVATE:
1684 decl = OMP_CLAUSE_DECL (c);
1685 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1686 goto do_private;
1687 else if (!is_variable_sized (decl))
1688 install_var_local (decl, ctx);
1689 break;
1691 case OMP_CLAUSE_SHARED:
1692 decl = OMP_CLAUSE_DECL (c);
1693 /* Ignore shared directives in teams construct. */
1694 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1696 /* Global variables don't need to be copied,
1697 the receiver side will use them directly. */
1698 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1699 if (is_global_var (odecl))
1700 break;
1701 insert_decl_map (&ctx->cb, decl, odecl);
1702 break;
1704 gcc_assert (is_taskreg_ctx (ctx));
1705 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1706 || !is_variable_sized (decl));
1707 /* Global variables don't need to be copied,
1708 the receiver side will use them directly. */
1709 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1710 break;
1711 by_ref = use_pointer_for_field (decl, ctx);
1712 if (! TREE_READONLY (decl)
1713 || TREE_ADDRESSABLE (decl)
1714 || by_ref
1715 || is_reference (decl))
1717 install_var_field (decl, by_ref, 3, ctx);
1718 install_var_local (decl, ctx);
1719 break;
1721 /* We don't need to copy const scalar vars back. */
1722 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1723 goto do_private;
1725 case OMP_CLAUSE_LASTPRIVATE:
1726 /* Let the corresponding firstprivate clause create
1727 the variable. */
1728 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1729 break;
1730 /* FALLTHRU */
1732 case OMP_CLAUSE_FIRSTPRIVATE:
1733 if (is_gimple_omp_oacc (ctx->stmt))
1735 sorry ("clause not supported yet");
1736 break;
1738 /* FALLTHRU */
1739 case OMP_CLAUSE_REDUCTION:
1740 case OMP_CLAUSE_LINEAR:
1741 decl = OMP_CLAUSE_DECL (c);
1742 do_private:
1743 if (is_variable_sized (decl))
1745 if (is_task_ctx (ctx))
1746 install_var_field (decl, false, 1, ctx);
1747 break;
1749 else if (is_taskreg_ctx (ctx))
1751 bool global
1752 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1753 by_ref = use_pointer_for_field (decl, NULL);
1755 if (is_task_ctx (ctx)
1756 && (global || by_ref || is_reference (decl)))
1758 install_var_field (decl, false, 1, ctx);
1759 if (!global)
1760 install_var_field (decl, by_ref, 2, ctx);
1762 else if (!global)
1763 install_var_field (decl, by_ref, 3, ctx);
1765 install_var_local (decl, ctx);
1766 if (is_gimple_omp_oacc (ctx->stmt)
1767 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1769 /* Create a decl for the reduction array. */
1770 tree var = OMP_CLAUSE_DECL (c);
1771 tree type = get_base_type (var);
1772 tree ptype = build_pointer_type (type);
1773 tree array = create_tmp_var (ptype,
1774 oacc_get_reduction_array_id (var));
1775 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1776 install_var_field (array, true, 3, c);
1777 install_var_local (array, c);
1779 /* Insert it into the current context. */
1780 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1781 oacc_get_reduction_array_id (var),
1782 (splay_tree_value) array);
1783 splay_tree_insert (ctx->reduction_map,
1784 (splay_tree_key) array,
1785 (splay_tree_value) array);
1787 break;
1789 case OMP_CLAUSE__LOOPTEMP_:
1790 gcc_assert (is_parallel_ctx (ctx));
1791 decl = OMP_CLAUSE_DECL (c);
1792 install_var_field (decl, false, 3, ctx);
1793 install_var_local (decl, ctx);
1794 break;
1796 case OMP_CLAUSE_COPYPRIVATE:
1797 case OMP_CLAUSE_COPYIN:
1798 decl = OMP_CLAUSE_DECL (c);
1799 by_ref = use_pointer_for_field (decl, NULL);
1800 install_var_field (decl, by_ref, 3, ctx);
1801 break;
1803 case OMP_CLAUSE_DEFAULT:
1804 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1805 break;
1807 case OMP_CLAUSE_FINAL:
1808 case OMP_CLAUSE_IF:
1809 case OMP_CLAUSE_NUM_THREADS:
1810 case OMP_CLAUSE_NUM_TEAMS:
1811 case OMP_CLAUSE_THREAD_LIMIT:
1812 case OMP_CLAUSE_DEVICE:
1813 case OMP_CLAUSE_SCHEDULE:
1814 case OMP_CLAUSE_DIST_SCHEDULE:
1815 case OMP_CLAUSE_DEPEND:
1816 case OMP_CLAUSE__CILK_FOR_COUNT_:
1817 case OMP_CLAUSE_NUM_GANGS:
1818 case OMP_CLAUSE_NUM_WORKERS:
1819 case OMP_CLAUSE_VECTOR_LENGTH:
1820 if (ctx->outer)
1821 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1822 break;
1824 case OMP_CLAUSE_TO:
1825 case OMP_CLAUSE_FROM:
1826 case OMP_CLAUSE_MAP:
1827 if (ctx->outer)
1828 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1829 decl = OMP_CLAUSE_DECL (c);
1830 /* Global variables with "omp declare target" attribute
1831 don't need to be copied, the receiver side will use them
1832 directly. */
1833 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1834 && DECL_P (decl)
1835 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1836 && varpool_node::get_create (decl)->offloadable)
1837 break;
1838 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1839 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
1841 /* Ignore OMP_CLAUSE_MAP_POINTER kind for arrays in
1842 regions that are not offloaded; there is nothing to map for
1843 those. */
1844 if (!is_gimple_omp_offloaded (ctx->stmt)
1845 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1846 break;
1848 if (DECL_P (decl))
1850 if (DECL_SIZE (decl)
1851 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1853 tree decl2 = DECL_VALUE_EXPR (decl);
1854 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1855 decl2 = TREE_OPERAND (decl2, 0);
1856 gcc_assert (DECL_P (decl2));
1857 install_var_field (decl2, true, 3, ctx);
1858 install_var_local (decl2, ctx);
1859 install_var_local (decl, ctx);
1861 else
1863 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1864 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
1865 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1866 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1867 install_var_field (decl, true, 7, ctx);
1868 else
1869 install_var_field (decl, true, 3, ctx);
1870 if (is_gimple_omp_offloaded (ctx->stmt))
1871 install_var_local (decl, ctx);
1874 else
1876 tree base = get_base_address (decl);
1877 tree nc = OMP_CLAUSE_CHAIN (c);
1878 if (DECL_P (base)
1879 && nc != NULL_TREE
1880 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1881 && OMP_CLAUSE_DECL (nc) == base
1882 && OMP_CLAUSE_MAP_KIND (nc) == OMP_CLAUSE_MAP_POINTER
1883 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1885 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1886 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1888 else
1890 if (ctx->outer)
1892 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1893 decl = OMP_CLAUSE_DECL (c);
1895 gcc_assert (!splay_tree_lookup (ctx->field_map,
1896 (splay_tree_key) decl));
1897 tree field
1898 = build_decl (OMP_CLAUSE_LOCATION (c),
1899 FIELD_DECL, NULL_TREE, ptr_type_node);
1900 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1901 insert_field_into_struct (ctx->record_type, field);
1902 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1903 (splay_tree_value) field);
1906 break;
1908 case OMP_CLAUSE_NOWAIT:
1909 case OMP_CLAUSE_ORDERED:
1910 case OMP_CLAUSE_COLLAPSE:
1911 case OMP_CLAUSE_UNTIED:
1912 case OMP_CLAUSE_MERGEABLE:
1913 case OMP_CLAUSE_PROC_BIND:
1914 case OMP_CLAUSE_SAFELEN:
1915 case OMP_CLAUSE_ASYNC:
1916 case OMP_CLAUSE_WAIT:
1917 case OMP_CLAUSE_GANG:
1918 case OMP_CLAUSE_WORKER:
1919 case OMP_CLAUSE_VECTOR:
1920 break;
1922 case OMP_CLAUSE_ALIGNED:
1923 decl = OMP_CLAUSE_DECL (c);
1924 if (is_global_var (decl)
1925 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1926 install_var_local (decl, ctx);
1927 break;
1929 case OMP_CLAUSE_DEVICE_RESIDENT:
1930 case OMP_CLAUSE_USE_DEVICE:
1931 case OMP_CLAUSE__CACHE_:
1932 case OMP_CLAUSE_INDEPENDENT:
1933 case OMP_CLAUSE_AUTO:
1934 case OMP_CLAUSE_SEQ:
1935 sorry ("Clause not supported yet");
1936 break;
1938 default:
1939 gcc_unreachable ();
1943 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1945 switch (OMP_CLAUSE_CODE (c))
1947 case OMP_CLAUSE_LASTPRIVATE:
1948 /* Let the corresponding firstprivate clause create
1949 the variable. */
1950 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1951 scan_array_reductions = true;
1952 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1953 break;
1954 /* FALLTHRU */
1956 case OMP_CLAUSE_FIRSTPRIVATE:
1957 if (is_gimple_omp_oacc (ctx->stmt))
1959 sorry ("clause not supported yet");
1960 break;
1962 /* FALLTHRU */
1963 case OMP_CLAUSE_PRIVATE:
1964 case OMP_CLAUSE_REDUCTION:
1965 case OMP_CLAUSE_LINEAR:
1966 decl = OMP_CLAUSE_DECL (c);
1967 if (is_variable_sized (decl))
1968 install_var_local (decl, ctx);
1969 fixup_remapped_decl (decl, ctx,
1970 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1971 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1972 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1973 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1974 scan_array_reductions = true;
1975 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1976 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1977 scan_array_reductions = true;
1978 break;
1980 case OMP_CLAUSE_SHARED:
1981 /* Ignore shared directives in teams construct. */
1982 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1983 break;
1984 decl = OMP_CLAUSE_DECL (c);
1985 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1986 fixup_remapped_decl (decl, ctx, false);
1987 break;
1989 case OMP_CLAUSE_MAP:
1990 if (!is_gimple_omp_offloaded (ctx->stmt))
1991 break;
1992 decl = OMP_CLAUSE_DECL (c);
1993 if (DECL_P (decl)
1994 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1995 && varpool_node::get_create (decl)->offloadable)
1996 break;
1997 if (DECL_P (decl))
1999 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
2000 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2001 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2003 tree new_decl = lookup_decl (decl, ctx);
2004 TREE_TYPE (new_decl)
2005 = remap_type (TREE_TYPE (decl), &ctx->cb);
2007 else if (DECL_SIZE (decl)
2008 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2010 tree decl2 = DECL_VALUE_EXPR (decl);
2011 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2012 decl2 = TREE_OPERAND (decl2, 0);
2013 gcc_assert (DECL_P (decl2));
2014 fixup_remapped_decl (decl2, ctx, false);
2015 fixup_remapped_decl (decl, ctx, true);
2017 else
2018 fixup_remapped_decl (decl, ctx, false);
2020 break;
2022 case OMP_CLAUSE_COPYPRIVATE:
2023 case OMP_CLAUSE_COPYIN:
2024 case OMP_CLAUSE_DEFAULT:
2025 case OMP_CLAUSE_IF:
2026 case OMP_CLAUSE_NUM_THREADS:
2027 case OMP_CLAUSE_NUM_TEAMS:
2028 case OMP_CLAUSE_THREAD_LIMIT:
2029 case OMP_CLAUSE_DEVICE:
2030 case OMP_CLAUSE_SCHEDULE:
2031 case OMP_CLAUSE_DIST_SCHEDULE:
2032 case OMP_CLAUSE_NOWAIT:
2033 case OMP_CLAUSE_ORDERED:
2034 case OMP_CLAUSE_COLLAPSE:
2035 case OMP_CLAUSE_UNTIED:
2036 case OMP_CLAUSE_FINAL:
2037 case OMP_CLAUSE_MERGEABLE:
2038 case OMP_CLAUSE_PROC_BIND:
2039 case OMP_CLAUSE_SAFELEN:
2040 case OMP_CLAUSE_ALIGNED:
2041 case OMP_CLAUSE_DEPEND:
2042 case OMP_CLAUSE__LOOPTEMP_:
2043 case OMP_CLAUSE_TO:
2044 case OMP_CLAUSE_FROM:
2045 case OMP_CLAUSE__CILK_FOR_COUNT_:
2046 case OMP_CLAUSE_ASYNC:
2047 case OMP_CLAUSE_WAIT:
2048 case OMP_CLAUSE_NUM_GANGS:
2049 case OMP_CLAUSE_NUM_WORKERS:
2050 case OMP_CLAUSE_VECTOR_LENGTH:
2051 case OMP_CLAUSE_GANG:
2052 case OMP_CLAUSE_WORKER:
2053 case OMP_CLAUSE_VECTOR:
2054 break;
2056 case OMP_CLAUSE_DEVICE_RESIDENT:
2057 case OMP_CLAUSE_USE_DEVICE:
2058 case OMP_CLAUSE__CACHE_:
2059 case OMP_CLAUSE_INDEPENDENT:
2060 case OMP_CLAUSE_AUTO:
2061 case OMP_CLAUSE_SEQ:
2062 sorry ("Clause not supported yet");
2063 break;
2065 default:
2066 gcc_unreachable ();
2070 gcc_checking_assert (!scan_array_reductions
2071 || !is_gimple_omp_oacc (ctx->stmt));
2072 if (scan_array_reductions)
2073 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2074 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2075 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2077 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2078 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2080 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2081 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2082 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2083 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2084 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2085 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2088 /* Create a new name for omp child function. Returns an identifier. If
2089 IS_CILK_FOR is true then the suffix for the child function is
2090 "_cilk_for_fn." */
2092 static tree
2093 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2095 if (is_cilk_for)
2096 return clone_function_name (current_function_decl, "_cilk_for_fn");
2097 return clone_function_name (current_function_decl,
2098 task_copy ? "_omp_cpyfn" : "_omp_fn");
2101 /* Returns the type of the induction variable for the child function for
2102 _Cilk_for and the types for _high and _low variables based on TYPE. */
2104 static tree
2105 cilk_for_check_loop_diff_type (tree type)
2107 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2109 if (TYPE_UNSIGNED (type))
2110 return uint32_type_node;
2111 else
2112 return integer_type_node;
2114 else
2116 if (TYPE_UNSIGNED (type))
2117 return uint64_type_node;
2118 else
2119 return long_long_integer_type_node;
2123 /* Build a decl for the omp child function. It'll not contain a body
2124 yet, just the bare decl. */
2126 static void
2127 create_omp_child_function (omp_context *ctx, bool task_copy)
2129 tree decl, type, name, t;
2131 tree cilk_for_count
2132 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2133 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2134 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2135 tree cilk_var_type = NULL_TREE;
2137 name = create_omp_child_function_name (task_copy,
2138 cilk_for_count != NULL_TREE);
2139 if (task_copy)
2140 type = build_function_type_list (void_type_node, ptr_type_node,
2141 ptr_type_node, NULL_TREE);
2142 else if (cilk_for_count)
2144 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2145 cilk_var_type = cilk_for_check_loop_diff_type (type);
2146 type = build_function_type_list (void_type_node, ptr_type_node,
2147 cilk_var_type, cilk_var_type, NULL_TREE);
2149 else
2150 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2152 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2154 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2155 || !task_copy);
2156 if (!task_copy)
2157 ctx->cb.dst_fn = decl;
2158 else
2159 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2161 TREE_STATIC (decl) = 1;
2162 TREE_USED (decl) = 1;
2163 DECL_ARTIFICIAL (decl) = 1;
2164 DECL_IGNORED_P (decl) = 0;
2165 TREE_PUBLIC (decl) = 0;
2166 DECL_UNINLINABLE (decl) = 1;
2167 DECL_EXTERNAL (decl) = 0;
2168 DECL_CONTEXT (decl) = NULL_TREE;
2169 DECL_INITIAL (decl) = make_node (BLOCK);
2170 if (cgraph_node::get (current_function_decl)->offloadable)
2171 cgraph_node::get_create (decl)->offloadable = 1;
2172 else
2174 omp_context *octx;
2175 for (octx = ctx; octx; octx = octx->outer)
2176 if (is_gimple_omp_offloaded (octx->stmt))
2178 cgraph_node::get_create (decl)->offloadable = 1;
2179 #ifdef ENABLE_OFFLOADING
2180 g->have_offload = true;
2181 #endif
2182 break;
2186 t = build_decl (DECL_SOURCE_LOCATION (decl),
2187 RESULT_DECL, NULL_TREE, void_type_node);
2188 DECL_ARTIFICIAL (t) = 1;
2189 DECL_IGNORED_P (t) = 1;
2190 DECL_CONTEXT (t) = decl;
2191 DECL_RESULT (decl) = t;
2193 /* _Cilk_for's child function requires two extra parameters called
2194 __low and __high that are set the by Cilk runtime when it calls this
2195 function. */
2196 if (cilk_for_count)
2198 t = build_decl (DECL_SOURCE_LOCATION (decl),
2199 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2200 DECL_ARTIFICIAL (t) = 1;
2201 DECL_NAMELESS (t) = 1;
2202 DECL_ARG_TYPE (t) = ptr_type_node;
2203 DECL_CONTEXT (t) = current_function_decl;
2204 TREE_USED (t) = 1;
2205 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2206 DECL_ARGUMENTS (decl) = t;
2208 t = build_decl (DECL_SOURCE_LOCATION (decl),
2209 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2210 DECL_ARTIFICIAL (t) = 1;
2211 DECL_NAMELESS (t) = 1;
2212 DECL_ARG_TYPE (t) = ptr_type_node;
2213 DECL_CONTEXT (t) = current_function_decl;
2214 TREE_USED (t) = 1;
2215 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2216 DECL_ARGUMENTS (decl) = t;
2219 tree data_name = get_identifier (".omp_data_i");
2220 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2221 ptr_type_node);
2222 DECL_ARTIFICIAL (t) = 1;
2223 DECL_NAMELESS (t) = 1;
2224 DECL_ARG_TYPE (t) = ptr_type_node;
2225 DECL_CONTEXT (t) = current_function_decl;
2226 TREE_USED (t) = 1;
2227 if (cilk_for_count)
2228 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2229 DECL_ARGUMENTS (decl) = t;
2230 if (!task_copy)
2231 ctx->receiver_decl = t;
2232 else
2234 t = build_decl (DECL_SOURCE_LOCATION (decl),
2235 PARM_DECL, get_identifier (".omp_data_o"),
2236 ptr_type_node);
2237 DECL_ARTIFICIAL (t) = 1;
2238 DECL_NAMELESS (t) = 1;
2239 DECL_ARG_TYPE (t) = ptr_type_node;
2240 DECL_CONTEXT (t) = current_function_decl;
2241 TREE_USED (t) = 1;
2242 TREE_ADDRESSABLE (t) = 1;
2243 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2244 DECL_ARGUMENTS (decl) = t;
2247 /* Allocate memory for the function structure. The call to
2248 allocate_struct_function clobbers CFUN, so we need to restore
2249 it afterward. */
2250 push_struct_function (decl);
2251 cfun->function_end_locus = gimple_location (ctx->stmt);
2252 pop_cfun ();
2255 /* Callback for walk_gimple_seq. Check if combined parallel
2256 contains gimple_omp_for_combined_into_p OMP_FOR. */
2258 static tree
2259 find_combined_for (gimple_stmt_iterator *gsi_p,
2260 bool *handled_ops_p,
2261 struct walk_stmt_info *wi)
2263 gimple stmt = gsi_stmt (*gsi_p);
2265 *handled_ops_p = true;
2266 switch (gimple_code (stmt))
2268 WALK_SUBSTMTS;
2270 case GIMPLE_OMP_FOR:
2271 if (gimple_omp_for_combined_into_p (stmt)
2272 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2274 wi->info = stmt;
2275 return integer_zero_node;
2277 break;
2278 default:
2279 break;
2281 return NULL;
2284 /* Scan an OpenMP parallel directive. */
2286 static void
2287 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2289 omp_context *ctx;
2290 tree name;
2291 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2293 /* Ignore parallel directives with empty bodies, unless there
2294 are copyin clauses. */
2295 if (optimize > 0
2296 && empty_body_p (gimple_omp_body (stmt))
2297 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2298 OMP_CLAUSE_COPYIN) == NULL)
2300 gsi_replace (gsi, gimple_build_nop (), false);
2301 return;
2304 if (gimple_omp_parallel_combined_p (stmt))
2306 struct walk_stmt_info wi;
2308 memset (&wi, 0, sizeof (wi));
2309 wi.val_only = true;
2310 walk_gimple_seq (gimple_omp_body (stmt),
2311 find_combined_for, NULL, &wi);
2312 if (wi.info)
2314 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2315 struct omp_for_data fd;
2316 extract_omp_for_data (for_stmt, &fd, NULL);
2317 /* We need two temporaries with fd.loop.v type (istart/iend)
2318 and then (fd.collapse - 1) temporaries with the same
2319 type for count2 ... countN-1 vars if not constant. */
2320 size_t count = 2, i;
2321 tree type = fd.iter_type;
2322 if (fd.collapse > 1
2323 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2324 count += fd.collapse - 1;
2325 for (i = 0; i < count; i++)
2327 tree temp = create_tmp_var (type);
2328 tree c = build_omp_clause (UNKNOWN_LOCATION,
2329 OMP_CLAUSE__LOOPTEMP_);
2330 insert_decl_map (&outer_ctx->cb, temp, temp);
2331 OMP_CLAUSE_DECL (c) = temp;
2332 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2333 gimple_omp_parallel_set_clauses (stmt, c);
2338 ctx = new_omp_context (stmt, outer_ctx);
2339 taskreg_contexts.safe_push (ctx);
2340 if (taskreg_nesting_level > 1)
2341 ctx->is_nested = true;
2342 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2343 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2344 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2345 name = create_tmp_var_name (".omp_data_s");
2346 name = build_decl (gimple_location (stmt),
2347 TYPE_DECL, name, ctx->record_type);
2348 DECL_ARTIFICIAL (name) = 1;
2349 DECL_NAMELESS (name) = 1;
2350 TYPE_NAME (ctx->record_type) = name;
2351 create_omp_child_function (ctx, false);
2352 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2354 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2355 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2357 if (TYPE_FIELDS (ctx->record_type) == NULL)
2358 ctx->record_type = ctx->receiver_decl = NULL;
2361 /* Scan an OpenMP task directive. */
2363 static void
2364 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2366 omp_context *ctx;
2367 tree name, t;
2368 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2370 /* Ignore task directives with empty bodies. */
2371 if (optimize > 0
2372 && empty_body_p (gimple_omp_body (stmt)))
2374 gsi_replace (gsi, gimple_build_nop (), false);
2375 return;
2378 ctx = new_omp_context (stmt, outer_ctx);
2379 taskreg_contexts.safe_push (ctx);
2380 if (taskreg_nesting_level > 1)
2381 ctx->is_nested = true;
2382 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2383 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2384 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2385 name = create_tmp_var_name (".omp_data_s");
2386 name = build_decl (gimple_location (stmt),
2387 TYPE_DECL, name, ctx->record_type);
2388 DECL_ARTIFICIAL (name) = 1;
2389 DECL_NAMELESS (name) = 1;
2390 TYPE_NAME (ctx->record_type) = name;
2391 create_omp_child_function (ctx, false);
2392 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2394 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2396 if (ctx->srecord_type)
2398 name = create_tmp_var_name (".omp_data_a");
2399 name = build_decl (gimple_location (stmt),
2400 TYPE_DECL, name, ctx->srecord_type);
2401 DECL_ARTIFICIAL (name) = 1;
2402 DECL_NAMELESS (name) = 1;
2403 TYPE_NAME (ctx->srecord_type) = name;
2404 create_omp_child_function (ctx, true);
2407 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2409 if (TYPE_FIELDS (ctx->record_type) == NULL)
2411 ctx->record_type = ctx->receiver_decl = NULL;
2412 t = build_int_cst (long_integer_type_node, 0);
2413 gimple_omp_task_set_arg_size (stmt, t);
2414 t = build_int_cst (long_integer_type_node, 1);
2415 gimple_omp_task_set_arg_align (stmt, t);
2420 /* If any decls have been made addressable during scan_omp,
2421 adjust their fields if needed, and layout record types
2422 of parallel/task constructs. */
2424 static void
2425 finish_taskreg_scan (omp_context *ctx)
2427 if (ctx->record_type == NULL_TREE)
2428 return;
2430 /* If any task_shared_vars were needed, verify all
2431 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2432 statements if use_pointer_for_field hasn't changed
2433 because of that. If it did, update field types now. */
2434 if (task_shared_vars)
2436 tree c;
2438 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2439 c; c = OMP_CLAUSE_CHAIN (c))
2440 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2442 tree decl = OMP_CLAUSE_DECL (c);
2444 /* Global variables don't need to be copied,
2445 the receiver side will use them directly. */
2446 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2447 continue;
2448 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2449 || !use_pointer_for_field (decl, ctx))
2450 continue;
2451 tree field = lookup_field (decl, ctx);
2452 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2453 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2454 continue;
2455 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2456 TREE_THIS_VOLATILE (field) = 0;
2457 DECL_USER_ALIGN (field) = 0;
2458 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2459 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2460 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2461 if (ctx->srecord_type)
2463 tree sfield = lookup_sfield (decl, ctx);
2464 TREE_TYPE (sfield) = TREE_TYPE (field);
2465 TREE_THIS_VOLATILE (sfield) = 0;
2466 DECL_USER_ALIGN (sfield) = 0;
2467 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2468 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2469 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2474 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2476 layout_type (ctx->record_type);
2477 fixup_child_record_type (ctx);
2479 else
2481 location_t loc = gimple_location (ctx->stmt);
2482 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2483 /* Move VLA fields to the end. */
2484 p = &TYPE_FIELDS (ctx->record_type);
2485 while (*p)
2486 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2487 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2489 *q = *p;
2490 *p = TREE_CHAIN (*p);
2491 TREE_CHAIN (*q) = NULL_TREE;
2492 q = &TREE_CHAIN (*q);
2494 else
2495 p = &DECL_CHAIN (*p);
2496 *p = vla_fields;
2497 layout_type (ctx->record_type);
2498 fixup_child_record_type (ctx);
2499 if (ctx->srecord_type)
2500 layout_type (ctx->srecord_type);
2501 tree t = fold_convert_loc (loc, long_integer_type_node,
2502 TYPE_SIZE_UNIT (ctx->record_type));
2503 gimple_omp_task_set_arg_size (ctx->stmt, t);
2504 t = build_int_cst (long_integer_type_node,
2505 TYPE_ALIGN_UNIT (ctx->record_type));
2506 gimple_omp_task_set_arg_align (ctx->stmt, t);
2511 static omp_context *
2512 enclosing_target_ctx (omp_context *ctx)
2514 while (ctx != NULL
2515 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2516 ctx = ctx->outer;
2517 gcc_assert (ctx != NULL);
2518 return ctx;
2521 static bool
2522 oacc_loop_or_target_p (gimple stmt)
2524 enum gimple_code outer_type = gimple_code (stmt);
2525 return ((outer_type == GIMPLE_OMP_TARGET
2526 && ((gimple_omp_target_kind (stmt)
2527 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2528 || (gimple_omp_target_kind (stmt)
2529 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2530 || (outer_type == GIMPLE_OMP_FOR
2531 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2534 /* Scan a GIMPLE_OMP_FOR. */
2536 static void
2537 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2539 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
2540 omp_context *ctx;
2541 size_t i;
2542 tree clauses = gimple_omp_for_clauses (stmt);
2544 if (outer_ctx)
2545 outer_type = gimple_code (outer_ctx->stmt);
2547 ctx = new_omp_context (stmt, outer_ctx);
2549 if (is_gimple_omp_oacc (stmt))
2551 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2552 ctx->gwv_this = outer_ctx->gwv_this;
2553 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2555 int val;
2556 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2557 val = MASK_GANG;
2558 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2559 val = MASK_WORKER;
2560 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2561 val = MASK_VECTOR;
2562 else
2563 continue;
2564 ctx->gwv_this |= val;
2565 if (!outer_ctx)
2567 /* Skip; not nested inside a region. */
2568 continue;
2570 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2572 /* Skip; not nested inside an OpenACC region. */
2573 continue;
2575 if (outer_type == GIMPLE_OMP_FOR)
2576 outer_ctx->gwv_below |= val;
2577 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2579 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2580 if (gimple_omp_target_kind (enclosing->stmt)
2581 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2582 error_at (gimple_location (stmt),
2583 "no arguments allowed to gang, worker and vector clauses inside parallel");
2588 scan_sharing_clauses (clauses, ctx);
2590 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2591 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2593 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2594 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2595 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2596 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2598 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2600 if (is_gimple_omp_oacc (stmt))
2602 if (ctx->gwv_this & ctx->gwv_below)
2603 error_at (gimple_location (stmt),
2604 "gang, worker and vector may occur only once in a loop nest");
2605 else if (ctx->gwv_below != 0
2606 && ctx->gwv_this > ctx->gwv_below)
2607 error_at (gimple_location (stmt),
2608 "gang, worker and vector must occur in this order in a loop nest");
2609 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2610 outer_ctx->gwv_below |= ctx->gwv_below;
2614 /* Scan an OpenMP sections directive. */
2616 static void
2617 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2619 omp_context *ctx;
2621 ctx = new_omp_context (stmt, outer_ctx);
2622 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2623 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2626 /* Scan an OpenMP single directive. */
2628 static void
2629 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2631 omp_context *ctx;
2632 tree name;
2634 ctx = new_omp_context (stmt, outer_ctx);
2635 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2636 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2637 name = create_tmp_var_name (".omp_copy_s");
2638 name = build_decl (gimple_location (stmt),
2639 TYPE_DECL, name, ctx->record_type);
2640 TYPE_NAME (ctx->record_type) = name;
2642 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2643 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2645 if (TYPE_FIELDS (ctx->record_type) == NULL)
2646 ctx->record_type = NULL;
2647 else
2648 layout_type (ctx->record_type);
2651 /* Scan a GIMPLE_OMP_TARGET. */
2653 static void
2654 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2656 omp_context *ctx;
2657 tree name;
2658 bool offloaded = is_gimple_omp_offloaded (stmt);
2659 tree clauses = gimple_omp_target_clauses (stmt);
2661 ctx = new_omp_context (stmt, outer_ctx);
2662 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2663 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2664 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2665 name = create_tmp_var_name (".omp_data_t");
2666 name = build_decl (gimple_location (stmt),
2667 TYPE_DECL, name, ctx->record_type);
2668 DECL_ARTIFICIAL (name) = 1;
2669 DECL_NAMELESS (name) = 1;
2670 TYPE_NAME (ctx->record_type) = name;
2671 if (offloaded)
2673 if (is_gimple_omp_oacc (stmt))
2674 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2675 0, 0);
2677 create_omp_child_function (ctx, false);
2678 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2681 if (is_gimple_omp_oacc (stmt))
2683 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2685 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2686 ctx->gwv_this |= MASK_GANG;
2687 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2688 ctx->gwv_this |= MASK_WORKER;
2689 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2690 ctx->gwv_this |= MASK_VECTOR;
2694 scan_sharing_clauses (clauses, ctx);
2695 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2697 if (TYPE_FIELDS (ctx->record_type) == NULL)
2698 ctx->record_type = ctx->receiver_decl = NULL;
2699 else
2701 TYPE_FIELDS (ctx->record_type)
2702 = nreverse (TYPE_FIELDS (ctx->record_type));
2703 #ifdef ENABLE_CHECKING
2704 tree field;
2705 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2706 for (field = TYPE_FIELDS (ctx->record_type);
2707 field;
2708 field = DECL_CHAIN (field))
2709 gcc_assert (DECL_ALIGN (field) == align);
2710 #endif
2711 layout_type (ctx->record_type);
2712 if (offloaded)
2713 fixup_child_record_type (ctx);
2717 /* Scan an OpenMP teams directive. */
2719 static void
2720 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2722 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2723 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2724 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2727 /* Check nesting restrictions. */
2728 static bool
2729 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2731 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2732 inside an OpenACC CTX. */
2733 if (!(is_gimple_omp (stmt)
2734 && is_gimple_omp_oacc (stmt)))
2736 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2737 if (is_gimple_omp (ctx_->stmt)
2738 && is_gimple_omp_oacc (ctx_->stmt))
2740 error_at (gimple_location (stmt),
2741 "non-OpenACC construct inside of OpenACC region");
2742 return false;
2746 if (ctx != NULL)
2748 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2749 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2751 error_at (gimple_location (stmt),
2752 "OpenMP constructs may not be nested inside simd region");
2753 return false;
2755 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2757 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2758 || (gimple_omp_for_kind (stmt)
2759 != GF_OMP_FOR_KIND_DISTRIBUTE))
2760 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2762 error_at (gimple_location (stmt),
2763 "only distribute or parallel constructs are allowed to "
2764 "be closely nested inside teams construct");
2765 return false;
2769 switch (gimple_code (stmt))
2771 case GIMPLE_OMP_FOR:
2772 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2773 return true;
2774 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2776 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2778 error_at (gimple_location (stmt),
2779 "distribute construct must be closely nested inside "
2780 "teams construct");
2781 return false;
2783 return true;
2785 /* FALLTHRU */
2786 case GIMPLE_CALL:
2787 if (is_gimple_call (stmt)
2788 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2789 == BUILT_IN_GOMP_CANCEL
2790 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2791 == BUILT_IN_GOMP_CANCELLATION_POINT))
2793 const char *bad = NULL;
2794 const char *kind = NULL;
2795 if (ctx == NULL)
2797 error_at (gimple_location (stmt), "orphaned %qs construct",
2798 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2799 == BUILT_IN_GOMP_CANCEL
2800 ? "#pragma omp cancel"
2801 : "#pragma omp cancellation point");
2802 return false;
2804 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2805 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2806 : 0)
2808 case 1:
2809 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2810 bad = "#pragma omp parallel";
2811 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2812 == BUILT_IN_GOMP_CANCEL
2813 && !integer_zerop (gimple_call_arg (stmt, 1)))
2814 ctx->cancellable = true;
2815 kind = "parallel";
2816 break;
2817 case 2:
2818 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2819 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2820 bad = "#pragma omp for";
2821 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2822 == BUILT_IN_GOMP_CANCEL
2823 && !integer_zerop (gimple_call_arg (stmt, 1)))
2825 ctx->cancellable = true;
2826 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2827 OMP_CLAUSE_NOWAIT))
2828 warning_at (gimple_location (stmt), 0,
2829 "%<#pragma omp cancel for%> inside "
2830 "%<nowait%> for construct");
2831 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2832 OMP_CLAUSE_ORDERED))
2833 warning_at (gimple_location (stmt), 0,
2834 "%<#pragma omp cancel for%> inside "
2835 "%<ordered%> for construct");
2837 kind = "for";
2838 break;
2839 case 4:
2840 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2841 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2842 bad = "#pragma omp sections";
2843 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2844 == BUILT_IN_GOMP_CANCEL
2845 && !integer_zerop (gimple_call_arg (stmt, 1)))
2847 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2849 ctx->cancellable = true;
2850 if (find_omp_clause (gimple_omp_sections_clauses
2851 (ctx->stmt),
2852 OMP_CLAUSE_NOWAIT))
2853 warning_at (gimple_location (stmt), 0,
2854 "%<#pragma omp cancel sections%> inside "
2855 "%<nowait%> sections construct");
2857 else
2859 gcc_assert (ctx->outer
2860 && gimple_code (ctx->outer->stmt)
2861 == GIMPLE_OMP_SECTIONS);
2862 ctx->outer->cancellable = true;
2863 if (find_omp_clause (gimple_omp_sections_clauses
2864 (ctx->outer->stmt),
2865 OMP_CLAUSE_NOWAIT))
2866 warning_at (gimple_location (stmt), 0,
2867 "%<#pragma omp cancel sections%> inside "
2868 "%<nowait%> sections construct");
2871 kind = "sections";
2872 break;
2873 case 8:
2874 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2875 bad = "#pragma omp task";
2876 else
2877 ctx->cancellable = true;
2878 kind = "taskgroup";
2879 break;
2880 default:
2881 error_at (gimple_location (stmt), "invalid arguments");
2882 return false;
2884 if (bad)
2886 error_at (gimple_location (stmt),
2887 "%<%s %s%> construct not closely nested inside of %qs",
2888 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2889 == BUILT_IN_GOMP_CANCEL
2890 ? "#pragma omp cancel"
2891 : "#pragma omp cancellation point", kind, bad);
2892 return false;
2895 /* FALLTHRU */
2896 case GIMPLE_OMP_SECTIONS:
2897 case GIMPLE_OMP_SINGLE:
2898 for (; ctx != NULL; ctx = ctx->outer)
2899 switch (gimple_code (ctx->stmt))
2901 case GIMPLE_OMP_FOR:
2902 case GIMPLE_OMP_SECTIONS:
2903 case GIMPLE_OMP_SINGLE:
2904 case GIMPLE_OMP_ORDERED:
2905 case GIMPLE_OMP_MASTER:
2906 case GIMPLE_OMP_TASK:
2907 case GIMPLE_OMP_CRITICAL:
2908 if (is_gimple_call (stmt))
2910 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2911 != BUILT_IN_GOMP_BARRIER)
2912 return true;
2913 error_at (gimple_location (stmt),
2914 "barrier region may not be closely nested inside "
2915 "of work-sharing, critical, ordered, master or "
2916 "explicit task region");
2917 return false;
2919 error_at (gimple_location (stmt),
2920 "work-sharing region may not be closely nested inside "
2921 "of work-sharing, critical, ordered, master or explicit "
2922 "task region");
2923 return false;
2924 case GIMPLE_OMP_PARALLEL:
2925 return true;
2926 default:
2927 break;
2929 break;
2930 case GIMPLE_OMP_MASTER:
2931 for (; ctx != NULL; ctx = ctx->outer)
2932 switch (gimple_code (ctx->stmt))
2934 case GIMPLE_OMP_FOR:
2935 case GIMPLE_OMP_SECTIONS:
2936 case GIMPLE_OMP_SINGLE:
2937 case GIMPLE_OMP_TASK:
2938 error_at (gimple_location (stmt),
2939 "master region may not be closely nested inside "
2940 "of work-sharing or explicit task region");
2941 return false;
2942 case GIMPLE_OMP_PARALLEL:
2943 return true;
2944 default:
2945 break;
2947 break;
2948 case GIMPLE_OMP_ORDERED:
2949 for (; ctx != NULL; ctx = ctx->outer)
2950 switch (gimple_code (ctx->stmt))
2952 case GIMPLE_OMP_CRITICAL:
2953 case GIMPLE_OMP_TASK:
2954 error_at (gimple_location (stmt),
2955 "ordered region may not be closely nested inside "
2956 "of critical or explicit task region");
2957 return false;
2958 case GIMPLE_OMP_FOR:
2959 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2960 OMP_CLAUSE_ORDERED) == NULL)
2962 error_at (gimple_location (stmt),
2963 "ordered region must be closely nested inside "
2964 "a loop region with an ordered clause");
2965 return false;
2967 return true;
2968 case GIMPLE_OMP_PARALLEL:
2969 error_at (gimple_location (stmt),
2970 "ordered region must be closely nested inside "
2971 "a loop region with an ordered clause");
2972 return false;
2973 default:
2974 break;
2976 break;
2977 case GIMPLE_OMP_CRITICAL:
2979 tree this_stmt_name
2980 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2981 for (; ctx != NULL; ctx = ctx->outer)
2982 if (gomp_critical *other_crit
2983 = dyn_cast <gomp_critical *> (ctx->stmt))
2984 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2986 error_at (gimple_location (stmt),
2987 "critical region may not be nested inside a critical "
2988 "region with the same name");
2989 return false;
2992 break;
2993 case GIMPLE_OMP_TEAMS:
2994 if (ctx == NULL
2995 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2996 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2998 error_at (gimple_location (stmt),
2999 "teams construct not closely nested inside of target "
3000 "region");
3001 return false;
3003 break;
3004 case GIMPLE_OMP_TARGET:
3005 for (; ctx != NULL; ctx = ctx->outer)
3007 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3009 if (is_gimple_omp (stmt)
3010 && is_gimple_omp_oacc (stmt)
3011 && is_gimple_omp (ctx->stmt))
3013 error_at (gimple_location (stmt),
3014 "OpenACC construct inside of non-OpenACC region");
3015 return false;
3017 continue;
3020 const char *stmt_name, *ctx_stmt_name;
3021 switch (gimple_omp_target_kind (stmt))
3023 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3024 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3025 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3026 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3027 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3028 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3029 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3030 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3031 default: gcc_unreachable ();
3033 switch (gimple_omp_target_kind (ctx->stmt))
3035 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3036 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3037 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3038 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3039 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3040 default: gcc_unreachable ();
3043 /* OpenACC/OpenMP mismatch? */
3044 if (is_gimple_omp_oacc (stmt)
3045 != is_gimple_omp_oacc (ctx->stmt))
3047 error_at (gimple_location (stmt),
3048 "%s %s construct inside of %s %s region",
3049 (is_gimple_omp_oacc (stmt)
3050 ? "OpenACC" : "OpenMP"), stmt_name,
3051 (is_gimple_omp_oacc (ctx->stmt)
3052 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3053 return false;
3055 if (is_gimple_omp_offloaded (ctx->stmt))
3057 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3058 if (is_gimple_omp_oacc (ctx->stmt))
3060 error_at (gimple_location (stmt),
3061 "%s construct inside of %s region",
3062 stmt_name, ctx_stmt_name);
3063 return false;
3065 else
3067 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3068 warning_at (gimple_location (stmt), 0,
3069 "%s construct inside of %s region",
3070 stmt_name, ctx_stmt_name);
3074 break;
3075 default:
3076 break;
3078 return true;
3082 /* Helper function scan_omp.
3084 Callback for walk_tree or operators in walk_gimple_stmt used to
3085 scan for OMP directives in TP. */
3087 static tree
3088 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3090 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3091 omp_context *ctx = (omp_context *) wi->info;
3092 tree t = *tp;
3094 switch (TREE_CODE (t))
3096 case VAR_DECL:
3097 case PARM_DECL:
3098 case LABEL_DECL:
3099 case RESULT_DECL:
3100 if (ctx)
3101 *tp = remap_decl (t, &ctx->cb);
3102 break;
3104 default:
3105 if (ctx && TYPE_P (t))
3106 *tp = remap_type (t, &ctx->cb);
3107 else if (!DECL_P (t))
3109 *walk_subtrees = 1;
3110 if (ctx)
3112 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3113 if (tem != TREE_TYPE (t))
3115 if (TREE_CODE (t) == INTEGER_CST)
3116 *tp = wide_int_to_tree (tem, t);
3117 else
3118 TREE_TYPE (t) = tem;
3122 break;
3125 return NULL_TREE;
3128 /* Return true if FNDECL is a setjmp or a longjmp. */
3130 static bool
3131 setjmp_or_longjmp_p (const_tree fndecl)
3133 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3134 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3135 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3136 return true;
3138 tree declname = DECL_NAME (fndecl);
3139 if (!declname)
3140 return false;
3141 const char *name = IDENTIFIER_POINTER (declname);
3142 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3146 /* Helper function for scan_omp.
3148 Callback for walk_gimple_stmt used to scan for OMP directives in
3149 the current statement in GSI. */
3151 static tree
3152 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3153 struct walk_stmt_info *wi)
3155 gimple stmt = gsi_stmt (*gsi);
3156 omp_context *ctx = (omp_context *) wi->info;
3158 if (gimple_has_location (stmt))
3159 input_location = gimple_location (stmt);
3161 /* Check the nesting restrictions. */
3162 bool remove = false;
3163 if (is_gimple_omp (stmt))
3164 remove = !check_omp_nesting_restrictions (stmt, ctx);
3165 else if (is_gimple_call (stmt))
3167 tree fndecl = gimple_call_fndecl (stmt);
3168 if (fndecl)
3170 if (setjmp_or_longjmp_p (fndecl)
3171 && ctx
3172 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3173 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3175 remove = true;
3176 error_at (gimple_location (stmt),
3177 "setjmp/longjmp inside simd construct");
3179 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3180 switch (DECL_FUNCTION_CODE (fndecl))
3182 case BUILT_IN_GOMP_BARRIER:
3183 case BUILT_IN_GOMP_CANCEL:
3184 case BUILT_IN_GOMP_CANCELLATION_POINT:
3185 case BUILT_IN_GOMP_TASKYIELD:
3186 case BUILT_IN_GOMP_TASKWAIT:
3187 case BUILT_IN_GOMP_TASKGROUP_START:
3188 case BUILT_IN_GOMP_TASKGROUP_END:
3189 remove = !check_omp_nesting_restrictions (stmt, ctx);
3190 break;
3191 default:
3192 break;
3196 if (remove)
3198 stmt = gimple_build_nop ();
3199 gsi_replace (gsi, stmt, false);
3202 *handled_ops_p = true;
3204 switch (gimple_code (stmt))
3206 case GIMPLE_OMP_PARALLEL:
3207 taskreg_nesting_level++;
3208 scan_omp_parallel (gsi, ctx);
3209 taskreg_nesting_level--;
3210 break;
3212 case GIMPLE_OMP_TASK:
3213 taskreg_nesting_level++;
3214 scan_omp_task (gsi, ctx);
3215 taskreg_nesting_level--;
3216 break;
3218 case GIMPLE_OMP_FOR:
3219 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3220 break;
3222 case GIMPLE_OMP_SECTIONS:
3223 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3224 break;
3226 case GIMPLE_OMP_SINGLE:
3227 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3228 break;
3230 case GIMPLE_OMP_SECTION:
3231 case GIMPLE_OMP_MASTER:
3232 case GIMPLE_OMP_TASKGROUP:
3233 case GIMPLE_OMP_ORDERED:
3234 case GIMPLE_OMP_CRITICAL:
3235 ctx = new_omp_context (stmt, ctx);
3236 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3237 break;
3239 case GIMPLE_OMP_TARGET:
3240 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3241 break;
3243 case GIMPLE_OMP_TEAMS:
3244 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3245 break;
3247 case GIMPLE_BIND:
3249 tree var;
3251 *handled_ops_p = false;
3252 if (ctx)
3253 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3254 var ;
3255 var = DECL_CHAIN (var))
3256 insert_decl_map (&ctx->cb, var, var);
3258 break;
3259 default:
3260 *handled_ops_p = false;
3261 break;
3264 return NULL_TREE;
3268 /* Scan all the statements starting at the current statement. CTX
3269 contains context information about the OMP directives and
3270 clauses found during the scan. */
3272 static void
3273 scan_omp (gimple_seq *body_p, omp_context *ctx)
3275 location_t saved_location;
3276 struct walk_stmt_info wi;
3278 memset (&wi, 0, sizeof (wi));
3279 wi.info = ctx;
3280 wi.want_locations = true;
3282 saved_location = input_location;
3283 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3284 input_location = saved_location;
3287 /* Re-gimplification and code generation routines. */
3289 /* Build a call to GOMP_barrier. */
3291 static gimple
3292 build_omp_barrier (tree lhs)
3294 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3295 : BUILT_IN_GOMP_BARRIER);
3296 gcall *g = gimple_build_call (fndecl, 0);
3297 if (lhs)
3298 gimple_call_set_lhs (g, lhs);
3299 return g;
3302 /* If a context was created for STMT when it was scanned, return it. */
3304 static omp_context *
3305 maybe_lookup_ctx (gimple stmt)
3307 splay_tree_node n;
3308 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3309 return n ? (omp_context *) n->value : NULL;
3313 /* Find the mapping for DECL in CTX or the immediately enclosing
3314 context that has a mapping for DECL.
3316 If CTX is a nested parallel directive, we may have to use the decl
3317 mappings created in CTX's parent context. Suppose that we have the
3318 following parallel nesting (variable UIDs showed for clarity):
3320 iD.1562 = 0;
3321 #omp parallel shared(iD.1562) -> outer parallel
3322 iD.1562 = iD.1562 + 1;
3324 #omp parallel shared (iD.1562) -> inner parallel
3325 iD.1562 = iD.1562 - 1;
3327 Each parallel structure will create a distinct .omp_data_s structure
3328 for copying iD.1562 in/out of the directive:
3330 outer parallel .omp_data_s.1.i -> iD.1562
3331 inner parallel .omp_data_s.2.i -> iD.1562
3333 A shared variable mapping will produce a copy-out operation before
3334 the parallel directive and a copy-in operation after it. So, in
3335 this case we would have:
3337 iD.1562 = 0;
3338 .omp_data_o.1.i = iD.1562;
3339 #omp parallel shared(iD.1562) -> outer parallel
3340 .omp_data_i.1 = &.omp_data_o.1
3341 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3343 .omp_data_o.2.i = iD.1562; -> **
3344 #omp parallel shared(iD.1562) -> inner parallel
3345 .omp_data_i.2 = &.omp_data_o.2
3346 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3349 ** This is a problem. The symbol iD.1562 cannot be referenced
3350 inside the body of the outer parallel region. But since we are
3351 emitting this copy operation while expanding the inner parallel
3352 directive, we need to access the CTX structure of the outer
3353 parallel directive to get the correct mapping:
3355 .omp_data_o.2.i = .omp_data_i.1->i
3357 Since there may be other workshare or parallel directives enclosing
3358 the parallel directive, it may be necessary to walk up the context
3359 parent chain. This is not a problem in general because nested
3360 parallelism happens only rarely. */
3362 static tree
3363 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3365 tree t;
3366 omp_context *up;
3368 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3369 t = maybe_lookup_decl (decl, up);
3371 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3373 return t ? t : decl;
3377 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3378 in outer contexts. */
3380 static tree
3381 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3383 tree t = NULL;
3384 omp_context *up;
3386 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3387 t = maybe_lookup_decl (decl, up);
3389 return t ? t : decl;
3393 /* Construct the initialization value for reduction CLAUSE. */
3395 tree
3396 omp_reduction_init (tree clause, tree type)
3398 location_t loc = OMP_CLAUSE_LOCATION (clause);
3399 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3401 case PLUS_EXPR:
3402 case MINUS_EXPR:
3403 case BIT_IOR_EXPR:
3404 case BIT_XOR_EXPR:
3405 case TRUTH_OR_EXPR:
3406 case TRUTH_ORIF_EXPR:
3407 case TRUTH_XOR_EXPR:
3408 case NE_EXPR:
3409 return build_zero_cst (type);
3411 case MULT_EXPR:
3412 case TRUTH_AND_EXPR:
3413 case TRUTH_ANDIF_EXPR:
3414 case EQ_EXPR:
3415 return fold_convert_loc (loc, type, integer_one_node);
3417 case BIT_AND_EXPR:
3418 return fold_convert_loc (loc, type, integer_minus_one_node);
3420 case MAX_EXPR:
3421 if (SCALAR_FLOAT_TYPE_P (type))
3423 REAL_VALUE_TYPE max, min;
3424 if (HONOR_INFINITIES (type))
3426 real_inf (&max);
3427 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3429 else
3430 real_maxval (&min, 1, TYPE_MODE (type));
3431 return build_real (type, min);
3433 else
3435 gcc_assert (INTEGRAL_TYPE_P (type));
3436 return TYPE_MIN_VALUE (type);
3439 case MIN_EXPR:
3440 if (SCALAR_FLOAT_TYPE_P (type))
3442 REAL_VALUE_TYPE max;
3443 if (HONOR_INFINITIES (type))
3444 real_inf (&max);
3445 else
3446 real_maxval (&max, 0, TYPE_MODE (type));
3447 return build_real (type, max);
3449 else
3451 gcc_assert (INTEGRAL_TYPE_P (type));
3452 return TYPE_MAX_VALUE (type);
3455 default:
3456 gcc_unreachable ();
3460 /* Return alignment to be assumed for var in CLAUSE, which should be
3461 OMP_CLAUSE_ALIGNED. */
3463 static tree
3464 omp_clause_aligned_alignment (tree clause)
3466 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3467 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3469 /* Otherwise return implementation defined alignment. */
3470 unsigned int al = 1;
3471 machine_mode mode, vmode;
3472 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3473 if (vs)
3474 vs = 1 << floor_log2 (vs);
3475 static enum mode_class classes[]
3476 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3477 for (int i = 0; i < 4; i += 2)
3478 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3479 mode != VOIDmode;
3480 mode = GET_MODE_WIDER_MODE (mode))
3482 vmode = targetm.vectorize.preferred_simd_mode (mode);
3483 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3484 continue;
3485 while (vs
3486 && GET_MODE_SIZE (vmode) < vs
3487 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3488 vmode = GET_MODE_2XWIDER_MODE (vmode);
3490 tree type = lang_hooks.types.type_for_mode (mode, 1);
3491 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3492 continue;
3493 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3494 / GET_MODE_SIZE (mode));
3495 if (TYPE_MODE (type) != vmode)
3496 continue;
3497 if (TYPE_ALIGN_UNIT (type) > al)
3498 al = TYPE_ALIGN_UNIT (type);
3500 return build_int_cst (integer_type_node, al);
3503 /* Return maximum possible vectorization factor for the target. */
3505 static int
3506 omp_max_vf (void)
3508 if (!optimize
3509 || optimize_debug
3510 || !flag_tree_loop_optimize
3511 || (!flag_tree_loop_vectorize
3512 && (global_options_set.x_flag_tree_loop_vectorize
3513 || global_options_set.x_flag_tree_vectorize)))
3514 return 1;
3516 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3517 if (vs)
3519 vs = 1 << floor_log2 (vs);
3520 return vs;
3522 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3523 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3524 return GET_MODE_NUNITS (vqimode);
3525 return 1;
3528 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3529 privatization. */
3531 static bool
3532 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3533 tree &idx, tree &lane, tree &ivar, tree &lvar)
3535 if (max_vf == 0)
3537 max_vf = omp_max_vf ();
3538 if (max_vf > 1)
3540 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3541 OMP_CLAUSE_SAFELEN);
3542 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3543 max_vf = 1;
3544 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3545 max_vf) == -1)
3546 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3548 if (max_vf > 1)
3550 idx = create_tmp_var (unsigned_type_node);
3551 lane = create_tmp_var (unsigned_type_node);
3554 if (max_vf == 1)
3555 return false;
3557 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3558 tree avar = create_tmp_var_raw (atype);
3559 if (TREE_ADDRESSABLE (new_var))
3560 TREE_ADDRESSABLE (avar) = 1;
3561 DECL_ATTRIBUTES (avar)
3562 = tree_cons (get_identifier ("omp simd array"), NULL,
3563 DECL_ATTRIBUTES (avar));
3564 gimple_add_tmp_var (avar);
3565 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3566 NULL_TREE, NULL_TREE);
3567 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3568 NULL_TREE, NULL_TREE);
3569 if (DECL_P (new_var))
3571 SET_DECL_VALUE_EXPR (new_var, lvar);
3572 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3574 return true;
3577 /* Helper function of lower_rec_input_clauses. For a reference
3578 in simd reduction, add an underlying variable it will reference. */
3580 static void
3581 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3583 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3584 if (TREE_CONSTANT (z))
3586 const char *name = NULL;
3587 if (DECL_NAME (new_vard))
3588 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3590 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3591 gimple_add_tmp_var (z);
3592 TREE_ADDRESSABLE (z) = 1;
3593 z = build_fold_addr_expr_loc (loc, z);
3594 gimplify_assign (new_vard, z, ilist);
3598 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3599 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3600 private variables. Initialization statements go in ILIST, while calls
3601 to destructors go in DLIST. */
3603 static void
3604 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3605 omp_context *ctx, struct omp_for_data *fd)
3607 tree c, dtor, copyin_seq, x, ptr;
3608 bool copyin_by_ref = false;
3609 bool lastprivate_firstprivate = false;
3610 bool reduction_omp_orig_ref = false;
3611 int pass;
3612 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3613 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3614 int max_vf = 0;
3615 tree lane = NULL_TREE, idx = NULL_TREE;
3616 tree ivar = NULL_TREE, lvar = NULL_TREE;
3617 gimple_seq llist[2] = { NULL, NULL };
3619 copyin_seq = NULL;
3621 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3622 with data sharing clauses referencing variable sized vars. That
3623 is unnecessarily hard to support and very unlikely to result in
3624 vectorized code anyway. */
3625 if (is_simd)
3626 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3627 switch (OMP_CLAUSE_CODE (c))
3629 case OMP_CLAUSE_LINEAR:
3630 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3631 max_vf = 1;
3632 /* FALLTHRU */
3633 case OMP_CLAUSE_REDUCTION:
3634 case OMP_CLAUSE_PRIVATE:
3635 case OMP_CLAUSE_FIRSTPRIVATE:
3636 case OMP_CLAUSE_LASTPRIVATE:
3637 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3638 max_vf = 1;
3639 break;
3640 default:
3641 continue;
3644 /* Do all the fixed sized types in the first pass, and the variable sized
3645 types in the second pass. This makes sure that the scalar arguments to
3646 the variable sized types are processed before we use them in the
3647 variable sized operations. */
3648 for (pass = 0; pass < 2; ++pass)
3650 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3652 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3653 tree var, new_var;
3654 bool by_ref;
3655 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3657 switch (c_kind)
3659 case OMP_CLAUSE_PRIVATE:
3660 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3661 continue;
3662 break;
3663 case OMP_CLAUSE_SHARED:
3664 /* Ignore shared directives in teams construct. */
3665 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3666 continue;
3667 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3669 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3670 continue;
3672 case OMP_CLAUSE_FIRSTPRIVATE:
3673 case OMP_CLAUSE_COPYIN:
3674 case OMP_CLAUSE_LINEAR:
3675 break;
3676 case OMP_CLAUSE_REDUCTION:
3677 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3678 reduction_omp_orig_ref = true;
3679 break;
3680 case OMP_CLAUSE__LOOPTEMP_:
3681 /* Handle _looptemp_ clauses only on parallel. */
3682 if (fd)
3683 continue;
3684 break;
3685 case OMP_CLAUSE_LASTPRIVATE:
3686 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3688 lastprivate_firstprivate = true;
3689 if (pass != 0)
3690 continue;
3692 /* Even without corresponding firstprivate, if
3693 decl is Fortran allocatable, it needs outer var
3694 reference. */
3695 else if (pass == 0
3696 && lang_hooks.decls.omp_private_outer_ref
3697 (OMP_CLAUSE_DECL (c)))
3698 lastprivate_firstprivate = true;
3699 break;
3700 case OMP_CLAUSE_ALIGNED:
3701 if (pass == 0)
3702 continue;
3703 var = OMP_CLAUSE_DECL (c);
3704 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3705 && !is_global_var (var))
3707 new_var = maybe_lookup_decl (var, ctx);
3708 if (new_var == NULL_TREE)
3709 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3710 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3711 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3712 omp_clause_aligned_alignment (c));
3713 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3714 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3715 gimplify_and_add (x, ilist);
3717 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3718 && is_global_var (var))
3720 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3721 new_var = lookup_decl (var, ctx);
3722 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3723 t = build_fold_addr_expr_loc (clause_loc, t);
3724 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3725 t = build_call_expr_loc (clause_loc, t2, 2, t,
3726 omp_clause_aligned_alignment (c));
3727 t = fold_convert_loc (clause_loc, ptype, t);
3728 x = create_tmp_var (ptype);
3729 t = build2 (MODIFY_EXPR, ptype, x, t);
3730 gimplify_and_add (t, ilist);
3731 t = build_simple_mem_ref_loc (clause_loc, x);
3732 SET_DECL_VALUE_EXPR (new_var, t);
3733 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3735 continue;
3736 default:
3737 continue;
3740 new_var = var = OMP_CLAUSE_DECL (c);
3741 if (c_kind != OMP_CLAUSE_COPYIN)
3742 new_var = lookup_decl (var, ctx);
3744 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3746 if (pass != 0)
3747 continue;
3749 else if (is_variable_sized (var))
3751 /* For variable sized types, we need to allocate the
3752 actual storage here. Call alloca and store the
3753 result in the pointer decl that we created elsewhere. */
3754 if (pass == 0)
3755 continue;
3757 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3759 gcall *stmt;
3760 tree tmp, atmp;
3762 ptr = DECL_VALUE_EXPR (new_var);
3763 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3764 ptr = TREE_OPERAND (ptr, 0);
3765 gcc_assert (DECL_P (ptr));
3766 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3768 /* void *tmp = __builtin_alloca */
3769 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3770 stmt = gimple_build_call (atmp, 1, x);
3771 tmp = create_tmp_var_raw (ptr_type_node);
3772 gimple_add_tmp_var (tmp);
3773 gimple_call_set_lhs (stmt, tmp);
3775 gimple_seq_add_stmt (ilist, stmt);
3777 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3778 gimplify_assign (ptr, x, ilist);
3781 else if (is_reference (var))
3783 /* For references that are being privatized for Fortran,
3784 allocate new backing storage for the new pointer
3785 variable. This allows us to avoid changing all the
3786 code that expects a pointer to something that expects
3787 a direct variable. */
3788 if (pass == 0)
3789 continue;
3791 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3792 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3794 x = build_receiver_ref (var, false, ctx);
3795 x = build_fold_addr_expr_loc (clause_loc, x);
3797 else if (TREE_CONSTANT (x))
3799 /* For reduction in SIMD loop, defer adding the
3800 initialization of the reference, because if we decide
3801 to use SIMD array for it, the initilization could cause
3802 expansion ICE. */
3803 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3804 x = NULL_TREE;
3805 else
3807 const char *name = NULL;
3808 if (DECL_NAME (var))
3809 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3811 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3812 name);
3813 gimple_add_tmp_var (x);
3814 TREE_ADDRESSABLE (x) = 1;
3815 x = build_fold_addr_expr_loc (clause_loc, x);
3818 else
3820 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3821 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3824 if (x)
3826 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3827 gimplify_assign (new_var, x, ilist);
3830 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3832 else if (c_kind == OMP_CLAUSE_REDUCTION
3833 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3835 if (pass == 0)
3836 continue;
3838 else if (pass != 0)
3839 continue;
3841 switch (OMP_CLAUSE_CODE (c))
3843 case OMP_CLAUSE_SHARED:
3844 /* Ignore shared directives in teams construct. */
3845 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3846 continue;
3847 /* Shared global vars are just accessed directly. */
3848 if (is_global_var (new_var))
3849 break;
3850 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3851 needs to be delayed until after fixup_child_record_type so
3852 that we get the correct type during the dereference. */
3853 by_ref = use_pointer_for_field (var, ctx);
3854 x = build_receiver_ref (var, by_ref, ctx);
3855 SET_DECL_VALUE_EXPR (new_var, x);
3856 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3858 /* ??? If VAR is not passed by reference, and the variable
3859 hasn't been initialized yet, then we'll get a warning for
3860 the store into the omp_data_s structure. Ideally, we'd be
3861 able to notice this and not store anything at all, but
3862 we're generating code too early. Suppress the warning. */
3863 if (!by_ref)
3864 TREE_NO_WARNING (var) = 1;
3865 break;
3867 case OMP_CLAUSE_LASTPRIVATE:
3868 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3869 break;
3870 /* FALLTHRU */
3872 case OMP_CLAUSE_PRIVATE:
3873 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3874 x = build_outer_var_ref (var, ctx);
3875 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3877 if (is_task_ctx (ctx))
3878 x = build_receiver_ref (var, false, ctx);
3879 else
3880 x = build_outer_var_ref (var, ctx);
3882 else
3883 x = NULL;
3884 do_private:
3885 tree nx;
3886 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3887 if (is_simd)
3889 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3890 if ((TREE_ADDRESSABLE (new_var) || nx || y
3891 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3892 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3893 idx, lane, ivar, lvar))
3895 if (nx)
3896 x = lang_hooks.decls.omp_clause_default_ctor
3897 (c, unshare_expr (ivar), x);
3898 if (nx && x)
3899 gimplify_and_add (x, &llist[0]);
3900 if (y)
3902 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3903 if (y)
3905 gimple_seq tseq = NULL;
3907 dtor = y;
3908 gimplify_stmt (&dtor, &tseq);
3909 gimple_seq_add_seq (&llist[1], tseq);
3912 break;
3915 if (nx)
3916 gimplify_and_add (nx, ilist);
3917 /* FALLTHRU */
3919 do_dtor:
3920 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3921 if (x)
3923 gimple_seq tseq = NULL;
3925 dtor = x;
3926 gimplify_stmt (&dtor, &tseq);
3927 gimple_seq_add_seq (dlist, tseq);
3929 break;
3931 case OMP_CLAUSE_LINEAR:
3932 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3933 goto do_firstprivate;
3934 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3935 x = NULL;
3936 else
3937 x = build_outer_var_ref (var, ctx);
3938 goto do_private;
3940 case OMP_CLAUSE_FIRSTPRIVATE:
3941 if (is_task_ctx (ctx))
3943 if (is_reference (var) || is_variable_sized (var))
3944 goto do_dtor;
3945 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3946 ctx))
3947 || use_pointer_for_field (var, NULL))
3949 x = build_receiver_ref (var, false, ctx);
3950 SET_DECL_VALUE_EXPR (new_var, x);
3951 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3952 goto do_dtor;
3955 do_firstprivate:
3956 x = build_outer_var_ref (var, ctx);
3957 if (is_simd)
3959 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3960 && gimple_omp_for_combined_into_p (ctx->stmt))
3962 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3963 tree stept = TREE_TYPE (t);
3964 tree ct = find_omp_clause (clauses,
3965 OMP_CLAUSE__LOOPTEMP_);
3966 gcc_assert (ct);
3967 tree l = OMP_CLAUSE_DECL (ct);
3968 tree n1 = fd->loop.n1;
3969 tree step = fd->loop.step;
3970 tree itype = TREE_TYPE (l);
3971 if (POINTER_TYPE_P (itype))
3972 itype = signed_type_for (itype);
3973 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3974 if (TYPE_UNSIGNED (itype)
3975 && fd->loop.cond_code == GT_EXPR)
3976 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3977 fold_build1 (NEGATE_EXPR, itype, l),
3978 fold_build1 (NEGATE_EXPR,
3979 itype, step));
3980 else
3981 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3982 t = fold_build2 (MULT_EXPR, stept,
3983 fold_convert (stept, l), t);
3985 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3987 x = lang_hooks.decls.omp_clause_linear_ctor
3988 (c, new_var, x, t);
3989 gimplify_and_add (x, ilist);
3990 goto do_dtor;
3993 if (POINTER_TYPE_P (TREE_TYPE (x)))
3994 x = fold_build2 (POINTER_PLUS_EXPR,
3995 TREE_TYPE (x), x, t);
3996 else
3997 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4000 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4001 || TREE_ADDRESSABLE (new_var))
4002 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4003 idx, lane, ivar, lvar))
4005 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4007 tree iv = create_tmp_var (TREE_TYPE (new_var));
4008 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4009 gimplify_and_add (x, ilist);
4010 gimple_stmt_iterator gsi
4011 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4012 gassign *g
4013 = gimple_build_assign (unshare_expr (lvar), iv);
4014 gsi_insert_before_without_update (&gsi, g,
4015 GSI_SAME_STMT);
4016 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4017 enum tree_code code = PLUS_EXPR;
4018 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4019 code = POINTER_PLUS_EXPR;
4020 g = gimple_build_assign (iv, code, iv, t);
4021 gsi_insert_before_without_update (&gsi, g,
4022 GSI_SAME_STMT);
4023 break;
4025 x = lang_hooks.decls.omp_clause_copy_ctor
4026 (c, unshare_expr (ivar), x);
4027 gimplify_and_add (x, &llist[0]);
4028 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4029 if (x)
4031 gimple_seq tseq = NULL;
4033 dtor = x;
4034 gimplify_stmt (&dtor, &tseq);
4035 gimple_seq_add_seq (&llist[1], tseq);
4037 break;
4040 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4041 gimplify_and_add (x, ilist);
4042 goto do_dtor;
4044 case OMP_CLAUSE__LOOPTEMP_:
4045 gcc_assert (is_parallel_ctx (ctx));
4046 x = build_outer_var_ref (var, ctx);
4047 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4048 gimplify_and_add (x, ilist);
4049 break;
4051 case OMP_CLAUSE_COPYIN:
4052 by_ref = use_pointer_for_field (var, NULL);
4053 x = build_receiver_ref (var, by_ref, ctx);
4054 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4055 append_to_statement_list (x, &copyin_seq);
4056 copyin_by_ref |= by_ref;
4057 break;
4059 case OMP_CLAUSE_REDUCTION:
4060 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4062 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4063 gimple tseq;
4064 x = build_outer_var_ref (var, ctx);
4066 if (is_reference (var)
4067 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4068 TREE_TYPE (x)))
4069 x = build_fold_addr_expr_loc (clause_loc, x);
4070 SET_DECL_VALUE_EXPR (placeholder, x);
4071 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4072 tree new_vard = new_var;
4073 if (is_reference (var))
4075 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4076 new_vard = TREE_OPERAND (new_var, 0);
4077 gcc_assert (DECL_P (new_vard));
4079 if (is_simd
4080 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4081 idx, lane, ivar, lvar))
4083 if (new_vard == new_var)
4085 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4086 SET_DECL_VALUE_EXPR (new_var, ivar);
4088 else
4090 SET_DECL_VALUE_EXPR (new_vard,
4091 build_fold_addr_expr (ivar));
4092 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4094 x = lang_hooks.decls.omp_clause_default_ctor
4095 (c, unshare_expr (ivar),
4096 build_outer_var_ref (var, ctx));
4097 if (x)
4098 gimplify_and_add (x, &llist[0]);
4099 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4101 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4102 lower_omp (&tseq, ctx);
4103 gimple_seq_add_seq (&llist[0], tseq);
4105 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4106 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4107 lower_omp (&tseq, ctx);
4108 gimple_seq_add_seq (&llist[1], tseq);
4109 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4110 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4111 if (new_vard == new_var)
4112 SET_DECL_VALUE_EXPR (new_var, lvar);
4113 else
4114 SET_DECL_VALUE_EXPR (new_vard,
4115 build_fold_addr_expr (lvar));
4116 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4117 if (x)
4119 tseq = NULL;
4120 dtor = x;
4121 gimplify_stmt (&dtor, &tseq);
4122 gimple_seq_add_seq (&llist[1], tseq);
4124 break;
4126 /* If this is a reference to constant size reduction var
4127 with placeholder, we haven't emitted the initializer
4128 for it because it is undesirable if SIMD arrays are used.
4129 But if they aren't used, we need to emit the deferred
4130 initialization now. */
4131 else if (is_reference (var) && is_simd)
4132 handle_simd_reference (clause_loc, new_vard, ilist);
4133 x = lang_hooks.decls.omp_clause_default_ctor
4134 (c, unshare_expr (new_var),
4135 build_outer_var_ref (var, ctx));
4136 if (x)
4137 gimplify_and_add (x, ilist);
4138 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4140 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4141 lower_omp (&tseq, ctx);
4142 gimple_seq_add_seq (ilist, tseq);
4144 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4145 if (is_simd)
4147 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4148 lower_omp (&tseq, ctx);
4149 gimple_seq_add_seq (dlist, tseq);
4150 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4152 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4153 goto do_dtor;
4155 else
4157 x = omp_reduction_init (c, TREE_TYPE (new_var));
4158 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4159 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4161 /* reduction(-:var) sums up the partial results, so it
4162 acts identically to reduction(+:var). */
4163 if (code == MINUS_EXPR)
4164 code = PLUS_EXPR;
4166 tree new_vard = new_var;
4167 if (is_simd && is_reference (var))
4169 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4170 new_vard = TREE_OPERAND (new_var, 0);
4171 gcc_assert (DECL_P (new_vard));
4173 if (is_simd
4174 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4175 idx, lane, ivar, lvar))
4177 tree ref = build_outer_var_ref (var, ctx);
4179 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4181 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4182 ref = build_outer_var_ref (var, ctx);
4183 gimplify_assign (ref, x, &llist[1]);
4185 if (new_vard != new_var)
4187 SET_DECL_VALUE_EXPR (new_vard,
4188 build_fold_addr_expr (lvar));
4189 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4192 else
4194 if (is_reference (var) && is_simd)
4195 handle_simd_reference (clause_loc, new_vard, ilist);
4196 gimplify_assign (new_var, x, ilist);
4197 if (is_simd)
4199 tree ref = build_outer_var_ref (var, ctx);
4201 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4202 ref = build_outer_var_ref (var, ctx);
4203 gimplify_assign (ref, x, dlist);
4207 break;
4209 default:
4210 gcc_unreachable ();
4215 if (lane)
4217 tree uid = create_tmp_var (ptr_type_node, "simduid");
4218 /* Don't want uninit warnings on simduid, it is always uninitialized,
4219 but we use it not for the value, but for the DECL_UID only. */
4220 TREE_NO_WARNING (uid) = 1;
4221 gimple g
4222 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4223 gimple_call_set_lhs (g, lane);
4224 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4225 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4226 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4227 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4228 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4229 gimple_omp_for_set_clauses (ctx->stmt, c);
4230 g = gimple_build_assign (lane, INTEGER_CST,
4231 build_int_cst (unsigned_type_node, 0));
4232 gimple_seq_add_stmt (ilist, g);
4233 for (int i = 0; i < 2; i++)
4234 if (llist[i])
4236 tree vf = create_tmp_var (unsigned_type_node);
4237 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4238 gimple_call_set_lhs (g, vf);
4239 gimple_seq *seq = i == 0 ? ilist : dlist;
4240 gimple_seq_add_stmt (seq, g);
4241 tree t = build_int_cst (unsigned_type_node, 0);
4242 g = gimple_build_assign (idx, INTEGER_CST, t);
4243 gimple_seq_add_stmt (seq, g);
4244 tree body = create_artificial_label (UNKNOWN_LOCATION);
4245 tree header = create_artificial_label (UNKNOWN_LOCATION);
4246 tree end = create_artificial_label (UNKNOWN_LOCATION);
4247 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4248 gimple_seq_add_stmt (seq, gimple_build_label (body));
4249 gimple_seq_add_seq (seq, llist[i]);
4250 t = build_int_cst (unsigned_type_node, 1);
4251 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4252 gimple_seq_add_stmt (seq, g);
4253 gimple_seq_add_stmt (seq, gimple_build_label (header));
4254 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4255 gimple_seq_add_stmt (seq, g);
4256 gimple_seq_add_stmt (seq, gimple_build_label (end));
4260 /* The copyin sequence is not to be executed by the main thread, since
4261 that would result in self-copies. Perhaps not visible to scalars,
4262 but it certainly is to C++ operator=. */
4263 if (copyin_seq)
4265 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4267 x = build2 (NE_EXPR, boolean_type_node, x,
4268 build_int_cst (TREE_TYPE (x), 0));
4269 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4270 gimplify_and_add (x, ilist);
4273 /* If any copyin variable is passed by reference, we must ensure the
4274 master thread doesn't modify it before it is copied over in all
4275 threads. Similarly for variables in both firstprivate and
4276 lastprivate clauses we need to ensure the lastprivate copying
4277 happens after firstprivate copying in all threads. And similarly
4278 for UDRs if initializer expression refers to omp_orig. */
4279 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4281 /* Don't add any barrier for #pragma omp simd or
4282 #pragma omp distribute. */
4283 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4284 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4285 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4288 /* If max_vf is non-zero, then we can use only a vectorization factor
4289 up to the max_vf we chose. So stick it into the safelen clause. */
4290 if (max_vf)
4292 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4293 OMP_CLAUSE_SAFELEN);
4294 if (c == NULL_TREE
4295 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4296 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4297 max_vf) == 1))
4299 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4300 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4301 max_vf);
4302 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4303 gimple_omp_for_set_clauses (ctx->stmt, c);
4309 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4310 both parallel and workshare constructs. PREDICATE may be NULL if it's
4311 always true. */
4313 static void
4314 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4315 omp_context *ctx)
4317 tree x, c, label = NULL, orig_clauses = clauses;
4318 bool par_clauses = false;
4319 tree simduid = NULL, lastlane = NULL;
4321 /* Early exit if there are no lastprivate or linear clauses. */
4322 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4323 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4324 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4325 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4326 break;
4327 if (clauses == NULL)
4329 /* If this was a workshare clause, see if it had been combined
4330 with its parallel. In that case, look for the clauses on the
4331 parallel statement itself. */
4332 if (is_parallel_ctx (ctx))
4333 return;
4335 ctx = ctx->outer;
4336 if (ctx == NULL || !is_parallel_ctx (ctx))
4337 return;
4339 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4340 OMP_CLAUSE_LASTPRIVATE);
4341 if (clauses == NULL)
4342 return;
4343 par_clauses = true;
4346 if (predicate)
4348 gcond *stmt;
4349 tree label_true, arm1, arm2;
4351 label = create_artificial_label (UNKNOWN_LOCATION);
4352 label_true = create_artificial_label (UNKNOWN_LOCATION);
4353 arm1 = TREE_OPERAND (predicate, 0);
4354 arm2 = TREE_OPERAND (predicate, 1);
4355 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4356 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4357 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4358 label_true, label);
4359 gimple_seq_add_stmt (stmt_list, stmt);
4360 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4363 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4364 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4366 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4367 if (simduid)
4368 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4371 for (c = clauses; c ;)
4373 tree var, new_var;
4374 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4376 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4377 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4378 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4380 var = OMP_CLAUSE_DECL (c);
4381 new_var = lookup_decl (var, ctx);
4383 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4385 tree val = DECL_VALUE_EXPR (new_var);
4386 if (TREE_CODE (val) == ARRAY_REF
4387 && VAR_P (TREE_OPERAND (val, 0))
4388 && lookup_attribute ("omp simd array",
4389 DECL_ATTRIBUTES (TREE_OPERAND (val,
4390 0))))
4392 if (lastlane == NULL)
4394 lastlane = create_tmp_var (unsigned_type_node);
4395 gcall *g
4396 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4397 2, simduid,
4398 TREE_OPERAND (val, 1));
4399 gimple_call_set_lhs (g, lastlane);
4400 gimple_seq_add_stmt (stmt_list, g);
4402 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4403 TREE_OPERAND (val, 0), lastlane,
4404 NULL_TREE, NULL_TREE);
4408 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4409 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4411 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4412 gimple_seq_add_seq (stmt_list,
4413 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4414 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4416 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4417 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4419 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4420 gimple_seq_add_seq (stmt_list,
4421 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4422 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4425 x = build_outer_var_ref (var, ctx);
4426 if (is_reference (var))
4427 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4428 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4429 gimplify_and_add (x, stmt_list);
4431 c = OMP_CLAUSE_CHAIN (c);
4432 if (c == NULL && !par_clauses)
4434 /* If this was a workshare clause, see if it had been combined
4435 with its parallel. In that case, continue looking for the
4436 clauses also on the parallel statement itself. */
4437 if (is_parallel_ctx (ctx))
4438 break;
4440 ctx = ctx->outer;
4441 if (ctx == NULL || !is_parallel_ctx (ctx))
4442 break;
4444 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4445 OMP_CLAUSE_LASTPRIVATE);
4446 par_clauses = true;
4450 if (label)
4451 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4454 static void
4455 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4456 tree tid, tree var, tree new_var)
4458 /* The atomic add at the end of the sum creates unnecessary
4459 write contention on accelerators. To work around this,
4460 create an array to store the partial reductions. Later, in
4461 lower_omp_for (for openacc), the values of array will be
4462 combined. */
4464 tree t = NULL_TREE, array, x;
4465 tree type = get_base_type (var);
4466 gimple stmt;
4468 /* Now insert the partial reductions into the array. */
4470 /* Find the reduction array. */
4472 tree ptype = build_pointer_type (type);
4474 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4475 t = build_receiver_ref (t, false, ctx->outer);
4477 array = create_tmp_var (ptype);
4478 gimplify_assign (array, t, stmt_seqp);
4480 tree ptr = create_tmp_var (TREE_TYPE (array));
4482 /* Find the reduction array. */
4484 /* testing a unary conversion. */
4485 tree offset = create_tmp_var (sizetype);
4486 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4487 stmt_seqp);
4488 t = create_tmp_var (sizetype);
4489 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4490 stmt_seqp);
4491 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4492 gimple_seq_add_stmt (stmt_seqp, stmt);
4494 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4495 of adding sizeof(var) to the array? */
4496 ptr = create_tmp_var (ptype);
4497 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4498 offset);
4499 gimple_seq_add_stmt (stmt_seqp, stmt);
4501 /* Move the local sum to gfc$sum[i]. */
4502 x = unshare_expr (build_simple_mem_ref (ptr));
4503 stmt = gimplify_assign (x, new_var, stmt_seqp);
4506 /* Generate code to implement the REDUCTION clauses. */
4508 static void
4509 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4511 gimple_seq sub_seq = NULL;
4512 gimple stmt;
4513 tree x, c, tid = NULL_TREE;
4514 int count = 0;
4516 /* SIMD reductions are handled in lower_rec_input_clauses. */
4517 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4518 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4519 return;
4521 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4522 update in that case, otherwise use a lock. */
4523 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4524 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4526 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4528 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4529 count = -1;
4530 break;
4532 count++;
4535 if (count == 0)
4536 return;
4538 /* Initialize thread info for OpenACC. */
4539 if (is_gimple_omp_oacc (ctx->stmt))
4541 /* Get the current thread id. */
4542 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4543 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4544 gimple stmt = gimple_build_call (call, 0);
4545 gimple_call_set_lhs (stmt, tid);
4546 gimple_seq_add_stmt (stmt_seqp, stmt);
4549 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4551 tree var, ref, new_var;
4552 enum tree_code code;
4553 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4555 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4556 continue;
4558 var = OMP_CLAUSE_DECL (c);
4559 new_var = lookup_decl (var, ctx);
4560 if (is_reference (var))
4561 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4562 ref = build_outer_var_ref (var, ctx);
4563 code = OMP_CLAUSE_REDUCTION_CODE (c);
4565 /* reduction(-:var) sums up the partial results, so it acts
4566 identically to reduction(+:var). */
4567 if (code == MINUS_EXPR)
4568 code = PLUS_EXPR;
4570 if (is_gimple_omp_oacc (ctx->stmt))
4572 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4574 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4576 else if (count == 1)
4578 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4580 addr = save_expr (addr);
4581 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4582 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4583 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4584 gimplify_and_add (x, stmt_seqp);
4585 return;
4587 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4589 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4591 if (is_reference (var)
4592 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4593 TREE_TYPE (ref)))
4594 ref = build_fold_addr_expr_loc (clause_loc, ref);
4595 SET_DECL_VALUE_EXPR (placeholder, ref);
4596 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4597 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4598 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4599 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4600 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4602 else
4604 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4605 ref = build_outer_var_ref (var, ctx);
4606 gimplify_assign (ref, x, &sub_seq);
4610 if (is_gimple_omp_oacc (ctx->stmt))
4611 return;
4613 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4615 gimple_seq_add_stmt (stmt_seqp, stmt);
4617 gimple_seq_add_seq (stmt_seqp, sub_seq);
4619 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4621 gimple_seq_add_stmt (stmt_seqp, stmt);
4625 /* Generate code to implement the COPYPRIVATE clauses. */
4627 static void
4628 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4629 omp_context *ctx)
4631 tree c;
4633 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4635 tree var, new_var, ref, x;
4636 bool by_ref;
4637 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4639 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4640 continue;
4642 var = OMP_CLAUSE_DECL (c);
4643 by_ref = use_pointer_for_field (var, NULL);
4645 ref = build_sender_ref (var, ctx);
4646 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4647 if (by_ref)
4649 x = build_fold_addr_expr_loc (clause_loc, new_var);
4650 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4652 gimplify_assign (ref, x, slist);
4654 ref = build_receiver_ref (var, false, ctx);
4655 if (by_ref)
4657 ref = fold_convert_loc (clause_loc,
4658 build_pointer_type (TREE_TYPE (new_var)),
4659 ref);
4660 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4662 if (is_reference (var))
4664 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4665 ref = build_simple_mem_ref_loc (clause_loc, ref);
4666 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4668 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4669 gimplify_and_add (x, rlist);
4674 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4675 and REDUCTION from the sender (aka parent) side. */
4677 static void
4678 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4679 omp_context *ctx)
4681 tree c;
4683 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4685 tree val, ref, x, var;
4686 bool by_ref, do_in = false, do_out = false;
4687 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4689 switch (OMP_CLAUSE_CODE (c))
4691 case OMP_CLAUSE_PRIVATE:
4692 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4693 break;
4694 continue;
4695 case OMP_CLAUSE_FIRSTPRIVATE:
4696 case OMP_CLAUSE_COPYIN:
4697 case OMP_CLAUSE_LASTPRIVATE:
4698 case OMP_CLAUSE_REDUCTION:
4699 case OMP_CLAUSE__LOOPTEMP_:
4700 break;
4701 default:
4702 continue;
4705 val = OMP_CLAUSE_DECL (c);
4706 var = lookup_decl_in_outer_ctx (val, ctx);
4708 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4709 && is_global_var (var))
4710 continue;
4711 if (is_variable_sized (val))
4712 continue;
4713 by_ref = use_pointer_for_field (val, NULL);
4715 switch (OMP_CLAUSE_CODE (c))
4717 case OMP_CLAUSE_PRIVATE:
4718 case OMP_CLAUSE_FIRSTPRIVATE:
4719 case OMP_CLAUSE_COPYIN:
4720 case OMP_CLAUSE__LOOPTEMP_:
4721 do_in = true;
4722 break;
4724 case OMP_CLAUSE_LASTPRIVATE:
4725 if (by_ref || is_reference (val))
4727 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4728 continue;
4729 do_in = true;
4731 else
4733 do_out = true;
4734 if (lang_hooks.decls.omp_private_outer_ref (val))
4735 do_in = true;
4737 break;
4739 case OMP_CLAUSE_REDUCTION:
4740 do_in = true;
4741 do_out = !(by_ref || is_reference (val));
4742 break;
4744 default:
4745 gcc_unreachable ();
4748 if (do_in)
4750 ref = build_sender_ref (val, ctx);
4751 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4752 gimplify_assign (ref, x, ilist);
4753 if (is_task_ctx (ctx))
4754 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4757 if (do_out)
4759 ref = build_sender_ref (val, ctx);
4760 gimplify_assign (var, ref, olist);
4765 /* Generate code to implement SHARED from the sender (aka parent)
4766 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4767 list things that got automatically shared. */
4769 static void
4770 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4772 tree var, ovar, nvar, f, x, record_type;
4774 if (ctx->record_type == NULL)
4775 return;
4777 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4778 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4780 ovar = DECL_ABSTRACT_ORIGIN (f);
4781 nvar = maybe_lookup_decl (ovar, ctx);
4782 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4783 continue;
4785 /* If CTX is a nested parallel directive. Find the immediately
4786 enclosing parallel or workshare construct that contains a
4787 mapping for OVAR. */
4788 var = lookup_decl_in_outer_ctx (ovar, ctx);
4790 if (use_pointer_for_field (ovar, ctx))
4792 x = build_sender_ref (ovar, ctx);
4793 var = build_fold_addr_expr (var);
4794 gimplify_assign (x, var, ilist);
4796 else
4798 x = build_sender_ref (ovar, ctx);
4799 gimplify_assign (x, var, ilist);
4801 if (!TREE_READONLY (var)
4802 /* We don't need to receive a new reference to a result
4803 or parm decl. In fact we may not store to it as we will
4804 invalidate any pending RSO and generate wrong gimple
4805 during inlining. */
4806 && !((TREE_CODE (var) == RESULT_DECL
4807 || TREE_CODE (var) == PARM_DECL)
4808 && DECL_BY_REFERENCE (var)))
4810 x = build_sender_ref (ovar, ctx);
4811 gimplify_assign (var, x, olist);
4818 /* A convenience function to build an empty GIMPLE_COND with just the
4819 condition. */
4821 static gcond *
4822 gimple_build_cond_empty (tree cond)
4824 enum tree_code pred_code;
4825 tree lhs, rhs;
4827 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4828 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4832 /* Build the function calls to GOMP_parallel_start etc to actually
4833 generate the parallel operation. REGION is the parallel region
4834 being expanded. BB is the block where to insert the code. WS_ARGS
4835 will be set if this is a call to a combined parallel+workshare
4836 construct, it contains the list of additional arguments needed by
4837 the workshare construct. */
4839 static void
4840 expand_parallel_call (struct omp_region *region, basic_block bb,
4841 gomp_parallel *entry_stmt,
4842 vec<tree, va_gc> *ws_args)
4844 tree t, t1, t2, val, cond, c, clauses, flags;
4845 gimple_stmt_iterator gsi;
4846 gimple stmt;
4847 enum built_in_function start_ix;
4848 int start_ix2;
4849 location_t clause_loc;
4850 vec<tree, va_gc> *args;
4852 clauses = gimple_omp_parallel_clauses (entry_stmt);
4854 /* Determine what flavor of GOMP_parallel we will be
4855 emitting. */
4856 start_ix = BUILT_IN_GOMP_PARALLEL;
4857 if (is_combined_parallel (region))
4859 switch (region->inner->type)
4861 case GIMPLE_OMP_FOR:
4862 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4863 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4864 + (region->inner->sched_kind
4865 == OMP_CLAUSE_SCHEDULE_RUNTIME
4866 ? 3 : region->inner->sched_kind));
4867 start_ix = (enum built_in_function)start_ix2;
4868 break;
4869 case GIMPLE_OMP_SECTIONS:
4870 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4871 break;
4872 default:
4873 gcc_unreachable ();
4877 /* By default, the value of NUM_THREADS is zero (selected at run time)
4878 and there is no conditional. */
4879 cond = NULL_TREE;
4880 val = build_int_cst (unsigned_type_node, 0);
4881 flags = build_int_cst (unsigned_type_node, 0);
4883 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4884 if (c)
4885 cond = OMP_CLAUSE_IF_EXPR (c);
4887 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4888 if (c)
4890 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4891 clause_loc = OMP_CLAUSE_LOCATION (c);
4893 else
4894 clause_loc = gimple_location (entry_stmt);
4896 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4897 if (c)
4898 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4900 /* Ensure 'val' is of the correct type. */
4901 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4903 /* If we found the clause 'if (cond)', build either
4904 (cond != 0) or (cond ? val : 1u). */
4905 if (cond)
4907 cond = gimple_boolify (cond);
4909 if (integer_zerop (val))
4910 val = fold_build2_loc (clause_loc,
4911 EQ_EXPR, unsigned_type_node, cond,
4912 build_int_cst (TREE_TYPE (cond), 0));
4913 else
4915 basic_block cond_bb, then_bb, else_bb;
4916 edge e, e_then, e_else;
4917 tree tmp_then, tmp_else, tmp_join, tmp_var;
4919 tmp_var = create_tmp_var (TREE_TYPE (val));
4920 if (gimple_in_ssa_p (cfun))
4922 tmp_then = make_ssa_name (tmp_var);
4923 tmp_else = make_ssa_name (tmp_var);
4924 tmp_join = make_ssa_name (tmp_var);
4926 else
4928 tmp_then = tmp_var;
4929 tmp_else = tmp_var;
4930 tmp_join = tmp_var;
4933 e = split_block (bb, NULL);
4934 cond_bb = e->src;
4935 bb = e->dest;
4936 remove_edge (e);
4938 then_bb = create_empty_bb (cond_bb);
4939 else_bb = create_empty_bb (then_bb);
4940 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4941 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4943 stmt = gimple_build_cond_empty (cond);
4944 gsi = gsi_start_bb (cond_bb);
4945 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4947 gsi = gsi_start_bb (then_bb);
4948 stmt = gimple_build_assign (tmp_then, val);
4949 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4951 gsi = gsi_start_bb (else_bb);
4952 stmt = gimple_build_assign
4953 (tmp_else, build_int_cst (unsigned_type_node, 1));
4954 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4956 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4957 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4958 add_bb_to_loop (then_bb, cond_bb->loop_father);
4959 add_bb_to_loop (else_bb, cond_bb->loop_father);
4960 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4961 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4963 if (gimple_in_ssa_p (cfun))
4965 gphi *phi = create_phi_node (tmp_join, bb);
4966 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4967 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4970 val = tmp_join;
4973 gsi = gsi_start_bb (bb);
4974 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4975 false, GSI_CONTINUE_LINKING);
4978 gsi = gsi_last_bb (bb);
4979 t = gimple_omp_parallel_data_arg (entry_stmt);
4980 if (t == NULL)
4981 t1 = null_pointer_node;
4982 else
4983 t1 = build_fold_addr_expr (t);
4984 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4986 vec_alloc (args, 4 + vec_safe_length (ws_args));
4987 args->quick_push (t2);
4988 args->quick_push (t1);
4989 args->quick_push (val);
4990 if (ws_args)
4991 args->splice (*ws_args);
4992 args->quick_push (flags);
4994 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4995 builtin_decl_explicit (start_ix), args);
4997 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4998 false, GSI_CONTINUE_LINKING);
5001 /* Insert a function call whose name is FUNC_NAME with the information from
5002 ENTRY_STMT into the basic_block BB. */
5004 static void
5005 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
5006 vec <tree, va_gc> *ws_args)
5008 tree t, t1, t2;
5009 gimple_stmt_iterator gsi;
5010 vec <tree, va_gc> *args;
5012 gcc_assert (vec_safe_length (ws_args) == 2);
5013 tree func_name = (*ws_args)[0];
5014 tree grain = (*ws_args)[1];
5016 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5017 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5018 gcc_assert (count != NULL_TREE);
5019 count = OMP_CLAUSE_OPERAND (count, 0);
5021 gsi = gsi_last_bb (bb);
5022 t = gimple_omp_parallel_data_arg (entry_stmt);
5023 if (t == NULL)
5024 t1 = null_pointer_node;
5025 else
5026 t1 = build_fold_addr_expr (t);
5027 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5029 vec_alloc (args, 4);
5030 args->quick_push (t2);
5031 args->quick_push (t1);
5032 args->quick_push (count);
5033 args->quick_push (grain);
5034 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5036 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5037 GSI_CONTINUE_LINKING);
5040 /* Build the function call to GOMP_task to actually
5041 generate the task operation. BB is the block where to insert the code. */
5043 static void
5044 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5046 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5047 gimple_stmt_iterator gsi;
5048 location_t loc = gimple_location (entry_stmt);
5050 clauses = gimple_omp_task_clauses (entry_stmt);
5052 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5053 if (c)
5054 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5055 else
5056 cond = boolean_true_node;
5058 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5059 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5060 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5061 flags = build_int_cst (unsigned_type_node,
5062 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5064 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5065 if (c)
5067 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5068 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5069 build_int_cst (unsigned_type_node, 2),
5070 build_int_cst (unsigned_type_node, 0));
5071 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5073 if (depend)
5074 depend = OMP_CLAUSE_DECL (depend);
5075 else
5076 depend = build_int_cst (ptr_type_node, 0);
5078 gsi = gsi_last_bb (bb);
5079 t = gimple_omp_task_data_arg (entry_stmt);
5080 if (t == NULL)
5081 t2 = null_pointer_node;
5082 else
5083 t2 = build_fold_addr_expr_loc (loc, t);
5084 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5085 t = gimple_omp_task_copy_fn (entry_stmt);
5086 if (t == NULL)
5087 t3 = null_pointer_node;
5088 else
5089 t3 = build_fold_addr_expr_loc (loc, t);
5091 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5092 8, t1, t2, t3,
5093 gimple_omp_task_arg_size (entry_stmt),
5094 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5095 depend);
5097 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5098 false, GSI_CONTINUE_LINKING);
5102 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5103 catch handler and return it. This prevents programs from violating the
5104 structured block semantics with throws. */
5106 static gimple_seq
5107 maybe_catch_exception (gimple_seq body)
5109 gimple g;
5110 tree decl;
5112 if (!flag_exceptions)
5113 return body;
5115 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5116 decl = lang_hooks.eh_protect_cleanup_actions ();
5117 else
5118 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5120 g = gimple_build_eh_must_not_throw (decl);
5121 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5122 GIMPLE_TRY_CATCH);
5124 return gimple_seq_alloc_with_stmt (g);
5127 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5129 static tree
5130 vec2chain (vec<tree, va_gc> *v)
5132 tree chain = NULL_TREE, t;
5133 unsigned ix;
5135 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5137 DECL_CHAIN (t) = chain;
5138 chain = t;
5141 return chain;
5145 /* Remove barriers in REGION->EXIT's block. Note that this is only
5146 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5147 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5148 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5149 removed. */
5151 static void
5152 remove_exit_barrier (struct omp_region *region)
5154 gimple_stmt_iterator gsi;
5155 basic_block exit_bb;
5156 edge_iterator ei;
5157 edge e;
5158 gimple stmt;
5159 int any_addressable_vars = -1;
5161 exit_bb = region->exit;
5163 /* If the parallel region doesn't return, we don't have REGION->EXIT
5164 block at all. */
5165 if (! exit_bb)
5166 return;
5168 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5169 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5170 statements that can appear in between are extremely limited -- no
5171 memory operations at all. Here, we allow nothing at all, so the
5172 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5173 gsi = gsi_last_bb (exit_bb);
5174 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5175 gsi_prev (&gsi);
5176 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5177 return;
5179 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5181 gsi = gsi_last_bb (e->src);
5182 if (gsi_end_p (gsi))
5183 continue;
5184 stmt = gsi_stmt (gsi);
5185 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5186 && !gimple_omp_return_nowait_p (stmt))
5188 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5189 in many cases. If there could be tasks queued, the barrier
5190 might be needed to let the tasks run before some local
5191 variable of the parallel that the task uses as shared
5192 runs out of scope. The task can be spawned either
5193 from within current function (this would be easy to check)
5194 or from some function it calls and gets passed an address
5195 of such a variable. */
5196 if (any_addressable_vars < 0)
5198 gomp_parallel *parallel_stmt
5199 = as_a <gomp_parallel *> (last_stmt (region->entry));
5200 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5201 tree local_decls, block, decl;
5202 unsigned ix;
5204 any_addressable_vars = 0;
5205 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5206 if (TREE_ADDRESSABLE (decl))
5208 any_addressable_vars = 1;
5209 break;
5211 for (block = gimple_block (stmt);
5212 !any_addressable_vars
5213 && block
5214 && TREE_CODE (block) == BLOCK;
5215 block = BLOCK_SUPERCONTEXT (block))
5217 for (local_decls = BLOCK_VARS (block);
5218 local_decls;
5219 local_decls = DECL_CHAIN (local_decls))
5220 if (TREE_ADDRESSABLE (local_decls))
5222 any_addressable_vars = 1;
5223 break;
5225 if (block == gimple_block (parallel_stmt))
5226 break;
5229 if (!any_addressable_vars)
5230 gimple_omp_return_set_nowait (stmt);
5235 static void
5236 remove_exit_barriers (struct omp_region *region)
5238 if (region->type == GIMPLE_OMP_PARALLEL)
5239 remove_exit_barrier (region);
5241 if (region->inner)
5243 region = region->inner;
5244 remove_exit_barriers (region);
5245 while (region->next)
5247 region = region->next;
5248 remove_exit_barriers (region);
5253 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5254 calls. These can't be declared as const functions, but
5255 within one parallel body they are constant, so they can be
5256 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5257 which are declared const. Similarly for task body, except
5258 that in untied task omp_get_thread_num () can change at any task
5259 scheduling point. */
5261 static void
5262 optimize_omp_library_calls (gimple entry_stmt)
5264 basic_block bb;
5265 gimple_stmt_iterator gsi;
5266 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5267 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5268 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5269 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5270 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5271 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5272 OMP_CLAUSE_UNTIED) != NULL);
5274 FOR_EACH_BB_FN (bb, cfun)
5275 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5277 gimple call = gsi_stmt (gsi);
5278 tree decl;
5280 if (is_gimple_call (call)
5281 && (decl = gimple_call_fndecl (call))
5282 && DECL_EXTERNAL (decl)
5283 && TREE_PUBLIC (decl)
5284 && DECL_INITIAL (decl) == NULL)
5286 tree built_in;
5288 if (DECL_NAME (decl) == thr_num_id)
5290 /* In #pragma omp task untied omp_get_thread_num () can change
5291 during the execution of the task region. */
5292 if (untied_task)
5293 continue;
5294 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5296 else if (DECL_NAME (decl) == num_thr_id)
5297 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5298 else
5299 continue;
5301 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5302 || gimple_call_num_args (call) != 0)
5303 continue;
5305 if (flag_exceptions && !TREE_NOTHROW (decl))
5306 continue;
5308 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5309 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5310 TREE_TYPE (TREE_TYPE (built_in))))
5311 continue;
5313 gimple_call_set_fndecl (call, built_in);
5318 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5319 regimplified. */
5321 static tree
5322 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5324 tree t = *tp;
5326 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5327 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5328 return t;
5330 if (TREE_CODE (t) == ADDR_EXPR)
5331 recompute_tree_invariant_for_addr_expr (t);
5333 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5334 return NULL_TREE;
5337 /* Prepend TO = FROM assignment before *GSI_P. */
5339 static void
5340 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5342 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5343 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5344 true, GSI_SAME_STMT);
5345 gimple stmt = gimple_build_assign (to, from);
5346 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5347 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5348 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5350 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5351 gimple_regimplify_operands (stmt, &gsi);
5355 /* Expand the OpenMP parallel or task directive starting at REGION. */
5357 static void
5358 expand_omp_taskreg (struct omp_region *region)
5360 basic_block entry_bb, exit_bb, new_bb;
5361 struct function *child_cfun;
5362 tree child_fn, block, t;
5363 gimple_stmt_iterator gsi;
5364 gimple entry_stmt, stmt;
5365 edge e;
5366 vec<tree, va_gc> *ws_args;
5368 entry_stmt = last_stmt (region->entry);
5369 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5370 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5372 entry_bb = region->entry;
5373 exit_bb = region->exit;
5375 bool is_cilk_for
5376 = (flag_cilkplus
5377 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5378 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5379 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5381 if (is_cilk_for)
5382 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5383 and the inner statement contains the name of the built-in function
5384 and grain. */
5385 ws_args = region->inner->ws_args;
5386 else if (is_combined_parallel (region))
5387 ws_args = region->ws_args;
5388 else
5389 ws_args = NULL;
5391 if (child_cfun->cfg)
5393 /* Due to inlining, it may happen that we have already outlined
5394 the region, in which case all we need to do is make the
5395 sub-graph unreachable and emit the parallel call. */
5396 edge entry_succ_e, exit_succ_e;
5398 entry_succ_e = single_succ_edge (entry_bb);
5400 gsi = gsi_last_bb (entry_bb);
5401 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5402 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5403 gsi_remove (&gsi, true);
5405 new_bb = entry_bb;
5406 if (exit_bb)
5408 exit_succ_e = single_succ_edge (exit_bb);
5409 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5411 remove_edge_and_dominated_blocks (entry_succ_e);
5413 else
5415 unsigned srcidx, dstidx, num;
5417 /* If the parallel region needs data sent from the parent
5418 function, then the very first statement (except possible
5419 tree profile counter updates) of the parallel body
5420 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5421 &.OMP_DATA_O is passed as an argument to the child function,
5422 we need to replace it with the argument as seen by the child
5423 function.
5425 In most cases, this will end up being the identity assignment
5426 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5427 a function call that has been inlined, the original PARM_DECL
5428 .OMP_DATA_I may have been converted into a different local
5429 variable. In which case, we need to keep the assignment. */
5430 if (gimple_omp_taskreg_data_arg (entry_stmt))
5432 basic_block entry_succ_bb = single_succ (entry_bb);
5433 tree arg, narg;
5434 gimple parcopy_stmt = NULL;
5436 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5438 gimple stmt;
5440 gcc_assert (!gsi_end_p (gsi));
5441 stmt = gsi_stmt (gsi);
5442 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5443 continue;
5445 if (gimple_num_ops (stmt) == 2)
5447 tree arg = gimple_assign_rhs1 (stmt);
5449 /* We're ignore the subcode because we're
5450 effectively doing a STRIP_NOPS. */
5452 if (TREE_CODE (arg) == ADDR_EXPR
5453 && TREE_OPERAND (arg, 0)
5454 == gimple_omp_taskreg_data_arg (entry_stmt))
5456 parcopy_stmt = stmt;
5457 break;
5462 gcc_assert (parcopy_stmt != NULL);
5463 arg = DECL_ARGUMENTS (child_fn);
5465 if (!gimple_in_ssa_p (cfun))
5467 if (gimple_assign_lhs (parcopy_stmt) == arg)
5468 gsi_remove (&gsi, true);
5469 else
5471 /* ?? Is setting the subcode really necessary ?? */
5472 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5473 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5476 else
5478 /* If we are in ssa form, we must load the value from the default
5479 definition of the argument. That should not be defined now,
5480 since the argument is not used uninitialized. */
5481 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5482 narg = make_ssa_name (arg, gimple_build_nop ());
5483 set_ssa_default_def (cfun, arg, narg);
5484 /* ?? Is setting the subcode really necessary ?? */
5485 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5486 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5487 update_stmt (parcopy_stmt);
5491 /* Declare local variables needed in CHILD_CFUN. */
5492 block = DECL_INITIAL (child_fn);
5493 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5494 /* The gimplifier could record temporaries in parallel/task block
5495 rather than in containing function's local_decls chain,
5496 which would mean cgraph missed finalizing them. Do it now. */
5497 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5498 if (TREE_CODE (t) == VAR_DECL
5499 && TREE_STATIC (t)
5500 && !DECL_EXTERNAL (t))
5501 varpool_node::finalize_decl (t);
5502 DECL_SAVED_TREE (child_fn) = NULL;
5503 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5504 gimple_set_body (child_fn, NULL);
5505 TREE_USED (block) = 1;
5507 /* Reset DECL_CONTEXT on function arguments. */
5508 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5509 DECL_CONTEXT (t) = child_fn;
5511 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5512 so that it can be moved to the child function. */
5513 gsi = gsi_last_bb (entry_bb);
5514 stmt = gsi_stmt (gsi);
5515 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5516 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5517 gsi_remove (&gsi, true);
5518 e = split_block (entry_bb, stmt);
5519 entry_bb = e->dest;
5520 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5522 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5523 if (exit_bb)
5525 gsi = gsi_last_bb (exit_bb);
5526 gcc_assert (!gsi_end_p (gsi)
5527 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5528 stmt = gimple_build_return (NULL);
5529 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5530 gsi_remove (&gsi, true);
5533 /* Move the parallel region into CHILD_CFUN. */
5535 if (gimple_in_ssa_p (cfun))
5537 init_tree_ssa (child_cfun);
5538 init_ssa_operands (child_cfun);
5539 child_cfun->gimple_df->in_ssa_p = true;
5540 block = NULL_TREE;
5542 else
5543 block = gimple_block (entry_stmt);
5545 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5546 if (exit_bb)
5547 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5548 /* When the OMP expansion process cannot guarantee an up-to-date
5549 loop tree arrange for the child function to fixup loops. */
5550 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5551 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5553 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5554 num = vec_safe_length (child_cfun->local_decls);
5555 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5557 t = (*child_cfun->local_decls)[srcidx];
5558 if (DECL_CONTEXT (t) == cfun->decl)
5559 continue;
5560 if (srcidx != dstidx)
5561 (*child_cfun->local_decls)[dstidx] = t;
5562 dstidx++;
5564 if (dstidx != num)
5565 vec_safe_truncate (child_cfun->local_decls, dstidx);
5567 /* Inform the callgraph about the new function. */
5568 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5569 cgraph_node::add_new_function (child_fn, true);
5571 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5572 fixed in a following pass. */
5573 push_cfun (child_cfun);
5574 if (optimize)
5575 optimize_omp_library_calls (entry_stmt);
5576 cgraph_edge::rebuild_edges ();
5578 /* Some EH regions might become dead, see PR34608. If
5579 pass_cleanup_cfg isn't the first pass to happen with the
5580 new child, these dead EH edges might cause problems.
5581 Clean them up now. */
5582 if (flag_exceptions)
5584 basic_block bb;
5585 bool changed = false;
5587 FOR_EACH_BB_FN (bb, cfun)
5588 changed |= gimple_purge_dead_eh_edges (bb);
5589 if (changed)
5590 cleanup_tree_cfg ();
5592 if (gimple_in_ssa_p (cfun))
5593 update_ssa (TODO_update_ssa);
5594 pop_cfun ();
5597 /* Emit a library call to launch the children threads. */
5598 if (is_cilk_for)
5599 expand_cilk_for_call (new_bb,
5600 as_a <gomp_parallel *> (entry_stmt), ws_args);
5601 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5602 expand_parallel_call (region, new_bb,
5603 as_a <gomp_parallel *> (entry_stmt), ws_args);
5604 else
5605 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5606 if (gimple_in_ssa_p (cfun))
5607 update_ssa (TODO_update_ssa_only_virtuals);
5611 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5612 of the combined collapse > 1 loop constructs, generate code like:
5613 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5614 if (cond3 is <)
5615 adj = STEP3 - 1;
5616 else
5617 adj = STEP3 + 1;
5618 count3 = (adj + N32 - N31) / STEP3;
5619 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5620 if (cond2 is <)
5621 adj = STEP2 - 1;
5622 else
5623 adj = STEP2 + 1;
5624 count2 = (adj + N22 - N21) / STEP2;
5625 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5626 if (cond1 is <)
5627 adj = STEP1 - 1;
5628 else
5629 adj = STEP1 + 1;
5630 count1 = (adj + N12 - N11) / STEP1;
5631 count = count1 * count2 * count3;
5632 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5633 count = 0;
5634 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5635 of the combined loop constructs, just initialize COUNTS array
5636 from the _looptemp_ clauses. */
5638 /* NOTE: It *could* be better to moosh all of the BBs together,
5639 creating one larger BB with all the computation and the unexpected
5640 jump at the end. I.e.
5642 bool zero3, zero2, zero1, zero;
5644 zero3 = N32 c3 N31;
5645 count3 = (N32 - N31) /[cl] STEP3;
5646 zero2 = N22 c2 N21;
5647 count2 = (N22 - N21) /[cl] STEP2;
5648 zero1 = N12 c1 N11;
5649 count1 = (N12 - N11) /[cl] STEP1;
5650 zero = zero3 || zero2 || zero1;
5651 count = count1 * count2 * count3;
5652 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5654 After all, we expect the zero=false, and thus we expect to have to
5655 evaluate all of the comparison expressions, so short-circuiting
5656 oughtn't be a win. Since the condition isn't protecting a
5657 denominator, we're not concerned about divide-by-zero, so we can
5658 fully evaluate count even if a numerator turned out to be wrong.
5660 It seems like putting this all together would create much better
5661 scheduling opportunities, and less pressure on the chip's branch
5662 predictor. */
5664 static void
5665 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5666 basic_block &entry_bb, tree *counts,
5667 basic_block &zero_iter_bb, int &first_zero_iter,
5668 basic_block &l2_dom_bb)
5670 tree t, type = TREE_TYPE (fd->loop.v);
5671 edge e, ne;
5672 int i;
5674 /* Collapsed loops need work for expansion into SSA form. */
5675 gcc_assert (!gimple_in_ssa_p (cfun));
5677 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5678 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5680 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5681 isn't supposed to be handled, as the inner loop doesn't
5682 use it. */
5683 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5684 OMP_CLAUSE__LOOPTEMP_);
5685 gcc_assert (innerc);
5686 for (i = 0; i < fd->collapse; i++)
5688 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5689 OMP_CLAUSE__LOOPTEMP_);
5690 gcc_assert (innerc);
5691 if (i)
5692 counts[i] = OMP_CLAUSE_DECL (innerc);
5693 else
5694 counts[0] = NULL_TREE;
5696 return;
5699 for (i = 0; i < fd->collapse; i++)
5701 tree itype = TREE_TYPE (fd->loops[i].v);
5703 if (SSA_VAR_P (fd->loop.n2)
5704 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5705 fold_convert (itype, fd->loops[i].n1),
5706 fold_convert (itype, fd->loops[i].n2)))
5707 == NULL_TREE || !integer_onep (t)))
5709 gcond *cond_stmt;
5710 tree n1, n2;
5711 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5712 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5713 true, GSI_SAME_STMT);
5714 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5715 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5716 true, GSI_SAME_STMT);
5717 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5718 NULL_TREE, NULL_TREE);
5719 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5720 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5721 expand_omp_regimplify_p, NULL, NULL)
5722 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5723 expand_omp_regimplify_p, NULL, NULL))
5725 *gsi = gsi_for_stmt (cond_stmt);
5726 gimple_regimplify_operands (cond_stmt, gsi);
5728 e = split_block (entry_bb, cond_stmt);
5729 if (zero_iter_bb == NULL)
5731 gassign *assign_stmt;
5732 first_zero_iter = i;
5733 zero_iter_bb = create_empty_bb (entry_bb);
5734 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5735 *gsi = gsi_after_labels (zero_iter_bb);
5736 assign_stmt = gimple_build_assign (fd->loop.n2,
5737 build_zero_cst (type));
5738 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5739 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5740 entry_bb);
5742 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5743 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5744 e->flags = EDGE_TRUE_VALUE;
5745 e->probability = REG_BR_PROB_BASE - ne->probability;
5746 if (l2_dom_bb == NULL)
5747 l2_dom_bb = entry_bb;
5748 entry_bb = e->dest;
5749 *gsi = gsi_last_bb (entry_bb);
5752 if (POINTER_TYPE_P (itype))
5753 itype = signed_type_for (itype);
5754 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5755 ? -1 : 1));
5756 t = fold_build2 (PLUS_EXPR, itype,
5757 fold_convert (itype, fd->loops[i].step), t);
5758 t = fold_build2 (PLUS_EXPR, itype, t,
5759 fold_convert (itype, fd->loops[i].n2));
5760 t = fold_build2 (MINUS_EXPR, itype, t,
5761 fold_convert (itype, fd->loops[i].n1));
5762 /* ?? We could probably use CEIL_DIV_EXPR instead of
5763 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5764 generate the same code in the end because generically we
5765 don't know that the values involved must be negative for
5766 GT?? */
5767 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5768 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5769 fold_build1 (NEGATE_EXPR, itype, t),
5770 fold_build1 (NEGATE_EXPR, itype,
5771 fold_convert (itype,
5772 fd->loops[i].step)));
5773 else
5774 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5775 fold_convert (itype, fd->loops[i].step));
5776 t = fold_convert (type, t);
5777 if (TREE_CODE (t) == INTEGER_CST)
5778 counts[i] = t;
5779 else
5781 counts[i] = create_tmp_reg (type, ".count");
5782 expand_omp_build_assign (gsi, counts[i], t);
5784 if (SSA_VAR_P (fd->loop.n2))
5786 if (i == 0)
5787 t = counts[0];
5788 else
5789 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5790 expand_omp_build_assign (gsi, fd->loop.n2, t);
5796 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5797 T = V;
5798 V3 = N31 + (T % count3) * STEP3;
5799 T = T / count3;
5800 V2 = N21 + (T % count2) * STEP2;
5801 T = T / count2;
5802 V1 = N11 + T * STEP1;
5803 if this loop doesn't have an inner loop construct combined with it.
5804 If it does have an inner loop construct combined with it and the
5805 iteration count isn't known constant, store values from counts array
5806 into its _looptemp_ temporaries instead. */
5808 static void
5809 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5810 tree *counts, gimple inner_stmt, tree startvar)
5812 int i;
5813 if (gimple_omp_for_combined_p (fd->for_stmt))
5815 /* If fd->loop.n2 is constant, then no propagation of the counts
5816 is needed, they are constant. */
5817 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5818 return;
5820 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5821 ? gimple_omp_parallel_clauses (inner_stmt)
5822 : gimple_omp_for_clauses (inner_stmt);
5823 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5824 isn't supposed to be handled, as the inner loop doesn't
5825 use it. */
5826 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5827 gcc_assert (innerc);
5828 for (i = 0; i < fd->collapse; i++)
5830 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5831 OMP_CLAUSE__LOOPTEMP_);
5832 gcc_assert (innerc);
5833 if (i)
5835 tree tem = OMP_CLAUSE_DECL (innerc);
5836 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5837 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5838 false, GSI_CONTINUE_LINKING);
5839 gassign *stmt = gimple_build_assign (tem, t);
5840 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5843 return;
5846 tree type = TREE_TYPE (fd->loop.v);
5847 tree tem = create_tmp_reg (type, ".tem");
5848 gassign *stmt = gimple_build_assign (tem, startvar);
5849 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5851 for (i = fd->collapse - 1; i >= 0; i--)
5853 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5854 itype = vtype;
5855 if (POINTER_TYPE_P (vtype))
5856 itype = signed_type_for (vtype);
5857 if (i != 0)
5858 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5859 else
5860 t = tem;
5861 t = fold_convert (itype, t);
5862 t = fold_build2 (MULT_EXPR, itype, t,
5863 fold_convert (itype, fd->loops[i].step));
5864 if (POINTER_TYPE_P (vtype))
5865 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5866 else
5867 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5868 t = force_gimple_operand_gsi (gsi, t,
5869 DECL_P (fd->loops[i].v)
5870 && TREE_ADDRESSABLE (fd->loops[i].v),
5871 NULL_TREE, false,
5872 GSI_CONTINUE_LINKING);
5873 stmt = gimple_build_assign (fd->loops[i].v, t);
5874 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5875 if (i != 0)
5877 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5878 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5879 false, GSI_CONTINUE_LINKING);
5880 stmt = gimple_build_assign (tem, t);
5881 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5887 /* Helper function for expand_omp_for_*. Generate code like:
5888 L10:
5889 V3 += STEP3;
5890 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5891 L11:
5892 V3 = N31;
5893 V2 += STEP2;
5894 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5895 L12:
5896 V2 = N21;
5897 V1 += STEP1;
5898 goto BODY_BB; */
5900 static basic_block
5901 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5902 basic_block body_bb)
5904 basic_block last_bb, bb, collapse_bb = NULL;
5905 int i;
5906 gimple_stmt_iterator gsi;
5907 edge e;
5908 tree t;
5909 gimple stmt;
5911 last_bb = cont_bb;
5912 for (i = fd->collapse - 1; i >= 0; i--)
5914 tree vtype = TREE_TYPE (fd->loops[i].v);
5916 bb = create_empty_bb (last_bb);
5917 add_bb_to_loop (bb, last_bb->loop_father);
5918 gsi = gsi_start_bb (bb);
5920 if (i < fd->collapse - 1)
5922 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5923 e->probability = REG_BR_PROB_BASE / 8;
5925 t = fd->loops[i + 1].n1;
5926 t = force_gimple_operand_gsi (&gsi, t,
5927 DECL_P (fd->loops[i + 1].v)
5928 && TREE_ADDRESSABLE (fd->loops[i
5929 + 1].v),
5930 NULL_TREE, false,
5931 GSI_CONTINUE_LINKING);
5932 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5933 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5935 else
5936 collapse_bb = bb;
5938 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5940 if (POINTER_TYPE_P (vtype))
5941 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5942 else
5943 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5944 t = force_gimple_operand_gsi (&gsi, t,
5945 DECL_P (fd->loops[i].v)
5946 && TREE_ADDRESSABLE (fd->loops[i].v),
5947 NULL_TREE, false, GSI_CONTINUE_LINKING);
5948 stmt = gimple_build_assign (fd->loops[i].v, t);
5949 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5951 if (i > 0)
5953 t = fd->loops[i].n2;
5954 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5955 false, GSI_CONTINUE_LINKING);
5956 tree v = fd->loops[i].v;
5957 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5958 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5959 false, GSI_CONTINUE_LINKING);
5960 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5961 stmt = gimple_build_cond_empty (t);
5962 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5963 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5964 e->probability = REG_BR_PROB_BASE * 7 / 8;
5966 else
5967 make_edge (bb, body_bb, EDGE_FALLTHRU);
5968 last_bb = bb;
5971 return collapse_bb;
5975 /* A subroutine of expand_omp_for. Generate code for a parallel
5976 loop with any schedule. Given parameters:
5978 for (V = N1; V cond N2; V += STEP) BODY;
5980 where COND is "<" or ">", we generate pseudocode
5982 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5983 if (more) goto L0; else goto L3;
5985 V = istart0;
5986 iend = iend0;
5988 BODY;
5989 V += STEP;
5990 if (V cond iend) goto L1; else goto L2;
5992 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5995 If this is a combined omp parallel loop, instead of the call to
5996 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5997 If this is gimple_omp_for_combined_p loop, then instead of assigning
5998 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5999 inner GIMPLE_OMP_FOR and V += STEP; and
6000 if (V cond iend) goto L1; else goto L2; are removed.
6002 For collapsed loops, given parameters:
6003 collapse(3)
6004 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6005 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6006 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6007 BODY;
6009 we generate pseudocode
6011 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6012 if (cond3 is <)
6013 adj = STEP3 - 1;
6014 else
6015 adj = STEP3 + 1;
6016 count3 = (adj + N32 - N31) / STEP3;
6017 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6018 if (cond2 is <)
6019 adj = STEP2 - 1;
6020 else
6021 adj = STEP2 + 1;
6022 count2 = (adj + N22 - N21) / STEP2;
6023 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6024 if (cond1 is <)
6025 adj = STEP1 - 1;
6026 else
6027 adj = STEP1 + 1;
6028 count1 = (adj + N12 - N11) / STEP1;
6029 count = count1 * count2 * count3;
6030 goto Z1;
6032 count = 0;
6034 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6035 if (more) goto L0; else goto L3;
6037 V = istart0;
6038 T = V;
6039 V3 = N31 + (T % count3) * STEP3;
6040 T = T / count3;
6041 V2 = N21 + (T % count2) * STEP2;
6042 T = T / count2;
6043 V1 = N11 + T * STEP1;
6044 iend = iend0;
6046 BODY;
6047 V += 1;
6048 if (V < iend) goto L10; else goto L2;
6049 L10:
6050 V3 += STEP3;
6051 if (V3 cond3 N32) goto L1; else goto L11;
6052 L11:
6053 V3 = N31;
6054 V2 += STEP2;
6055 if (V2 cond2 N22) goto L1; else goto L12;
6056 L12:
6057 V2 = N21;
6058 V1 += STEP1;
6059 goto L1;
6061 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6066 static void
6067 expand_omp_for_generic (struct omp_region *region,
6068 struct omp_for_data *fd,
6069 enum built_in_function start_fn,
6070 enum built_in_function next_fn,
6071 gimple inner_stmt)
6073 tree type, istart0, iend0, iend;
6074 tree t, vmain, vback, bias = NULL_TREE;
6075 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6076 basic_block l2_bb = NULL, l3_bb = NULL;
6077 gimple_stmt_iterator gsi;
6078 gassign *assign_stmt;
6079 bool in_combined_parallel = is_combined_parallel (region);
6080 bool broken_loop = region->cont == NULL;
6081 edge e, ne;
6082 tree *counts = NULL;
6083 int i;
6085 gcc_assert (!broken_loop || !in_combined_parallel);
6086 gcc_assert (fd->iter_type == long_integer_type_node
6087 || !in_combined_parallel);
6089 type = TREE_TYPE (fd->loop.v);
6090 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6091 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6092 TREE_ADDRESSABLE (istart0) = 1;
6093 TREE_ADDRESSABLE (iend0) = 1;
6095 /* See if we need to bias by LLONG_MIN. */
6096 if (fd->iter_type == long_long_unsigned_type_node
6097 && TREE_CODE (type) == INTEGER_TYPE
6098 && !TYPE_UNSIGNED (type))
6100 tree n1, n2;
6102 if (fd->loop.cond_code == LT_EXPR)
6104 n1 = fd->loop.n1;
6105 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6107 else
6109 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6110 n2 = fd->loop.n1;
6112 if (TREE_CODE (n1) != INTEGER_CST
6113 || TREE_CODE (n2) != INTEGER_CST
6114 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6115 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6118 entry_bb = region->entry;
6119 cont_bb = region->cont;
6120 collapse_bb = NULL;
6121 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6122 gcc_assert (broken_loop
6123 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6124 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6125 l1_bb = single_succ (l0_bb);
6126 if (!broken_loop)
6128 l2_bb = create_empty_bb (cont_bb);
6129 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6130 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6132 else
6133 l2_bb = NULL;
6134 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6135 exit_bb = region->exit;
6137 gsi = gsi_last_bb (entry_bb);
6139 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6140 if (fd->collapse > 1)
6142 int first_zero_iter = -1;
6143 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6145 counts = XALLOCAVEC (tree, fd->collapse);
6146 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6147 zero_iter_bb, first_zero_iter,
6148 l2_dom_bb);
6150 if (zero_iter_bb)
6152 /* Some counts[i] vars might be uninitialized if
6153 some loop has zero iterations. But the body shouldn't
6154 be executed in that case, so just avoid uninit warnings. */
6155 for (i = first_zero_iter; i < fd->collapse; i++)
6156 if (SSA_VAR_P (counts[i]))
6157 TREE_NO_WARNING (counts[i]) = 1;
6158 gsi_prev (&gsi);
6159 e = split_block (entry_bb, gsi_stmt (gsi));
6160 entry_bb = e->dest;
6161 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6162 gsi = gsi_last_bb (entry_bb);
6163 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6164 get_immediate_dominator (CDI_DOMINATORS,
6165 zero_iter_bb));
6168 if (in_combined_parallel)
6170 /* In a combined parallel loop, emit a call to
6171 GOMP_loop_foo_next. */
6172 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6173 build_fold_addr_expr (istart0),
6174 build_fold_addr_expr (iend0));
6176 else
6178 tree t0, t1, t2, t3, t4;
6179 /* If this is not a combined parallel loop, emit a call to
6180 GOMP_loop_foo_start in ENTRY_BB. */
6181 t4 = build_fold_addr_expr (iend0);
6182 t3 = build_fold_addr_expr (istart0);
6183 t2 = fold_convert (fd->iter_type, fd->loop.step);
6184 t1 = fd->loop.n2;
6185 t0 = fd->loop.n1;
6186 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6188 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6189 OMP_CLAUSE__LOOPTEMP_);
6190 gcc_assert (innerc);
6191 t0 = OMP_CLAUSE_DECL (innerc);
6192 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6193 OMP_CLAUSE__LOOPTEMP_);
6194 gcc_assert (innerc);
6195 t1 = OMP_CLAUSE_DECL (innerc);
6197 if (POINTER_TYPE_P (TREE_TYPE (t0))
6198 && TYPE_PRECISION (TREE_TYPE (t0))
6199 != TYPE_PRECISION (fd->iter_type))
6201 /* Avoid casting pointers to integer of a different size. */
6202 tree itype = signed_type_for (type);
6203 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6204 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6206 else
6208 t1 = fold_convert (fd->iter_type, t1);
6209 t0 = fold_convert (fd->iter_type, t0);
6211 if (bias)
6213 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6214 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6216 if (fd->iter_type == long_integer_type_node)
6218 if (fd->chunk_size)
6220 t = fold_convert (fd->iter_type, fd->chunk_size);
6221 t = build_call_expr (builtin_decl_explicit (start_fn),
6222 6, t0, t1, t2, t, t3, t4);
6224 else
6225 t = build_call_expr (builtin_decl_explicit (start_fn),
6226 5, t0, t1, t2, t3, t4);
6228 else
6230 tree t5;
6231 tree c_bool_type;
6232 tree bfn_decl;
6234 /* The GOMP_loop_ull_*start functions have additional boolean
6235 argument, true for < loops and false for > loops.
6236 In Fortran, the C bool type can be different from
6237 boolean_type_node. */
6238 bfn_decl = builtin_decl_explicit (start_fn);
6239 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6240 t5 = build_int_cst (c_bool_type,
6241 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6242 if (fd->chunk_size)
6244 tree bfn_decl = builtin_decl_explicit (start_fn);
6245 t = fold_convert (fd->iter_type, fd->chunk_size);
6246 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6248 else
6249 t = build_call_expr (builtin_decl_explicit (start_fn),
6250 6, t5, t0, t1, t2, t3, t4);
6253 if (TREE_TYPE (t) != boolean_type_node)
6254 t = fold_build2 (NE_EXPR, boolean_type_node,
6255 t, build_int_cst (TREE_TYPE (t), 0));
6256 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6257 true, GSI_SAME_STMT);
6258 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6260 /* Remove the GIMPLE_OMP_FOR statement. */
6261 gsi_remove (&gsi, true);
6263 /* Iteration setup for sequential loop goes in L0_BB. */
6264 tree startvar = fd->loop.v;
6265 tree endvar = NULL_TREE;
6267 if (gimple_omp_for_combined_p (fd->for_stmt))
6269 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6270 && gimple_omp_for_kind (inner_stmt)
6271 == GF_OMP_FOR_KIND_SIMD);
6272 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6273 OMP_CLAUSE__LOOPTEMP_);
6274 gcc_assert (innerc);
6275 startvar = OMP_CLAUSE_DECL (innerc);
6276 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6277 OMP_CLAUSE__LOOPTEMP_);
6278 gcc_assert (innerc);
6279 endvar = OMP_CLAUSE_DECL (innerc);
6282 gsi = gsi_start_bb (l0_bb);
6283 t = istart0;
6284 if (bias)
6285 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6286 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6287 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6288 t = fold_convert (TREE_TYPE (startvar), t);
6289 t = force_gimple_operand_gsi (&gsi, t,
6290 DECL_P (startvar)
6291 && TREE_ADDRESSABLE (startvar),
6292 NULL_TREE, false, GSI_CONTINUE_LINKING);
6293 assign_stmt = gimple_build_assign (startvar, t);
6294 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6296 t = iend0;
6297 if (bias)
6298 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6299 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6300 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6301 t = fold_convert (TREE_TYPE (startvar), t);
6302 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6303 false, GSI_CONTINUE_LINKING);
6304 if (endvar)
6306 assign_stmt = gimple_build_assign (endvar, iend);
6307 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6308 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6309 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6310 else
6311 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6312 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6314 if (fd->collapse > 1)
6315 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6317 if (!broken_loop)
6319 /* Code to control the increment and predicate for the sequential
6320 loop goes in the CONT_BB. */
6321 gsi = gsi_last_bb (cont_bb);
6322 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6323 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6324 vmain = gimple_omp_continue_control_use (cont_stmt);
6325 vback = gimple_omp_continue_control_def (cont_stmt);
6327 if (!gimple_omp_for_combined_p (fd->for_stmt))
6329 if (POINTER_TYPE_P (type))
6330 t = fold_build_pointer_plus (vmain, fd->loop.step);
6331 else
6332 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6333 t = force_gimple_operand_gsi (&gsi, t,
6334 DECL_P (vback)
6335 && TREE_ADDRESSABLE (vback),
6336 NULL_TREE, true, GSI_SAME_STMT);
6337 assign_stmt = gimple_build_assign (vback, t);
6338 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6340 t = build2 (fd->loop.cond_code, boolean_type_node,
6341 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6342 iend);
6343 gcond *cond_stmt = gimple_build_cond_empty (t);
6344 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6347 /* Remove GIMPLE_OMP_CONTINUE. */
6348 gsi_remove (&gsi, true);
6350 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6351 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6353 /* Emit code to get the next parallel iteration in L2_BB. */
6354 gsi = gsi_start_bb (l2_bb);
6356 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6357 build_fold_addr_expr (istart0),
6358 build_fold_addr_expr (iend0));
6359 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6360 false, GSI_CONTINUE_LINKING);
6361 if (TREE_TYPE (t) != boolean_type_node)
6362 t = fold_build2 (NE_EXPR, boolean_type_node,
6363 t, build_int_cst (TREE_TYPE (t), 0));
6364 gcond *cond_stmt = gimple_build_cond_empty (t);
6365 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6368 /* Add the loop cleanup function. */
6369 gsi = gsi_last_bb (exit_bb);
6370 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6371 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6372 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6373 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6374 else
6375 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6376 gcall *call_stmt = gimple_build_call (t, 0);
6377 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6378 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6379 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6380 gsi_remove (&gsi, true);
6382 /* Connect the new blocks. */
6383 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6384 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6386 if (!broken_loop)
6388 gimple_seq phis;
6390 e = find_edge (cont_bb, l3_bb);
6391 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6393 phis = phi_nodes (l3_bb);
6394 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6396 gimple phi = gsi_stmt (gsi);
6397 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6398 PHI_ARG_DEF_FROM_EDGE (phi, e));
6400 remove_edge (e);
6402 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6403 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6404 e = find_edge (cont_bb, l1_bb);
6405 if (gimple_omp_for_combined_p (fd->for_stmt))
6407 remove_edge (e);
6408 e = NULL;
6410 else if (fd->collapse > 1)
6412 remove_edge (e);
6413 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6415 else
6416 e->flags = EDGE_TRUE_VALUE;
6417 if (e)
6419 e->probability = REG_BR_PROB_BASE * 7 / 8;
6420 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6422 else
6424 e = find_edge (cont_bb, l2_bb);
6425 e->flags = EDGE_FALLTHRU;
6427 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6429 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6430 recompute_dominator (CDI_DOMINATORS, l2_bb));
6431 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6432 recompute_dominator (CDI_DOMINATORS, l3_bb));
6433 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6434 recompute_dominator (CDI_DOMINATORS, l0_bb));
6435 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6436 recompute_dominator (CDI_DOMINATORS, l1_bb));
6438 struct loop *outer_loop = alloc_loop ();
6439 outer_loop->header = l0_bb;
6440 outer_loop->latch = l2_bb;
6441 add_loop (outer_loop, l0_bb->loop_father);
6443 if (!gimple_omp_for_combined_p (fd->for_stmt))
6445 struct loop *loop = alloc_loop ();
6446 loop->header = l1_bb;
6447 /* The loop may have multiple latches. */
6448 add_loop (loop, outer_loop);
6454 /* A subroutine of expand_omp_for. Generate code for a parallel
6455 loop with static schedule and no specified chunk size. Given
6456 parameters:
6458 for (V = N1; V cond N2; V += STEP) BODY;
6460 where COND is "<" or ">", we generate pseudocode
6462 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6463 if (cond is <)
6464 adj = STEP - 1;
6465 else
6466 adj = STEP + 1;
6467 if ((__typeof (V)) -1 > 0 && cond is >)
6468 n = -(adj + N2 - N1) / -STEP;
6469 else
6470 n = (adj + N2 - N1) / STEP;
6471 q = n / nthreads;
6472 tt = n % nthreads;
6473 if (threadid < tt) goto L3; else goto L4;
6475 tt = 0;
6476 q = q + 1;
6478 s0 = q * threadid + tt;
6479 e0 = s0 + q;
6480 V = s0 * STEP + N1;
6481 if (s0 >= e0) goto L2; else goto L0;
6483 e = e0 * STEP + N1;
6485 BODY;
6486 V += STEP;
6487 if (V cond e) goto L1;
6491 static void
6492 expand_omp_for_static_nochunk (struct omp_region *region,
6493 struct omp_for_data *fd,
6494 gimple inner_stmt)
6496 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6497 tree type, itype, vmain, vback;
6498 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6499 basic_block body_bb, cont_bb, collapse_bb = NULL;
6500 basic_block fin_bb;
6501 gimple_stmt_iterator gsi;
6502 edge ep;
6503 bool broken_loop = region->cont == NULL;
6504 tree *counts = NULL;
6505 tree n1, n2, step;
6507 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6508 != GF_OMP_FOR_KIND_OACC_LOOP)
6509 || !inner_stmt);
6511 itype = type = TREE_TYPE (fd->loop.v);
6512 if (POINTER_TYPE_P (type))
6513 itype = signed_type_for (type);
6515 entry_bb = region->entry;
6516 cont_bb = region->cont;
6517 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6518 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6519 gcc_assert (broken_loop
6520 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6521 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6522 body_bb = single_succ (seq_start_bb);
6523 if (!broken_loop)
6525 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6526 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6528 exit_bb = region->exit;
6530 /* Iteration space partitioning goes in ENTRY_BB. */
6531 gsi = gsi_last_bb (entry_bb);
6532 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6534 if (fd->collapse > 1)
6536 int first_zero_iter = -1;
6537 basic_block l2_dom_bb = NULL;
6539 counts = XALLOCAVEC (tree, fd->collapse);
6540 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6541 fin_bb, first_zero_iter,
6542 l2_dom_bb);
6543 t = NULL_TREE;
6545 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6546 t = integer_one_node;
6547 else
6548 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6549 fold_convert (type, fd->loop.n1),
6550 fold_convert (type, fd->loop.n2));
6551 if (fd->collapse == 1
6552 && TYPE_UNSIGNED (type)
6553 && (t == NULL_TREE || !integer_onep (t)))
6555 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6556 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6557 true, GSI_SAME_STMT);
6558 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6559 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6560 true, GSI_SAME_STMT);
6561 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6562 NULL_TREE, NULL_TREE);
6563 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6564 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6565 expand_omp_regimplify_p, NULL, NULL)
6566 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6567 expand_omp_regimplify_p, NULL, NULL))
6569 gsi = gsi_for_stmt (cond_stmt);
6570 gimple_regimplify_operands (cond_stmt, &gsi);
6572 ep = split_block (entry_bb, cond_stmt);
6573 ep->flags = EDGE_TRUE_VALUE;
6574 entry_bb = ep->dest;
6575 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6576 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6577 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6578 if (gimple_in_ssa_p (cfun))
6580 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6581 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6582 !gsi_end_p (gpi); gsi_next (&gpi))
6584 gphi *phi = gpi.phi ();
6585 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6586 ep, UNKNOWN_LOCATION);
6589 gsi = gsi_last_bb (entry_bb);
6592 switch (gimple_omp_for_kind (fd->for_stmt))
6594 case GF_OMP_FOR_KIND_FOR:
6595 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6596 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6597 break;
6598 case GF_OMP_FOR_KIND_DISTRIBUTE:
6599 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6600 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6601 break;
6602 case GF_OMP_FOR_KIND_OACC_LOOP:
6603 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6604 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6605 break;
6606 default:
6607 gcc_unreachable ();
6609 nthreads = build_call_expr (nthreads, 0);
6610 nthreads = fold_convert (itype, nthreads);
6611 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6612 true, GSI_SAME_STMT);
6613 threadid = build_call_expr (threadid, 0);
6614 threadid = fold_convert (itype, threadid);
6615 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6616 true, GSI_SAME_STMT);
6618 n1 = fd->loop.n1;
6619 n2 = fd->loop.n2;
6620 step = fd->loop.step;
6621 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6623 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6624 OMP_CLAUSE__LOOPTEMP_);
6625 gcc_assert (innerc);
6626 n1 = OMP_CLAUSE_DECL (innerc);
6627 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6628 OMP_CLAUSE__LOOPTEMP_);
6629 gcc_assert (innerc);
6630 n2 = OMP_CLAUSE_DECL (innerc);
6632 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6633 true, NULL_TREE, true, GSI_SAME_STMT);
6634 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6635 true, NULL_TREE, true, GSI_SAME_STMT);
6636 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6637 true, NULL_TREE, true, GSI_SAME_STMT);
6639 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6640 t = fold_build2 (PLUS_EXPR, itype, step, t);
6641 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6642 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6643 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6644 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6645 fold_build1 (NEGATE_EXPR, itype, t),
6646 fold_build1 (NEGATE_EXPR, itype, step));
6647 else
6648 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6649 t = fold_convert (itype, t);
6650 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6652 q = create_tmp_reg (itype, "q");
6653 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6654 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6655 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6657 tt = create_tmp_reg (itype, "tt");
6658 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6659 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6660 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6662 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6663 gcond *cond_stmt = gimple_build_cond_empty (t);
6664 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6666 second_bb = split_block (entry_bb, cond_stmt)->dest;
6667 gsi = gsi_last_bb (second_bb);
6668 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6670 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6671 GSI_SAME_STMT);
6672 gassign *assign_stmt
6673 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6674 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6676 third_bb = split_block (second_bb, assign_stmt)->dest;
6677 gsi = gsi_last_bb (third_bb);
6678 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6680 t = build2 (MULT_EXPR, itype, q, threadid);
6681 t = build2 (PLUS_EXPR, itype, t, tt);
6682 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6684 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6685 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6687 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6688 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6690 /* Remove the GIMPLE_OMP_FOR statement. */
6691 gsi_remove (&gsi, true);
6693 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6694 gsi = gsi_start_bb (seq_start_bb);
6696 tree startvar = fd->loop.v;
6697 tree endvar = NULL_TREE;
6699 if (gimple_omp_for_combined_p (fd->for_stmt))
6701 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6702 ? gimple_omp_parallel_clauses (inner_stmt)
6703 : gimple_omp_for_clauses (inner_stmt);
6704 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6705 gcc_assert (innerc);
6706 startvar = OMP_CLAUSE_DECL (innerc);
6707 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6708 OMP_CLAUSE__LOOPTEMP_);
6709 gcc_assert (innerc);
6710 endvar = OMP_CLAUSE_DECL (innerc);
6712 t = fold_convert (itype, s0);
6713 t = fold_build2 (MULT_EXPR, itype, t, step);
6714 if (POINTER_TYPE_P (type))
6715 t = fold_build_pointer_plus (n1, t);
6716 else
6717 t = fold_build2 (PLUS_EXPR, type, t, n1);
6718 t = fold_convert (TREE_TYPE (startvar), t);
6719 t = force_gimple_operand_gsi (&gsi, t,
6720 DECL_P (startvar)
6721 && TREE_ADDRESSABLE (startvar),
6722 NULL_TREE, false, GSI_CONTINUE_LINKING);
6723 assign_stmt = gimple_build_assign (startvar, t);
6724 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6726 t = fold_convert (itype, e0);
6727 t = fold_build2 (MULT_EXPR, itype, t, step);
6728 if (POINTER_TYPE_P (type))
6729 t = fold_build_pointer_plus (n1, t);
6730 else
6731 t = fold_build2 (PLUS_EXPR, type, t, n1);
6732 t = fold_convert (TREE_TYPE (startvar), t);
6733 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6734 false, GSI_CONTINUE_LINKING);
6735 if (endvar)
6737 assign_stmt = gimple_build_assign (endvar, e);
6738 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6739 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6740 assign_stmt = gimple_build_assign (fd->loop.v, e);
6741 else
6742 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6743 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6745 if (fd->collapse > 1)
6746 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6748 if (!broken_loop)
6750 /* The code controlling the sequential loop replaces the
6751 GIMPLE_OMP_CONTINUE. */
6752 gsi = gsi_last_bb (cont_bb);
6753 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6754 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6755 vmain = gimple_omp_continue_control_use (cont_stmt);
6756 vback = gimple_omp_continue_control_def (cont_stmt);
6758 if (!gimple_omp_for_combined_p (fd->for_stmt))
6760 if (POINTER_TYPE_P (type))
6761 t = fold_build_pointer_plus (vmain, step);
6762 else
6763 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6764 t = force_gimple_operand_gsi (&gsi, t,
6765 DECL_P (vback)
6766 && TREE_ADDRESSABLE (vback),
6767 NULL_TREE, true, GSI_SAME_STMT);
6768 assign_stmt = gimple_build_assign (vback, t);
6769 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6771 t = build2 (fd->loop.cond_code, boolean_type_node,
6772 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6773 ? t : vback, e);
6774 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6777 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6778 gsi_remove (&gsi, true);
6780 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6781 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6784 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6785 gsi = gsi_last_bb (exit_bb);
6786 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6788 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6789 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6790 gcc_checking_assert (t == NULL_TREE);
6791 else
6792 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6794 gsi_remove (&gsi, true);
6796 /* Connect all the blocks. */
6797 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6798 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6799 ep = find_edge (entry_bb, second_bb);
6800 ep->flags = EDGE_TRUE_VALUE;
6801 ep->probability = REG_BR_PROB_BASE / 4;
6802 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6803 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6805 if (!broken_loop)
6807 ep = find_edge (cont_bb, body_bb);
6808 if (gimple_omp_for_combined_p (fd->for_stmt))
6810 remove_edge (ep);
6811 ep = NULL;
6813 else if (fd->collapse > 1)
6815 remove_edge (ep);
6816 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6818 else
6819 ep->flags = EDGE_TRUE_VALUE;
6820 find_edge (cont_bb, fin_bb)->flags
6821 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6824 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6825 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6826 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6828 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6829 recompute_dominator (CDI_DOMINATORS, body_bb));
6830 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6831 recompute_dominator (CDI_DOMINATORS, fin_bb));
6833 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6835 struct loop *loop = alloc_loop ();
6836 loop->header = body_bb;
6837 if (collapse_bb == NULL)
6838 loop->latch = cont_bb;
6839 add_loop (loop, body_bb->loop_father);
6844 /* A subroutine of expand_omp_for. Generate code for a parallel
6845 loop with static schedule and a specified chunk size. Given
6846 parameters:
6848 for (V = N1; V cond N2; V += STEP) BODY;
6850 where COND is "<" or ">", we generate pseudocode
6852 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6853 if (cond is <)
6854 adj = STEP - 1;
6855 else
6856 adj = STEP + 1;
6857 if ((__typeof (V)) -1 > 0 && cond is >)
6858 n = -(adj + N2 - N1) / -STEP;
6859 else
6860 n = (adj + N2 - N1) / STEP;
6861 trip = 0;
6862 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6863 here so that V is defined
6864 if the loop is not entered
6866 s0 = (trip * nthreads + threadid) * CHUNK;
6867 e0 = min(s0 + CHUNK, n);
6868 if (s0 < n) goto L1; else goto L4;
6870 V = s0 * STEP + N1;
6871 e = e0 * STEP + N1;
6873 BODY;
6874 V += STEP;
6875 if (V cond e) goto L2; else goto L3;
6877 trip += 1;
6878 goto L0;
6882 static void
6883 expand_omp_for_static_chunk (struct omp_region *region,
6884 struct omp_for_data *fd, gimple inner_stmt)
6886 tree n, s0, e0, e, t;
6887 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6888 tree type, itype, vmain, vback, vextra;
6889 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6890 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6891 gimple_stmt_iterator gsi;
6892 edge se;
6893 bool broken_loop = region->cont == NULL;
6894 tree *counts = NULL;
6895 tree n1, n2, step;
6897 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6898 != GF_OMP_FOR_KIND_OACC_LOOP)
6899 || !inner_stmt);
6901 itype = type = TREE_TYPE (fd->loop.v);
6902 if (POINTER_TYPE_P (type))
6903 itype = signed_type_for (type);
6905 entry_bb = region->entry;
6906 se = split_block (entry_bb, last_stmt (entry_bb));
6907 entry_bb = se->src;
6908 iter_part_bb = se->dest;
6909 cont_bb = region->cont;
6910 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6911 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6912 gcc_assert (broken_loop
6913 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6914 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6915 body_bb = single_succ (seq_start_bb);
6916 if (!broken_loop)
6918 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6919 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6920 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6922 exit_bb = region->exit;
6924 /* Trip and adjustment setup goes in ENTRY_BB. */
6925 gsi = gsi_last_bb (entry_bb);
6926 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6928 if (fd->collapse > 1)
6930 int first_zero_iter = -1;
6931 basic_block l2_dom_bb = NULL;
6933 counts = XALLOCAVEC (tree, fd->collapse);
6934 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6935 fin_bb, first_zero_iter,
6936 l2_dom_bb);
6937 t = NULL_TREE;
6939 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6940 t = integer_one_node;
6941 else
6942 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6943 fold_convert (type, fd->loop.n1),
6944 fold_convert (type, fd->loop.n2));
6945 if (fd->collapse == 1
6946 && TYPE_UNSIGNED (type)
6947 && (t == NULL_TREE || !integer_onep (t)))
6949 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6950 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6951 true, GSI_SAME_STMT);
6952 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6953 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6954 true, GSI_SAME_STMT);
6955 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6956 NULL_TREE, NULL_TREE);
6957 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6958 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6959 expand_omp_regimplify_p, NULL, NULL)
6960 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6961 expand_omp_regimplify_p, NULL, NULL))
6963 gsi = gsi_for_stmt (cond_stmt);
6964 gimple_regimplify_operands (cond_stmt, &gsi);
6966 se = split_block (entry_bb, cond_stmt);
6967 se->flags = EDGE_TRUE_VALUE;
6968 entry_bb = se->dest;
6969 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6970 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6971 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6972 if (gimple_in_ssa_p (cfun))
6974 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6975 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6976 !gsi_end_p (gpi); gsi_next (&gpi))
6978 gphi *phi = gpi.phi ();
6979 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6980 se, UNKNOWN_LOCATION);
6983 gsi = gsi_last_bb (entry_bb);
6986 switch (gimple_omp_for_kind (fd->for_stmt))
6988 case GF_OMP_FOR_KIND_FOR:
6989 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6990 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6991 break;
6992 case GF_OMP_FOR_KIND_DISTRIBUTE:
6993 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6994 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6995 break;
6996 case GF_OMP_FOR_KIND_OACC_LOOP:
6997 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6998 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6999 break;
7000 default:
7001 gcc_unreachable ();
7003 nthreads = build_call_expr (nthreads, 0);
7004 nthreads = fold_convert (itype, nthreads);
7005 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7006 true, GSI_SAME_STMT);
7007 threadid = build_call_expr (threadid, 0);
7008 threadid = fold_convert (itype, threadid);
7009 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7010 true, GSI_SAME_STMT);
7012 n1 = fd->loop.n1;
7013 n2 = fd->loop.n2;
7014 step = fd->loop.step;
7015 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7017 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7018 OMP_CLAUSE__LOOPTEMP_);
7019 gcc_assert (innerc);
7020 n1 = OMP_CLAUSE_DECL (innerc);
7021 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7022 OMP_CLAUSE__LOOPTEMP_);
7023 gcc_assert (innerc);
7024 n2 = OMP_CLAUSE_DECL (innerc);
7026 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7027 true, NULL_TREE, true, GSI_SAME_STMT);
7028 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7029 true, NULL_TREE, true, GSI_SAME_STMT);
7030 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7031 true, NULL_TREE, true, GSI_SAME_STMT);
7032 fd->chunk_size
7033 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7034 true, NULL_TREE, true, GSI_SAME_STMT);
7036 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7037 t = fold_build2 (PLUS_EXPR, itype, step, t);
7038 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7039 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7040 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7041 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7042 fold_build1 (NEGATE_EXPR, itype, t),
7043 fold_build1 (NEGATE_EXPR, itype, step));
7044 else
7045 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7046 t = fold_convert (itype, t);
7047 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7048 true, GSI_SAME_STMT);
7050 trip_var = create_tmp_reg (itype, ".trip");
7051 if (gimple_in_ssa_p (cfun))
7053 trip_init = make_ssa_name (trip_var);
7054 trip_main = make_ssa_name (trip_var);
7055 trip_back = make_ssa_name (trip_var);
7057 else
7059 trip_init = trip_var;
7060 trip_main = trip_var;
7061 trip_back = trip_var;
7064 gassign *assign_stmt
7065 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7066 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7068 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7069 t = fold_build2 (MULT_EXPR, itype, t, step);
7070 if (POINTER_TYPE_P (type))
7071 t = fold_build_pointer_plus (n1, t);
7072 else
7073 t = fold_build2 (PLUS_EXPR, type, t, n1);
7074 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7075 true, GSI_SAME_STMT);
7077 /* Remove the GIMPLE_OMP_FOR. */
7078 gsi_remove (&gsi, true);
7080 /* Iteration space partitioning goes in ITER_PART_BB. */
7081 gsi = gsi_last_bb (iter_part_bb);
7083 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7084 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7085 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7086 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7087 false, GSI_CONTINUE_LINKING);
7089 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7090 t = fold_build2 (MIN_EXPR, itype, t, n);
7091 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7092 false, GSI_CONTINUE_LINKING);
7094 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7095 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7097 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7098 gsi = gsi_start_bb (seq_start_bb);
7100 tree startvar = fd->loop.v;
7101 tree endvar = NULL_TREE;
7103 if (gimple_omp_for_combined_p (fd->for_stmt))
7105 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7106 ? gimple_omp_parallel_clauses (inner_stmt)
7107 : gimple_omp_for_clauses (inner_stmt);
7108 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7109 gcc_assert (innerc);
7110 startvar = OMP_CLAUSE_DECL (innerc);
7111 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7112 OMP_CLAUSE__LOOPTEMP_);
7113 gcc_assert (innerc);
7114 endvar = OMP_CLAUSE_DECL (innerc);
7117 t = fold_convert (itype, s0);
7118 t = fold_build2 (MULT_EXPR, itype, t, step);
7119 if (POINTER_TYPE_P (type))
7120 t = fold_build_pointer_plus (n1, t);
7121 else
7122 t = fold_build2 (PLUS_EXPR, type, t, n1);
7123 t = fold_convert (TREE_TYPE (startvar), t);
7124 t = force_gimple_operand_gsi (&gsi, t,
7125 DECL_P (startvar)
7126 && TREE_ADDRESSABLE (startvar),
7127 NULL_TREE, false, GSI_CONTINUE_LINKING);
7128 assign_stmt = gimple_build_assign (startvar, t);
7129 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7131 t = fold_convert (itype, e0);
7132 t = fold_build2 (MULT_EXPR, itype, t, step);
7133 if (POINTER_TYPE_P (type))
7134 t = fold_build_pointer_plus (n1, t);
7135 else
7136 t = fold_build2 (PLUS_EXPR, type, t, n1);
7137 t = fold_convert (TREE_TYPE (startvar), t);
7138 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7139 false, GSI_CONTINUE_LINKING);
7140 if (endvar)
7142 assign_stmt = gimple_build_assign (endvar, e);
7143 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7144 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7145 assign_stmt = gimple_build_assign (fd->loop.v, e);
7146 else
7147 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7148 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7150 if (fd->collapse > 1)
7151 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7153 if (!broken_loop)
7155 /* The code controlling the sequential loop goes in CONT_BB,
7156 replacing the GIMPLE_OMP_CONTINUE. */
7157 gsi = gsi_last_bb (cont_bb);
7158 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7159 vmain = gimple_omp_continue_control_use (cont_stmt);
7160 vback = gimple_omp_continue_control_def (cont_stmt);
7162 if (!gimple_omp_for_combined_p (fd->for_stmt))
7164 if (POINTER_TYPE_P (type))
7165 t = fold_build_pointer_plus (vmain, step);
7166 else
7167 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7168 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7169 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7170 true, GSI_SAME_STMT);
7171 assign_stmt = gimple_build_assign (vback, t);
7172 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7174 t = build2 (fd->loop.cond_code, boolean_type_node,
7175 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7176 ? t : vback, e);
7177 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7180 /* Remove GIMPLE_OMP_CONTINUE. */
7181 gsi_remove (&gsi, true);
7183 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7184 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7186 /* Trip update code goes into TRIP_UPDATE_BB. */
7187 gsi = gsi_start_bb (trip_update_bb);
7189 t = build_int_cst (itype, 1);
7190 t = build2 (PLUS_EXPR, itype, trip_main, t);
7191 assign_stmt = gimple_build_assign (trip_back, t);
7192 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7195 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7196 gsi = gsi_last_bb (exit_bb);
7197 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7199 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7200 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7201 gcc_checking_assert (t == NULL_TREE);
7202 else
7203 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7205 gsi_remove (&gsi, true);
7207 /* Connect the new blocks. */
7208 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7209 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7211 if (!broken_loop)
7213 se = find_edge (cont_bb, body_bb);
7214 if (gimple_omp_for_combined_p (fd->for_stmt))
7216 remove_edge (se);
7217 se = NULL;
7219 else if (fd->collapse > 1)
7221 remove_edge (se);
7222 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7224 else
7225 se->flags = EDGE_TRUE_VALUE;
7226 find_edge (cont_bb, trip_update_bb)->flags
7227 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7229 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7232 if (gimple_in_ssa_p (cfun))
7234 gphi_iterator psi;
7235 gphi *phi;
7236 edge re, ene;
7237 edge_var_map *vm;
7238 size_t i;
7240 gcc_assert (fd->collapse == 1 && !broken_loop);
7242 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7243 remove arguments of the phi nodes in fin_bb. We need to create
7244 appropriate phi nodes in iter_part_bb instead. */
7245 se = single_pred_edge (fin_bb);
7246 re = single_succ_edge (trip_update_bb);
7247 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7248 ene = single_succ_edge (entry_bb);
7250 psi = gsi_start_phis (fin_bb);
7251 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7252 gsi_next (&psi), ++i)
7254 gphi *nphi;
7255 source_location locus;
7257 phi = psi.phi ();
7258 t = gimple_phi_result (phi);
7259 gcc_assert (t == redirect_edge_var_map_result (vm));
7260 nphi = create_phi_node (t, iter_part_bb);
7262 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7263 locus = gimple_phi_arg_location_from_edge (phi, se);
7265 /* A special case -- fd->loop.v is not yet computed in
7266 iter_part_bb, we need to use vextra instead. */
7267 if (t == fd->loop.v)
7268 t = vextra;
7269 add_phi_arg (nphi, t, ene, locus);
7270 locus = redirect_edge_var_map_location (vm);
7271 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7273 gcc_assert (!gsi_end_p (psi) && i == head->length ());
7274 redirect_edge_var_map_clear (re);
7275 while (1)
7277 psi = gsi_start_phis (fin_bb);
7278 if (gsi_end_p (psi))
7279 break;
7280 remove_phi_node (&psi, false);
7283 /* Make phi node for trip. */
7284 phi = create_phi_node (trip_main, iter_part_bb);
7285 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7286 UNKNOWN_LOCATION);
7287 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7288 UNKNOWN_LOCATION);
7291 if (!broken_loop)
7292 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7293 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7294 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7295 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7296 recompute_dominator (CDI_DOMINATORS, fin_bb));
7297 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7298 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7299 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7300 recompute_dominator (CDI_DOMINATORS, body_bb));
7302 if (!broken_loop)
7304 struct loop *trip_loop = alloc_loop ();
7305 trip_loop->header = iter_part_bb;
7306 trip_loop->latch = trip_update_bb;
7307 add_loop (trip_loop, iter_part_bb->loop_father);
7309 if (!gimple_omp_for_combined_p (fd->for_stmt))
7311 struct loop *loop = alloc_loop ();
7312 loop->header = body_bb;
7313 if (collapse_bb == NULL)
7314 loop->latch = cont_bb;
7315 add_loop (loop, trip_loop);
7320 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7321 Given parameters:
7322 for (V = N1; V cond N2; V += STEP) BODY;
7324 where COND is "<" or ">" or "!=", we generate pseudocode
7326 for (ind_var = low; ind_var < high; ind_var++)
7328 V = n1 + (ind_var * STEP)
7330 <BODY>
7333 In the above pseudocode, low and high are function parameters of the
7334 child function. In the function below, we are inserting a temp.
7335 variable that will be making a call to two OMP functions that will not be
7336 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7337 with _Cilk_for). These functions are replaced with low and high
7338 by the function that handles taskreg. */
7341 static void
7342 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7344 bool broken_loop = region->cont == NULL;
7345 basic_block entry_bb = region->entry;
7346 basic_block cont_bb = region->cont;
7348 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7349 gcc_assert (broken_loop
7350 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7351 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7352 basic_block l1_bb, l2_bb;
7354 if (!broken_loop)
7356 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7357 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7358 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7359 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7361 else
7363 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7364 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7365 l2_bb = single_succ (l1_bb);
7367 basic_block exit_bb = region->exit;
7368 basic_block l2_dom_bb = NULL;
7370 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7372 /* Below statements until the "tree high_val = ..." are pseudo statements
7373 used to pass information to be used by expand_omp_taskreg.
7374 low_val and high_val will be replaced by the __low and __high
7375 parameter from the child function.
7377 The call_exprs part is a place-holder, it is mainly used
7378 to distinctly identify to the top-level part that this is
7379 where we should put low and high (reasoning given in header
7380 comment). */
7382 tree child_fndecl
7383 = gimple_omp_parallel_child_fn (
7384 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7385 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7386 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7388 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7389 high_val = t;
7390 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7391 low_val = t;
7393 gcc_assert (low_val && high_val);
7395 tree type = TREE_TYPE (low_val);
7396 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7397 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7399 /* Not needed in SSA form right now. */
7400 gcc_assert (!gimple_in_ssa_p (cfun));
7401 if (l2_dom_bb == NULL)
7402 l2_dom_bb = l1_bb;
7404 tree n1 = low_val;
7405 tree n2 = high_val;
7407 gimple stmt = gimple_build_assign (ind_var, n1);
7409 /* Replace the GIMPLE_OMP_FOR statement. */
7410 gsi_replace (&gsi, stmt, true);
7412 if (!broken_loop)
7414 /* Code to control the increment goes in the CONT_BB. */
7415 gsi = gsi_last_bb (cont_bb);
7416 stmt = gsi_stmt (gsi);
7417 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7418 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7419 build_one_cst (type));
7421 /* Replace GIMPLE_OMP_CONTINUE. */
7422 gsi_replace (&gsi, stmt, true);
7425 /* Emit the condition in L1_BB. */
7426 gsi = gsi_after_labels (l1_bb);
7427 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7428 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7429 fd->loop.step);
7430 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7431 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7432 fd->loop.n1, fold_convert (sizetype, t));
7433 else
7434 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7435 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7436 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7437 expand_omp_build_assign (&gsi, fd->loop.v, t);
7439 /* The condition is always '<' since the runtime will fill in the low
7440 and high values. */
7441 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7442 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7444 /* Remove GIMPLE_OMP_RETURN. */
7445 gsi = gsi_last_bb (exit_bb);
7446 gsi_remove (&gsi, true);
7448 /* Connect the new blocks. */
7449 remove_edge (FALLTHRU_EDGE (entry_bb));
7451 edge e, ne;
7452 if (!broken_loop)
7454 remove_edge (BRANCH_EDGE (entry_bb));
7455 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7457 e = BRANCH_EDGE (l1_bb);
7458 ne = FALLTHRU_EDGE (l1_bb);
7459 e->flags = EDGE_TRUE_VALUE;
7461 else
7463 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7465 ne = single_succ_edge (l1_bb);
7466 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7469 ne->flags = EDGE_FALSE_VALUE;
7470 e->probability = REG_BR_PROB_BASE * 7 / 8;
7471 ne->probability = REG_BR_PROB_BASE / 8;
7473 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7474 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7475 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7477 if (!broken_loop)
7479 struct loop *loop = alloc_loop ();
7480 loop->header = l1_bb;
7481 loop->latch = cont_bb;
7482 add_loop (loop, l1_bb->loop_father);
7483 loop->safelen = INT_MAX;
7486 /* Pick the correct library function based on the precision of the
7487 induction variable type. */
7488 tree lib_fun = NULL_TREE;
7489 if (TYPE_PRECISION (type) == 32)
7490 lib_fun = cilk_for_32_fndecl;
7491 else if (TYPE_PRECISION (type) == 64)
7492 lib_fun = cilk_for_64_fndecl;
7493 else
7494 gcc_unreachable ();
7496 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7498 /* WS_ARGS contains the library function flavor to call:
7499 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7500 user-defined grain value. If the user does not define one, then zero
7501 is passed in by the parser. */
7502 vec_alloc (region->ws_args, 2);
7503 region->ws_args->quick_push (lib_fun);
7504 region->ws_args->quick_push (fd->chunk_size);
7507 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7508 loop. Given parameters:
7510 for (V = N1; V cond N2; V += STEP) BODY;
7512 where COND is "<" or ">", we generate pseudocode
7514 V = N1;
7515 goto L1;
7517 BODY;
7518 V += STEP;
7520 if (V cond N2) goto L0; else goto L2;
7523 For collapsed loops, given parameters:
7524 collapse(3)
7525 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7526 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7527 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7528 BODY;
7530 we generate pseudocode
7532 if (cond3 is <)
7533 adj = STEP3 - 1;
7534 else
7535 adj = STEP3 + 1;
7536 count3 = (adj + N32 - N31) / STEP3;
7537 if (cond2 is <)
7538 adj = STEP2 - 1;
7539 else
7540 adj = STEP2 + 1;
7541 count2 = (adj + N22 - N21) / STEP2;
7542 if (cond1 is <)
7543 adj = STEP1 - 1;
7544 else
7545 adj = STEP1 + 1;
7546 count1 = (adj + N12 - N11) / STEP1;
7547 count = count1 * count2 * count3;
7548 V = 0;
7549 V1 = N11;
7550 V2 = N21;
7551 V3 = N31;
7552 goto L1;
7554 BODY;
7555 V += 1;
7556 V3 += STEP3;
7557 V2 += (V3 cond3 N32) ? 0 : STEP2;
7558 V3 = (V3 cond3 N32) ? V3 : N31;
7559 V1 += (V2 cond2 N22) ? 0 : STEP1;
7560 V2 = (V2 cond2 N22) ? V2 : N21;
7562 if (V < count) goto L0; else goto L2;
7567 static void
7568 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7570 tree type, t;
7571 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7572 gimple_stmt_iterator gsi;
7573 gimple stmt;
7574 gcond *cond_stmt;
7575 bool broken_loop = region->cont == NULL;
7576 edge e, ne;
7577 tree *counts = NULL;
7578 int i;
7579 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7580 OMP_CLAUSE_SAFELEN);
7581 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7582 OMP_CLAUSE__SIMDUID_);
7583 tree n1, n2;
7585 type = TREE_TYPE (fd->loop.v);
7586 entry_bb = region->entry;
7587 cont_bb = region->cont;
7588 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7589 gcc_assert (broken_loop
7590 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7591 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7592 if (!broken_loop)
7594 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7595 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7596 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7597 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7599 else
7601 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7602 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7603 l2_bb = single_succ (l1_bb);
7605 exit_bb = region->exit;
7606 l2_dom_bb = NULL;
7608 gsi = gsi_last_bb (entry_bb);
7610 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7611 /* Not needed in SSA form right now. */
7612 gcc_assert (!gimple_in_ssa_p (cfun));
7613 if (fd->collapse > 1)
7615 int first_zero_iter = -1;
7616 basic_block zero_iter_bb = l2_bb;
7618 counts = XALLOCAVEC (tree, fd->collapse);
7619 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7620 zero_iter_bb, first_zero_iter,
7621 l2_dom_bb);
7623 if (l2_dom_bb == NULL)
7624 l2_dom_bb = l1_bb;
7626 n1 = fd->loop.n1;
7627 n2 = fd->loop.n2;
7628 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7630 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7631 OMP_CLAUSE__LOOPTEMP_);
7632 gcc_assert (innerc);
7633 n1 = OMP_CLAUSE_DECL (innerc);
7634 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7635 OMP_CLAUSE__LOOPTEMP_);
7636 gcc_assert (innerc);
7637 n2 = OMP_CLAUSE_DECL (innerc);
7638 expand_omp_build_assign (&gsi, fd->loop.v,
7639 fold_convert (type, n1));
7640 if (fd->collapse > 1)
7642 gsi_prev (&gsi);
7643 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7644 gsi_next (&gsi);
7647 else
7649 expand_omp_build_assign (&gsi, fd->loop.v,
7650 fold_convert (type, fd->loop.n1));
7651 if (fd->collapse > 1)
7652 for (i = 0; i < fd->collapse; i++)
7654 tree itype = TREE_TYPE (fd->loops[i].v);
7655 if (POINTER_TYPE_P (itype))
7656 itype = signed_type_for (itype);
7657 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7658 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7662 /* Remove the GIMPLE_OMP_FOR statement. */
7663 gsi_remove (&gsi, true);
7665 if (!broken_loop)
7667 /* Code to control the increment goes in the CONT_BB. */
7668 gsi = gsi_last_bb (cont_bb);
7669 stmt = gsi_stmt (gsi);
7670 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7672 if (POINTER_TYPE_P (type))
7673 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7674 else
7675 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7676 expand_omp_build_assign (&gsi, fd->loop.v, t);
7678 if (fd->collapse > 1)
7680 i = fd->collapse - 1;
7681 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7683 t = fold_convert (sizetype, fd->loops[i].step);
7684 t = fold_build_pointer_plus (fd->loops[i].v, t);
7686 else
7688 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7689 fd->loops[i].step);
7690 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7691 fd->loops[i].v, t);
7693 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7695 for (i = fd->collapse - 1; i > 0; i--)
7697 tree itype = TREE_TYPE (fd->loops[i].v);
7698 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7699 if (POINTER_TYPE_P (itype2))
7700 itype2 = signed_type_for (itype2);
7701 t = build3 (COND_EXPR, itype2,
7702 build2 (fd->loops[i].cond_code, boolean_type_node,
7703 fd->loops[i].v,
7704 fold_convert (itype, fd->loops[i].n2)),
7705 build_int_cst (itype2, 0),
7706 fold_convert (itype2, fd->loops[i - 1].step));
7707 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7708 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7709 else
7710 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7711 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7713 t = build3 (COND_EXPR, itype,
7714 build2 (fd->loops[i].cond_code, boolean_type_node,
7715 fd->loops[i].v,
7716 fold_convert (itype, fd->loops[i].n2)),
7717 fd->loops[i].v,
7718 fold_convert (itype, fd->loops[i].n1));
7719 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7723 /* Remove GIMPLE_OMP_CONTINUE. */
7724 gsi_remove (&gsi, true);
7727 /* Emit the condition in L1_BB. */
7728 gsi = gsi_start_bb (l1_bb);
7730 t = fold_convert (type, n2);
7731 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7732 false, GSI_CONTINUE_LINKING);
7733 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7734 cond_stmt = gimple_build_cond_empty (t);
7735 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7736 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7737 NULL, NULL)
7738 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7739 NULL, NULL))
7741 gsi = gsi_for_stmt (cond_stmt);
7742 gimple_regimplify_operands (cond_stmt, &gsi);
7745 /* Remove GIMPLE_OMP_RETURN. */
7746 gsi = gsi_last_bb (exit_bb);
7747 gsi_remove (&gsi, true);
7749 /* Connect the new blocks. */
7750 remove_edge (FALLTHRU_EDGE (entry_bb));
7752 if (!broken_loop)
7754 remove_edge (BRANCH_EDGE (entry_bb));
7755 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7757 e = BRANCH_EDGE (l1_bb);
7758 ne = FALLTHRU_EDGE (l1_bb);
7759 e->flags = EDGE_TRUE_VALUE;
7761 else
7763 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7765 ne = single_succ_edge (l1_bb);
7766 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7769 ne->flags = EDGE_FALSE_VALUE;
7770 e->probability = REG_BR_PROB_BASE * 7 / 8;
7771 ne->probability = REG_BR_PROB_BASE / 8;
7773 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7774 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7775 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7777 if (!broken_loop)
7779 struct loop *loop = alloc_loop ();
7780 loop->header = l1_bb;
7781 loop->latch = cont_bb;
7782 add_loop (loop, l1_bb->loop_father);
7783 if (safelen == NULL_TREE)
7784 loop->safelen = INT_MAX;
7785 else
7787 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7788 if (TREE_CODE (safelen) != INTEGER_CST)
7789 loop->safelen = 0;
7790 else if (!tree_fits_uhwi_p (safelen)
7791 || tree_to_uhwi (safelen) > INT_MAX)
7792 loop->safelen = INT_MAX;
7793 else
7794 loop->safelen = tree_to_uhwi (safelen);
7795 if (loop->safelen == 1)
7796 loop->safelen = 0;
7798 if (simduid)
7800 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7801 cfun->has_simduid_loops = true;
7803 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7804 the loop. */
7805 if ((flag_tree_loop_vectorize
7806 || (!global_options_set.x_flag_tree_loop_vectorize
7807 && !global_options_set.x_flag_tree_vectorize))
7808 && flag_tree_loop_optimize
7809 && loop->safelen > 1)
7811 loop->force_vectorize = true;
7812 cfun->has_force_vectorize_loops = true;
7818 /* Expand the OMP loop defined by REGION. */
7820 static void
7821 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7823 struct omp_for_data fd;
7824 struct omp_for_data_loop *loops;
7826 loops
7827 = (struct omp_for_data_loop *)
7828 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7829 * sizeof (struct omp_for_data_loop));
7830 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7831 &fd, loops);
7832 region->sched_kind = fd.sched_kind;
7834 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7835 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7836 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7837 if (region->cont)
7839 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7840 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7841 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7843 else
7844 /* If there isn't a continue then this is a degerate case where
7845 the introduction of abnormal edges during lowering will prevent
7846 original loops from being detected. Fix that up. */
7847 loops_state_set (LOOPS_NEED_FIXUP);
7849 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7850 expand_omp_simd (region, &fd);
7851 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7852 expand_cilk_for (region, &fd);
7853 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7854 && !fd.have_ordered)
7856 if (fd.chunk_size == NULL)
7857 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7858 else
7859 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7861 else
7863 int fn_index, start_ix, next_ix;
7865 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7866 == GF_OMP_FOR_KIND_FOR);
7867 if (fd.chunk_size == NULL
7868 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7869 fd.chunk_size = integer_zero_node;
7870 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7871 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7872 ? 3 : fd.sched_kind;
7873 fn_index += fd.have_ordered * 4;
7874 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7875 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7876 if (fd.iter_type == long_long_unsigned_type_node)
7878 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7879 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7880 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7881 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7883 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7884 (enum built_in_function) next_ix, inner_stmt);
7887 if (gimple_in_ssa_p (cfun))
7888 update_ssa (TODO_update_ssa_only_virtuals);
7892 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7894 v = GOMP_sections_start (n);
7896 switch (v)
7898 case 0:
7899 goto L2;
7900 case 1:
7901 section 1;
7902 goto L1;
7903 case 2:
7905 case n:
7907 default:
7908 abort ();
7911 v = GOMP_sections_next ();
7912 goto L0;
7914 reduction;
7916 If this is a combined parallel sections, replace the call to
7917 GOMP_sections_start with call to GOMP_sections_next. */
7919 static void
7920 expand_omp_sections (struct omp_region *region)
7922 tree t, u, vin = NULL, vmain, vnext, l2;
7923 unsigned len;
7924 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7925 gimple_stmt_iterator si, switch_si;
7926 gomp_sections *sections_stmt;
7927 gimple stmt;
7928 gomp_continue *cont;
7929 edge_iterator ei;
7930 edge e;
7931 struct omp_region *inner;
7932 unsigned i, casei;
7933 bool exit_reachable = region->cont != NULL;
7935 gcc_assert (region->exit != NULL);
7936 entry_bb = region->entry;
7937 l0_bb = single_succ (entry_bb);
7938 l1_bb = region->cont;
7939 l2_bb = region->exit;
7940 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7941 l2 = gimple_block_label (l2_bb);
7942 else
7944 /* This can happen if there are reductions. */
7945 len = EDGE_COUNT (l0_bb->succs);
7946 gcc_assert (len > 0);
7947 e = EDGE_SUCC (l0_bb, len - 1);
7948 si = gsi_last_bb (e->dest);
7949 l2 = NULL_TREE;
7950 if (gsi_end_p (si)
7951 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7952 l2 = gimple_block_label (e->dest);
7953 else
7954 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7956 si = gsi_last_bb (e->dest);
7957 if (gsi_end_p (si)
7958 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7960 l2 = gimple_block_label (e->dest);
7961 break;
7965 if (exit_reachable)
7966 default_bb = create_empty_bb (l1_bb->prev_bb);
7967 else
7968 default_bb = create_empty_bb (l0_bb);
7970 /* We will build a switch() with enough cases for all the
7971 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7972 and a default case to abort if something goes wrong. */
7973 len = EDGE_COUNT (l0_bb->succs);
7975 /* Use vec::quick_push on label_vec throughout, since we know the size
7976 in advance. */
7977 auto_vec<tree> label_vec (len);
7979 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7980 GIMPLE_OMP_SECTIONS statement. */
7981 si = gsi_last_bb (entry_bb);
7982 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
7983 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7984 vin = gimple_omp_sections_control (sections_stmt);
7985 if (!is_combined_parallel (region))
7987 /* If we are not inside a combined parallel+sections region,
7988 call GOMP_sections_start. */
7989 t = build_int_cst (unsigned_type_node, len - 1);
7990 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7991 stmt = gimple_build_call (u, 1, t);
7993 else
7995 /* Otherwise, call GOMP_sections_next. */
7996 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7997 stmt = gimple_build_call (u, 0);
7999 gimple_call_set_lhs (stmt, vin);
8000 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8001 gsi_remove (&si, true);
8003 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8004 L0_BB. */
8005 switch_si = gsi_last_bb (l0_bb);
8006 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8007 if (exit_reachable)
8009 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8010 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8011 vmain = gimple_omp_continue_control_use (cont);
8012 vnext = gimple_omp_continue_control_def (cont);
8014 else
8016 vmain = vin;
8017 vnext = NULL_TREE;
8020 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8021 label_vec.quick_push (t);
8022 i = 1;
8024 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8025 for (inner = region->inner, casei = 1;
8026 inner;
8027 inner = inner->next, i++, casei++)
8029 basic_block s_entry_bb, s_exit_bb;
8031 /* Skip optional reduction region. */
8032 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8034 --i;
8035 --casei;
8036 continue;
8039 s_entry_bb = inner->entry;
8040 s_exit_bb = inner->exit;
8042 t = gimple_block_label (s_entry_bb);
8043 u = build_int_cst (unsigned_type_node, casei);
8044 u = build_case_label (u, NULL, t);
8045 label_vec.quick_push (u);
8047 si = gsi_last_bb (s_entry_bb);
8048 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8049 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8050 gsi_remove (&si, true);
8051 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8053 if (s_exit_bb == NULL)
8054 continue;
8056 si = gsi_last_bb (s_exit_bb);
8057 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8058 gsi_remove (&si, true);
8060 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8063 /* Error handling code goes in DEFAULT_BB. */
8064 t = gimple_block_label (default_bb);
8065 u = build_case_label (NULL, NULL, t);
8066 make_edge (l0_bb, default_bb, 0);
8067 add_bb_to_loop (default_bb, current_loops->tree_root);
8069 stmt = gimple_build_switch (vmain, u, label_vec);
8070 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8071 gsi_remove (&switch_si, true);
8073 si = gsi_start_bb (default_bb);
8074 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8075 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8077 if (exit_reachable)
8079 tree bfn_decl;
8081 /* Code to get the next section goes in L1_BB. */
8082 si = gsi_last_bb (l1_bb);
8083 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8085 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8086 stmt = gimple_build_call (bfn_decl, 0);
8087 gimple_call_set_lhs (stmt, vnext);
8088 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8089 gsi_remove (&si, true);
8091 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8094 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8095 si = gsi_last_bb (l2_bb);
8096 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8097 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8098 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8099 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8100 else
8101 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8102 stmt = gimple_build_call (t, 0);
8103 if (gimple_omp_return_lhs (gsi_stmt (si)))
8104 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8105 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8106 gsi_remove (&si, true);
8108 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8112 /* Expand code for an OpenMP single directive. We've already expanded
8113 much of the code, here we simply place the GOMP_barrier call. */
8115 static void
8116 expand_omp_single (struct omp_region *region)
8118 basic_block entry_bb, exit_bb;
8119 gimple_stmt_iterator si;
8121 entry_bb = region->entry;
8122 exit_bb = region->exit;
8124 si = gsi_last_bb (entry_bb);
8125 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8126 gsi_remove (&si, true);
8127 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8129 si = gsi_last_bb (exit_bb);
8130 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8132 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8133 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8135 gsi_remove (&si, true);
8136 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8140 /* Generic expansion for OpenMP synchronization directives: master,
8141 ordered and critical. All we need to do here is remove the entry
8142 and exit markers for REGION. */
8144 static void
8145 expand_omp_synch (struct omp_region *region)
8147 basic_block entry_bb, exit_bb;
8148 gimple_stmt_iterator si;
8150 entry_bb = region->entry;
8151 exit_bb = region->exit;
8153 si = gsi_last_bb (entry_bb);
8154 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8155 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8156 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8157 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8158 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8159 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8160 gsi_remove (&si, true);
8161 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8163 if (exit_bb)
8165 si = gsi_last_bb (exit_bb);
8166 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8167 gsi_remove (&si, true);
8168 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8172 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8173 operation as a normal volatile load. */
8175 static bool
8176 expand_omp_atomic_load (basic_block load_bb, tree addr,
8177 tree loaded_val, int index)
8179 enum built_in_function tmpbase;
8180 gimple_stmt_iterator gsi;
8181 basic_block store_bb;
8182 location_t loc;
8183 gimple stmt;
8184 tree decl, call, type, itype;
8186 gsi = gsi_last_bb (load_bb);
8187 stmt = gsi_stmt (gsi);
8188 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8189 loc = gimple_location (stmt);
8191 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8192 is smaller than word size, then expand_atomic_load assumes that the load
8193 is atomic. We could avoid the builtin entirely in this case. */
8195 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8196 decl = builtin_decl_explicit (tmpbase);
8197 if (decl == NULL_TREE)
8198 return false;
8200 type = TREE_TYPE (loaded_val);
8201 itype = TREE_TYPE (TREE_TYPE (decl));
8203 call = build_call_expr_loc (loc, decl, 2, addr,
8204 build_int_cst (NULL,
8205 gimple_omp_atomic_seq_cst_p (stmt)
8206 ? MEMMODEL_SEQ_CST
8207 : MEMMODEL_RELAXED));
8208 if (!useless_type_conversion_p (type, itype))
8209 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8210 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8212 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8213 gsi_remove (&gsi, true);
8215 store_bb = single_succ (load_bb);
8216 gsi = gsi_last_bb (store_bb);
8217 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8218 gsi_remove (&gsi, true);
8220 if (gimple_in_ssa_p (cfun))
8221 update_ssa (TODO_update_ssa_no_phi);
8223 return true;
8226 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8227 operation as a normal volatile store. */
8229 static bool
8230 expand_omp_atomic_store (basic_block load_bb, tree addr,
8231 tree loaded_val, tree stored_val, int index)
8233 enum built_in_function tmpbase;
8234 gimple_stmt_iterator gsi;
8235 basic_block store_bb = single_succ (load_bb);
8236 location_t loc;
8237 gimple stmt;
8238 tree decl, call, type, itype;
8239 machine_mode imode;
8240 bool exchange;
8242 gsi = gsi_last_bb (load_bb);
8243 stmt = gsi_stmt (gsi);
8244 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8246 /* If the load value is needed, then this isn't a store but an exchange. */
8247 exchange = gimple_omp_atomic_need_value_p (stmt);
8249 gsi = gsi_last_bb (store_bb);
8250 stmt = gsi_stmt (gsi);
8251 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8252 loc = gimple_location (stmt);
8254 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8255 is smaller than word size, then expand_atomic_store assumes that the store
8256 is atomic. We could avoid the builtin entirely in this case. */
8258 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8259 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8260 decl = builtin_decl_explicit (tmpbase);
8261 if (decl == NULL_TREE)
8262 return false;
8264 type = TREE_TYPE (stored_val);
8266 /* Dig out the type of the function's second argument. */
8267 itype = TREE_TYPE (decl);
8268 itype = TYPE_ARG_TYPES (itype);
8269 itype = TREE_CHAIN (itype);
8270 itype = TREE_VALUE (itype);
8271 imode = TYPE_MODE (itype);
8273 if (exchange && !can_atomic_exchange_p (imode, true))
8274 return false;
8276 if (!useless_type_conversion_p (itype, type))
8277 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8278 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8279 build_int_cst (NULL,
8280 gimple_omp_atomic_seq_cst_p (stmt)
8281 ? MEMMODEL_SEQ_CST
8282 : MEMMODEL_RELAXED));
8283 if (exchange)
8285 if (!useless_type_conversion_p (type, itype))
8286 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8287 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8290 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8291 gsi_remove (&gsi, true);
8293 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8294 gsi = gsi_last_bb (load_bb);
8295 gsi_remove (&gsi, true);
8297 if (gimple_in_ssa_p (cfun))
8298 update_ssa (TODO_update_ssa_no_phi);
8300 return true;
8303 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8304 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8305 size of the data type, and thus usable to find the index of the builtin
8306 decl. Returns false if the expression is not of the proper form. */
8308 static bool
8309 expand_omp_atomic_fetch_op (basic_block load_bb,
8310 tree addr, tree loaded_val,
8311 tree stored_val, int index)
8313 enum built_in_function oldbase, newbase, tmpbase;
8314 tree decl, itype, call;
8315 tree lhs, rhs;
8316 basic_block store_bb = single_succ (load_bb);
8317 gimple_stmt_iterator gsi;
8318 gimple stmt;
8319 location_t loc;
8320 enum tree_code code;
8321 bool need_old, need_new;
8322 machine_mode imode;
8323 bool seq_cst;
8325 /* We expect to find the following sequences:
8327 load_bb:
8328 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8330 store_bb:
8331 val = tmp OP something; (or: something OP tmp)
8332 GIMPLE_OMP_STORE (val)
8334 ???FIXME: Allow a more flexible sequence.
8335 Perhaps use data flow to pick the statements.
8339 gsi = gsi_after_labels (store_bb);
8340 stmt = gsi_stmt (gsi);
8341 loc = gimple_location (stmt);
8342 if (!is_gimple_assign (stmt))
8343 return false;
8344 gsi_next (&gsi);
8345 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8346 return false;
8347 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8348 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8349 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8350 gcc_checking_assert (!need_old || !need_new);
8352 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8353 return false;
8355 /* Check for one of the supported fetch-op operations. */
8356 code = gimple_assign_rhs_code (stmt);
8357 switch (code)
8359 case PLUS_EXPR:
8360 case POINTER_PLUS_EXPR:
8361 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8362 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8363 break;
8364 case MINUS_EXPR:
8365 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8366 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8367 break;
8368 case BIT_AND_EXPR:
8369 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8370 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8371 break;
8372 case BIT_IOR_EXPR:
8373 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8374 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8375 break;
8376 case BIT_XOR_EXPR:
8377 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8378 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8379 break;
8380 default:
8381 return false;
8384 /* Make sure the expression is of the proper form. */
8385 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8386 rhs = gimple_assign_rhs2 (stmt);
8387 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8388 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8389 rhs = gimple_assign_rhs1 (stmt);
8390 else
8391 return false;
8393 tmpbase = ((enum built_in_function)
8394 ((need_new ? newbase : oldbase) + index + 1));
8395 decl = builtin_decl_explicit (tmpbase);
8396 if (decl == NULL_TREE)
8397 return false;
8398 itype = TREE_TYPE (TREE_TYPE (decl));
8399 imode = TYPE_MODE (itype);
8401 /* We could test all of the various optabs involved, but the fact of the
8402 matter is that (with the exception of i486 vs i586 and xadd) all targets
8403 that support any atomic operaton optab also implements compare-and-swap.
8404 Let optabs.c take care of expanding any compare-and-swap loop. */
8405 if (!can_compare_and_swap_p (imode, true))
8406 return false;
8408 gsi = gsi_last_bb (load_bb);
8409 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8411 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8412 It only requires that the operation happen atomically. Thus we can
8413 use the RELAXED memory model. */
8414 call = build_call_expr_loc (loc, decl, 3, addr,
8415 fold_convert_loc (loc, itype, rhs),
8416 build_int_cst (NULL,
8417 seq_cst ? MEMMODEL_SEQ_CST
8418 : MEMMODEL_RELAXED));
8420 if (need_old || need_new)
8422 lhs = need_old ? loaded_val : stored_val;
8423 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8424 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8426 else
8427 call = fold_convert_loc (loc, void_type_node, call);
8428 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8429 gsi_remove (&gsi, true);
8431 gsi = gsi_last_bb (store_bb);
8432 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8433 gsi_remove (&gsi, true);
8434 gsi = gsi_last_bb (store_bb);
8435 gsi_remove (&gsi, true);
8437 if (gimple_in_ssa_p (cfun))
8438 update_ssa (TODO_update_ssa_no_phi);
8440 return true;
8443 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8445 oldval = *addr;
8446 repeat:
8447 newval = rhs; // with oldval replacing *addr in rhs
8448 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8449 if (oldval != newval)
8450 goto repeat;
8452 INDEX is log2 of the size of the data type, and thus usable to find the
8453 index of the builtin decl. */
8455 static bool
8456 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8457 tree addr, tree loaded_val, tree stored_val,
8458 int index)
8460 tree loadedi, storedi, initial, new_storedi, old_vali;
8461 tree type, itype, cmpxchg, iaddr;
8462 gimple_stmt_iterator si;
8463 basic_block loop_header = single_succ (load_bb);
8464 gimple phi, stmt;
8465 edge e;
8466 enum built_in_function fncode;
8468 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8469 order to use the RELAXED memory model effectively. */
8470 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8471 + index + 1);
8472 cmpxchg = builtin_decl_explicit (fncode);
8473 if (cmpxchg == NULL_TREE)
8474 return false;
8475 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8476 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8478 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8479 return false;
8481 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8482 si = gsi_last_bb (load_bb);
8483 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8485 /* For floating-point values, we'll need to view-convert them to integers
8486 so that we can perform the atomic compare and swap. Simplify the
8487 following code by always setting up the "i"ntegral variables. */
8488 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8490 tree iaddr_val;
8492 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8493 true));
8494 iaddr_val
8495 = force_gimple_operand_gsi (&si,
8496 fold_convert (TREE_TYPE (iaddr), addr),
8497 false, NULL_TREE, true, GSI_SAME_STMT);
8498 stmt = gimple_build_assign (iaddr, iaddr_val);
8499 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8500 loadedi = create_tmp_var (itype);
8501 if (gimple_in_ssa_p (cfun))
8502 loadedi = make_ssa_name (loadedi);
8504 else
8506 iaddr = addr;
8507 loadedi = loaded_val;
8510 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8511 tree loaddecl = builtin_decl_explicit (fncode);
8512 if (loaddecl)
8513 initial
8514 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8515 build_call_expr (loaddecl, 2, iaddr,
8516 build_int_cst (NULL_TREE,
8517 MEMMODEL_RELAXED)));
8518 else
8519 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8520 build_int_cst (TREE_TYPE (iaddr), 0));
8522 initial
8523 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8524 GSI_SAME_STMT);
8526 /* Move the value to the LOADEDI temporary. */
8527 if (gimple_in_ssa_p (cfun))
8529 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8530 phi = create_phi_node (loadedi, loop_header);
8531 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8532 initial);
8534 else
8535 gsi_insert_before (&si,
8536 gimple_build_assign (loadedi, initial),
8537 GSI_SAME_STMT);
8538 if (loadedi != loaded_val)
8540 gimple_stmt_iterator gsi2;
8541 tree x;
8543 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8544 gsi2 = gsi_start_bb (loop_header);
8545 if (gimple_in_ssa_p (cfun))
8547 gassign *stmt;
8548 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8549 true, GSI_SAME_STMT);
8550 stmt = gimple_build_assign (loaded_val, x);
8551 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8553 else
8555 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8556 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8557 true, GSI_SAME_STMT);
8560 gsi_remove (&si, true);
8562 si = gsi_last_bb (store_bb);
8563 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8565 if (iaddr == addr)
8566 storedi = stored_val;
8567 else
8568 storedi =
8569 force_gimple_operand_gsi (&si,
8570 build1 (VIEW_CONVERT_EXPR, itype,
8571 stored_val), true, NULL_TREE, true,
8572 GSI_SAME_STMT);
8574 /* Build the compare&swap statement. */
8575 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8576 new_storedi = force_gimple_operand_gsi (&si,
8577 fold_convert (TREE_TYPE (loadedi),
8578 new_storedi),
8579 true, NULL_TREE,
8580 true, GSI_SAME_STMT);
8582 if (gimple_in_ssa_p (cfun))
8583 old_vali = loadedi;
8584 else
8586 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8587 stmt = gimple_build_assign (old_vali, loadedi);
8588 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8590 stmt = gimple_build_assign (loadedi, new_storedi);
8591 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8594 /* Note that we always perform the comparison as an integer, even for
8595 floating point. This allows the atomic operation to properly
8596 succeed even with NaNs and -0.0. */
8597 stmt = gimple_build_cond_empty
8598 (build2 (NE_EXPR, boolean_type_node,
8599 new_storedi, old_vali));
8600 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8602 /* Update cfg. */
8603 e = single_succ_edge (store_bb);
8604 e->flags &= ~EDGE_FALLTHRU;
8605 e->flags |= EDGE_FALSE_VALUE;
8607 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8609 /* Copy the new value to loadedi (we already did that before the condition
8610 if we are not in SSA). */
8611 if (gimple_in_ssa_p (cfun))
8613 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8614 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8617 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8618 gsi_remove (&si, true);
8620 struct loop *loop = alloc_loop ();
8621 loop->header = loop_header;
8622 loop->latch = store_bb;
8623 add_loop (loop, loop_header->loop_father);
8625 if (gimple_in_ssa_p (cfun))
8626 update_ssa (TODO_update_ssa_no_phi);
8628 return true;
8631 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8633 GOMP_atomic_start ();
8634 *addr = rhs;
8635 GOMP_atomic_end ();
8637 The result is not globally atomic, but works so long as all parallel
8638 references are within #pragma omp atomic directives. According to
8639 responses received from omp@openmp.org, appears to be within spec.
8640 Which makes sense, since that's how several other compilers handle
8641 this situation as well.
8642 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8643 expanding. STORED_VAL is the operand of the matching
8644 GIMPLE_OMP_ATOMIC_STORE.
8646 We replace
8647 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8648 loaded_val = *addr;
8650 and replace
8651 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8652 *addr = stored_val;
8655 static bool
8656 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8657 tree addr, tree loaded_val, tree stored_val)
8659 gimple_stmt_iterator si;
8660 gassign *stmt;
8661 tree t;
8663 si = gsi_last_bb (load_bb);
8664 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8666 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8667 t = build_call_expr (t, 0);
8668 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8670 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8671 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8672 gsi_remove (&si, true);
8674 si = gsi_last_bb (store_bb);
8675 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8677 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8678 stored_val);
8679 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8681 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8682 t = build_call_expr (t, 0);
8683 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8684 gsi_remove (&si, true);
8686 if (gimple_in_ssa_p (cfun))
8687 update_ssa (TODO_update_ssa_no_phi);
8688 return true;
8691 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8692 using expand_omp_atomic_fetch_op. If it failed, we try to
8693 call expand_omp_atomic_pipeline, and if it fails too, the
8694 ultimate fallback is wrapping the operation in a mutex
8695 (expand_omp_atomic_mutex). REGION is the atomic region built
8696 by build_omp_regions_1(). */
8698 static void
8699 expand_omp_atomic (struct omp_region *region)
8701 basic_block load_bb = region->entry, store_bb = region->exit;
8702 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8703 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8704 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8705 tree addr = gimple_omp_atomic_load_rhs (load);
8706 tree stored_val = gimple_omp_atomic_store_val (store);
8707 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8708 HOST_WIDE_INT index;
8710 /* Make sure the type is one of the supported sizes. */
8711 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8712 index = exact_log2 (index);
8713 if (index >= 0 && index <= 4)
8715 unsigned int align = TYPE_ALIGN_UNIT (type);
8717 /* __sync builtins require strict data alignment. */
8718 if (exact_log2 (align) >= index)
8720 /* Atomic load. */
8721 if (loaded_val == stored_val
8722 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8723 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8724 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8725 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8726 return;
8728 /* Atomic store. */
8729 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8730 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8731 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8732 && store_bb == single_succ (load_bb)
8733 && first_stmt (store_bb) == store
8734 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8735 stored_val, index))
8736 return;
8738 /* When possible, use specialized atomic update functions. */
8739 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8740 && store_bb == single_succ (load_bb)
8741 && expand_omp_atomic_fetch_op (load_bb, addr,
8742 loaded_val, stored_val, index))
8743 return;
8745 /* If we don't have specialized __sync builtins, try and implement
8746 as a compare and swap loop. */
8747 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8748 loaded_val, stored_val, index))
8749 return;
8753 /* The ultimate fallback is wrapping the operation in a mutex. */
8754 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8758 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8760 static void
8761 expand_omp_target (struct omp_region *region)
8763 basic_block entry_bb, exit_bb, new_bb;
8764 struct function *child_cfun;
8765 tree child_fn, block, t;
8766 gimple_stmt_iterator gsi;
8767 gomp_target *entry_stmt;
8768 gimple stmt;
8769 edge e;
8770 bool offloaded, data_region;
8772 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8773 new_bb = region->entry;
8775 offloaded = is_gimple_omp_offloaded (entry_stmt);
8776 switch (gimple_omp_target_kind (entry_stmt))
8778 case GF_OMP_TARGET_KIND_REGION:
8779 case GF_OMP_TARGET_KIND_UPDATE:
8780 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8781 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8782 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8783 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8784 data_region = false;
8785 break;
8786 case GF_OMP_TARGET_KIND_DATA:
8787 case GF_OMP_TARGET_KIND_OACC_DATA:
8788 data_region = true;
8789 break;
8790 default:
8791 gcc_unreachable ();
8794 child_fn = NULL_TREE;
8795 child_cfun = NULL;
8796 if (offloaded)
8798 child_fn = gimple_omp_target_child_fn (entry_stmt);
8799 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8802 /* Supported by expand_omp_taskreg, but not here. */
8803 if (child_cfun != NULL)
8804 gcc_checking_assert (!child_cfun->cfg);
8805 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8807 entry_bb = region->entry;
8808 exit_bb = region->exit;
8810 if (offloaded)
8812 unsigned srcidx, dstidx, num;
8814 /* If the offloading region needs data sent from the parent
8815 function, then the very first statement (except possible
8816 tree profile counter updates) of the offloading body
8817 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8818 &.OMP_DATA_O is passed as an argument to the child function,
8819 we need to replace it with the argument as seen by the child
8820 function.
8822 In most cases, this will end up being the identity assignment
8823 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8824 a function call that has been inlined, the original PARM_DECL
8825 .OMP_DATA_I may have been converted into a different local
8826 variable. In which case, we need to keep the assignment. */
8827 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8828 if (data_arg)
8830 basic_block entry_succ_bb = single_succ (entry_bb);
8831 gimple_stmt_iterator gsi;
8832 tree arg;
8833 gimple tgtcopy_stmt = NULL;
8834 tree sender = TREE_VEC_ELT (data_arg, 0);
8836 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8838 gcc_assert (!gsi_end_p (gsi));
8839 stmt = gsi_stmt (gsi);
8840 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8841 continue;
8843 if (gimple_num_ops (stmt) == 2)
8845 tree arg = gimple_assign_rhs1 (stmt);
8847 /* We're ignoring the subcode because we're
8848 effectively doing a STRIP_NOPS. */
8850 if (TREE_CODE (arg) == ADDR_EXPR
8851 && TREE_OPERAND (arg, 0) == sender)
8853 tgtcopy_stmt = stmt;
8854 break;
8859 gcc_assert (tgtcopy_stmt != NULL);
8860 arg = DECL_ARGUMENTS (child_fn);
8862 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8863 gsi_remove (&gsi, true);
8866 /* Declare local variables needed in CHILD_CFUN. */
8867 block = DECL_INITIAL (child_fn);
8868 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8869 /* The gimplifier could record temporaries in the offloading block
8870 rather than in containing function's local_decls chain,
8871 which would mean cgraph missed finalizing them. Do it now. */
8872 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8873 if (TREE_CODE (t) == VAR_DECL
8874 && TREE_STATIC (t)
8875 && !DECL_EXTERNAL (t))
8876 varpool_node::finalize_decl (t);
8877 DECL_SAVED_TREE (child_fn) = NULL;
8878 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8879 gimple_set_body (child_fn, NULL);
8880 TREE_USED (block) = 1;
8882 /* Reset DECL_CONTEXT on function arguments. */
8883 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8884 DECL_CONTEXT (t) = child_fn;
8886 /* Split ENTRY_BB at GIMPLE_*,
8887 so that it can be moved to the child function. */
8888 gsi = gsi_last_bb (entry_bb);
8889 stmt = gsi_stmt (gsi);
8890 gcc_assert (stmt
8891 && gimple_code (stmt) == gimple_code (entry_stmt));
8892 gsi_remove (&gsi, true);
8893 e = split_block (entry_bb, stmt);
8894 entry_bb = e->dest;
8895 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8897 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8898 if (exit_bb)
8900 gsi = gsi_last_bb (exit_bb);
8901 gcc_assert (!gsi_end_p (gsi)
8902 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8903 stmt = gimple_build_return (NULL);
8904 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8905 gsi_remove (&gsi, true);
8908 /* Move the offloading region into CHILD_CFUN. */
8910 block = gimple_block (entry_stmt);
8912 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8913 if (exit_bb)
8914 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8915 /* When the OMP expansion process cannot guarantee an up-to-date
8916 loop tree arrange for the child function to fixup loops. */
8917 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8918 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8920 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8921 num = vec_safe_length (child_cfun->local_decls);
8922 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8924 t = (*child_cfun->local_decls)[srcidx];
8925 if (DECL_CONTEXT (t) == cfun->decl)
8926 continue;
8927 if (srcidx != dstidx)
8928 (*child_cfun->local_decls)[dstidx] = t;
8929 dstidx++;
8931 if (dstidx != num)
8932 vec_safe_truncate (child_cfun->local_decls, dstidx);
8934 /* Inform the callgraph about the new function. */
8935 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8936 cgraph_node::add_new_function (child_fn, true);
8938 #ifdef ENABLE_OFFLOADING
8939 /* Add the new function to the offload table. */
8940 vec_safe_push (offload_funcs, child_fn);
8941 #endif
8943 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8944 fixed in a following pass. */
8945 push_cfun (child_cfun);
8946 cgraph_edge::rebuild_edges ();
8948 #ifdef ENABLE_OFFLOADING
8949 /* Prevent IPA from removing child_fn as unreachable, since there are no
8950 refs from the parent function to child_fn in offload LTO mode. */
8951 struct cgraph_node *node = cgraph_node::get (child_fn);
8952 node->mark_force_output ();
8953 #endif
8955 /* Some EH regions might become dead, see PR34608. If
8956 pass_cleanup_cfg isn't the first pass to happen with the
8957 new child, these dead EH edges might cause problems.
8958 Clean them up now. */
8959 if (flag_exceptions)
8961 basic_block bb;
8962 bool changed = false;
8964 FOR_EACH_BB_FN (bb, cfun)
8965 changed |= gimple_purge_dead_eh_edges (bb);
8966 if (changed)
8967 cleanup_tree_cfg ();
8969 pop_cfun ();
8972 /* Emit a library call to launch the offloading region, or do data
8973 transfers. */
8974 tree t1, t2, t3, t4, device, cond, c, clauses;
8975 enum built_in_function start_ix;
8976 location_t clause_loc;
8978 switch (gimple_omp_target_kind (entry_stmt))
8980 case GF_OMP_TARGET_KIND_REGION:
8981 start_ix = BUILT_IN_GOMP_TARGET;
8982 break;
8983 case GF_OMP_TARGET_KIND_DATA:
8984 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8985 break;
8986 case GF_OMP_TARGET_KIND_UPDATE:
8987 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8988 break;
8989 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8990 start_ix = BUILT_IN_GOACC_PARALLEL;
8991 break;
8992 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8993 start_ix = BUILT_IN_GOACC_KERNELS;
8994 break;
8995 case GF_OMP_TARGET_KIND_OACC_DATA:
8996 start_ix = BUILT_IN_GOACC_DATA_START;
8997 break;
8998 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8999 start_ix = BUILT_IN_GOACC_UPDATE;
9000 break;
9001 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9002 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9003 break;
9004 default:
9005 gcc_unreachable ();
9008 clauses = gimple_omp_target_clauses (entry_stmt);
9010 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9011 library choose) and there is no conditional. */
9012 cond = NULL_TREE;
9013 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
9015 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9016 if (c)
9017 cond = OMP_CLAUSE_IF_EXPR (c);
9019 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9020 if (c)
9022 /* Even if we pass it to all library function calls, it is currently only
9023 defined/used for the OpenMP target ones. */
9024 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9025 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9026 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9028 device = OMP_CLAUSE_DEVICE_ID (c);
9029 clause_loc = OMP_CLAUSE_LOCATION (c);
9031 else
9032 clause_loc = gimple_location (entry_stmt);
9034 /* Ensure 'device' is of the correct type. */
9035 device = fold_convert_loc (clause_loc, integer_type_node, device);
9037 /* If we found the clause 'if (cond)', build
9038 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9039 if (cond)
9041 cond = gimple_boolify (cond);
9043 basic_block cond_bb, then_bb, else_bb;
9044 edge e;
9045 tree tmp_var;
9047 tmp_var = create_tmp_var (TREE_TYPE (device));
9048 if (offloaded)
9049 e = split_block (new_bb, NULL);
9050 else
9052 gsi = gsi_last_bb (new_bb);
9053 gsi_prev (&gsi);
9054 e = split_block (new_bb, gsi_stmt (gsi));
9056 cond_bb = e->src;
9057 new_bb = e->dest;
9058 remove_edge (e);
9060 then_bb = create_empty_bb (cond_bb);
9061 else_bb = create_empty_bb (then_bb);
9062 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9063 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9065 stmt = gimple_build_cond_empty (cond);
9066 gsi = gsi_last_bb (cond_bb);
9067 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9069 gsi = gsi_start_bb (then_bb);
9070 stmt = gimple_build_assign (tmp_var, device);
9071 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9073 gsi = gsi_start_bb (else_bb);
9074 stmt = gimple_build_assign (tmp_var,
9075 build_int_cst (integer_type_node,
9076 GOMP_DEVICE_HOST_FALLBACK));
9077 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9079 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9080 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9081 add_bb_to_loop (then_bb, cond_bb->loop_father);
9082 add_bb_to_loop (else_bb, cond_bb->loop_father);
9083 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9084 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9086 device = tmp_var;
9089 gsi = gsi_last_bb (new_bb);
9090 t = gimple_omp_target_data_arg (entry_stmt);
9091 if (t == NULL)
9093 t1 = size_zero_node;
9094 t2 = build_zero_cst (ptr_type_node);
9095 t3 = t2;
9096 t4 = t2;
9098 else
9100 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9101 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9102 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9103 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9104 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9107 gimple g;
9108 tree offload_table = get_offload_symbol_decl ();
9109 vec<tree> *args;
9110 /* The maximum number used by any start_ix, without varargs. */
9111 unsigned int argcnt = 12;
9113 vec_alloc (args, argcnt);
9114 args->quick_push (device);
9115 if (offloaded)
9116 args->quick_push (build_fold_addr_expr (child_fn));
9117 args->quick_push (build_fold_addr_expr (offload_table));
9118 args->quick_push (t1);
9119 args->quick_push (t2);
9120 args->quick_push (t3);
9121 args->quick_push (t4);
9122 switch (start_ix)
9124 case BUILT_IN_GOACC_DATA_START:
9125 case BUILT_IN_GOMP_TARGET:
9126 case BUILT_IN_GOMP_TARGET_DATA:
9127 case BUILT_IN_GOMP_TARGET_UPDATE:
9128 break;
9129 case BUILT_IN_GOACC_KERNELS:
9130 case BUILT_IN_GOACC_PARALLEL:
9132 tree t_num_gangs, t_num_workers, t_vector_length;
9134 /* Default values for num_gangs, num_workers, and vector_length. */
9135 t_num_gangs = t_num_workers = t_vector_length
9136 = fold_convert_loc (gimple_location (entry_stmt),
9137 integer_type_node, integer_one_node);
9138 /* ..., but if present, use the value specified by the respective
9139 clause, making sure that are of the correct type. */
9140 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9141 if (c)
9142 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9143 integer_type_node,
9144 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9145 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9146 if (c)
9147 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9148 integer_type_node,
9149 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9150 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9151 if (c)
9152 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9153 integer_type_node,
9154 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9155 args->quick_push (t_num_gangs);
9156 args->quick_push (t_num_workers);
9157 args->quick_push (t_vector_length);
9159 /* FALLTHRU */
9160 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9161 case BUILT_IN_GOACC_UPDATE:
9163 tree t_async;
9164 int t_wait_idx;
9166 /* Default values for t_async. */
9167 t_async = fold_convert_loc (gimple_location (entry_stmt),
9168 integer_type_node,
9169 build_int_cst (integer_type_node,
9170 GOMP_ASYNC_SYNC));
9171 /* ..., but if present, use the value specified by the respective
9172 clause, making sure that is of the correct type. */
9173 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9174 if (c)
9175 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9176 integer_type_node,
9177 OMP_CLAUSE_ASYNC_EXPR (c));
9179 args->quick_push (t_async);
9180 /* Save the index, and... */
9181 t_wait_idx = args->length ();
9182 /* ... push a default value. */
9183 args->quick_push (fold_convert_loc (gimple_location (entry_stmt),
9184 integer_type_node,
9185 integer_zero_node));
9186 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9187 if (c)
9189 int n = 0;
9191 for (; c; c = OMP_CLAUSE_CHAIN (c))
9193 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9195 args->safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9196 integer_type_node,
9197 OMP_CLAUSE_WAIT_EXPR (c)));
9198 n++;
9202 /* Now that we know the number, replace the default value. */
9203 args->ordered_remove (t_wait_idx);
9204 args->quick_insert (t_wait_idx,
9205 fold_convert_loc (gimple_location (entry_stmt),
9206 integer_type_node,
9207 build_int_cst (integer_type_node, n)));
9210 break;
9211 default:
9212 gcc_unreachable ();
9215 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), *args);
9216 args->release ();
9217 gimple_set_location (g, gimple_location (entry_stmt));
9218 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9219 if (!offloaded)
9221 g = gsi_stmt (gsi);
9222 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9223 gsi_remove (&gsi, true);
9225 if (data_region
9226 && region->exit)
9228 gsi = gsi_last_bb (region->exit);
9229 g = gsi_stmt (gsi);
9230 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9231 gsi_remove (&gsi, true);
9236 /* Expand the parallel region tree rooted at REGION. Expansion
9237 proceeds in depth-first order. Innermost regions are expanded
9238 first. This way, parallel regions that require a new function to
9239 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9240 internal dependencies in their body. */
9242 static void
9243 expand_omp (struct omp_region *region)
9245 while (region)
9247 location_t saved_location;
9248 gimple inner_stmt = NULL;
9250 /* First, determine whether this is a combined parallel+workshare
9251 region. */
9252 if (region->type == GIMPLE_OMP_PARALLEL)
9253 determine_parallel_type (region);
9255 if (region->type == GIMPLE_OMP_FOR
9256 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9257 inner_stmt = last_stmt (region->inner->entry);
9259 if (region->inner)
9260 expand_omp (region->inner);
9262 saved_location = input_location;
9263 if (gimple_has_location (last_stmt (region->entry)))
9264 input_location = gimple_location (last_stmt (region->entry));
9266 switch (region->type)
9268 case GIMPLE_OMP_PARALLEL:
9269 case GIMPLE_OMP_TASK:
9270 expand_omp_taskreg (region);
9271 break;
9273 case GIMPLE_OMP_FOR:
9274 expand_omp_for (region, inner_stmt);
9275 break;
9277 case GIMPLE_OMP_SECTIONS:
9278 expand_omp_sections (region);
9279 break;
9281 case GIMPLE_OMP_SECTION:
9282 /* Individual omp sections are handled together with their
9283 parent GIMPLE_OMP_SECTIONS region. */
9284 break;
9286 case GIMPLE_OMP_SINGLE:
9287 expand_omp_single (region);
9288 break;
9290 case GIMPLE_OMP_MASTER:
9291 case GIMPLE_OMP_TASKGROUP:
9292 case GIMPLE_OMP_ORDERED:
9293 case GIMPLE_OMP_CRITICAL:
9294 case GIMPLE_OMP_TEAMS:
9295 expand_omp_synch (region);
9296 break;
9298 case GIMPLE_OMP_ATOMIC_LOAD:
9299 expand_omp_atomic (region);
9300 break;
9302 case GIMPLE_OMP_TARGET:
9303 expand_omp_target (region);
9304 break;
9306 default:
9307 gcc_unreachable ();
9310 input_location = saved_location;
9311 region = region->next;
9316 /* Helper for build_omp_regions. Scan the dominator tree starting at
9317 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9318 true, the function ends once a single tree is built (otherwise, whole
9319 forest of OMP constructs may be built). */
9321 static void
9322 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9323 bool single_tree)
9325 gimple_stmt_iterator gsi;
9326 gimple stmt;
9327 basic_block son;
9329 gsi = gsi_last_bb (bb);
9330 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9332 struct omp_region *region;
9333 enum gimple_code code;
9335 stmt = gsi_stmt (gsi);
9336 code = gimple_code (stmt);
9337 if (code == GIMPLE_OMP_RETURN)
9339 /* STMT is the return point out of region PARENT. Mark it
9340 as the exit point and make PARENT the immediately
9341 enclosing region. */
9342 gcc_assert (parent);
9343 region = parent;
9344 region->exit = bb;
9345 parent = parent->outer;
9347 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9349 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9350 GIMPLE_OMP_RETURN, but matches with
9351 GIMPLE_OMP_ATOMIC_LOAD. */
9352 gcc_assert (parent);
9353 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9354 region = parent;
9355 region->exit = bb;
9356 parent = parent->outer;
9358 else if (code == GIMPLE_OMP_CONTINUE)
9360 gcc_assert (parent);
9361 parent->cont = bb;
9363 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9365 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9366 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9368 else
9370 region = new_omp_region (bb, code, parent);
9371 /* Otherwise... */
9372 if (code == GIMPLE_OMP_TARGET)
9374 switch (gimple_omp_target_kind (stmt))
9376 case GF_OMP_TARGET_KIND_REGION:
9377 case GF_OMP_TARGET_KIND_DATA:
9378 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9379 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9380 case GF_OMP_TARGET_KIND_OACC_DATA:
9381 break;
9382 case GF_OMP_TARGET_KIND_UPDATE:
9383 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9384 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9385 /* ..., other than for those stand-alone directives... */
9386 region = NULL;
9387 break;
9388 default:
9389 gcc_unreachable ();
9392 /* ..., this directive becomes the parent for a new region. */
9393 if (region)
9394 parent = region;
9398 if (single_tree && !parent)
9399 return;
9401 for (son = first_dom_son (CDI_DOMINATORS, bb);
9402 son;
9403 son = next_dom_son (CDI_DOMINATORS, son))
9404 build_omp_regions_1 (son, parent, single_tree);
9407 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9408 root_omp_region. */
9410 static void
9411 build_omp_regions_root (basic_block root)
9413 gcc_assert (root_omp_region == NULL);
9414 build_omp_regions_1 (root, NULL, true);
9415 gcc_assert (root_omp_region != NULL);
9418 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9420 void
9421 omp_expand_local (basic_block head)
9423 build_omp_regions_root (head);
9424 if (dump_file && (dump_flags & TDF_DETAILS))
9426 fprintf (dump_file, "\nOMP region tree\n\n");
9427 dump_omp_region (dump_file, root_omp_region, 0);
9428 fprintf (dump_file, "\n");
9431 remove_exit_barriers (root_omp_region);
9432 expand_omp (root_omp_region);
9434 free_omp_regions ();
9437 /* Scan the CFG and build a tree of OMP regions. Return the root of
9438 the OMP region tree. */
9440 static void
9441 build_omp_regions (void)
9443 gcc_assert (root_omp_region == NULL);
9444 calculate_dominance_info (CDI_DOMINATORS);
9445 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9448 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9450 static unsigned int
9451 execute_expand_omp (void)
9453 build_omp_regions ();
9455 if (!root_omp_region)
9456 return 0;
9458 if (dump_file)
9460 fprintf (dump_file, "\nOMP region tree\n\n");
9461 dump_omp_region (dump_file, root_omp_region, 0);
9462 fprintf (dump_file, "\n");
9465 remove_exit_barriers (root_omp_region);
9467 expand_omp (root_omp_region);
9469 cleanup_tree_cfg ();
9471 free_omp_regions ();
9473 return 0;
9476 /* OMP expansion -- the default pass, run before creation of SSA form. */
9478 namespace {
9480 const pass_data pass_data_expand_omp =
9482 GIMPLE_PASS, /* type */
9483 "ompexp", /* name */
9484 OPTGROUP_NONE, /* optinfo_flags */
9485 TV_NONE, /* tv_id */
9486 PROP_gimple_any, /* properties_required */
9487 PROP_gimple_eomp, /* properties_provided */
9488 0, /* properties_destroyed */
9489 0, /* todo_flags_start */
9490 0, /* todo_flags_finish */
9493 class pass_expand_omp : public gimple_opt_pass
9495 public:
9496 pass_expand_omp (gcc::context *ctxt)
9497 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9500 /* opt_pass methods: */
9501 virtual unsigned int execute (function *)
9503 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9504 || flag_openmp_simd != 0)
9505 && !seen_error ());
9507 /* This pass always runs, to provide PROP_gimple_eomp.
9508 But often, there is nothing to do. */
9509 if (!gate)
9510 return 0;
9512 return execute_expand_omp ();
9515 }; // class pass_expand_omp
9517 } // anon namespace
9519 gimple_opt_pass *
9520 make_pass_expand_omp (gcc::context *ctxt)
9522 return new pass_expand_omp (ctxt);
9525 namespace {
9527 const pass_data pass_data_expand_omp_ssa =
9529 GIMPLE_PASS, /* type */
9530 "ompexpssa", /* name */
9531 OPTGROUP_NONE, /* optinfo_flags */
9532 TV_NONE, /* tv_id */
9533 PROP_cfg | PROP_ssa, /* properties_required */
9534 PROP_gimple_eomp, /* properties_provided */
9535 0, /* properties_destroyed */
9536 0, /* todo_flags_start */
9537 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9540 class pass_expand_omp_ssa : public gimple_opt_pass
9542 public:
9543 pass_expand_omp_ssa (gcc::context *ctxt)
9544 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9547 /* opt_pass methods: */
9548 virtual bool gate (function *fun)
9550 return !(fun->curr_properties & PROP_gimple_eomp);
9552 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9554 }; // class pass_expand_omp_ssa
9556 } // anon namespace
9558 gimple_opt_pass *
9559 make_pass_expand_omp_ssa (gcc::context *ctxt)
9561 return new pass_expand_omp_ssa (ctxt);
9564 /* Routines to lower OMP directives into OMP-GIMPLE. */
9566 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9567 convert it to gimple. */
9568 static void
9569 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9571 gimple stmt;
9573 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9575 stmt = gimple_build_assign (dest, op, dest, src);
9576 gimple_seq_add_stmt (seq, stmt);
9577 return;
9580 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9581 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9582 gimplify_assign (t, rdest, seq);
9583 rdest = t;
9585 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9586 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9587 gimplify_assign (t, idest, seq);
9588 idest = t;
9590 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9591 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9592 gimplify_assign (t, rsrc, seq);
9593 rsrc = t;
9595 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9596 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9597 gimplify_assign (t, isrc, seq);
9598 isrc = t;
9600 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9601 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9602 tree result;
9604 if (op == PLUS_EXPR)
9606 stmt = gimple_build_assign (r, op, rdest, rsrc);
9607 gimple_seq_add_stmt (seq, stmt);
9609 stmt = gimple_build_assign (i, op, idest, isrc);
9610 gimple_seq_add_stmt (seq, stmt);
9612 else if (op == MULT_EXPR)
9614 /* Let x = a + ib = dest, y = c + id = src.
9615 x * y = (ac - bd) + i(ad + bc) */
9616 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9617 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9618 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9619 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9621 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9622 gimple_seq_add_stmt (seq, stmt);
9624 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9625 gimple_seq_add_stmt (seq, stmt);
9627 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9628 gimple_seq_add_stmt (seq, stmt);
9630 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9631 gimple_seq_add_stmt (seq, stmt);
9633 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9634 gimple_seq_add_stmt (seq, stmt);
9636 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9637 gimple_seq_add_stmt (seq, stmt);
9639 else
9640 gcc_unreachable ();
9642 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9643 gimplify_assign (dest, result, seq);
9646 /* Helper function to initialize local data for the reduction arrays.
9647 The reduction arrays need to be placed inside the calling function
9648 for accelerators, or else the host won't be able to preform the final
9649 reduction. */
9651 static void
9652 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9653 gimple_seq *stmt_seqp, omp_context *ctx)
9655 tree c, t, oc;
9656 gimple stmt;
9657 omp_context *octx;
9659 /* Find the innermost OpenACC parallel context. */
9660 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9661 && (gimple_omp_target_kind (ctx->stmt)
9662 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9663 octx = ctx;
9664 else
9665 octx = ctx->outer;
9666 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9667 && (gimple_omp_target_kind (octx->stmt)
9668 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9670 /* Extract the clauses. */
9671 oc = gimple_omp_target_clauses (octx->stmt);
9673 /* Find the last outer clause. */
9674 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9677 /* Allocate arrays for each reduction variable. */
9678 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9680 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9681 continue;
9683 tree var = OMP_CLAUSE_DECL (c);
9684 tree type = get_base_type (var);
9685 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9686 ctx);
9687 tree size, call;
9689 /* Calculate size of the reduction array. */
9690 t = create_tmp_var (TREE_TYPE (nthreads));
9691 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9692 fold_convert (TREE_TYPE (nthreads),
9693 TYPE_SIZE_UNIT (type)));
9694 gimple_seq_add_stmt (stmt_seqp, stmt);
9696 size = create_tmp_var (sizetype);
9697 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9699 /* Now allocate memory for it. */
9700 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9701 stmt = gimple_build_call (call, 1, size);
9702 gimple_call_set_lhs (stmt, array);
9703 gimple_seq_add_stmt (stmt_seqp, stmt);
9705 /* Map this array into the accelerator. */
9707 /* Add the reduction array to the list of clauses. */
9708 tree x = array;
9709 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9710 OMP_CLAUSE_MAP_KIND (t) = OMP_CLAUSE_MAP_FORCE_FROM;
9711 OMP_CLAUSE_DECL (t) = x;
9712 OMP_CLAUSE_CHAIN (t) = NULL;
9713 if (oc)
9714 OMP_CLAUSE_CHAIN (oc) = t;
9715 else
9716 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9717 OMP_CLAUSE_SIZE (t) = size;
9718 oc = t;
9722 /* Helper function to process the array of partial reductions. Nthreads
9723 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9724 cannot be used here, because nthreads on the host may be different than
9725 on the accelerator. */
9727 static void
9728 oacc_finalize_reduction_data (tree clauses, tree nthreads,
9729 gimple_seq *stmt_seqp, omp_context *ctx)
9731 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9732 gimple stmt;
9734 /* Create for loop.
9736 let var = the original reduction variable
9737 let array = reduction variable array
9739 for (i = 0; i < nthreads; i++)
9740 var op= array[i]
9743 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9744 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9745 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9747 /* Create and initialize an index variable. */
9748 tree ix = create_tmp_var (sizetype);
9749 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9750 stmt_seqp);
9752 /* Insert the loop header label here. */
9753 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9755 /* Exit loop if ix >= nthreads. */
9756 x = create_tmp_var (sizetype);
9757 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9758 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9759 gimple_seq_add_stmt (stmt_seqp, stmt);
9761 /* Insert the loop body label here. */
9762 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9764 /* Collapse each reduction array, one element at a time. */
9765 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9767 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9768 continue;
9770 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9772 /* reduction(-:var) sums up the partial results, so it acts
9773 identically to reduction(+:var). */
9774 if (reduction_code == MINUS_EXPR)
9775 reduction_code = PLUS_EXPR;
9777 /* Set up reduction variable var. */
9778 var = OMP_CLAUSE_DECL (c);
9779 type = get_base_type (var);
9780 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9781 (OMP_CLAUSE_DECL (c)), ctx);
9783 /* Calculate the array offset. */
9784 tree offset = create_tmp_var (sizetype);
9785 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9786 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9787 gimple_seq_add_stmt (stmt_seqp, stmt);
9789 tree ptr = create_tmp_var (TREE_TYPE (array));
9790 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9791 gimple_seq_add_stmt (stmt_seqp, stmt);
9793 /* Extract array[ix] into mem. */
9794 tree mem = create_tmp_var (type);
9795 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9797 /* Find the original reduction variable. */
9798 if (is_reference (var))
9799 var = build_simple_mem_ref (var);
9801 tree t = create_tmp_var (type);
9803 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9804 gimplify_and_add (unshare_expr(x), stmt_seqp);
9806 /* var = var op mem */
9807 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9809 case TRUTH_ANDIF_EXPR:
9810 case TRUTH_ORIF_EXPR:
9811 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9812 t, mem);
9813 gimplify_and_add (t, stmt_seqp);
9814 break;
9815 default:
9816 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9817 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9818 stmt_seqp);
9821 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9822 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9823 gimplify_and_add (unshare_expr(x), stmt_seqp);
9826 /* Increment the induction variable. */
9827 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9828 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9829 gimple_seq_add_stmt (stmt_seqp, stmt);
9831 /* Go back to the top of the loop. */
9832 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9834 /* Place the loop exit label here. */
9835 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9838 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9839 scan that for reductions. */
9841 static void
9842 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9843 gimple_seq *out_stmt_seqp, omp_context *ctx)
9845 gimple_stmt_iterator gsi;
9846 gimple_seq inner = NULL;
9848 /* A collapse clause may have inserted a new bind block. */
9849 gsi = gsi_start (*body);
9850 while (!gsi_end_p (gsi))
9852 gimple stmt = gsi_stmt (gsi);
9853 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9855 inner = gimple_bind_body (bind_stmt);
9856 body = &inner;
9857 gsi = gsi_start (*body);
9859 else if (dyn_cast <gomp_for *> (stmt))
9860 break;
9861 else
9862 gsi_next (&gsi);
9865 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9867 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9868 enter, exit;
9869 bool reduction_found = false;
9871 gimple stmt = gsi_stmt (gsi);
9873 switch (gimple_code (stmt))
9875 case GIMPLE_OMP_FOR:
9876 clauses = gimple_omp_for_clauses (stmt);
9878 /* Search for a reduction clause. */
9879 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9880 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9882 reduction_found = true;
9883 break;
9886 if (!reduction_found)
9887 break;
9889 ctx = maybe_lookup_ctx (stmt);
9890 t = NULL_TREE;
9892 /* Extract the number of threads. */
9893 nthreads = create_tmp_var (sizetype);
9894 t = oacc_max_threads (ctx);
9895 gimplify_assign (nthreads, t, in_stmt_seqp);
9897 /* Determine if this is kernel will be executed on the host. */
9898 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9899 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9900 stmt = gimple_build_call (call, 0);
9901 gimple_call_set_lhs (stmt, acc_device);
9902 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9904 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9905 acc_device_host = create_tmp_var (integer_type_node,
9906 ".acc_device_host");
9907 gimplify_assign (acc_device_host,
9908 build_int_cst (integer_type_node,
9909 GOMP_DEVICE_HOST),
9910 in_stmt_seqp);
9912 enter = create_artificial_label (UNKNOWN_LOCATION);
9913 exit = create_artificial_label (UNKNOWN_LOCATION);
9915 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9916 enter, exit);
9917 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9918 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9919 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9920 integer_one_node),
9921 in_stmt_seqp);
9922 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9924 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9925 gimplify_assign (acc_device_host,
9926 build_int_cst (integer_type_node,
9927 GOMP_DEVICE_HOST_NONSHM),
9928 in_stmt_seqp);
9930 enter = create_artificial_label (UNKNOWN_LOCATION);
9931 exit = create_artificial_label (UNKNOWN_LOCATION);
9933 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9934 enter, exit);
9935 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9936 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9937 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9938 integer_one_node),
9939 in_stmt_seqp);
9940 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9942 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9943 ctx);
9944 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9945 break;
9946 default:
9947 // Scan for other directives which support reduction here.
9948 break;
9953 /* If ctx is a worksharing context inside of a cancellable parallel
9954 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9955 and conditional branch to parallel's cancel_label to handle
9956 cancellation in the implicit barrier. */
9958 static void
9959 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9961 gimple omp_return = gimple_seq_last_stmt (*body);
9962 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
9963 if (gimple_omp_return_nowait_p (omp_return))
9964 return;
9965 if (ctx->outer
9966 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
9967 && ctx->outer->cancellable)
9969 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
9970 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
9971 tree lhs = create_tmp_var (c_bool_type);
9972 gimple_omp_return_set_lhs (omp_return, lhs);
9973 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
9974 gimple g = gimple_build_cond (NE_EXPR, lhs,
9975 fold_convert (c_bool_type,
9976 boolean_false_node),
9977 ctx->outer->cancel_label, fallthru_label);
9978 gimple_seq_add_stmt (body, g);
9979 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
9983 /* Lower the OpenMP sections directive in the current statement in GSI_P.
9984 CTX is the enclosing OMP context for the current statement. */
9986 static void
9987 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9989 tree block, control;
9990 gimple_stmt_iterator tgsi;
9991 gomp_sections *stmt;
9992 gimple t;
9993 gbind *new_stmt, *bind;
9994 gimple_seq ilist, dlist, olist, new_body;
9996 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
9998 push_gimplify_context ();
10000 dlist = NULL;
10001 ilist = NULL;
10002 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10003 &ilist, &dlist, ctx, NULL);
10005 new_body = gimple_omp_body (stmt);
10006 gimple_omp_set_body (stmt, NULL);
10007 tgsi = gsi_start (new_body);
10008 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10010 omp_context *sctx;
10011 gimple sec_start;
10013 sec_start = gsi_stmt (tgsi);
10014 sctx = maybe_lookup_ctx (sec_start);
10015 gcc_assert (sctx);
10017 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10018 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10019 GSI_CONTINUE_LINKING);
10020 gimple_omp_set_body (sec_start, NULL);
10022 if (gsi_one_before_end_p (tgsi))
10024 gimple_seq l = NULL;
10025 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10026 &l, ctx);
10027 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10028 gimple_omp_section_set_last (sec_start);
10031 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10032 GSI_CONTINUE_LINKING);
10035 block = make_node (BLOCK);
10036 bind = gimple_build_bind (NULL, new_body, block);
10038 olist = NULL;
10039 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10041 block = make_node (BLOCK);
10042 new_stmt = gimple_build_bind (NULL, NULL, block);
10043 gsi_replace (gsi_p, new_stmt, true);
10045 pop_gimplify_context (new_stmt);
10046 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10047 BLOCK_VARS (block) = gimple_bind_vars (bind);
10048 if (BLOCK_VARS (block))
10049 TREE_USED (block) = 1;
10051 new_body = NULL;
10052 gimple_seq_add_seq (&new_body, ilist);
10053 gimple_seq_add_stmt (&new_body, stmt);
10054 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10055 gimple_seq_add_stmt (&new_body, bind);
10057 control = create_tmp_var (unsigned_type_node, ".section");
10058 t = gimple_build_omp_continue (control, control);
10059 gimple_omp_sections_set_control (stmt, control);
10060 gimple_seq_add_stmt (&new_body, t);
10062 gimple_seq_add_seq (&new_body, olist);
10063 if (ctx->cancellable)
10064 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10065 gimple_seq_add_seq (&new_body, dlist);
10067 new_body = maybe_catch_exception (new_body);
10069 t = gimple_build_omp_return
10070 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10071 OMP_CLAUSE_NOWAIT));
10072 gimple_seq_add_stmt (&new_body, t);
10073 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10075 gimple_bind_set_body (new_stmt, new_body);
10079 /* A subroutine of lower_omp_single. Expand the simple form of
10080 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10082 if (GOMP_single_start ())
10083 BODY;
10084 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10086 FIXME. It may be better to delay expanding the logic of this until
10087 pass_expand_omp. The expanded logic may make the job more difficult
10088 to a synchronization analysis pass. */
10090 static void
10091 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10093 location_t loc = gimple_location (single_stmt);
10094 tree tlabel = create_artificial_label (loc);
10095 tree flabel = create_artificial_label (loc);
10096 gimple call, cond;
10097 tree lhs, decl;
10099 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10100 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10101 call = gimple_build_call (decl, 0);
10102 gimple_call_set_lhs (call, lhs);
10103 gimple_seq_add_stmt (pre_p, call);
10105 cond = gimple_build_cond (EQ_EXPR, lhs,
10106 fold_convert_loc (loc, TREE_TYPE (lhs),
10107 boolean_true_node),
10108 tlabel, flabel);
10109 gimple_seq_add_stmt (pre_p, cond);
10110 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10111 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10112 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10116 /* A subroutine of lower_omp_single. Expand the simple form of
10117 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10119 #pragma omp single copyprivate (a, b, c)
10121 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10124 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10126 BODY;
10127 copyout.a = a;
10128 copyout.b = b;
10129 copyout.c = c;
10130 GOMP_single_copy_end (&copyout);
10132 else
10134 a = copyout_p->a;
10135 b = copyout_p->b;
10136 c = copyout_p->c;
10138 GOMP_barrier ();
10141 FIXME. It may be better to delay expanding the logic of this until
10142 pass_expand_omp. The expanded logic may make the job more difficult
10143 to a synchronization analysis pass. */
10145 static void
10146 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10147 omp_context *ctx)
10149 tree ptr_type, t, l0, l1, l2, bfn_decl;
10150 gimple_seq copyin_seq;
10151 location_t loc = gimple_location (single_stmt);
10153 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10155 ptr_type = build_pointer_type (ctx->record_type);
10156 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10158 l0 = create_artificial_label (loc);
10159 l1 = create_artificial_label (loc);
10160 l2 = create_artificial_label (loc);
10162 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10163 t = build_call_expr_loc (loc, bfn_decl, 0);
10164 t = fold_convert_loc (loc, ptr_type, t);
10165 gimplify_assign (ctx->receiver_decl, t, pre_p);
10167 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10168 build_int_cst (ptr_type, 0));
10169 t = build3 (COND_EXPR, void_type_node, t,
10170 build_and_jump (&l0), build_and_jump (&l1));
10171 gimplify_and_add (t, pre_p);
10173 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10175 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10177 copyin_seq = NULL;
10178 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10179 &copyin_seq, ctx);
10181 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10182 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10183 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10184 gimplify_and_add (t, pre_p);
10186 t = build_and_jump (&l2);
10187 gimplify_and_add (t, pre_p);
10189 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10191 gimple_seq_add_seq (pre_p, copyin_seq);
10193 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10197 /* Expand code for an OpenMP single directive. */
10199 static void
10200 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10202 tree block;
10203 gimple t;
10204 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10205 gbind *bind;
10206 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10208 push_gimplify_context ();
10210 block = make_node (BLOCK);
10211 bind = gimple_build_bind (NULL, NULL, block);
10212 gsi_replace (gsi_p, bind, true);
10213 bind_body = NULL;
10214 dlist = NULL;
10215 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10216 &bind_body, &dlist, ctx, NULL);
10217 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10219 gimple_seq_add_stmt (&bind_body, single_stmt);
10221 if (ctx->record_type)
10222 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10223 else
10224 lower_omp_single_simple (single_stmt, &bind_body);
10226 gimple_omp_set_body (single_stmt, NULL);
10228 gimple_seq_add_seq (&bind_body, dlist);
10230 bind_body = maybe_catch_exception (bind_body);
10232 t = gimple_build_omp_return
10233 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10234 OMP_CLAUSE_NOWAIT));
10235 gimple_seq_add_stmt (&bind_body_tail, t);
10236 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10237 if (ctx->record_type)
10239 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10240 tree clobber = build_constructor (ctx->record_type, NULL);
10241 TREE_THIS_VOLATILE (clobber) = 1;
10242 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10243 clobber), GSI_SAME_STMT);
10245 gimple_seq_add_seq (&bind_body, bind_body_tail);
10246 gimple_bind_set_body (bind, bind_body);
10248 pop_gimplify_context (bind);
10250 gimple_bind_append_vars (bind, ctx->block_vars);
10251 BLOCK_VARS (block) = ctx->block_vars;
10252 if (BLOCK_VARS (block))
10253 TREE_USED (block) = 1;
10257 /* Expand code for an OpenMP master directive. */
10259 static void
10260 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10262 tree block, lab = NULL, x, bfn_decl;
10263 gimple stmt = gsi_stmt (*gsi_p);
10264 gbind *bind;
10265 location_t loc = gimple_location (stmt);
10266 gimple_seq tseq;
10268 push_gimplify_context ();
10270 block = make_node (BLOCK);
10271 bind = gimple_build_bind (NULL, NULL, block);
10272 gsi_replace (gsi_p, bind, true);
10273 gimple_bind_add_stmt (bind, stmt);
10275 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10276 x = build_call_expr_loc (loc, bfn_decl, 0);
10277 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10278 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10279 tseq = NULL;
10280 gimplify_and_add (x, &tseq);
10281 gimple_bind_add_seq (bind, tseq);
10283 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10284 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10285 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10286 gimple_omp_set_body (stmt, NULL);
10288 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10290 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10292 pop_gimplify_context (bind);
10294 gimple_bind_append_vars (bind, ctx->block_vars);
10295 BLOCK_VARS (block) = ctx->block_vars;
10299 /* Expand code for an OpenMP taskgroup directive. */
10301 static void
10302 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10304 gimple stmt = gsi_stmt (*gsi_p);
10305 gcall *x;
10306 gbind *bind;
10307 tree block = make_node (BLOCK);
10309 bind = gimple_build_bind (NULL, NULL, block);
10310 gsi_replace (gsi_p, bind, true);
10311 gimple_bind_add_stmt (bind, stmt);
10313 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10315 gimple_bind_add_stmt (bind, x);
10317 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10318 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10319 gimple_omp_set_body (stmt, NULL);
10321 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10323 gimple_bind_append_vars (bind, ctx->block_vars);
10324 BLOCK_VARS (block) = ctx->block_vars;
10328 /* Expand code for an OpenMP ordered directive. */
10330 static void
10331 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10333 tree block;
10334 gimple stmt = gsi_stmt (*gsi_p);
10335 gcall *x;
10336 gbind *bind;
10338 push_gimplify_context ();
10340 block = make_node (BLOCK);
10341 bind = gimple_build_bind (NULL, NULL, block);
10342 gsi_replace (gsi_p, bind, true);
10343 gimple_bind_add_stmt (bind, stmt);
10345 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10347 gimple_bind_add_stmt (bind, x);
10349 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10350 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10351 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10352 gimple_omp_set_body (stmt, NULL);
10354 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10355 gimple_bind_add_stmt (bind, x);
10357 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10359 pop_gimplify_context (bind);
10361 gimple_bind_append_vars (bind, ctx->block_vars);
10362 BLOCK_VARS (block) = gimple_bind_vars (bind);
10366 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10367 substitution of a couple of function calls. But in the NAMED case,
10368 requires that languages coordinate a symbol name. It is therefore
10369 best put here in common code. */
10371 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10373 static void
10374 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10376 tree block;
10377 tree name, lock, unlock;
10378 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10379 gbind *bind;
10380 location_t loc = gimple_location (stmt);
10381 gimple_seq tbody;
10383 name = gimple_omp_critical_name (stmt);
10384 if (name)
10386 tree decl;
10388 if (!critical_name_mutexes)
10389 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10391 tree *n = critical_name_mutexes->get (name);
10392 if (n == NULL)
10394 char *new_str;
10396 decl = create_tmp_var_raw (ptr_type_node);
10398 new_str = ACONCAT ((".gomp_critical_user_",
10399 IDENTIFIER_POINTER (name), NULL));
10400 DECL_NAME (decl) = get_identifier (new_str);
10401 TREE_PUBLIC (decl) = 1;
10402 TREE_STATIC (decl) = 1;
10403 DECL_COMMON (decl) = 1;
10404 DECL_ARTIFICIAL (decl) = 1;
10405 DECL_IGNORED_P (decl) = 1;
10407 varpool_node::finalize_decl (decl);
10409 critical_name_mutexes->put (name, decl);
10411 else
10412 decl = *n;
10414 /* If '#pragma omp critical' is inside offloaded region or
10415 inside function marked as offloadable, the symbol must be
10416 marked as offloadable too. */
10417 omp_context *octx;
10418 if (cgraph_node::get (current_function_decl)->offloadable)
10419 varpool_node::get_create (decl)->offloadable = 1;
10420 else
10421 for (octx = ctx->outer; octx; octx = octx->outer)
10422 if (is_gimple_omp_offloaded (octx->stmt))
10424 varpool_node::get_create (decl)->offloadable = 1;
10425 break;
10428 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10429 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10431 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10432 unlock = build_call_expr_loc (loc, unlock, 1,
10433 build_fold_addr_expr_loc (loc, decl));
10435 else
10437 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10438 lock = build_call_expr_loc (loc, lock, 0);
10440 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10441 unlock = build_call_expr_loc (loc, unlock, 0);
10444 push_gimplify_context ();
10446 block = make_node (BLOCK);
10447 bind = gimple_build_bind (NULL, NULL, block);
10448 gsi_replace (gsi_p, bind, true);
10449 gimple_bind_add_stmt (bind, stmt);
10451 tbody = gimple_bind_body (bind);
10452 gimplify_and_add (lock, &tbody);
10453 gimple_bind_set_body (bind, tbody);
10455 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10456 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10457 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10458 gimple_omp_set_body (stmt, NULL);
10460 tbody = gimple_bind_body (bind);
10461 gimplify_and_add (unlock, &tbody);
10462 gimple_bind_set_body (bind, tbody);
10464 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10466 pop_gimplify_context (bind);
10467 gimple_bind_append_vars (bind, ctx->block_vars);
10468 BLOCK_VARS (block) = gimple_bind_vars (bind);
10472 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10473 for a lastprivate clause. Given a loop control predicate of (V
10474 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10475 is appended to *DLIST, iterator initialization is appended to
10476 *BODY_P. */
10478 static void
10479 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10480 gimple_seq *dlist, struct omp_context *ctx)
10482 tree clauses, cond, vinit;
10483 enum tree_code cond_code;
10484 gimple_seq stmts;
10486 cond_code = fd->loop.cond_code;
10487 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10489 /* When possible, use a strict equality expression. This can let VRP
10490 type optimizations deduce the value and remove a copy. */
10491 if (tree_fits_shwi_p (fd->loop.step))
10493 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10494 if (step == 1 || step == -1)
10495 cond_code = EQ_EXPR;
10498 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
10500 clauses = gimple_omp_for_clauses (fd->for_stmt);
10501 stmts = NULL;
10502 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10503 if (!gimple_seq_empty_p (stmts))
10505 gimple_seq_add_seq (&stmts, *dlist);
10506 *dlist = stmts;
10508 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10509 vinit = fd->loop.n1;
10510 if (cond_code == EQ_EXPR
10511 && tree_fits_shwi_p (fd->loop.n2)
10512 && ! integer_zerop (fd->loop.n2))
10513 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10514 else
10515 vinit = unshare_expr (vinit);
10517 /* Initialize the iterator variable, so that threads that don't execute
10518 any iterations don't execute the lastprivate clauses by accident. */
10519 gimplify_assign (fd->loop.v, vinit, body_p);
10524 /* Lower code for an OMP loop directive. */
10526 static void
10527 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10529 tree *rhs_p, block;
10530 struct omp_for_data fd, *fdp = NULL;
10531 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10532 gbind *new_stmt;
10533 gimple_seq omp_for_body, body, dlist;
10534 size_t i;
10536 push_gimplify_context ();
10538 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10540 block = make_node (BLOCK);
10541 new_stmt = gimple_build_bind (NULL, NULL, block);
10542 /* Replace at gsi right away, so that 'stmt' is no member
10543 of a sequence anymore as we're going to add to to a different
10544 one below. */
10545 gsi_replace (gsi_p, new_stmt, true);
10547 /* Move declaration of temporaries in the loop body before we make
10548 it go away. */
10549 omp_for_body = gimple_omp_body (stmt);
10550 if (!gimple_seq_empty_p (omp_for_body)
10551 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10553 gbind *inner_bind
10554 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10555 tree vars = gimple_bind_vars (inner_bind);
10556 gimple_bind_append_vars (new_stmt, vars);
10557 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10558 keep them on the inner_bind and it's block. */
10559 gimple_bind_set_vars (inner_bind, NULL_TREE);
10560 if (gimple_bind_block (inner_bind))
10561 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10564 if (gimple_omp_for_combined_into_p (stmt))
10566 extract_omp_for_data (stmt, &fd, NULL);
10567 fdp = &fd;
10569 /* We need two temporaries with fd.loop.v type (istart/iend)
10570 and then (fd.collapse - 1) temporaries with the same
10571 type for count2 ... countN-1 vars if not constant. */
10572 size_t count = 2;
10573 tree type = fd.iter_type;
10574 if (fd.collapse > 1
10575 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10576 count += fd.collapse - 1;
10577 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10578 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10579 tree clauses = *pc;
10580 if (parallel_for)
10581 outerc
10582 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10583 OMP_CLAUSE__LOOPTEMP_);
10584 for (i = 0; i < count; i++)
10586 tree temp;
10587 if (parallel_for)
10589 gcc_assert (outerc);
10590 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10591 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10592 OMP_CLAUSE__LOOPTEMP_);
10594 else
10596 temp = create_tmp_var (type);
10597 insert_decl_map (&ctx->outer->cb, temp, temp);
10599 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10600 OMP_CLAUSE_DECL (*pc) = temp;
10601 pc = &OMP_CLAUSE_CHAIN (*pc);
10603 *pc = clauses;
10606 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10607 dlist = NULL;
10608 body = NULL;
10609 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10610 fdp);
10611 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10613 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10615 /* Lower the header expressions. At this point, we can assume that
10616 the header is of the form:
10618 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10620 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10621 using the .omp_data_s mapping, if needed. */
10622 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10624 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10625 if (!is_gimple_min_invariant (*rhs_p))
10626 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10628 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10629 if (!is_gimple_min_invariant (*rhs_p))
10630 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10632 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10633 if (!is_gimple_min_invariant (*rhs_p))
10634 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10637 /* Once lowered, extract the bounds and clauses. */
10638 extract_omp_for_data (stmt, &fd, NULL);
10640 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10642 gimple_seq_add_stmt (&body, stmt);
10643 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10645 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10646 fd.loop.v));
10648 /* After the loop, add exit clauses. */
10649 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10651 if (ctx->cancellable)
10652 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10654 gimple_seq_add_seq (&body, dlist);
10656 body = maybe_catch_exception (body);
10658 /* Region exit marker goes at the end of the loop body. */
10659 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10660 maybe_add_implicit_barrier_cancel (ctx, &body);
10661 pop_gimplify_context (new_stmt);
10663 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10664 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10665 if (BLOCK_VARS (block))
10666 TREE_USED (block) = 1;
10668 gimple_bind_set_body (new_stmt, body);
10669 gimple_omp_set_body (stmt, NULL);
10670 gimple_omp_for_set_pre_body (stmt, NULL);
10673 /* Callback for walk_stmts. Check if the current statement only contains
10674 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10676 static tree
10677 check_combined_parallel (gimple_stmt_iterator *gsi_p,
10678 bool *handled_ops_p,
10679 struct walk_stmt_info *wi)
10681 int *info = (int *) wi->info;
10682 gimple stmt = gsi_stmt (*gsi_p);
10684 *handled_ops_p = true;
10685 switch (gimple_code (stmt))
10687 WALK_SUBSTMTS;
10689 case GIMPLE_OMP_FOR:
10690 case GIMPLE_OMP_SECTIONS:
10691 *info = *info == 0 ? 1 : -1;
10692 break;
10693 default:
10694 *info = -1;
10695 break;
10697 return NULL;
10700 struct omp_taskcopy_context
10702 /* This field must be at the beginning, as we do "inheritance": Some
10703 callback functions for tree-inline.c (e.g., omp_copy_decl)
10704 receive a copy_body_data pointer that is up-casted to an
10705 omp_context pointer. */
10706 copy_body_data cb;
10707 omp_context *ctx;
10710 static tree
10711 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10713 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10715 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10716 return create_tmp_var (TREE_TYPE (var));
10718 return var;
10721 static tree
10722 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10724 tree name, new_fields = NULL, type, f;
10726 type = lang_hooks.types.make_type (RECORD_TYPE);
10727 name = DECL_NAME (TYPE_NAME (orig_type));
10728 name = build_decl (gimple_location (tcctx->ctx->stmt),
10729 TYPE_DECL, name, type);
10730 TYPE_NAME (type) = name;
10732 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10734 tree new_f = copy_node (f);
10735 DECL_CONTEXT (new_f) = type;
10736 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10737 TREE_CHAIN (new_f) = new_fields;
10738 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10739 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10740 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10741 &tcctx->cb, NULL);
10742 new_fields = new_f;
10743 tcctx->cb.decl_map->put (f, new_f);
10745 TYPE_FIELDS (type) = nreverse (new_fields);
10746 layout_type (type);
10747 return type;
10750 /* Create task copyfn. */
10752 static void
10753 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
10755 struct function *child_cfun;
10756 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10757 tree record_type, srecord_type, bind, list;
10758 bool record_needs_remap = false, srecord_needs_remap = false;
10759 splay_tree_node n;
10760 struct omp_taskcopy_context tcctx;
10761 location_t loc = gimple_location (task_stmt);
10763 child_fn = gimple_omp_task_copy_fn (task_stmt);
10764 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10765 gcc_assert (child_cfun->cfg == NULL);
10766 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10768 /* Reset DECL_CONTEXT on function arguments. */
10769 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10770 DECL_CONTEXT (t) = child_fn;
10772 /* Populate the function. */
10773 push_gimplify_context ();
10774 push_cfun (child_cfun);
10776 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10777 TREE_SIDE_EFFECTS (bind) = 1;
10778 list = NULL;
10779 DECL_SAVED_TREE (child_fn) = bind;
10780 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10782 /* Remap src and dst argument types if needed. */
10783 record_type = ctx->record_type;
10784 srecord_type = ctx->srecord_type;
10785 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10786 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10788 record_needs_remap = true;
10789 break;
10791 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10792 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10794 srecord_needs_remap = true;
10795 break;
10798 if (record_needs_remap || srecord_needs_remap)
10800 memset (&tcctx, '\0', sizeof (tcctx));
10801 tcctx.cb.src_fn = ctx->cb.src_fn;
10802 tcctx.cb.dst_fn = child_fn;
10803 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
10804 gcc_checking_assert (tcctx.cb.src_node);
10805 tcctx.cb.dst_node = tcctx.cb.src_node;
10806 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10807 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10808 tcctx.cb.eh_lp_nr = 0;
10809 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10810 tcctx.cb.decl_map = new hash_map<tree, tree>;
10811 tcctx.ctx = ctx;
10813 if (record_needs_remap)
10814 record_type = task_copyfn_remap_type (&tcctx, record_type);
10815 if (srecord_needs_remap)
10816 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10818 else
10819 tcctx.cb.decl_map = NULL;
10821 arg = DECL_ARGUMENTS (child_fn);
10822 TREE_TYPE (arg) = build_pointer_type (record_type);
10823 sarg = DECL_CHAIN (arg);
10824 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10826 /* First pass: initialize temporaries used in record_type and srecord_type
10827 sizes and field offsets. */
10828 if (tcctx.cb.decl_map)
10829 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10830 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10832 tree *p;
10834 decl = OMP_CLAUSE_DECL (c);
10835 p = tcctx.cb.decl_map->get (decl);
10836 if (p == NULL)
10837 continue;
10838 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10839 sf = (tree) n->value;
10840 sf = *tcctx.cb.decl_map->get (sf);
10841 src = build_simple_mem_ref_loc (loc, sarg);
10842 src = omp_build_component_ref (src, sf);
10843 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10844 append_to_statement_list (t, &list);
10847 /* Second pass: copy shared var pointers and copy construct non-VLA
10848 firstprivate vars. */
10849 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10850 switch (OMP_CLAUSE_CODE (c))
10852 case OMP_CLAUSE_SHARED:
10853 decl = OMP_CLAUSE_DECL (c);
10854 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10855 if (n == NULL)
10856 break;
10857 f = (tree) n->value;
10858 if (tcctx.cb.decl_map)
10859 f = *tcctx.cb.decl_map->get (f);
10860 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10861 sf = (tree) n->value;
10862 if (tcctx.cb.decl_map)
10863 sf = *tcctx.cb.decl_map->get (sf);
10864 src = build_simple_mem_ref_loc (loc, sarg);
10865 src = omp_build_component_ref (src, sf);
10866 dst = build_simple_mem_ref_loc (loc, arg);
10867 dst = omp_build_component_ref (dst, f);
10868 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10869 append_to_statement_list (t, &list);
10870 break;
10871 case OMP_CLAUSE_FIRSTPRIVATE:
10872 decl = OMP_CLAUSE_DECL (c);
10873 if (is_variable_sized (decl))
10874 break;
10875 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10876 if (n == NULL)
10877 break;
10878 f = (tree) n->value;
10879 if (tcctx.cb.decl_map)
10880 f = *tcctx.cb.decl_map->get (f);
10881 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10882 if (n != NULL)
10884 sf = (tree) n->value;
10885 if (tcctx.cb.decl_map)
10886 sf = *tcctx.cb.decl_map->get (sf);
10887 src = build_simple_mem_ref_loc (loc, sarg);
10888 src = omp_build_component_ref (src, sf);
10889 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
10890 src = build_simple_mem_ref_loc (loc, src);
10892 else
10893 src = decl;
10894 dst = build_simple_mem_ref_loc (loc, arg);
10895 dst = omp_build_component_ref (dst, f);
10896 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10897 append_to_statement_list (t, &list);
10898 break;
10899 case OMP_CLAUSE_PRIVATE:
10900 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10901 break;
10902 decl = OMP_CLAUSE_DECL (c);
10903 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10904 f = (tree) n->value;
10905 if (tcctx.cb.decl_map)
10906 f = *tcctx.cb.decl_map->get (f);
10907 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10908 if (n != NULL)
10910 sf = (tree) n->value;
10911 if (tcctx.cb.decl_map)
10912 sf = *tcctx.cb.decl_map->get (sf);
10913 src = build_simple_mem_ref_loc (loc, sarg);
10914 src = omp_build_component_ref (src, sf);
10915 if (use_pointer_for_field (decl, NULL))
10916 src = build_simple_mem_ref_loc (loc, src);
10918 else
10919 src = decl;
10920 dst = build_simple_mem_ref_loc (loc, arg);
10921 dst = omp_build_component_ref (dst, f);
10922 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10923 append_to_statement_list (t, &list);
10924 break;
10925 default:
10926 break;
10929 /* Last pass: handle VLA firstprivates. */
10930 if (tcctx.cb.decl_map)
10931 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10932 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10934 tree ind, ptr, df;
10936 decl = OMP_CLAUSE_DECL (c);
10937 if (!is_variable_sized (decl))
10938 continue;
10939 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10940 if (n == NULL)
10941 continue;
10942 f = (tree) n->value;
10943 f = *tcctx.cb.decl_map->get (f);
10944 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10945 ind = DECL_VALUE_EXPR (decl);
10946 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10947 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10948 n = splay_tree_lookup (ctx->sfield_map,
10949 (splay_tree_key) TREE_OPERAND (ind, 0));
10950 sf = (tree) n->value;
10951 sf = *tcctx.cb.decl_map->get (sf);
10952 src = build_simple_mem_ref_loc (loc, sarg);
10953 src = omp_build_component_ref (src, sf);
10954 src = build_simple_mem_ref_loc (loc, src);
10955 dst = build_simple_mem_ref_loc (loc, arg);
10956 dst = omp_build_component_ref (dst, f);
10957 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10958 append_to_statement_list (t, &list);
10959 n = splay_tree_lookup (ctx->field_map,
10960 (splay_tree_key) TREE_OPERAND (ind, 0));
10961 df = (tree) n->value;
10962 df = *tcctx.cb.decl_map->get (df);
10963 ptr = build_simple_mem_ref_loc (loc, arg);
10964 ptr = omp_build_component_ref (ptr, df);
10965 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
10966 build_fold_addr_expr_loc (loc, dst));
10967 append_to_statement_list (t, &list);
10970 t = build1 (RETURN_EXPR, void_type_node, NULL);
10971 append_to_statement_list (t, &list);
10973 if (tcctx.cb.decl_map)
10974 delete tcctx.cb.decl_map;
10975 pop_gimplify_context (NULL);
10976 BIND_EXPR_BODY (bind) = list;
10977 pop_cfun ();
10980 static void
10981 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
10983 tree c, clauses;
10984 gimple g;
10985 size_t n_in = 0, n_out = 0, idx = 2, i;
10987 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
10988 OMP_CLAUSE_DEPEND);
10989 gcc_assert (clauses);
10990 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10991 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
10992 switch (OMP_CLAUSE_DEPEND_KIND (c))
10994 case OMP_CLAUSE_DEPEND_IN:
10995 n_in++;
10996 break;
10997 case OMP_CLAUSE_DEPEND_OUT:
10998 case OMP_CLAUSE_DEPEND_INOUT:
10999 n_out++;
11000 break;
11001 default:
11002 gcc_unreachable ();
11004 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11005 tree array = create_tmp_var (type);
11006 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11007 NULL_TREE);
11008 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11009 gimple_seq_add_stmt (iseq, g);
11010 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11011 NULL_TREE);
11012 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11013 gimple_seq_add_stmt (iseq, g);
11014 for (i = 0; i < 2; i++)
11016 if ((i ? n_in : n_out) == 0)
11017 continue;
11018 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11019 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11020 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11022 tree t = OMP_CLAUSE_DECL (c);
11023 t = fold_convert (ptr_type_node, t);
11024 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11025 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11026 NULL_TREE, NULL_TREE);
11027 g = gimple_build_assign (r, t);
11028 gimple_seq_add_stmt (iseq, g);
11031 tree *p = gimple_omp_task_clauses_ptr (stmt);
11032 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11033 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11034 OMP_CLAUSE_CHAIN (c) = *p;
11035 *p = c;
11036 tree clobber = build_constructor (type, NULL);
11037 TREE_THIS_VOLATILE (clobber) = 1;
11038 g = gimple_build_assign (array, clobber);
11039 gimple_seq_add_stmt (oseq, g);
11042 /* Lower the OpenMP parallel or task directive in the current statement
11043 in GSI_P. CTX holds context information for the directive. */
11045 static void
11046 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11048 tree clauses;
11049 tree child_fn, t;
11050 gimple stmt = gsi_stmt (*gsi_p);
11051 gbind *par_bind, *bind, *dep_bind = NULL;
11052 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11053 location_t loc = gimple_location (stmt);
11055 clauses = gimple_omp_taskreg_clauses (stmt);
11056 par_bind
11057 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11058 par_body = gimple_bind_body (par_bind);
11059 child_fn = ctx->cb.dst_fn;
11060 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11061 && !gimple_omp_parallel_combined_p (stmt))
11063 struct walk_stmt_info wi;
11064 int ws_num = 0;
11066 memset (&wi, 0, sizeof (wi));
11067 wi.info = &ws_num;
11068 wi.val_only = true;
11069 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11070 if (ws_num == 1)
11071 gimple_omp_parallel_set_combined_p (stmt, true);
11073 gimple_seq dep_ilist = NULL;
11074 gimple_seq dep_olist = NULL;
11075 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11076 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11078 push_gimplify_context ();
11079 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11080 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11083 if (ctx->srecord_type)
11084 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11086 push_gimplify_context ();
11088 par_olist = NULL;
11089 par_ilist = NULL;
11090 par_rlist = NULL;
11091 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11092 lower_omp (&par_body, ctx);
11093 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11094 lower_reduction_clauses (clauses, &par_rlist, ctx);
11096 /* Declare all the variables created by mapping and the variables
11097 declared in the scope of the parallel body. */
11098 record_vars_into (ctx->block_vars, child_fn);
11099 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11101 if (ctx->record_type)
11103 ctx->sender_decl
11104 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11105 : ctx->record_type, ".omp_data_o");
11106 DECL_NAMELESS (ctx->sender_decl) = 1;
11107 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11108 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11111 olist = NULL;
11112 ilist = NULL;
11113 lower_send_clauses (clauses, &ilist, &olist, ctx);
11114 lower_send_shared_vars (&ilist, &olist, ctx);
11116 if (ctx->record_type)
11118 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11119 TREE_THIS_VOLATILE (clobber) = 1;
11120 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11121 clobber));
11124 /* Once all the expansions are done, sequence all the different
11125 fragments inside gimple_omp_body. */
11127 new_body = NULL;
11129 if (ctx->record_type)
11131 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11132 /* fixup_child_record_type might have changed receiver_decl's type. */
11133 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11134 gimple_seq_add_stmt (&new_body,
11135 gimple_build_assign (ctx->receiver_decl, t));
11138 gimple_seq_add_seq (&new_body, par_ilist);
11139 gimple_seq_add_seq (&new_body, par_body);
11140 gimple_seq_add_seq (&new_body, par_rlist);
11141 if (ctx->cancellable)
11142 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11143 gimple_seq_add_seq (&new_body, par_olist);
11144 new_body = maybe_catch_exception (new_body);
11145 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11146 gimple_omp_set_body (stmt, new_body);
11148 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11149 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11150 gimple_bind_add_seq (bind, ilist);
11151 gimple_bind_add_stmt (bind, stmt);
11152 gimple_bind_add_seq (bind, olist);
11154 pop_gimplify_context (NULL);
11156 if (dep_bind)
11158 gimple_bind_add_seq (dep_bind, dep_ilist);
11159 gimple_bind_add_stmt (dep_bind, bind);
11160 gimple_bind_add_seq (dep_bind, dep_olist);
11161 pop_gimplify_context (dep_bind);
11165 /* Lower the GIMPLE_OMP_TARGET in the current statement
11166 in GSI_P. CTX holds context information for the directive. */
11168 static void
11169 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11171 tree clauses;
11172 tree child_fn, t, c;
11173 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11174 gbind *tgt_bind, *bind;
11175 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11176 location_t loc = gimple_location (stmt);
11177 bool offloaded, data_region;
11178 unsigned int map_cnt = 0;
11180 offloaded = is_gimple_omp_offloaded (stmt);
11181 switch (gimple_omp_target_kind (stmt))
11183 case GF_OMP_TARGET_KIND_REGION:
11184 case GF_OMP_TARGET_KIND_UPDATE:
11185 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11186 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11187 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11188 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11189 data_region = false;
11190 break;
11191 case GF_OMP_TARGET_KIND_DATA:
11192 case GF_OMP_TARGET_KIND_OACC_DATA:
11193 data_region = true;
11194 break;
11195 default:
11196 gcc_unreachable ();
11199 clauses = gimple_omp_target_clauses (stmt);
11201 tgt_bind = NULL;
11202 tgt_body = NULL;
11203 if (offloaded)
11205 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11206 tgt_body = gimple_bind_body (tgt_bind);
11208 else if (data_region)
11209 tgt_body = gimple_omp_body (stmt);
11210 child_fn = ctx->cb.dst_fn;
11212 push_gimplify_context ();
11214 irlist = NULL;
11215 orlist = NULL;
11216 if (offloaded
11217 && is_gimple_omp_oacc (stmt))
11218 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11220 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11221 switch (OMP_CLAUSE_CODE (c))
11223 tree var, x;
11225 default:
11226 break;
11227 case OMP_CLAUSE_MAP:
11228 #ifdef ENABLE_CHECKING
11229 /* First check what we're prepared to handle in the following. */
11230 switch (OMP_CLAUSE_MAP_KIND (c))
11232 case OMP_CLAUSE_MAP_ALLOC:
11233 case OMP_CLAUSE_MAP_TO:
11234 case OMP_CLAUSE_MAP_FROM:
11235 case OMP_CLAUSE_MAP_TOFROM:
11236 case OMP_CLAUSE_MAP_POINTER:
11237 case OMP_CLAUSE_MAP_TO_PSET:
11238 break;
11239 case OMP_CLAUSE_MAP_FORCE_ALLOC:
11240 case OMP_CLAUSE_MAP_FORCE_TO:
11241 case OMP_CLAUSE_MAP_FORCE_FROM:
11242 case OMP_CLAUSE_MAP_FORCE_TOFROM:
11243 case OMP_CLAUSE_MAP_FORCE_PRESENT:
11244 case OMP_CLAUSE_MAP_FORCE_DEALLOC:
11245 case OMP_CLAUSE_MAP_FORCE_DEVICEPTR:
11246 gcc_assert (is_gimple_omp_oacc (stmt));
11247 break;
11248 default:
11249 gcc_unreachable ();
11251 #endif
11252 /* FALLTHRU */
11253 case OMP_CLAUSE_TO:
11254 case OMP_CLAUSE_FROM:
11255 var = OMP_CLAUSE_DECL (c);
11256 if (!DECL_P (var))
11258 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11259 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11260 map_cnt++;
11261 continue;
11264 if (DECL_SIZE (var)
11265 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11267 tree var2 = DECL_VALUE_EXPR (var);
11268 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11269 var2 = TREE_OPERAND (var2, 0);
11270 gcc_assert (DECL_P (var2));
11271 var = var2;
11274 if (!maybe_lookup_field (var, ctx))
11275 continue;
11277 if (offloaded)
11279 x = build_receiver_ref (var, true, ctx);
11280 tree new_var = lookup_decl (var, ctx);
11281 if (OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
11282 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11283 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11284 x = build_simple_mem_ref (x);
11285 SET_DECL_VALUE_EXPR (new_var, x);
11286 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11288 map_cnt++;
11291 if (offloaded)
11293 target_nesting_level++;
11294 lower_omp (&tgt_body, ctx);
11295 target_nesting_level--;
11297 else if (data_region)
11298 lower_omp (&tgt_body, ctx);
11300 if (offloaded)
11302 /* Declare all the variables created by mapping and the variables
11303 declared in the scope of the target body. */
11304 record_vars_into (ctx->block_vars, child_fn);
11305 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11308 olist = NULL;
11309 ilist = NULL;
11310 if (ctx->record_type)
11312 ctx->sender_decl
11313 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11314 DECL_NAMELESS (ctx->sender_decl) = 1;
11315 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11316 t = make_tree_vec (3);
11317 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11318 TREE_VEC_ELT (t, 1)
11319 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11320 ".omp_data_sizes");
11321 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11322 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11323 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11324 tree tkind_type;
11325 int talign_shift;
11326 if (is_gimple_omp_oacc (stmt))
11328 tkind_type = short_unsigned_type_node;
11329 talign_shift = 8;
11331 else
11333 tkind_type = unsigned_char_type_node;
11334 talign_shift = 3;
11336 TREE_VEC_ELT (t, 2)
11337 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11338 ".omp_data_kinds");
11339 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11340 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11341 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11342 gimple_omp_target_set_data_arg (stmt, t);
11344 vec<constructor_elt, va_gc> *vsize;
11345 vec<constructor_elt, va_gc> *vkind;
11346 vec_alloc (vsize, map_cnt);
11347 vec_alloc (vkind, map_cnt);
11348 unsigned int map_idx = 0;
11350 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11351 switch (OMP_CLAUSE_CODE (c))
11353 tree ovar, nc;
11355 default:
11356 break;
11357 case OMP_CLAUSE_MAP:
11358 case OMP_CLAUSE_TO:
11359 case OMP_CLAUSE_FROM:
11360 nc = c;
11361 ovar = OMP_CLAUSE_DECL (c);
11362 if (!DECL_P (ovar))
11364 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11365 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11367 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11368 == get_base_address (ovar));
11369 nc = OMP_CLAUSE_CHAIN (c);
11370 ovar = OMP_CLAUSE_DECL (nc);
11372 else
11374 tree x = build_sender_ref (ovar, ctx);
11375 tree v
11376 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11377 gimplify_assign (x, v, &ilist);
11378 nc = NULL_TREE;
11381 else
11383 if (DECL_SIZE (ovar)
11384 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11386 tree ovar2 = DECL_VALUE_EXPR (ovar);
11387 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11388 ovar2 = TREE_OPERAND (ovar2, 0);
11389 gcc_assert (DECL_P (ovar2));
11390 ovar = ovar2;
11392 if (!maybe_lookup_field (ovar, ctx))
11393 continue;
11396 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11397 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11398 talign = DECL_ALIGN_UNIT (ovar);
11399 if (nc)
11401 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11402 tree x = build_sender_ref (ovar, ctx);
11403 if (maybe_lookup_oacc_reduction (var, ctx))
11405 gcc_checking_assert (offloaded
11406 && is_gimple_omp_oacc (stmt));
11407 gimplify_assign (x, var, &ilist);
11409 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11410 && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER
11411 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11412 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11414 gcc_assert (offloaded);
11415 tree avar
11416 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11417 mark_addressable (avar);
11418 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11419 talign = DECL_ALIGN_UNIT (avar);
11420 avar = build_fold_addr_expr (avar);
11421 gimplify_assign (x, avar, &ilist);
11423 else if (is_gimple_reg (var))
11425 gcc_assert (offloaded);
11426 tree avar = create_tmp_var (TREE_TYPE (var));
11427 mark_addressable (avar);
11428 enum omp_clause_map_kind map_kind
11429 = OMP_CLAUSE_MAP_KIND (c);
11430 if (GOMP_MAP_COPY_TO_P (map_kind)
11431 || map_kind == OMP_CLAUSE_MAP_POINTER
11432 || map_kind == OMP_CLAUSE_MAP_TO_PSET
11433 || map_kind == OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
11434 gimplify_assign (avar, var, &ilist);
11435 avar = build_fold_addr_expr (avar);
11436 gimplify_assign (x, avar, &ilist);
11437 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11438 || map_kind == OMP_CLAUSE_MAP_FORCE_DEVICEPTR)
11439 && !TYPE_READONLY (TREE_TYPE (var)))
11441 x = build_sender_ref (ovar, ctx);
11442 x = build_simple_mem_ref (x);
11443 gimplify_assign (var, x, &olist);
11446 else
11448 var = build_fold_addr_expr (var);
11449 gimplify_assign (x, var, &ilist);
11452 tree s = OMP_CLAUSE_SIZE (c);
11453 if (s == NULL_TREE)
11454 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11455 s = fold_convert (size_type_node, s);
11456 tree purpose = size_int (map_idx++);
11457 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11458 if (TREE_CODE (s) != INTEGER_CST)
11459 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11461 unsigned HOST_WIDE_INT tkind;
11462 switch (OMP_CLAUSE_CODE (c))
11464 case OMP_CLAUSE_MAP:
11465 tkind = OMP_CLAUSE_MAP_KIND (c);
11466 break;
11467 case OMP_CLAUSE_TO:
11468 tkind = OMP_CLAUSE_MAP_TO;
11469 break;
11470 case OMP_CLAUSE_FROM:
11471 tkind = OMP_CLAUSE_MAP_FROM;
11472 break;
11473 default:
11474 gcc_unreachable ();
11476 gcc_checking_assert (tkind
11477 < (HOST_WIDE_INT_C (1U) << talign_shift));
11478 talign = ceil_log2 (talign);
11479 tkind |= talign << talign_shift;
11480 gcc_checking_assert (tkind
11481 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11482 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11483 build_int_cstu (tkind_type, tkind));
11484 if (nc && nc != c)
11485 c = nc;
11488 gcc_assert (map_idx == map_cnt);
11490 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11491 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11492 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11493 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11494 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11496 gimple_seq initlist = NULL;
11497 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11498 TREE_VEC_ELT (t, 1)),
11499 &initlist, true, NULL_TREE);
11500 gimple_seq_add_seq (&ilist, initlist);
11502 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11503 NULL);
11504 TREE_THIS_VOLATILE (clobber) = 1;
11505 gimple_seq_add_stmt (&olist,
11506 gimple_build_assign (TREE_VEC_ELT (t, 1),
11507 clobber));
11510 tree clobber = build_constructor (ctx->record_type, NULL);
11511 TREE_THIS_VOLATILE (clobber) = 1;
11512 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11513 clobber));
11516 /* Once all the expansions are done, sequence all the different
11517 fragments inside gimple_omp_body. */
11519 new_body = NULL;
11521 if (offloaded
11522 && ctx->record_type)
11524 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11525 /* fixup_child_record_type might have changed receiver_decl's type. */
11526 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11527 gimple_seq_add_stmt (&new_body,
11528 gimple_build_assign (ctx->receiver_decl, t));
11531 if (offloaded)
11533 gimple_seq_add_seq (&new_body, tgt_body);
11534 new_body = maybe_catch_exception (new_body);
11536 else if (data_region)
11537 new_body = tgt_body;
11538 if (offloaded || data_region)
11540 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11541 gimple_omp_set_body (stmt, new_body);
11544 bind = gimple_build_bind (NULL, NULL,
11545 tgt_bind ? gimple_bind_block (tgt_bind)
11546 : NULL_TREE);
11547 gsi_replace (gsi_p, bind, true);
11548 gimple_bind_add_seq (bind, irlist);
11549 gimple_bind_add_seq (bind, ilist);
11550 gimple_bind_add_stmt (bind, stmt);
11551 gimple_bind_add_seq (bind, olist);
11552 gimple_bind_add_seq (bind, orlist);
11554 pop_gimplify_context (NULL);
11557 /* Expand code for an OpenMP teams directive. */
11559 static void
11560 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11562 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11563 push_gimplify_context ();
11565 tree block = make_node (BLOCK);
11566 gbind *bind = gimple_build_bind (NULL, NULL, block);
11567 gsi_replace (gsi_p, bind, true);
11568 gimple_seq bind_body = NULL;
11569 gimple_seq dlist = NULL;
11570 gimple_seq olist = NULL;
11572 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11573 OMP_CLAUSE_NUM_TEAMS);
11574 if (num_teams == NULL_TREE)
11575 num_teams = build_int_cst (unsigned_type_node, 0);
11576 else
11578 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11579 num_teams = fold_convert (unsigned_type_node, num_teams);
11580 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11582 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11583 OMP_CLAUSE_THREAD_LIMIT);
11584 if (thread_limit == NULL_TREE)
11585 thread_limit = build_int_cst (unsigned_type_node, 0);
11586 else
11588 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11589 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11590 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11591 fb_rvalue);
11594 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11595 &bind_body, &dlist, ctx, NULL);
11596 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11597 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11598 gimple_seq_add_stmt (&bind_body, teams_stmt);
11600 location_t loc = gimple_location (teams_stmt);
11601 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11602 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11603 gimple_set_location (call, loc);
11604 gimple_seq_add_stmt (&bind_body, call);
11606 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11607 gimple_omp_set_body (teams_stmt, NULL);
11608 gimple_seq_add_seq (&bind_body, olist);
11609 gimple_seq_add_seq (&bind_body, dlist);
11610 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11611 gimple_bind_set_body (bind, bind_body);
11613 pop_gimplify_context (bind);
11615 gimple_bind_append_vars (bind, ctx->block_vars);
11616 BLOCK_VARS (block) = ctx->block_vars;
11617 if (BLOCK_VARS (block))
11618 TREE_USED (block) = 1;
11622 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11623 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11624 of OMP context, but with task_shared_vars set. */
11626 static tree
11627 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11628 void *data)
11630 tree t = *tp;
11632 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11633 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11634 return t;
11636 if (task_shared_vars
11637 && DECL_P (t)
11638 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11639 return t;
11641 /* If a global variable has been privatized, TREE_CONSTANT on
11642 ADDR_EXPR might be wrong. */
11643 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11644 recompute_tree_invariant_for_addr_expr (t);
11646 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11647 return NULL_TREE;
11650 static void
11651 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11653 gimple stmt = gsi_stmt (*gsi_p);
11654 struct walk_stmt_info wi;
11655 gcall *call_stmt;
11657 if (gimple_has_location (stmt))
11658 input_location = gimple_location (stmt);
11660 if (task_shared_vars)
11661 memset (&wi, '\0', sizeof (wi));
11663 /* If we have issued syntax errors, avoid doing any heavy lifting.
11664 Just replace the OMP directives with a NOP to avoid
11665 confusing RTL expansion. */
11666 if (seen_error () && is_gimple_omp (stmt))
11668 gsi_replace (gsi_p, gimple_build_nop (), true);
11669 return;
11672 switch (gimple_code (stmt))
11674 case GIMPLE_COND:
11676 gcond *cond_stmt = as_a <gcond *> (stmt);
11677 if ((ctx || task_shared_vars)
11678 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11679 lower_omp_regimplify_p,
11680 ctx ? NULL : &wi, NULL)
11681 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11682 lower_omp_regimplify_p,
11683 ctx ? NULL : &wi, NULL)))
11684 gimple_regimplify_operands (cond_stmt, gsi_p);
11686 break;
11687 case GIMPLE_CATCH:
11688 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
11689 break;
11690 case GIMPLE_EH_FILTER:
11691 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
11692 break;
11693 case GIMPLE_TRY:
11694 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11695 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
11696 break;
11697 case GIMPLE_TRANSACTION:
11698 lower_omp (gimple_transaction_body_ptr (
11699 as_a <gtransaction *> (stmt)),
11700 ctx);
11701 break;
11702 case GIMPLE_BIND:
11703 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
11704 break;
11705 case GIMPLE_OMP_PARALLEL:
11706 case GIMPLE_OMP_TASK:
11707 ctx = maybe_lookup_ctx (stmt);
11708 gcc_assert (ctx);
11709 if (ctx->cancellable)
11710 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11711 lower_omp_taskreg (gsi_p, ctx);
11712 break;
11713 case GIMPLE_OMP_FOR:
11714 ctx = maybe_lookup_ctx (stmt);
11715 gcc_assert (ctx);
11716 if (ctx->cancellable)
11717 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11718 lower_omp_for (gsi_p, ctx);
11719 break;
11720 case GIMPLE_OMP_SECTIONS:
11721 ctx = maybe_lookup_ctx (stmt);
11722 gcc_assert (ctx);
11723 if (ctx->cancellable)
11724 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11725 lower_omp_sections (gsi_p, ctx);
11726 break;
11727 case GIMPLE_OMP_SINGLE:
11728 ctx = maybe_lookup_ctx (stmt);
11729 gcc_assert (ctx);
11730 lower_omp_single (gsi_p, ctx);
11731 break;
11732 case GIMPLE_OMP_MASTER:
11733 ctx = maybe_lookup_ctx (stmt);
11734 gcc_assert (ctx);
11735 lower_omp_master (gsi_p, ctx);
11736 break;
11737 case GIMPLE_OMP_TASKGROUP:
11738 ctx = maybe_lookup_ctx (stmt);
11739 gcc_assert (ctx);
11740 lower_omp_taskgroup (gsi_p, ctx);
11741 break;
11742 case GIMPLE_OMP_ORDERED:
11743 ctx = maybe_lookup_ctx (stmt);
11744 gcc_assert (ctx);
11745 lower_omp_ordered (gsi_p, ctx);
11746 break;
11747 case GIMPLE_OMP_CRITICAL:
11748 ctx = maybe_lookup_ctx (stmt);
11749 gcc_assert (ctx);
11750 lower_omp_critical (gsi_p, ctx);
11751 break;
11752 case GIMPLE_OMP_ATOMIC_LOAD:
11753 if ((ctx || task_shared_vars)
11754 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11755 as_a <gomp_atomic_load *> (stmt)),
11756 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11757 gimple_regimplify_operands (stmt, gsi_p);
11758 break;
11759 case GIMPLE_OMP_TARGET:
11760 ctx = maybe_lookup_ctx (stmt);
11761 gcc_assert (ctx);
11762 lower_omp_target (gsi_p, ctx);
11763 break;
11764 case GIMPLE_OMP_TEAMS:
11765 ctx = maybe_lookup_ctx (stmt);
11766 gcc_assert (ctx);
11767 lower_omp_teams (gsi_p, ctx);
11768 break;
11769 case GIMPLE_CALL:
11770 tree fndecl;
11771 call_stmt = as_a <gcall *> (stmt);
11772 fndecl = gimple_call_fndecl (call_stmt);
11773 if (fndecl
11774 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11775 switch (DECL_FUNCTION_CODE (fndecl))
11777 case BUILT_IN_GOMP_BARRIER:
11778 if (ctx == NULL)
11779 break;
11780 /* FALLTHRU */
11781 case BUILT_IN_GOMP_CANCEL:
11782 case BUILT_IN_GOMP_CANCELLATION_POINT:
11783 omp_context *cctx;
11784 cctx = ctx;
11785 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11786 cctx = cctx->outer;
11787 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
11788 if (!cctx->cancellable)
11790 if (DECL_FUNCTION_CODE (fndecl)
11791 == BUILT_IN_GOMP_CANCELLATION_POINT)
11793 stmt = gimple_build_nop ();
11794 gsi_replace (gsi_p, stmt, false);
11796 break;
11798 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11800 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
11801 gimple_call_set_fndecl (call_stmt, fndecl);
11802 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
11804 tree lhs;
11805 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
11806 gimple_call_set_lhs (call_stmt, lhs);
11807 tree fallthru_label;
11808 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11809 gimple g;
11810 g = gimple_build_label (fallthru_label);
11811 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11812 g = gimple_build_cond (NE_EXPR, lhs,
11813 fold_convert (TREE_TYPE (lhs),
11814 boolean_false_node),
11815 cctx->cancel_label, fallthru_label);
11816 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11817 break;
11818 default:
11819 break;
11821 /* FALLTHRU */
11822 default:
11823 if ((ctx || task_shared_vars)
11824 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11825 ctx ? NULL : &wi))
11827 /* Just remove clobbers, this should happen only if we have
11828 "privatized" local addressable variables in SIMD regions,
11829 the clobber isn't needed in that case and gimplifying address
11830 of the ARRAY_REF into a pointer and creating MEM_REF based
11831 clobber would create worse code than we get with the clobber
11832 dropped. */
11833 if (gimple_clobber_p (stmt))
11835 gsi_replace (gsi_p, gimple_build_nop (), true);
11836 break;
11838 gimple_regimplify_operands (stmt, gsi_p);
11840 break;
11844 static void
11845 lower_omp (gimple_seq *body, omp_context *ctx)
11847 location_t saved_location = input_location;
11848 gimple_stmt_iterator gsi;
11849 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11850 lower_omp_1 (&gsi, ctx);
11851 /* During gimplification, we haven't folded statments inside offloading
11852 regions (gimplify.c:maybe_fold_stmt); do that now. */
11853 if (target_nesting_level)
11854 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11855 fold_stmt (&gsi);
11856 input_location = saved_location;
11859 /* Main entry point. */
11861 static unsigned int
11862 execute_lower_omp (void)
11864 gimple_seq body;
11865 int i;
11866 omp_context *ctx;
11868 /* This pass always runs, to provide PROP_gimple_lomp.
11869 But often, there is nothing to do. */
11870 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11871 && flag_openmp_simd == 0)
11872 return 0;
11874 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11875 delete_omp_context);
11877 body = gimple_body (current_function_decl);
11878 scan_omp (&body, NULL);
11879 gcc_assert (taskreg_nesting_level == 0);
11880 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11881 finish_taskreg_scan (ctx);
11882 taskreg_contexts.release ();
11884 if (all_contexts->root)
11886 if (task_shared_vars)
11887 push_gimplify_context ();
11888 lower_omp (&body, NULL);
11889 if (task_shared_vars)
11890 pop_gimplify_context (NULL);
11893 if (all_contexts)
11895 splay_tree_delete (all_contexts);
11896 all_contexts = NULL;
11898 BITMAP_FREE (task_shared_vars);
11899 return 0;
11902 namespace {
11904 const pass_data pass_data_lower_omp =
11906 GIMPLE_PASS, /* type */
11907 "omplower", /* name */
11908 OPTGROUP_NONE, /* optinfo_flags */
11909 TV_NONE, /* tv_id */
11910 PROP_gimple_any, /* properties_required */
11911 PROP_gimple_lomp, /* properties_provided */
11912 0, /* properties_destroyed */
11913 0, /* todo_flags_start */
11914 0, /* todo_flags_finish */
11917 class pass_lower_omp : public gimple_opt_pass
11919 public:
11920 pass_lower_omp (gcc::context *ctxt)
11921 : gimple_opt_pass (pass_data_lower_omp, ctxt)
11924 /* opt_pass methods: */
11925 virtual unsigned int execute (function *) { return execute_lower_omp (); }
11927 }; // class pass_lower_omp
11929 } // anon namespace
11931 gimple_opt_pass *
11932 make_pass_lower_omp (gcc::context *ctxt)
11934 return new pass_lower_omp (ctxt);
11937 /* The following is a utility to diagnose structured block violations.
11938 It is not part of the "omplower" pass, as that's invoked too late. It
11939 should be invoked by the respective front ends after gimplification. */
11941 static splay_tree all_labels;
11943 /* Check for mismatched contexts and generate an error if needed. Return
11944 true if an error is detected. */
11946 static bool
11947 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
11948 gimple branch_ctx, gimple label_ctx)
11950 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
11951 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
11953 if (label_ctx == branch_ctx)
11954 return false;
11956 const char* kind = NULL;
11958 if (flag_cilkplus)
11960 if ((branch_ctx
11961 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
11962 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
11963 || (label_ctx
11964 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
11965 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
11966 kind = "Cilk Plus";
11968 if (flag_openacc)
11970 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
11971 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
11973 gcc_checking_assert (kind == NULL);
11974 kind = "OpenACC";
11977 if (kind == NULL)
11979 gcc_checking_assert (flag_openmp);
11980 kind = "OpenMP";
11984 Previously we kept track of the label's entire context in diagnose_sb_[12]
11985 so we could traverse it and issue a correct "exit" or "enter" error
11986 message upon a structured block violation.
11988 We built the context by building a list with tree_cons'ing, but there is
11989 no easy counterpart in gimple tuples. It seems like far too much work
11990 for issuing exit/enter error messages. If someone really misses the
11991 distinct error message... patches welcome.
11994 #if 0
11995 /* Try to avoid confusing the user by producing and error message
11996 with correct "exit" or "enter" verbiage. We prefer "exit"
11997 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
11998 if (branch_ctx == NULL)
11999 exit_p = false;
12000 else
12002 while (label_ctx)
12004 if (TREE_VALUE (label_ctx) == branch_ctx)
12006 exit_p = false;
12007 break;
12009 label_ctx = TREE_CHAIN (label_ctx);
12013 if (exit_p)
12014 error ("invalid exit from %s structured block", kind);
12015 else
12016 error ("invalid entry to %s structured block", kind);
12017 #endif
12019 /* If it's obvious we have an invalid entry, be specific about the error. */
12020 if (branch_ctx == NULL)
12021 error ("invalid entry to %s structured block", kind);
12022 else
12024 /* Otherwise, be vague and lazy, but efficient. */
12025 error ("invalid branch to/from %s structured block", kind);
12028 gsi_replace (gsi_p, gimple_build_nop (), false);
12029 return true;
12032 /* Pass 1: Create a minimal tree of structured blocks, and record
12033 where each label is found. */
12035 static tree
12036 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12037 struct walk_stmt_info *wi)
12039 gimple context = (gimple) wi->info;
12040 gimple inner_context;
12041 gimple stmt = gsi_stmt (*gsi_p);
12043 *handled_ops_p = true;
12045 switch (gimple_code (stmt))
12047 WALK_SUBSTMTS;
12049 case GIMPLE_OMP_PARALLEL:
12050 case GIMPLE_OMP_TASK:
12051 case GIMPLE_OMP_SECTIONS:
12052 case GIMPLE_OMP_SINGLE:
12053 case GIMPLE_OMP_SECTION:
12054 case GIMPLE_OMP_MASTER:
12055 case GIMPLE_OMP_ORDERED:
12056 case GIMPLE_OMP_CRITICAL:
12057 case GIMPLE_OMP_TARGET:
12058 case GIMPLE_OMP_TEAMS:
12059 case GIMPLE_OMP_TASKGROUP:
12060 /* The minimal context here is just the current OMP construct. */
12061 inner_context = stmt;
12062 wi->info = inner_context;
12063 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12064 wi->info = context;
12065 break;
12067 case GIMPLE_OMP_FOR:
12068 inner_context = stmt;
12069 wi->info = inner_context;
12070 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12071 walk them. */
12072 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12073 diagnose_sb_1, NULL, wi);
12074 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12075 wi->info = context;
12076 break;
12078 case GIMPLE_LABEL:
12079 splay_tree_insert (all_labels,
12080 (splay_tree_key) gimple_label_label (
12081 as_a <glabel *> (stmt)),
12082 (splay_tree_value) context);
12083 break;
12085 default:
12086 break;
12089 return NULL_TREE;
12092 /* Pass 2: Check each branch and see if its context differs from that of
12093 the destination label's context. */
12095 static tree
12096 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12097 struct walk_stmt_info *wi)
12099 gimple context = (gimple) wi->info;
12100 splay_tree_node n;
12101 gimple stmt = gsi_stmt (*gsi_p);
12103 *handled_ops_p = true;
12105 switch (gimple_code (stmt))
12107 WALK_SUBSTMTS;
12109 case GIMPLE_OMP_PARALLEL:
12110 case GIMPLE_OMP_TASK:
12111 case GIMPLE_OMP_SECTIONS:
12112 case GIMPLE_OMP_SINGLE:
12113 case GIMPLE_OMP_SECTION:
12114 case GIMPLE_OMP_MASTER:
12115 case GIMPLE_OMP_ORDERED:
12116 case GIMPLE_OMP_CRITICAL:
12117 case GIMPLE_OMP_TARGET:
12118 case GIMPLE_OMP_TEAMS:
12119 case GIMPLE_OMP_TASKGROUP:
12120 wi->info = stmt;
12121 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12122 wi->info = context;
12123 break;
12125 case GIMPLE_OMP_FOR:
12126 wi->info = stmt;
12127 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12128 walk them. */
12129 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12130 diagnose_sb_2, NULL, wi);
12131 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12132 wi->info = context;
12133 break;
12135 case GIMPLE_COND:
12137 gcond *cond_stmt = as_a <gcond *> (stmt);
12138 tree lab = gimple_cond_true_label (cond_stmt);
12139 if (lab)
12141 n = splay_tree_lookup (all_labels,
12142 (splay_tree_key) lab);
12143 diagnose_sb_0 (gsi_p, context,
12144 n ? (gimple) n->value : NULL);
12146 lab = gimple_cond_false_label (cond_stmt);
12147 if (lab)
12149 n = splay_tree_lookup (all_labels,
12150 (splay_tree_key) lab);
12151 diagnose_sb_0 (gsi_p, context,
12152 n ? (gimple) n->value : NULL);
12155 break;
12157 case GIMPLE_GOTO:
12159 tree lab = gimple_goto_dest (stmt);
12160 if (TREE_CODE (lab) != LABEL_DECL)
12161 break;
12163 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12164 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
12166 break;
12168 case GIMPLE_SWITCH:
12170 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12171 unsigned int i;
12172 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12174 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12175 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12176 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
12177 break;
12180 break;
12182 case GIMPLE_RETURN:
12183 diagnose_sb_0 (gsi_p, context, NULL);
12184 break;
12186 default:
12187 break;
12190 return NULL_TREE;
12193 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12194 GIMPLE_* codes. */
12195 bool
12196 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12197 int *region_idx)
12199 gimple last = last_stmt (bb);
12200 enum gimple_code code = gimple_code (last);
12201 struct omp_region *cur_region = *region;
12202 bool fallthru = false;
12204 switch (code)
12206 case GIMPLE_OMP_PARALLEL:
12207 case GIMPLE_OMP_TASK:
12208 case GIMPLE_OMP_FOR:
12209 case GIMPLE_OMP_SINGLE:
12210 case GIMPLE_OMP_TEAMS:
12211 case GIMPLE_OMP_MASTER:
12212 case GIMPLE_OMP_TASKGROUP:
12213 case GIMPLE_OMP_ORDERED:
12214 case GIMPLE_OMP_CRITICAL:
12215 case GIMPLE_OMP_SECTION:
12216 cur_region = new_omp_region (bb, code, cur_region);
12217 fallthru = true;
12218 break;
12220 case GIMPLE_OMP_TARGET:
12221 cur_region = new_omp_region (bb, code, cur_region);
12222 fallthru = true;
12223 switch (gimple_omp_target_kind (last))
12225 case GF_OMP_TARGET_KIND_REGION:
12226 case GF_OMP_TARGET_KIND_DATA:
12227 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12228 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12229 case GF_OMP_TARGET_KIND_OACC_DATA:
12230 break;
12231 case GF_OMP_TARGET_KIND_UPDATE:
12232 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12233 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12234 cur_region = cur_region->outer;
12235 break;
12236 default:
12237 gcc_unreachable ();
12239 break;
12241 case GIMPLE_OMP_SECTIONS:
12242 cur_region = new_omp_region (bb, code, cur_region);
12243 fallthru = true;
12244 break;
12246 case GIMPLE_OMP_SECTIONS_SWITCH:
12247 fallthru = false;
12248 break;
12250 case GIMPLE_OMP_ATOMIC_LOAD:
12251 case GIMPLE_OMP_ATOMIC_STORE:
12252 fallthru = true;
12253 break;
12255 case GIMPLE_OMP_RETURN:
12256 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12257 somewhere other than the next block. This will be
12258 created later. */
12259 cur_region->exit = bb;
12260 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12261 cur_region = cur_region->outer;
12262 break;
12264 case GIMPLE_OMP_CONTINUE:
12265 cur_region->cont = bb;
12266 switch (cur_region->type)
12268 case GIMPLE_OMP_FOR:
12269 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12270 succs edges as abnormal to prevent splitting
12271 them. */
12272 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12273 /* Make the loopback edge. */
12274 make_edge (bb, single_succ (cur_region->entry),
12275 EDGE_ABNORMAL);
12277 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12278 corresponds to the case that the body of the loop
12279 is not executed at all. */
12280 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12281 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12282 fallthru = false;
12283 break;
12285 case GIMPLE_OMP_SECTIONS:
12286 /* Wire up the edges into and out of the nested sections. */
12288 basic_block switch_bb = single_succ (cur_region->entry);
12290 struct omp_region *i;
12291 for (i = cur_region->inner; i ; i = i->next)
12293 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12294 make_edge (switch_bb, i->entry, 0);
12295 make_edge (i->exit, bb, EDGE_FALLTHRU);
12298 /* Make the loopback edge to the block with
12299 GIMPLE_OMP_SECTIONS_SWITCH. */
12300 make_edge (bb, switch_bb, 0);
12302 /* Make the edge from the switch to exit. */
12303 make_edge (switch_bb, bb->next_bb, 0);
12304 fallthru = false;
12306 break;
12308 default:
12309 gcc_unreachable ();
12311 break;
12313 default:
12314 gcc_unreachable ();
12317 if (*region != cur_region)
12319 *region = cur_region;
12320 if (cur_region)
12321 *region_idx = cur_region->entry->index;
12322 else
12323 *region_idx = 0;
12326 return fallthru;
12329 static unsigned int
12330 diagnose_omp_structured_block_errors (void)
12332 struct walk_stmt_info wi;
12333 gimple_seq body = gimple_body (current_function_decl);
12335 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12337 memset (&wi, 0, sizeof (wi));
12338 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12340 memset (&wi, 0, sizeof (wi));
12341 wi.want_locations = true;
12342 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12344 gimple_set_body (current_function_decl, body);
12346 splay_tree_delete (all_labels);
12347 all_labels = NULL;
12349 return 0;
12352 namespace {
12354 const pass_data pass_data_diagnose_omp_blocks =
12356 GIMPLE_PASS, /* type */
12357 "*diagnose_omp_blocks", /* name */
12358 OPTGROUP_NONE, /* optinfo_flags */
12359 TV_NONE, /* tv_id */
12360 PROP_gimple_any, /* properties_required */
12361 0, /* properties_provided */
12362 0, /* properties_destroyed */
12363 0, /* todo_flags_start */
12364 0, /* todo_flags_finish */
12367 class pass_diagnose_omp_blocks : public gimple_opt_pass
12369 public:
12370 pass_diagnose_omp_blocks (gcc::context *ctxt)
12371 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12374 /* opt_pass methods: */
12375 virtual bool gate (function *)
12377 return flag_cilkplus || flag_openacc || flag_openmp;
12379 virtual unsigned int execute (function *)
12381 return diagnose_omp_structured_block_errors ();
12384 }; // class pass_diagnose_omp_blocks
12386 } // anon namespace
12388 gimple_opt_pass *
12389 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12391 return new pass_diagnose_omp_blocks (ctxt);
12394 /* SIMD clone supporting code. */
12396 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12397 of arguments to reserve space for. */
12399 static struct cgraph_simd_clone *
12400 simd_clone_struct_alloc (int nargs)
12402 struct cgraph_simd_clone *clone_info;
12403 size_t len = (sizeof (struct cgraph_simd_clone)
12404 + nargs * sizeof (struct cgraph_simd_clone_arg));
12405 clone_info = (struct cgraph_simd_clone *)
12406 ggc_internal_cleared_alloc (len);
12407 return clone_info;
12410 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12412 static inline void
12413 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12414 struct cgraph_simd_clone *from)
12416 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12417 + ((from->nargs - from->inbranch)
12418 * sizeof (struct cgraph_simd_clone_arg))));
12421 /* Return vector of parameter types of function FNDECL. This uses
12422 TYPE_ARG_TYPES if available, otherwise falls back to types of
12423 DECL_ARGUMENTS types. */
12425 vec<tree>
12426 simd_clone_vector_of_formal_parm_types (tree fndecl)
12428 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12429 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12430 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12431 unsigned int i;
12432 tree arg;
12433 FOR_EACH_VEC_ELT (args, i, arg)
12434 args[i] = TREE_TYPE (args[i]);
12435 return args;
12438 /* Given a simd function in NODE, extract the simd specific
12439 information from the OMP clauses passed in CLAUSES, and return
12440 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12441 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12442 otherwise set to FALSE. */
12444 static struct cgraph_simd_clone *
12445 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12446 bool *inbranch_specified)
12448 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12449 tree t;
12450 int n;
12451 *inbranch_specified = false;
12453 n = args.length ();
12454 if (n > 0 && args.last () == void_type_node)
12455 n--;
12457 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12458 be cloned have a distinctive artificial label in addition to "omp
12459 declare simd". */
12460 bool cilk_clone
12461 = (flag_cilkplus
12462 && lookup_attribute ("cilk simd function",
12463 DECL_ATTRIBUTES (node->decl)));
12465 /* Allocate one more than needed just in case this is an in-branch
12466 clone which will require a mask argument. */
12467 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12468 clone_info->nargs = n;
12469 clone_info->cilk_elemental = cilk_clone;
12471 if (!clauses)
12473 args.release ();
12474 return clone_info;
12476 clauses = TREE_VALUE (clauses);
12477 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12478 return clone_info;
12480 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12482 switch (OMP_CLAUSE_CODE (t))
12484 case OMP_CLAUSE_INBRANCH:
12485 clone_info->inbranch = 1;
12486 *inbranch_specified = true;
12487 break;
12488 case OMP_CLAUSE_NOTINBRANCH:
12489 clone_info->inbranch = 0;
12490 *inbranch_specified = true;
12491 break;
12492 case OMP_CLAUSE_SIMDLEN:
12493 clone_info->simdlen
12494 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12495 break;
12496 case OMP_CLAUSE_LINEAR:
12498 tree decl = OMP_CLAUSE_DECL (t);
12499 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12500 int argno = TREE_INT_CST_LOW (decl);
12501 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12503 clone_info->args[argno].arg_type
12504 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12505 clone_info->args[argno].linear_step = tree_to_shwi (step);
12506 gcc_assert (clone_info->args[argno].linear_step >= 0
12507 && clone_info->args[argno].linear_step < n);
12509 else
12511 if (POINTER_TYPE_P (args[argno]))
12512 step = fold_convert (ssizetype, step);
12513 if (!tree_fits_shwi_p (step))
12515 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12516 "ignoring large linear step");
12517 args.release ();
12518 return NULL;
12520 else if (integer_zerop (step))
12522 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12523 "ignoring zero linear step");
12524 args.release ();
12525 return NULL;
12527 else
12529 clone_info->args[argno].arg_type
12530 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12531 clone_info->args[argno].linear_step = tree_to_shwi (step);
12534 break;
12536 case OMP_CLAUSE_UNIFORM:
12538 tree decl = OMP_CLAUSE_DECL (t);
12539 int argno = tree_to_uhwi (decl);
12540 clone_info->args[argno].arg_type
12541 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12542 break;
12544 case OMP_CLAUSE_ALIGNED:
12546 tree decl = OMP_CLAUSE_DECL (t);
12547 int argno = tree_to_uhwi (decl);
12548 clone_info->args[argno].alignment
12549 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12550 break;
12552 default:
12553 break;
12556 args.release ();
12557 return clone_info;
12560 /* Given a SIMD clone in NODE, calculate the characteristic data
12561 type and return the coresponding type. The characteristic data
12562 type is computed as described in the Intel Vector ABI. */
12564 static tree
12565 simd_clone_compute_base_data_type (struct cgraph_node *node,
12566 struct cgraph_simd_clone *clone_info)
12568 tree type = integer_type_node;
12569 tree fndecl = node->decl;
12571 /* a) For non-void function, the characteristic data type is the
12572 return type. */
12573 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12574 type = TREE_TYPE (TREE_TYPE (fndecl));
12576 /* b) If the function has any non-uniform, non-linear parameters,
12577 then the characteristic data type is the type of the first
12578 such parameter. */
12579 else
12581 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12582 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12583 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12585 type = map[i];
12586 break;
12588 map.release ();
12591 /* c) If the characteristic data type determined by a) or b) above
12592 is struct, union, or class type which is pass-by-value (except
12593 for the type that maps to the built-in complex data type), the
12594 characteristic data type is int. */
12595 if (RECORD_OR_UNION_TYPE_P (type)
12596 && !aggregate_value_p (type, NULL)
12597 && TREE_CODE (type) != COMPLEX_TYPE)
12598 return integer_type_node;
12600 /* d) If none of the above three classes is applicable, the
12601 characteristic data type is int. */
12603 return type;
12605 /* e) For Intel Xeon Phi native and offload compilation, if the
12606 resulting characteristic data type is 8-bit or 16-bit integer
12607 data type, the characteristic data type is int. */
12608 /* Well, we don't handle Xeon Phi yet. */
12611 static tree
12612 simd_clone_mangle (struct cgraph_node *node,
12613 struct cgraph_simd_clone *clone_info)
12615 char vecsize_mangle = clone_info->vecsize_mangle;
12616 char mask = clone_info->inbranch ? 'M' : 'N';
12617 unsigned int simdlen = clone_info->simdlen;
12618 unsigned int n;
12619 pretty_printer pp;
12621 gcc_assert (vecsize_mangle && simdlen);
12623 pp_string (&pp, "_ZGV");
12624 pp_character (&pp, vecsize_mangle);
12625 pp_character (&pp, mask);
12626 pp_decimal_int (&pp, simdlen);
12628 for (n = 0; n < clone_info->nargs; ++n)
12630 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12632 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12633 pp_character (&pp, 'u');
12634 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12636 gcc_assert (arg.linear_step != 0);
12637 pp_character (&pp, 'l');
12638 if (arg.linear_step > 1)
12639 pp_unsigned_wide_integer (&pp, arg.linear_step);
12640 else if (arg.linear_step < 0)
12642 pp_character (&pp, 'n');
12643 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12644 arg.linear_step));
12647 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12649 pp_character (&pp, 's');
12650 pp_unsigned_wide_integer (&pp, arg.linear_step);
12652 else
12653 pp_character (&pp, 'v');
12654 if (arg.alignment)
12656 pp_character (&pp, 'a');
12657 pp_decimal_int (&pp, arg.alignment);
12661 pp_underscore (&pp);
12662 pp_string (&pp,
12663 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
12664 const char *str = pp_formatted_text (&pp);
12666 /* If there already is a SIMD clone with the same mangled name, don't
12667 add another one. This can happen e.g. for
12668 #pragma omp declare simd
12669 #pragma omp declare simd simdlen(8)
12670 int foo (int, int);
12671 if the simdlen is assumed to be 8 for the first one, etc. */
12672 for (struct cgraph_node *clone = node->simd_clones; clone;
12673 clone = clone->simdclone->next_clone)
12674 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12675 str) == 0)
12676 return NULL_TREE;
12678 return get_identifier (str);
12681 /* Create a simd clone of OLD_NODE and return it. */
12683 static struct cgraph_node *
12684 simd_clone_create (struct cgraph_node *old_node)
12686 struct cgraph_node *new_node;
12687 if (old_node->definition)
12689 if (!old_node->has_gimple_body_p ())
12690 return NULL;
12691 old_node->get_body ();
12692 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12693 false, NULL, NULL,
12694 "simdclone");
12696 else
12698 tree old_decl = old_node->decl;
12699 tree new_decl = copy_node (old_node->decl);
12700 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12701 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12702 SET_DECL_RTL (new_decl, NULL);
12703 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12704 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
12705 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
12706 symtab->call_cgraph_insertion_hooks (new_node);
12708 if (new_node == NULL)
12709 return new_node;
12711 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12713 /* The function cgraph_function_versioning () will force the new
12714 symbol local. Undo this, and inherit external visability from
12715 the old node. */
12716 new_node->local.local = old_node->local.local;
12717 new_node->externally_visible = old_node->externally_visible;
12719 return new_node;
12722 /* Adjust the return type of the given function to its appropriate
12723 vector counterpart. Returns a simd array to be used throughout the
12724 function as a return value. */
12726 static tree
12727 simd_clone_adjust_return_type (struct cgraph_node *node)
12729 tree fndecl = node->decl;
12730 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12731 unsigned int veclen;
12732 tree t;
12734 /* Adjust the function return type. */
12735 if (orig_rettype == void_type_node)
12736 return NULL_TREE;
12737 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
12738 t = TREE_TYPE (TREE_TYPE (fndecl));
12739 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
12740 veclen = node->simdclone->vecsize_int;
12741 else
12742 veclen = node->simdclone->vecsize_float;
12743 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
12744 if (veclen > node->simdclone->simdlen)
12745 veclen = node->simdclone->simdlen;
12746 if (POINTER_TYPE_P (t))
12747 t = pointer_sized_int_node;
12748 if (veclen == node->simdclone->simdlen)
12749 t = build_vector_type (t, node->simdclone->simdlen);
12750 else
12752 t = build_vector_type (t, veclen);
12753 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
12755 TREE_TYPE (TREE_TYPE (fndecl)) = t;
12756 if (!node->definition)
12757 return NULL_TREE;
12759 t = DECL_RESULT (fndecl);
12760 /* Adjust the DECL_RESULT. */
12761 gcc_assert (TREE_TYPE (t) != void_type_node);
12762 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12763 relayout_decl (t);
12765 tree atype = build_array_type_nelts (orig_rettype,
12766 node->simdclone->simdlen);
12767 if (veclen != node->simdclone->simdlen)
12768 return build1 (VIEW_CONVERT_EXPR, atype, t);
12770 /* Set up a SIMD array to use as the return value. */
12771 tree retval = create_tmp_var_raw (atype, "retval");
12772 gimple_add_tmp_var (retval);
12773 return retval;
12776 /* Each vector argument has a corresponding array to be used locally
12777 as part of the eventual loop. Create such temporary array and
12778 return it.
12780 PREFIX is the prefix to be used for the temporary.
12782 TYPE is the inner element type.
12784 SIMDLEN is the number of elements. */
12786 static tree
12787 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12789 tree atype = build_array_type_nelts (type, simdlen);
12790 tree avar = create_tmp_var_raw (atype, prefix);
12791 gimple_add_tmp_var (avar);
12792 return avar;
12795 /* Modify the function argument types to their corresponding vector
12796 counterparts if appropriate. Also, create one array for each simd
12797 argument to be used locally when using the function arguments as
12798 part of the loop.
12800 NODE is the function whose arguments are to be adjusted.
12802 Returns an adjustment vector that will be filled describing how the
12803 argument types will be adjusted. */
12805 static ipa_parm_adjustment_vec
12806 simd_clone_adjust_argument_types (struct cgraph_node *node)
12808 vec<tree> args;
12809 ipa_parm_adjustment_vec adjustments;
12811 if (node->definition)
12812 args = ipa_get_vector_of_formal_parms (node->decl);
12813 else
12814 args = simd_clone_vector_of_formal_parm_types (node->decl);
12815 adjustments.create (args.length ());
12816 unsigned i, j, veclen;
12817 struct ipa_parm_adjustment adj;
12818 for (i = 0; i < node->simdclone->nargs; ++i)
12820 memset (&adj, 0, sizeof (adj));
12821 tree parm = args[i];
12822 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12823 adj.base_index = i;
12824 adj.base = parm;
12826 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12827 node->simdclone->args[i].orig_type = parm_type;
12829 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12831 /* No adjustment necessary for scalar arguments. */
12832 adj.op = IPA_PARM_OP_COPY;
12834 else
12836 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12837 veclen = node->simdclone->vecsize_int;
12838 else
12839 veclen = node->simdclone->vecsize_float;
12840 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12841 if (veclen > node->simdclone->simdlen)
12842 veclen = node->simdclone->simdlen;
12843 adj.arg_prefix = "simd";
12844 if (POINTER_TYPE_P (parm_type))
12845 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12846 else
12847 adj.type = build_vector_type (parm_type, veclen);
12848 node->simdclone->args[i].vector_type = adj.type;
12849 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12851 adjustments.safe_push (adj);
12852 if (j == veclen)
12854 memset (&adj, 0, sizeof (adj));
12855 adj.op = IPA_PARM_OP_NEW;
12856 adj.arg_prefix = "simd";
12857 adj.base_index = i;
12858 adj.type = node->simdclone->args[i].vector_type;
12862 if (node->definition)
12863 node->simdclone->args[i].simd_array
12864 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12865 parm_type, node->simdclone->simdlen);
12867 adjustments.safe_push (adj);
12870 if (node->simdclone->inbranch)
12872 tree base_type
12873 = simd_clone_compute_base_data_type (node->simdclone->origin,
12874 node->simdclone);
12876 memset (&adj, 0, sizeof (adj));
12877 adj.op = IPA_PARM_OP_NEW;
12878 adj.arg_prefix = "mask";
12880 adj.base_index = i;
12881 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12882 veclen = node->simdclone->vecsize_int;
12883 else
12884 veclen = node->simdclone->vecsize_float;
12885 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12886 if (veclen > node->simdclone->simdlen)
12887 veclen = node->simdclone->simdlen;
12888 if (POINTER_TYPE_P (base_type))
12889 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12890 else
12891 adj.type = build_vector_type (base_type, veclen);
12892 adjustments.safe_push (adj);
12894 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12895 adjustments.safe_push (adj);
12897 /* We have previously allocated one extra entry for the mask. Use
12898 it and fill it. */
12899 struct cgraph_simd_clone *sc = node->simdclone;
12900 sc->nargs++;
12901 if (node->definition)
12903 sc->args[i].orig_arg
12904 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12905 sc->args[i].simd_array
12906 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12908 sc->args[i].orig_type = base_type;
12909 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12912 if (node->definition)
12913 ipa_modify_formal_parameters (node->decl, adjustments);
12914 else
12916 tree new_arg_types = NULL_TREE, new_reversed;
12917 bool last_parm_void = false;
12918 if (args.length () > 0 && args.last () == void_type_node)
12919 last_parm_void = true;
12921 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12922 j = adjustments.length ();
12923 for (i = 0; i < j; i++)
12925 struct ipa_parm_adjustment *adj = &adjustments[i];
12926 tree ptype;
12927 if (adj->op == IPA_PARM_OP_COPY)
12928 ptype = args[adj->base_index];
12929 else
12930 ptype = adj->type;
12931 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12933 new_reversed = nreverse (new_arg_types);
12934 if (last_parm_void)
12936 if (new_reversed)
12937 TREE_CHAIN (new_arg_types) = void_list_node;
12938 else
12939 new_reversed = void_list_node;
12942 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
12943 TYPE_ARG_TYPES (new_type) = new_reversed;
12944 TREE_TYPE (node->decl) = new_type;
12946 adjustments.release ();
12948 args.release ();
12949 return adjustments;
12952 /* Initialize and copy the function arguments in NODE to their
12953 corresponding local simd arrays. Returns a fresh gimple_seq with
12954 the instruction sequence generated. */
12956 static gimple_seq
12957 simd_clone_init_simd_arrays (struct cgraph_node *node,
12958 ipa_parm_adjustment_vec adjustments)
12960 gimple_seq seq = NULL;
12961 unsigned i = 0, j = 0, k;
12963 for (tree arg = DECL_ARGUMENTS (node->decl);
12964 arg;
12965 arg = DECL_CHAIN (arg), i++, j++)
12967 if (adjustments[j].op == IPA_PARM_OP_COPY)
12968 continue;
12970 node->simdclone->args[i].vector_arg = arg;
12972 tree array = node->simdclone->args[i].simd_array;
12973 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
12975 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
12976 tree ptr = build_fold_addr_expr (array);
12977 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
12978 build_int_cst (ptype, 0));
12979 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
12980 gimplify_and_add (t, &seq);
12982 else
12984 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
12985 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
12986 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
12988 tree ptr = build_fold_addr_expr (array);
12989 int elemsize;
12990 if (k)
12992 arg = DECL_CHAIN (arg);
12993 j++;
12995 elemsize
12996 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
12997 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
12998 build_int_cst (ptype, k * elemsize));
12999 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13000 gimplify_and_add (t, &seq);
13004 return seq;
13007 /* Callback info for ipa_simd_modify_stmt_ops below. */
13009 struct modify_stmt_info {
13010 ipa_parm_adjustment_vec adjustments;
13011 gimple stmt;
13012 /* True if the parent statement was modified by
13013 ipa_simd_modify_stmt_ops. */
13014 bool modified;
13017 /* Callback for walk_gimple_op.
13019 Adjust operands from a given statement as specified in the
13020 adjustments vector in the callback data. */
13022 static tree
13023 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13025 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13026 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13027 tree *orig_tp = tp;
13028 if (TREE_CODE (*tp) == ADDR_EXPR)
13029 tp = &TREE_OPERAND (*tp, 0);
13030 struct ipa_parm_adjustment *cand = NULL;
13031 if (TREE_CODE (*tp) == PARM_DECL)
13032 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13033 else
13035 if (TYPE_P (*tp))
13036 *walk_subtrees = 0;
13039 tree repl = NULL_TREE;
13040 if (cand)
13041 repl = unshare_expr (cand->new_decl);
13042 else
13044 if (tp != orig_tp)
13046 *walk_subtrees = 0;
13047 bool modified = info->modified;
13048 info->modified = false;
13049 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13050 if (!info->modified)
13052 info->modified = modified;
13053 return NULL_TREE;
13055 info->modified = modified;
13056 repl = *tp;
13058 else
13059 return NULL_TREE;
13062 if (tp != orig_tp)
13064 repl = build_fold_addr_expr (repl);
13065 gimple stmt;
13066 if (is_gimple_debug (info->stmt))
13068 tree vexpr = make_node (DEBUG_EXPR_DECL);
13069 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13070 DECL_ARTIFICIAL (vexpr) = 1;
13071 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13072 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13073 repl = vexpr;
13075 else
13077 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13078 repl = gimple_assign_lhs (stmt);
13080 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13081 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13082 *orig_tp = repl;
13084 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13086 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13087 *tp = vce;
13089 else
13090 *tp = repl;
13092 info->modified = true;
13093 return NULL_TREE;
13096 /* Traverse the function body and perform all modifications as
13097 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13098 modified such that the replacement/reduction value will now be an
13099 offset into the corresponding simd_array.
13101 This function will replace all function argument uses with their
13102 corresponding simd array elements, and ajust the return values
13103 accordingly. */
13105 static void
13106 ipa_simd_modify_function_body (struct cgraph_node *node,
13107 ipa_parm_adjustment_vec adjustments,
13108 tree retval_array, tree iter)
13110 basic_block bb;
13111 unsigned int i, j, l;
13113 /* Re-use the adjustments array, but this time use it to replace
13114 every function argument use to an offset into the corresponding
13115 simd_array. */
13116 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13118 if (!node->simdclone->args[i].vector_arg)
13119 continue;
13121 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13122 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13123 adjustments[j].new_decl
13124 = build4 (ARRAY_REF,
13125 basetype,
13126 node->simdclone->args[i].simd_array,
13127 iter,
13128 NULL_TREE, NULL_TREE);
13129 if (adjustments[j].op == IPA_PARM_OP_NONE
13130 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13131 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13134 l = adjustments.length ();
13135 for (i = 1; i < num_ssa_names; i++)
13137 tree name = ssa_name (i);
13138 if (name
13139 && SSA_NAME_VAR (name)
13140 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13142 for (j = 0; j < l; j++)
13143 if (SSA_NAME_VAR (name) == adjustments[j].base
13144 && adjustments[j].new_decl)
13146 tree base_var;
13147 if (adjustments[j].new_ssa_base == NULL_TREE)
13149 base_var
13150 = copy_var_decl (adjustments[j].base,
13151 DECL_NAME (adjustments[j].base),
13152 TREE_TYPE (adjustments[j].base));
13153 adjustments[j].new_ssa_base = base_var;
13155 else
13156 base_var = adjustments[j].new_ssa_base;
13157 if (SSA_NAME_IS_DEFAULT_DEF (name))
13159 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13160 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13161 tree new_decl = unshare_expr (adjustments[j].new_decl);
13162 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13163 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13164 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13165 gimple stmt = gimple_build_assign (name, new_decl);
13166 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13168 else
13169 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13174 struct modify_stmt_info info;
13175 info.adjustments = adjustments;
13177 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13179 gimple_stmt_iterator gsi;
13181 gsi = gsi_start_bb (bb);
13182 while (!gsi_end_p (gsi))
13184 gimple stmt = gsi_stmt (gsi);
13185 info.stmt = stmt;
13186 struct walk_stmt_info wi;
13188 memset (&wi, 0, sizeof (wi));
13189 info.modified = false;
13190 wi.info = &info;
13191 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13193 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13195 tree retval = gimple_return_retval (return_stmt);
13196 if (!retval)
13198 gsi_remove (&gsi, true);
13199 continue;
13202 /* Replace `return foo' with `retval_array[iter] = foo'. */
13203 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13204 retval_array, iter, NULL, NULL);
13205 stmt = gimple_build_assign (ref, retval);
13206 gsi_replace (&gsi, stmt, true);
13207 info.modified = true;
13210 if (info.modified)
13212 update_stmt (stmt);
13213 if (maybe_clean_eh_stmt (stmt))
13214 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13216 gsi_next (&gsi);
13221 /* Adjust the argument types in NODE to their appropriate vector
13222 counterparts. */
13224 static void
13225 simd_clone_adjust (struct cgraph_node *node)
13227 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13229 targetm.simd_clone.adjust (node);
13231 tree retval = simd_clone_adjust_return_type (node);
13232 ipa_parm_adjustment_vec adjustments
13233 = simd_clone_adjust_argument_types (node);
13235 push_gimplify_context ();
13237 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13239 /* Adjust all uses of vector arguments accordingly. Adjust all
13240 return values accordingly. */
13241 tree iter = create_tmp_var (unsigned_type_node, "iter");
13242 tree iter1 = make_ssa_name (iter);
13243 tree iter2 = make_ssa_name (iter);
13244 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13246 /* Initialize the iteration variable. */
13247 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13248 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13249 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13250 /* Insert the SIMD array and iv initialization at function
13251 entry. */
13252 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13254 pop_gimplify_context (NULL);
13256 /* Create a new BB right before the original exit BB, to hold the
13257 iteration increment and the condition/branch. */
13258 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13259 basic_block incr_bb = create_empty_bb (orig_exit);
13260 add_bb_to_loop (incr_bb, body_bb->loop_father);
13261 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13262 flag. Set it now to be a FALLTHRU_EDGE. */
13263 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13264 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13265 for (unsigned i = 0;
13266 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13268 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13269 redirect_edge_succ (e, incr_bb);
13271 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13272 e->probability = REG_BR_PROB_BASE;
13273 gsi = gsi_last_bb (incr_bb);
13274 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13275 build_int_cst (unsigned_type_node, 1));
13276 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13278 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13279 struct loop *loop = alloc_loop ();
13280 cfun->has_force_vectorize_loops = true;
13281 loop->safelen = node->simdclone->simdlen;
13282 loop->force_vectorize = true;
13283 loop->header = body_bb;
13285 /* Branch around the body if the mask applies. */
13286 if (node->simdclone->inbranch)
13288 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13289 tree mask_array
13290 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13291 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13292 tree aref = build4 (ARRAY_REF,
13293 TREE_TYPE (TREE_TYPE (mask_array)),
13294 mask_array, iter1,
13295 NULL, NULL);
13296 g = gimple_build_assign (mask, aref);
13297 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13298 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13299 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13301 aref = build1 (VIEW_CONVERT_EXPR,
13302 build_nonstandard_integer_type (bitsize, 0), mask);
13303 mask = make_ssa_name (TREE_TYPE (aref));
13304 g = gimple_build_assign (mask, aref);
13305 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13308 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13309 NULL, NULL);
13310 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13311 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13312 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13315 /* Generate the condition. */
13316 g = gimple_build_cond (LT_EXPR,
13317 iter2,
13318 build_int_cst (unsigned_type_node,
13319 node->simdclone->simdlen),
13320 NULL, NULL);
13321 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13322 e = split_block (incr_bb, gsi_stmt (gsi));
13323 basic_block latch_bb = e->dest;
13324 basic_block new_exit_bb;
13325 new_exit_bb = split_block (latch_bb, NULL)->dest;
13326 loop->latch = latch_bb;
13328 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13330 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13331 /* The successor of incr_bb is already pointing to latch_bb; just
13332 change the flags.
13333 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13334 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13336 gphi *phi = create_phi_node (iter1, body_bb);
13337 edge preheader_edge = find_edge (entry_bb, body_bb);
13338 edge latch_edge = single_succ_edge (latch_bb);
13339 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13340 UNKNOWN_LOCATION);
13341 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13343 /* Generate the new return. */
13344 gsi = gsi_last_bb (new_exit_bb);
13345 if (retval
13346 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13347 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13348 retval = TREE_OPERAND (retval, 0);
13349 else if (retval)
13351 retval = build1 (VIEW_CONVERT_EXPR,
13352 TREE_TYPE (TREE_TYPE (node->decl)),
13353 retval);
13354 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13355 false, GSI_CONTINUE_LINKING);
13357 g = gimple_build_return (retval);
13358 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13360 /* Handle aligned clauses by replacing default defs of the aligned
13361 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13362 lhs. Handle linear by adding PHIs. */
13363 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13364 if (node->simdclone->args[i].alignment
13365 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13366 && (node->simdclone->args[i].alignment
13367 & (node->simdclone->args[i].alignment - 1)) == 0
13368 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13369 == POINTER_TYPE)
13371 unsigned int alignment = node->simdclone->args[i].alignment;
13372 tree orig_arg = node->simdclone->args[i].orig_arg;
13373 tree def = ssa_default_def (cfun, orig_arg);
13374 if (def && !has_zero_uses (def))
13376 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13377 gimple_seq seq = NULL;
13378 bool need_cvt = false;
13379 gcall *call
13380 = gimple_build_call (fn, 2, def, size_int (alignment));
13381 g = call;
13382 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13383 ptr_type_node))
13384 need_cvt = true;
13385 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13386 gimple_call_set_lhs (g, t);
13387 gimple_seq_add_stmt_without_update (&seq, g);
13388 if (need_cvt)
13390 t = make_ssa_name (orig_arg);
13391 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13392 gimple_seq_add_stmt_without_update (&seq, g);
13394 gsi_insert_seq_on_edge_immediate
13395 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13397 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13398 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13399 entry_bb);
13400 node->create_edge (cgraph_node::get_create (fn),
13401 call, entry_bb->count, freq);
13403 imm_use_iterator iter;
13404 use_operand_p use_p;
13405 gimple use_stmt;
13406 tree repl = gimple_get_lhs (g);
13407 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13408 if (is_gimple_debug (use_stmt) || use_stmt == call)
13409 continue;
13410 else
13411 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13412 SET_USE (use_p, repl);
13415 else if (node->simdclone->args[i].arg_type
13416 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13418 tree orig_arg = node->simdclone->args[i].orig_arg;
13419 tree def = ssa_default_def (cfun, orig_arg);
13420 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13421 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13422 if (def && !has_zero_uses (def))
13424 iter1 = make_ssa_name (orig_arg);
13425 iter2 = make_ssa_name (orig_arg);
13426 phi = create_phi_node (iter1, body_bb);
13427 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13428 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13429 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13430 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13431 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13432 ? TREE_TYPE (orig_arg) : sizetype;
13433 tree addcst
13434 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13435 g = gimple_build_assign (iter2, code, iter1, addcst);
13436 gsi = gsi_last_bb (incr_bb);
13437 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13439 imm_use_iterator iter;
13440 use_operand_p use_p;
13441 gimple use_stmt;
13442 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13443 if (use_stmt == phi)
13444 continue;
13445 else
13446 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13447 SET_USE (use_p, iter1);
13451 calculate_dominance_info (CDI_DOMINATORS);
13452 add_loop (loop, loop->header->loop_father);
13453 update_ssa (TODO_update_ssa);
13455 pop_cfun ();
13458 /* If the function in NODE is tagged as an elemental SIMD function,
13459 create the appropriate SIMD clones. */
13461 static void
13462 expand_simd_clones (struct cgraph_node *node)
13464 tree attr = lookup_attribute ("omp declare simd",
13465 DECL_ATTRIBUTES (node->decl));
13466 if (attr == NULL_TREE
13467 || node->global.inlined_to
13468 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13469 return;
13471 /* Ignore
13472 #pragma omp declare simd
13473 extern int foo ();
13474 in C, there we don't know the argument types at all. */
13475 if (!node->definition
13476 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13477 return;
13481 /* Start with parsing the "omp declare simd" attribute(s). */
13482 bool inbranch_clause_specified;
13483 struct cgraph_simd_clone *clone_info
13484 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13485 &inbranch_clause_specified);
13486 if (clone_info == NULL)
13487 continue;
13489 int orig_simdlen = clone_info->simdlen;
13490 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13491 /* The target can return 0 (no simd clones should be created),
13492 1 (just one ISA of simd clones should be created) or higher
13493 count of ISA variants. In that case, clone_info is initialized
13494 for the first ISA variant. */
13495 int count
13496 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13497 base_type, 0);
13498 if (count == 0)
13499 continue;
13501 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13502 also create one inbranch and one !inbranch clone of it. */
13503 for (int i = 0; i < count * 2; i++)
13505 struct cgraph_simd_clone *clone = clone_info;
13506 if (inbranch_clause_specified && (i & 1) != 0)
13507 continue;
13509 if (i != 0)
13511 clone = simd_clone_struct_alloc (clone_info->nargs
13512 + ((i & 1) != 0));
13513 simd_clone_struct_copy (clone, clone_info);
13514 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13515 and simd_clone_adjust_argument_types did to the first
13516 clone's info. */
13517 clone->nargs -= clone_info->inbranch;
13518 clone->simdlen = orig_simdlen;
13519 /* And call the target hook again to get the right ISA. */
13520 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13521 base_type,
13522 i / 2);
13523 if ((i & 1) != 0)
13524 clone->inbranch = 1;
13527 /* simd_clone_mangle might fail if such a clone has been created
13528 already. */
13529 tree id = simd_clone_mangle (node, clone);
13530 if (id == NULL_TREE)
13531 continue;
13533 /* Only when we are sure we want to create the clone actually
13534 clone the function (or definitions) or create another
13535 extern FUNCTION_DECL (for prototypes without definitions). */
13536 struct cgraph_node *n = simd_clone_create (node);
13537 if (n == NULL)
13538 continue;
13540 n->simdclone = clone;
13541 clone->origin = node;
13542 clone->next_clone = NULL;
13543 if (node->simd_clones == NULL)
13545 clone->prev_clone = n;
13546 node->simd_clones = n;
13548 else
13550 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13551 clone->prev_clone->simdclone->next_clone = n;
13552 node->simd_clones->simdclone->prev_clone = n;
13554 symtab->change_decl_assembler_name (n->decl, id);
13555 /* And finally adjust the return type, parameters and for
13556 definitions also function body. */
13557 if (node->definition)
13558 simd_clone_adjust (n);
13559 else
13561 simd_clone_adjust_return_type (n);
13562 simd_clone_adjust_argument_types (n);
13566 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13569 /* Entry point for IPA simd clone creation pass. */
13571 static unsigned int
13572 ipa_omp_simd_clone (void)
13574 struct cgraph_node *node;
13575 FOR_EACH_FUNCTION (node)
13576 expand_simd_clones (node);
13577 return 0;
13580 namespace {
13582 const pass_data pass_data_omp_simd_clone =
13584 SIMPLE_IPA_PASS, /* type */
13585 "simdclone", /* name */
13586 OPTGROUP_NONE, /* optinfo_flags */
13587 TV_NONE, /* tv_id */
13588 ( PROP_ssa | PROP_cfg ), /* properties_required */
13589 0, /* properties_provided */
13590 0, /* properties_destroyed */
13591 0, /* todo_flags_start */
13592 0, /* todo_flags_finish */
13595 class pass_omp_simd_clone : public simple_ipa_opt_pass
13597 public:
13598 pass_omp_simd_clone(gcc::context *ctxt)
13599 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13602 /* opt_pass methods: */
13603 virtual bool gate (function *);
13604 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
13607 bool
13608 pass_omp_simd_clone::gate (function *)
13610 return ((flag_openmp || flag_openmp_simd
13611 || flag_cilkplus
13612 || (in_lto_p && !flag_wpa))
13613 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13616 } // anon namespace
13618 simple_ipa_opt_pass *
13619 make_pass_omp_simd_clone (gcc::context *ctxt)
13621 return new pass_omp_simd_clone (ctxt);
13624 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13625 adds their addresses and sizes to constructor-vector V_CTOR. */
13626 static void
13627 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13628 vec<constructor_elt, va_gc> *v_ctor)
13630 unsigned len = vec_safe_length (v_decls);
13631 for (unsigned i = 0; i < len; i++)
13633 tree it = (*v_decls)[i];
13634 bool is_function = TREE_CODE (it) != VAR_DECL;
13636 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13637 if (!is_function)
13638 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13639 fold_convert (const_ptr_type_node,
13640 DECL_SIZE_UNIT (it)));
13644 /* Create new symbols containing (address, size) pairs for global variables,
13645 marked with "omp declare target" attribute, as well as addresses for the
13646 functions, which are outlined offloading regions. */
13647 void
13648 omp_finish_file (void)
13650 unsigned num_funcs = vec_safe_length (offload_funcs);
13651 unsigned num_vars = vec_safe_length (offload_vars);
13653 if (num_funcs == 0 && num_vars == 0)
13654 return;
13656 if (targetm_common.have_named_sections)
13658 vec<constructor_elt, va_gc> *v_f, *v_v;
13659 vec_alloc (v_f, num_funcs);
13660 vec_alloc (v_v, num_vars * 2);
13662 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13663 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13665 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13666 num_vars * 2);
13667 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13668 num_funcs);
13669 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13670 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13671 tree ctor_v = build_constructor (vars_decl_type, v_v);
13672 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13673 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13674 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13675 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13676 get_identifier (".offload_func_table"),
13677 funcs_decl_type);
13678 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13679 get_identifier (".offload_var_table"),
13680 vars_decl_type);
13681 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13682 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13683 otherwise a joint table in a binary will contain padding between
13684 tables from multiple object files. */
13685 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13686 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13687 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13688 DECL_INITIAL (funcs_decl) = ctor_f;
13689 DECL_INITIAL (vars_decl) = ctor_v;
13690 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13691 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13693 varpool_node::finalize_decl (vars_decl);
13694 varpool_node::finalize_decl (funcs_decl);
13696 else
13698 for (unsigned i = 0; i < num_funcs; i++)
13700 tree it = (*offload_funcs)[i];
13701 targetm.record_offload_symbol (it);
13703 for (unsigned i = 0; i < num_vars; i++)
13705 tree it = (*offload_vars)[i];
13706 targetm.record_offload_symbol (it);
13711 #include "gt-omp-low.h"