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