2015-05-19 Christophe Lyon <christophe.lyon@linaro.org>
[official-gcc.git] / gcc / omp-low.c
blobd352801c0cee173feab4a8594164b8d6e4277a2d
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);
1567 cgraph_node::get (child_fn)->parallelized_function = 1;
1570 /* Destroy a omp_context data structures. Called through the splay tree
1571 value delete callback. */
1573 static void
1574 delete_omp_context (splay_tree_value value)
1576 omp_context *ctx = (omp_context *) value;
1578 delete ctx->cb.decl_map;
1580 if (ctx->field_map)
1581 splay_tree_delete (ctx->field_map);
1582 if (ctx->sfield_map)
1583 splay_tree_delete (ctx->sfield_map);
1584 /* Reduction map is copied to nested contexts, so only delete it in the
1585 owner. */
1586 if (ctx->reduction_map
1587 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1588 && is_gimple_omp_offloaded (ctx->stmt)
1589 && is_gimple_omp_oacc (ctx->stmt))
1590 splay_tree_delete (ctx->reduction_map);
1592 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1593 it produces corrupt debug information. */
1594 if (ctx->record_type)
1596 tree t;
1597 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1598 DECL_ABSTRACT_ORIGIN (t) = NULL;
1600 if (ctx->srecord_type)
1602 tree t;
1603 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1604 DECL_ABSTRACT_ORIGIN (t) = NULL;
1607 if (is_task_ctx (ctx))
1608 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1610 XDELETE (ctx);
1613 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1614 context. */
1616 static void
1617 fixup_child_record_type (omp_context *ctx)
1619 tree f, type = ctx->record_type;
1621 /* ??? It isn't sufficient to just call remap_type here, because
1622 variably_modified_type_p doesn't work the way we expect for
1623 record types. Testing each field for whether it needs remapping
1624 and creating a new record by hand works, however. */
1625 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1626 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1627 break;
1628 if (f)
1630 tree name, new_fields = NULL;
1632 type = lang_hooks.types.make_type (RECORD_TYPE);
1633 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1634 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1635 TYPE_DECL, name, type);
1636 TYPE_NAME (type) = name;
1638 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1640 tree new_f = copy_node (f);
1641 DECL_CONTEXT (new_f) = type;
1642 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1643 DECL_CHAIN (new_f) = new_fields;
1644 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1645 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1646 &ctx->cb, NULL);
1647 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1648 &ctx->cb, NULL);
1649 new_fields = new_f;
1651 /* Arrange to be able to look up the receiver field
1652 given the sender field. */
1653 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1654 (splay_tree_value) new_f);
1656 TYPE_FIELDS (type) = nreverse (new_fields);
1657 layout_type (type);
1660 TREE_TYPE (ctx->receiver_decl)
1661 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1664 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1665 specified by CLAUSES. */
1667 static void
1668 scan_sharing_clauses (tree clauses, omp_context *ctx)
1670 tree c, decl;
1671 bool scan_array_reductions = false;
1673 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1675 bool by_ref;
1677 switch (OMP_CLAUSE_CODE (c))
1679 case OMP_CLAUSE_PRIVATE:
1680 decl = OMP_CLAUSE_DECL (c);
1681 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1682 goto do_private;
1683 else if (!is_variable_sized (decl))
1684 install_var_local (decl, ctx);
1685 break;
1687 case OMP_CLAUSE_SHARED:
1688 decl = OMP_CLAUSE_DECL (c);
1689 /* Ignore shared directives in teams construct. */
1690 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1692 /* Global variables don't need to be copied,
1693 the receiver side will use them directly. */
1694 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1695 if (is_global_var (odecl))
1696 break;
1697 insert_decl_map (&ctx->cb, decl, odecl);
1698 break;
1700 gcc_assert (is_taskreg_ctx (ctx));
1701 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1702 || !is_variable_sized (decl));
1703 /* Global variables don't need to be copied,
1704 the receiver side will use them directly. */
1705 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1706 break;
1707 by_ref = use_pointer_for_field (decl, ctx);
1708 if (! TREE_READONLY (decl)
1709 || TREE_ADDRESSABLE (decl)
1710 || by_ref
1711 || is_reference (decl))
1713 install_var_field (decl, by_ref, 3, ctx);
1714 install_var_local (decl, ctx);
1715 break;
1717 /* We don't need to copy const scalar vars back. */
1718 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1719 goto do_private;
1721 case OMP_CLAUSE_LASTPRIVATE:
1722 /* Let the corresponding firstprivate clause create
1723 the variable. */
1724 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1725 break;
1726 /* FALLTHRU */
1728 case OMP_CLAUSE_FIRSTPRIVATE:
1729 if (is_gimple_omp_oacc (ctx->stmt))
1731 sorry ("clause not supported yet");
1732 break;
1734 /* FALLTHRU */
1735 case OMP_CLAUSE_REDUCTION:
1736 case OMP_CLAUSE_LINEAR:
1737 decl = OMP_CLAUSE_DECL (c);
1738 do_private:
1739 if (is_variable_sized (decl))
1741 if (is_task_ctx (ctx))
1742 install_var_field (decl, false, 1, ctx);
1743 break;
1745 else if (is_taskreg_ctx (ctx))
1747 bool global
1748 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1749 by_ref = use_pointer_for_field (decl, NULL);
1751 if (is_task_ctx (ctx)
1752 && (global || by_ref || is_reference (decl)))
1754 install_var_field (decl, false, 1, ctx);
1755 if (!global)
1756 install_var_field (decl, by_ref, 2, ctx);
1758 else if (!global)
1759 install_var_field (decl, by_ref, 3, ctx);
1761 install_var_local (decl, ctx);
1762 if (is_gimple_omp_oacc (ctx->stmt)
1763 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1765 /* Create a decl for the reduction array. */
1766 tree var = OMP_CLAUSE_DECL (c);
1767 tree type = get_base_type (var);
1768 tree ptype = build_pointer_type (type);
1769 tree array = create_tmp_var (ptype,
1770 oacc_get_reduction_array_id (var));
1771 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1772 install_var_field (array, true, 3, c);
1773 install_var_local (array, c);
1775 /* Insert it into the current context. */
1776 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1777 oacc_get_reduction_array_id (var),
1778 (splay_tree_value) array);
1779 splay_tree_insert (ctx->reduction_map,
1780 (splay_tree_key) array,
1781 (splay_tree_value) array);
1783 break;
1785 case OMP_CLAUSE__LOOPTEMP_:
1786 gcc_assert (is_parallel_ctx (ctx));
1787 decl = OMP_CLAUSE_DECL (c);
1788 install_var_field (decl, false, 3, ctx);
1789 install_var_local (decl, ctx);
1790 break;
1792 case OMP_CLAUSE_COPYPRIVATE:
1793 case OMP_CLAUSE_COPYIN:
1794 decl = OMP_CLAUSE_DECL (c);
1795 by_ref = use_pointer_for_field (decl, NULL);
1796 install_var_field (decl, by_ref, 3, ctx);
1797 break;
1799 case OMP_CLAUSE_DEFAULT:
1800 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1801 break;
1803 case OMP_CLAUSE_FINAL:
1804 case OMP_CLAUSE_IF:
1805 case OMP_CLAUSE_NUM_THREADS:
1806 case OMP_CLAUSE_NUM_TEAMS:
1807 case OMP_CLAUSE_THREAD_LIMIT:
1808 case OMP_CLAUSE_DEVICE:
1809 case OMP_CLAUSE_SCHEDULE:
1810 case OMP_CLAUSE_DIST_SCHEDULE:
1811 case OMP_CLAUSE_DEPEND:
1812 case OMP_CLAUSE__CILK_FOR_COUNT_:
1813 case OMP_CLAUSE_NUM_GANGS:
1814 case OMP_CLAUSE_NUM_WORKERS:
1815 case OMP_CLAUSE_VECTOR_LENGTH:
1816 if (ctx->outer)
1817 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1818 break;
1820 case OMP_CLAUSE_TO:
1821 case OMP_CLAUSE_FROM:
1822 case OMP_CLAUSE_MAP:
1823 if (ctx->outer)
1824 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1825 decl = OMP_CLAUSE_DECL (c);
1826 /* Global variables with "omp declare target" attribute
1827 don't need to be copied, the receiver side will use them
1828 directly. */
1829 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1830 && DECL_P (decl)
1831 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1832 && varpool_node::get_create (decl)->offloadable)
1833 break;
1834 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1835 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
1837 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1838 not offloaded; there is nothing to map for those. */
1839 if (!is_gimple_omp_offloaded (ctx->stmt)
1840 && !POINTER_TYPE_P (TREE_TYPE (decl))
1841 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
1842 break;
1844 if (DECL_P (decl))
1846 if (DECL_SIZE (decl)
1847 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1849 tree decl2 = DECL_VALUE_EXPR (decl);
1850 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1851 decl2 = TREE_OPERAND (decl2, 0);
1852 gcc_assert (DECL_P (decl2));
1853 install_var_field (decl2, true, 3, ctx);
1854 install_var_local (decl2, ctx);
1855 install_var_local (decl, ctx);
1857 else
1859 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1860 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1861 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1862 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1863 install_var_field (decl, true, 7, ctx);
1864 else
1865 install_var_field (decl, true, 3, ctx);
1866 if (is_gimple_omp_offloaded (ctx->stmt))
1867 install_var_local (decl, ctx);
1870 else
1872 tree base = get_base_address (decl);
1873 tree nc = OMP_CLAUSE_CHAIN (c);
1874 if (DECL_P (base)
1875 && nc != NULL_TREE
1876 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1877 && OMP_CLAUSE_DECL (nc) == base
1878 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1879 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1881 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1882 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1884 else
1886 if (ctx->outer)
1888 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1889 decl = OMP_CLAUSE_DECL (c);
1891 gcc_assert (!splay_tree_lookup (ctx->field_map,
1892 (splay_tree_key) decl));
1893 tree field
1894 = build_decl (OMP_CLAUSE_LOCATION (c),
1895 FIELD_DECL, NULL_TREE, ptr_type_node);
1896 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1897 insert_field_into_struct (ctx->record_type, field);
1898 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1899 (splay_tree_value) field);
1902 break;
1904 case OMP_CLAUSE_NOWAIT:
1905 case OMP_CLAUSE_ORDERED:
1906 case OMP_CLAUSE_COLLAPSE:
1907 case OMP_CLAUSE_UNTIED:
1908 case OMP_CLAUSE_MERGEABLE:
1909 case OMP_CLAUSE_PROC_BIND:
1910 case OMP_CLAUSE_SAFELEN:
1911 case OMP_CLAUSE_ASYNC:
1912 case OMP_CLAUSE_WAIT:
1913 case OMP_CLAUSE_GANG:
1914 case OMP_CLAUSE_WORKER:
1915 case OMP_CLAUSE_VECTOR:
1916 break;
1918 case OMP_CLAUSE_ALIGNED:
1919 decl = OMP_CLAUSE_DECL (c);
1920 if (is_global_var (decl)
1921 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1922 install_var_local (decl, ctx);
1923 break;
1925 case OMP_CLAUSE_DEVICE_RESIDENT:
1926 case OMP_CLAUSE_USE_DEVICE:
1927 case OMP_CLAUSE__CACHE_:
1928 case OMP_CLAUSE_INDEPENDENT:
1929 case OMP_CLAUSE_AUTO:
1930 case OMP_CLAUSE_SEQ:
1931 sorry ("Clause not supported yet");
1932 break;
1934 default:
1935 gcc_unreachable ();
1939 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1941 switch (OMP_CLAUSE_CODE (c))
1943 case OMP_CLAUSE_LASTPRIVATE:
1944 /* Let the corresponding firstprivate clause create
1945 the variable. */
1946 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1947 scan_array_reductions = true;
1948 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1949 break;
1950 /* FALLTHRU */
1952 case OMP_CLAUSE_FIRSTPRIVATE:
1953 if (is_gimple_omp_oacc (ctx->stmt))
1955 sorry ("clause not supported yet");
1956 break;
1958 /* FALLTHRU */
1959 case OMP_CLAUSE_PRIVATE:
1960 case OMP_CLAUSE_REDUCTION:
1961 case OMP_CLAUSE_LINEAR:
1962 decl = OMP_CLAUSE_DECL (c);
1963 if (is_variable_sized (decl))
1964 install_var_local (decl, ctx);
1965 fixup_remapped_decl (decl, ctx,
1966 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1967 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1968 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1969 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1970 scan_array_reductions = true;
1971 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1972 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1973 scan_array_reductions = true;
1974 break;
1976 case OMP_CLAUSE_SHARED:
1977 /* Ignore shared directives in teams construct. */
1978 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1979 break;
1980 decl = OMP_CLAUSE_DECL (c);
1981 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1982 fixup_remapped_decl (decl, ctx, false);
1983 break;
1985 case OMP_CLAUSE_MAP:
1986 if (!is_gimple_omp_offloaded (ctx->stmt))
1987 break;
1988 decl = OMP_CLAUSE_DECL (c);
1989 if (DECL_P (decl)
1990 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1991 && varpool_node::get_create (decl)->offloadable)
1992 break;
1993 if (DECL_P (decl))
1995 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1996 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1997 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1999 tree new_decl = lookup_decl (decl, ctx);
2000 TREE_TYPE (new_decl)
2001 = remap_type (TREE_TYPE (decl), &ctx->cb);
2003 else if (DECL_SIZE (decl)
2004 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2006 tree decl2 = DECL_VALUE_EXPR (decl);
2007 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2008 decl2 = TREE_OPERAND (decl2, 0);
2009 gcc_assert (DECL_P (decl2));
2010 fixup_remapped_decl (decl2, ctx, false);
2011 fixup_remapped_decl (decl, ctx, true);
2013 else
2014 fixup_remapped_decl (decl, ctx, false);
2016 break;
2018 case OMP_CLAUSE_COPYPRIVATE:
2019 case OMP_CLAUSE_COPYIN:
2020 case OMP_CLAUSE_DEFAULT:
2021 case OMP_CLAUSE_IF:
2022 case OMP_CLAUSE_NUM_THREADS:
2023 case OMP_CLAUSE_NUM_TEAMS:
2024 case OMP_CLAUSE_THREAD_LIMIT:
2025 case OMP_CLAUSE_DEVICE:
2026 case OMP_CLAUSE_SCHEDULE:
2027 case OMP_CLAUSE_DIST_SCHEDULE:
2028 case OMP_CLAUSE_NOWAIT:
2029 case OMP_CLAUSE_ORDERED:
2030 case OMP_CLAUSE_COLLAPSE:
2031 case OMP_CLAUSE_UNTIED:
2032 case OMP_CLAUSE_FINAL:
2033 case OMP_CLAUSE_MERGEABLE:
2034 case OMP_CLAUSE_PROC_BIND:
2035 case OMP_CLAUSE_SAFELEN:
2036 case OMP_CLAUSE_ALIGNED:
2037 case OMP_CLAUSE_DEPEND:
2038 case OMP_CLAUSE__LOOPTEMP_:
2039 case OMP_CLAUSE_TO:
2040 case OMP_CLAUSE_FROM:
2041 case OMP_CLAUSE__CILK_FOR_COUNT_:
2042 case OMP_CLAUSE_ASYNC:
2043 case OMP_CLAUSE_WAIT:
2044 case OMP_CLAUSE_NUM_GANGS:
2045 case OMP_CLAUSE_NUM_WORKERS:
2046 case OMP_CLAUSE_VECTOR_LENGTH:
2047 case OMP_CLAUSE_GANG:
2048 case OMP_CLAUSE_WORKER:
2049 case OMP_CLAUSE_VECTOR:
2050 break;
2052 case OMP_CLAUSE_DEVICE_RESIDENT:
2053 case OMP_CLAUSE_USE_DEVICE:
2054 case OMP_CLAUSE__CACHE_:
2055 case OMP_CLAUSE_INDEPENDENT:
2056 case OMP_CLAUSE_AUTO:
2057 case OMP_CLAUSE_SEQ:
2058 sorry ("Clause not supported yet");
2059 break;
2061 default:
2062 gcc_unreachable ();
2066 gcc_checking_assert (!scan_array_reductions
2067 || !is_gimple_omp_oacc (ctx->stmt));
2068 if (scan_array_reductions)
2069 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2070 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2071 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2073 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2074 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2076 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2077 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2078 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2079 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2080 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2081 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2084 /* Create a new name for omp child function. Returns an identifier. If
2085 IS_CILK_FOR is true then the suffix for the child function is
2086 "_cilk_for_fn." */
2088 static tree
2089 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2091 if (is_cilk_for)
2092 return clone_function_name (current_function_decl, "_cilk_for_fn");
2093 return clone_function_name (current_function_decl,
2094 task_copy ? "_omp_cpyfn" : "_omp_fn");
2097 /* Returns the type of the induction variable for the child function for
2098 _Cilk_for and the types for _high and _low variables based on TYPE. */
2100 static tree
2101 cilk_for_check_loop_diff_type (tree type)
2103 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2105 if (TYPE_UNSIGNED (type))
2106 return uint32_type_node;
2107 else
2108 return integer_type_node;
2110 else
2112 if (TYPE_UNSIGNED (type))
2113 return uint64_type_node;
2114 else
2115 return long_long_integer_type_node;
2119 /* Build a decl for the omp child function. It'll not contain a body
2120 yet, just the bare decl. */
2122 static void
2123 create_omp_child_function (omp_context *ctx, bool task_copy)
2125 tree decl, type, name, t;
2127 tree cilk_for_count
2128 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2129 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2130 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2131 tree cilk_var_type = NULL_TREE;
2133 name = create_omp_child_function_name (task_copy,
2134 cilk_for_count != NULL_TREE);
2135 if (task_copy)
2136 type = build_function_type_list (void_type_node, ptr_type_node,
2137 ptr_type_node, NULL_TREE);
2138 else if (cilk_for_count)
2140 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2141 cilk_var_type = cilk_for_check_loop_diff_type (type);
2142 type = build_function_type_list (void_type_node, ptr_type_node,
2143 cilk_var_type, cilk_var_type, NULL_TREE);
2145 else
2146 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2148 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2150 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2151 || !task_copy);
2152 if (!task_copy)
2153 ctx->cb.dst_fn = decl;
2154 else
2155 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2157 TREE_STATIC (decl) = 1;
2158 TREE_USED (decl) = 1;
2159 DECL_ARTIFICIAL (decl) = 1;
2160 DECL_IGNORED_P (decl) = 0;
2161 TREE_PUBLIC (decl) = 0;
2162 DECL_UNINLINABLE (decl) = 1;
2163 DECL_EXTERNAL (decl) = 0;
2164 DECL_CONTEXT (decl) = NULL_TREE;
2165 DECL_INITIAL (decl) = make_node (BLOCK);
2166 if (cgraph_node::get (current_function_decl)->offloadable)
2167 cgraph_node::get_create (decl)->offloadable = 1;
2168 else
2170 omp_context *octx;
2171 for (octx = ctx; octx; octx = octx->outer)
2172 if (is_gimple_omp_offloaded (octx->stmt))
2174 cgraph_node::get_create (decl)->offloadable = 1;
2175 #ifdef ENABLE_OFFLOADING
2176 g->have_offload = true;
2177 #endif
2178 break;
2182 if (cgraph_node::get_create (decl)->offloadable
2183 && !lookup_attribute ("omp declare target",
2184 DECL_ATTRIBUTES (current_function_decl)))
2185 DECL_ATTRIBUTES (decl)
2186 = tree_cons (get_identifier ("omp target entrypoint"),
2187 NULL_TREE, DECL_ATTRIBUTES (decl));
2189 t = build_decl (DECL_SOURCE_LOCATION (decl),
2190 RESULT_DECL, NULL_TREE, void_type_node);
2191 DECL_ARTIFICIAL (t) = 1;
2192 DECL_IGNORED_P (t) = 1;
2193 DECL_CONTEXT (t) = decl;
2194 DECL_RESULT (decl) = t;
2196 /* _Cilk_for's child function requires two extra parameters called
2197 __low and __high that are set the by Cilk runtime when it calls this
2198 function. */
2199 if (cilk_for_count)
2201 t = build_decl (DECL_SOURCE_LOCATION (decl),
2202 PARM_DECL, get_identifier ("__high"), 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;
2211 t = build_decl (DECL_SOURCE_LOCATION (decl),
2212 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2213 DECL_ARTIFICIAL (t) = 1;
2214 DECL_NAMELESS (t) = 1;
2215 DECL_ARG_TYPE (t) = ptr_type_node;
2216 DECL_CONTEXT (t) = current_function_decl;
2217 TREE_USED (t) = 1;
2218 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2219 DECL_ARGUMENTS (decl) = t;
2222 tree data_name = get_identifier (".omp_data_i");
2223 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2224 ptr_type_node);
2225 DECL_ARTIFICIAL (t) = 1;
2226 DECL_NAMELESS (t) = 1;
2227 DECL_ARG_TYPE (t) = ptr_type_node;
2228 DECL_CONTEXT (t) = current_function_decl;
2229 TREE_USED (t) = 1;
2230 if (cilk_for_count)
2231 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2232 DECL_ARGUMENTS (decl) = t;
2233 if (!task_copy)
2234 ctx->receiver_decl = t;
2235 else
2237 t = build_decl (DECL_SOURCE_LOCATION (decl),
2238 PARM_DECL, get_identifier (".omp_data_o"),
2239 ptr_type_node);
2240 DECL_ARTIFICIAL (t) = 1;
2241 DECL_NAMELESS (t) = 1;
2242 DECL_ARG_TYPE (t) = ptr_type_node;
2243 DECL_CONTEXT (t) = current_function_decl;
2244 TREE_USED (t) = 1;
2245 TREE_ADDRESSABLE (t) = 1;
2246 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2247 DECL_ARGUMENTS (decl) = t;
2250 /* Allocate memory for the function structure. The call to
2251 allocate_struct_function clobbers CFUN, so we need to restore
2252 it afterward. */
2253 push_struct_function (decl);
2254 cfun->function_end_locus = gimple_location (ctx->stmt);
2255 pop_cfun ();
2258 /* Callback for walk_gimple_seq. Check if combined parallel
2259 contains gimple_omp_for_combined_into_p OMP_FOR. */
2261 static tree
2262 find_combined_for (gimple_stmt_iterator *gsi_p,
2263 bool *handled_ops_p,
2264 struct walk_stmt_info *wi)
2266 gimple stmt = gsi_stmt (*gsi_p);
2268 *handled_ops_p = true;
2269 switch (gimple_code (stmt))
2271 WALK_SUBSTMTS;
2273 case GIMPLE_OMP_FOR:
2274 if (gimple_omp_for_combined_into_p (stmt)
2275 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2277 wi->info = stmt;
2278 return integer_zero_node;
2280 break;
2281 default:
2282 break;
2284 return NULL;
2287 /* Scan an OpenMP parallel directive. */
2289 static void
2290 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2292 omp_context *ctx;
2293 tree name;
2294 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2296 /* Ignore parallel directives with empty bodies, unless there
2297 are copyin clauses. */
2298 if (optimize > 0
2299 && empty_body_p (gimple_omp_body (stmt))
2300 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2301 OMP_CLAUSE_COPYIN) == NULL)
2303 gsi_replace (gsi, gimple_build_nop (), false);
2304 return;
2307 if (gimple_omp_parallel_combined_p (stmt))
2309 struct walk_stmt_info wi;
2311 memset (&wi, 0, sizeof (wi));
2312 wi.val_only = true;
2313 walk_gimple_seq (gimple_omp_body (stmt),
2314 find_combined_for, NULL, &wi);
2315 if (wi.info)
2317 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2318 struct omp_for_data fd;
2319 extract_omp_for_data (for_stmt, &fd, NULL);
2320 /* We need two temporaries with fd.loop.v type (istart/iend)
2321 and then (fd.collapse - 1) temporaries with the same
2322 type for count2 ... countN-1 vars if not constant. */
2323 size_t count = 2, i;
2324 tree type = fd.iter_type;
2325 if (fd.collapse > 1
2326 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2327 count += fd.collapse - 1;
2328 for (i = 0; i < count; i++)
2330 tree temp = create_tmp_var (type);
2331 tree c = build_omp_clause (UNKNOWN_LOCATION,
2332 OMP_CLAUSE__LOOPTEMP_);
2333 insert_decl_map (&outer_ctx->cb, temp, temp);
2334 OMP_CLAUSE_DECL (c) = temp;
2335 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2336 gimple_omp_parallel_set_clauses (stmt, c);
2341 ctx = new_omp_context (stmt, outer_ctx);
2342 taskreg_contexts.safe_push (ctx);
2343 if (taskreg_nesting_level > 1)
2344 ctx->is_nested = true;
2345 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2346 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2347 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2348 name = create_tmp_var_name (".omp_data_s");
2349 name = build_decl (gimple_location (stmt),
2350 TYPE_DECL, name, ctx->record_type);
2351 DECL_ARTIFICIAL (name) = 1;
2352 DECL_NAMELESS (name) = 1;
2353 TYPE_NAME (ctx->record_type) = name;
2354 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2355 create_omp_child_function (ctx, false);
2356 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2358 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2359 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2361 if (TYPE_FIELDS (ctx->record_type) == NULL)
2362 ctx->record_type = ctx->receiver_decl = NULL;
2365 /* Scan an OpenMP task directive. */
2367 static void
2368 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2370 omp_context *ctx;
2371 tree name, t;
2372 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2374 /* Ignore task directives with empty bodies. */
2375 if (optimize > 0
2376 && empty_body_p (gimple_omp_body (stmt)))
2378 gsi_replace (gsi, gimple_build_nop (), false);
2379 return;
2382 ctx = new_omp_context (stmt, outer_ctx);
2383 taskreg_contexts.safe_push (ctx);
2384 if (taskreg_nesting_level > 1)
2385 ctx->is_nested = true;
2386 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2387 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2388 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2389 name = create_tmp_var_name (".omp_data_s");
2390 name = build_decl (gimple_location (stmt),
2391 TYPE_DECL, name, ctx->record_type);
2392 DECL_ARTIFICIAL (name) = 1;
2393 DECL_NAMELESS (name) = 1;
2394 TYPE_NAME (ctx->record_type) = name;
2395 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2396 create_omp_child_function (ctx, false);
2397 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2399 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2401 if (ctx->srecord_type)
2403 name = create_tmp_var_name (".omp_data_a");
2404 name = build_decl (gimple_location (stmt),
2405 TYPE_DECL, name, ctx->srecord_type);
2406 DECL_ARTIFICIAL (name) = 1;
2407 DECL_NAMELESS (name) = 1;
2408 TYPE_NAME (ctx->srecord_type) = name;
2409 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2410 create_omp_child_function (ctx, true);
2413 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2415 if (TYPE_FIELDS (ctx->record_type) == NULL)
2417 ctx->record_type = ctx->receiver_decl = NULL;
2418 t = build_int_cst (long_integer_type_node, 0);
2419 gimple_omp_task_set_arg_size (stmt, t);
2420 t = build_int_cst (long_integer_type_node, 1);
2421 gimple_omp_task_set_arg_align (stmt, t);
2426 /* If any decls have been made addressable during scan_omp,
2427 adjust their fields if needed, and layout record types
2428 of parallel/task constructs. */
2430 static void
2431 finish_taskreg_scan (omp_context *ctx)
2433 if (ctx->record_type == NULL_TREE)
2434 return;
2436 /* If any task_shared_vars were needed, verify all
2437 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2438 statements if use_pointer_for_field hasn't changed
2439 because of that. If it did, update field types now. */
2440 if (task_shared_vars)
2442 tree c;
2444 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2445 c; c = OMP_CLAUSE_CHAIN (c))
2446 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2448 tree decl = OMP_CLAUSE_DECL (c);
2450 /* Global variables don't need to be copied,
2451 the receiver side will use them directly. */
2452 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2453 continue;
2454 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2455 || !use_pointer_for_field (decl, ctx))
2456 continue;
2457 tree field = lookup_field (decl, ctx);
2458 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2459 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2460 continue;
2461 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2462 TREE_THIS_VOLATILE (field) = 0;
2463 DECL_USER_ALIGN (field) = 0;
2464 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2465 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2466 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2467 if (ctx->srecord_type)
2469 tree sfield = lookup_sfield (decl, ctx);
2470 TREE_TYPE (sfield) = TREE_TYPE (field);
2471 TREE_THIS_VOLATILE (sfield) = 0;
2472 DECL_USER_ALIGN (sfield) = 0;
2473 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2474 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2475 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2480 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2482 layout_type (ctx->record_type);
2483 fixup_child_record_type (ctx);
2485 else
2487 location_t loc = gimple_location (ctx->stmt);
2488 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2489 /* Move VLA fields to the end. */
2490 p = &TYPE_FIELDS (ctx->record_type);
2491 while (*p)
2492 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2493 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2495 *q = *p;
2496 *p = TREE_CHAIN (*p);
2497 TREE_CHAIN (*q) = NULL_TREE;
2498 q = &TREE_CHAIN (*q);
2500 else
2501 p = &DECL_CHAIN (*p);
2502 *p = vla_fields;
2503 layout_type (ctx->record_type);
2504 fixup_child_record_type (ctx);
2505 if (ctx->srecord_type)
2506 layout_type (ctx->srecord_type);
2507 tree t = fold_convert_loc (loc, long_integer_type_node,
2508 TYPE_SIZE_UNIT (ctx->record_type));
2509 gimple_omp_task_set_arg_size (ctx->stmt, t);
2510 t = build_int_cst (long_integer_type_node,
2511 TYPE_ALIGN_UNIT (ctx->record_type));
2512 gimple_omp_task_set_arg_align (ctx->stmt, t);
2517 static omp_context *
2518 enclosing_target_ctx (omp_context *ctx)
2520 while (ctx != NULL
2521 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2522 ctx = ctx->outer;
2523 gcc_assert (ctx != NULL);
2524 return ctx;
2527 static bool
2528 oacc_loop_or_target_p (gimple stmt)
2530 enum gimple_code outer_type = gimple_code (stmt);
2531 return ((outer_type == GIMPLE_OMP_TARGET
2532 && ((gimple_omp_target_kind (stmt)
2533 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2534 || (gimple_omp_target_kind (stmt)
2535 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2536 || (outer_type == GIMPLE_OMP_FOR
2537 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2540 /* Scan a GIMPLE_OMP_FOR. */
2542 static void
2543 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2545 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
2546 omp_context *ctx;
2547 size_t i;
2548 tree clauses = gimple_omp_for_clauses (stmt);
2550 if (outer_ctx)
2551 outer_type = gimple_code (outer_ctx->stmt);
2553 ctx = new_omp_context (stmt, outer_ctx);
2555 if (is_gimple_omp_oacc (stmt))
2557 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2558 ctx->gwv_this = outer_ctx->gwv_this;
2559 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2561 int val;
2562 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2563 val = MASK_GANG;
2564 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2565 val = MASK_WORKER;
2566 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2567 val = MASK_VECTOR;
2568 else
2569 continue;
2570 ctx->gwv_this |= val;
2571 if (!outer_ctx)
2573 /* Skip; not nested inside a region. */
2574 continue;
2576 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2578 /* Skip; not nested inside an OpenACC region. */
2579 continue;
2581 if (outer_type == GIMPLE_OMP_FOR)
2582 outer_ctx->gwv_below |= val;
2583 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2585 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2586 if (gimple_omp_target_kind (enclosing->stmt)
2587 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2588 error_at (gimple_location (stmt),
2589 "no arguments allowed to gang, worker and vector clauses inside parallel");
2594 scan_sharing_clauses (clauses, ctx);
2596 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2597 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2599 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2600 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2601 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2602 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2604 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2606 if (is_gimple_omp_oacc (stmt))
2608 if (ctx->gwv_this & ctx->gwv_below)
2609 error_at (gimple_location (stmt),
2610 "gang, worker and vector may occur only once in a loop nest");
2611 else if (ctx->gwv_below != 0
2612 && ctx->gwv_this > ctx->gwv_below)
2613 error_at (gimple_location (stmt),
2614 "gang, worker and vector must occur in this order in a loop nest");
2615 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2616 outer_ctx->gwv_below |= ctx->gwv_below;
2620 /* Scan an OpenMP sections directive. */
2622 static void
2623 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2625 omp_context *ctx;
2627 ctx = new_omp_context (stmt, outer_ctx);
2628 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2629 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2632 /* Scan an OpenMP single directive. */
2634 static void
2635 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2637 omp_context *ctx;
2638 tree name;
2640 ctx = new_omp_context (stmt, outer_ctx);
2641 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2642 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2643 name = create_tmp_var_name (".omp_copy_s");
2644 name = build_decl (gimple_location (stmt),
2645 TYPE_DECL, name, ctx->record_type);
2646 TYPE_NAME (ctx->record_type) = name;
2648 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2649 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2651 if (TYPE_FIELDS (ctx->record_type) == NULL)
2652 ctx->record_type = NULL;
2653 else
2654 layout_type (ctx->record_type);
2657 /* Scan a GIMPLE_OMP_TARGET. */
2659 static void
2660 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2662 omp_context *ctx;
2663 tree name;
2664 bool offloaded = is_gimple_omp_offloaded (stmt);
2665 tree clauses = gimple_omp_target_clauses (stmt);
2667 ctx = new_omp_context (stmt, outer_ctx);
2668 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2669 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2670 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2671 name = create_tmp_var_name (".omp_data_t");
2672 name = build_decl (gimple_location (stmt),
2673 TYPE_DECL, name, ctx->record_type);
2674 DECL_ARTIFICIAL (name) = 1;
2675 DECL_NAMELESS (name) = 1;
2676 TYPE_NAME (ctx->record_type) = name;
2677 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2678 if (offloaded)
2680 if (is_gimple_omp_oacc (stmt))
2681 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2682 0, 0);
2684 create_omp_child_function (ctx, false);
2685 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2688 if (is_gimple_omp_oacc (stmt))
2690 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2692 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2693 ctx->gwv_this |= MASK_GANG;
2694 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2695 ctx->gwv_this |= MASK_WORKER;
2696 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2697 ctx->gwv_this |= MASK_VECTOR;
2701 scan_sharing_clauses (clauses, ctx);
2702 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2704 if (TYPE_FIELDS (ctx->record_type) == NULL)
2705 ctx->record_type = ctx->receiver_decl = NULL;
2706 else
2708 TYPE_FIELDS (ctx->record_type)
2709 = nreverse (TYPE_FIELDS (ctx->record_type));
2710 #ifdef ENABLE_CHECKING
2711 tree field;
2712 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2713 for (field = TYPE_FIELDS (ctx->record_type);
2714 field;
2715 field = DECL_CHAIN (field))
2716 gcc_assert (DECL_ALIGN (field) == align);
2717 #endif
2718 layout_type (ctx->record_type);
2719 if (offloaded)
2720 fixup_child_record_type (ctx);
2724 /* Scan an OpenMP teams directive. */
2726 static void
2727 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2729 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2730 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2731 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2734 /* Check nesting restrictions. */
2735 static bool
2736 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2738 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2739 inside an OpenACC CTX. */
2740 if (!(is_gimple_omp (stmt)
2741 && is_gimple_omp_oacc (stmt)))
2743 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2744 if (is_gimple_omp (ctx_->stmt)
2745 && is_gimple_omp_oacc (ctx_->stmt))
2747 error_at (gimple_location (stmt),
2748 "non-OpenACC construct inside of OpenACC region");
2749 return false;
2753 if (ctx != NULL)
2755 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2756 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2758 error_at (gimple_location (stmt),
2759 "OpenMP constructs may not be nested inside simd region");
2760 return false;
2762 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2764 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2765 || (gimple_omp_for_kind (stmt)
2766 != GF_OMP_FOR_KIND_DISTRIBUTE))
2767 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2769 error_at (gimple_location (stmt),
2770 "only distribute or parallel constructs are allowed to "
2771 "be closely nested inside teams construct");
2772 return false;
2776 switch (gimple_code (stmt))
2778 case GIMPLE_OMP_FOR:
2779 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2780 return true;
2781 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2783 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2785 error_at (gimple_location (stmt),
2786 "distribute construct must be closely nested inside "
2787 "teams construct");
2788 return false;
2790 return true;
2792 /* FALLTHRU */
2793 case GIMPLE_CALL:
2794 if (is_gimple_call (stmt)
2795 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2796 == BUILT_IN_GOMP_CANCEL
2797 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2798 == BUILT_IN_GOMP_CANCELLATION_POINT))
2800 const char *bad = NULL;
2801 const char *kind = NULL;
2802 if (ctx == NULL)
2804 error_at (gimple_location (stmt), "orphaned %qs construct",
2805 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2806 == BUILT_IN_GOMP_CANCEL
2807 ? "#pragma omp cancel"
2808 : "#pragma omp cancellation point");
2809 return false;
2811 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2812 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2813 : 0)
2815 case 1:
2816 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2817 bad = "#pragma omp parallel";
2818 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2819 == BUILT_IN_GOMP_CANCEL
2820 && !integer_zerop (gimple_call_arg (stmt, 1)))
2821 ctx->cancellable = true;
2822 kind = "parallel";
2823 break;
2824 case 2:
2825 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2826 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2827 bad = "#pragma omp for";
2828 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2829 == BUILT_IN_GOMP_CANCEL
2830 && !integer_zerop (gimple_call_arg (stmt, 1)))
2832 ctx->cancellable = true;
2833 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2834 OMP_CLAUSE_NOWAIT))
2835 warning_at (gimple_location (stmt), 0,
2836 "%<#pragma omp cancel for%> inside "
2837 "%<nowait%> for construct");
2838 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2839 OMP_CLAUSE_ORDERED))
2840 warning_at (gimple_location (stmt), 0,
2841 "%<#pragma omp cancel for%> inside "
2842 "%<ordered%> for construct");
2844 kind = "for";
2845 break;
2846 case 4:
2847 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2848 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2849 bad = "#pragma omp sections";
2850 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2851 == BUILT_IN_GOMP_CANCEL
2852 && !integer_zerop (gimple_call_arg (stmt, 1)))
2854 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2856 ctx->cancellable = true;
2857 if (find_omp_clause (gimple_omp_sections_clauses
2858 (ctx->stmt),
2859 OMP_CLAUSE_NOWAIT))
2860 warning_at (gimple_location (stmt), 0,
2861 "%<#pragma omp cancel sections%> inside "
2862 "%<nowait%> sections construct");
2864 else
2866 gcc_assert (ctx->outer
2867 && gimple_code (ctx->outer->stmt)
2868 == GIMPLE_OMP_SECTIONS);
2869 ctx->outer->cancellable = true;
2870 if (find_omp_clause (gimple_omp_sections_clauses
2871 (ctx->outer->stmt),
2872 OMP_CLAUSE_NOWAIT))
2873 warning_at (gimple_location (stmt), 0,
2874 "%<#pragma omp cancel sections%> inside "
2875 "%<nowait%> sections construct");
2878 kind = "sections";
2879 break;
2880 case 8:
2881 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2882 bad = "#pragma omp task";
2883 else
2884 ctx->cancellable = true;
2885 kind = "taskgroup";
2886 break;
2887 default:
2888 error_at (gimple_location (stmt), "invalid arguments");
2889 return false;
2891 if (bad)
2893 error_at (gimple_location (stmt),
2894 "%<%s %s%> construct not closely nested inside of %qs",
2895 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2896 == BUILT_IN_GOMP_CANCEL
2897 ? "#pragma omp cancel"
2898 : "#pragma omp cancellation point", kind, bad);
2899 return false;
2902 /* FALLTHRU */
2903 case GIMPLE_OMP_SECTIONS:
2904 case GIMPLE_OMP_SINGLE:
2905 for (; ctx != NULL; ctx = ctx->outer)
2906 switch (gimple_code (ctx->stmt))
2908 case GIMPLE_OMP_FOR:
2909 case GIMPLE_OMP_SECTIONS:
2910 case GIMPLE_OMP_SINGLE:
2911 case GIMPLE_OMP_ORDERED:
2912 case GIMPLE_OMP_MASTER:
2913 case GIMPLE_OMP_TASK:
2914 case GIMPLE_OMP_CRITICAL:
2915 if (is_gimple_call (stmt))
2917 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2918 != BUILT_IN_GOMP_BARRIER)
2919 return true;
2920 error_at (gimple_location (stmt),
2921 "barrier region may not be closely nested inside "
2922 "of work-sharing, critical, ordered, master or "
2923 "explicit task region");
2924 return false;
2926 error_at (gimple_location (stmt),
2927 "work-sharing region may not be closely nested inside "
2928 "of work-sharing, critical, ordered, master or explicit "
2929 "task region");
2930 return false;
2931 case GIMPLE_OMP_PARALLEL:
2932 return true;
2933 default:
2934 break;
2936 break;
2937 case GIMPLE_OMP_MASTER:
2938 for (; ctx != NULL; ctx = ctx->outer)
2939 switch (gimple_code (ctx->stmt))
2941 case GIMPLE_OMP_FOR:
2942 case GIMPLE_OMP_SECTIONS:
2943 case GIMPLE_OMP_SINGLE:
2944 case GIMPLE_OMP_TASK:
2945 error_at (gimple_location (stmt),
2946 "master region may not be closely nested inside "
2947 "of work-sharing or explicit task region");
2948 return false;
2949 case GIMPLE_OMP_PARALLEL:
2950 return true;
2951 default:
2952 break;
2954 break;
2955 case GIMPLE_OMP_ORDERED:
2956 for (; ctx != NULL; ctx = ctx->outer)
2957 switch (gimple_code (ctx->stmt))
2959 case GIMPLE_OMP_CRITICAL:
2960 case GIMPLE_OMP_TASK:
2961 error_at (gimple_location (stmt),
2962 "ordered region may not be closely nested inside "
2963 "of critical or explicit task region");
2964 return false;
2965 case GIMPLE_OMP_FOR:
2966 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2967 OMP_CLAUSE_ORDERED) == NULL)
2969 error_at (gimple_location (stmt),
2970 "ordered region must be closely nested inside "
2971 "a loop region with an ordered clause");
2972 return false;
2974 return true;
2975 case GIMPLE_OMP_PARALLEL:
2976 error_at (gimple_location (stmt),
2977 "ordered region must be closely nested inside "
2978 "a loop region with an ordered clause");
2979 return false;
2980 default:
2981 break;
2983 break;
2984 case GIMPLE_OMP_CRITICAL:
2986 tree this_stmt_name
2987 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2988 for (; ctx != NULL; ctx = ctx->outer)
2989 if (gomp_critical *other_crit
2990 = dyn_cast <gomp_critical *> (ctx->stmt))
2991 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2993 error_at (gimple_location (stmt),
2994 "critical region may not be nested inside a critical "
2995 "region with the same name");
2996 return false;
2999 break;
3000 case GIMPLE_OMP_TEAMS:
3001 if (ctx == NULL
3002 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3003 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3005 error_at (gimple_location (stmt),
3006 "teams construct not closely nested inside of target "
3007 "region");
3008 return false;
3010 break;
3011 case GIMPLE_OMP_TARGET:
3012 for (; ctx != NULL; ctx = ctx->outer)
3014 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3016 if (is_gimple_omp (stmt)
3017 && is_gimple_omp_oacc (stmt)
3018 && is_gimple_omp (ctx->stmt))
3020 error_at (gimple_location (stmt),
3021 "OpenACC construct inside of non-OpenACC region");
3022 return false;
3024 continue;
3027 const char *stmt_name, *ctx_stmt_name;
3028 switch (gimple_omp_target_kind (stmt))
3030 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3031 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3032 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3033 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3034 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3035 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3036 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3037 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3038 default: gcc_unreachable ();
3040 switch (gimple_omp_target_kind (ctx->stmt))
3042 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3043 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3044 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3045 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3046 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3047 default: gcc_unreachable ();
3050 /* OpenACC/OpenMP mismatch? */
3051 if (is_gimple_omp_oacc (stmt)
3052 != is_gimple_omp_oacc (ctx->stmt))
3054 error_at (gimple_location (stmt),
3055 "%s %s construct inside of %s %s region",
3056 (is_gimple_omp_oacc (stmt)
3057 ? "OpenACC" : "OpenMP"), stmt_name,
3058 (is_gimple_omp_oacc (ctx->stmt)
3059 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3060 return false;
3062 if (is_gimple_omp_offloaded (ctx->stmt))
3064 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3065 if (is_gimple_omp_oacc (ctx->stmt))
3067 error_at (gimple_location (stmt),
3068 "%s construct inside of %s region",
3069 stmt_name, ctx_stmt_name);
3070 return false;
3072 else
3074 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3075 warning_at (gimple_location (stmt), 0,
3076 "%s construct inside of %s region",
3077 stmt_name, ctx_stmt_name);
3081 break;
3082 default:
3083 break;
3085 return true;
3089 /* Helper function scan_omp.
3091 Callback for walk_tree or operators in walk_gimple_stmt used to
3092 scan for OMP directives in TP. */
3094 static tree
3095 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3097 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3098 omp_context *ctx = (omp_context *) wi->info;
3099 tree t = *tp;
3101 switch (TREE_CODE (t))
3103 case VAR_DECL:
3104 case PARM_DECL:
3105 case LABEL_DECL:
3106 case RESULT_DECL:
3107 if (ctx)
3108 *tp = remap_decl (t, &ctx->cb);
3109 break;
3111 default:
3112 if (ctx && TYPE_P (t))
3113 *tp = remap_type (t, &ctx->cb);
3114 else if (!DECL_P (t))
3116 *walk_subtrees = 1;
3117 if (ctx)
3119 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3120 if (tem != TREE_TYPE (t))
3122 if (TREE_CODE (t) == INTEGER_CST)
3123 *tp = wide_int_to_tree (tem, t);
3124 else
3125 TREE_TYPE (t) = tem;
3129 break;
3132 return NULL_TREE;
3135 /* Return true if FNDECL is a setjmp or a longjmp. */
3137 static bool
3138 setjmp_or_longjmp_p (const_tree fndecl)
3140 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3141 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3142 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3143 return true;
3145 tree declname = DECL_NAME (fndecl);
3146 if (!declname)
3147 return false;
3148 const char *name = IDENTIFIER_POINTER (declname);
3149 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3153 /* Helper function for scan_omp.
3155 Callback for walk_gimple_stmt used to scan for OMP directives in
3156 the current statement in GSI. */
3158 static tree
3159 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3160 struct walk_stmt_info *wi)
3162 gimple stmt = gsi_stmt (*gsi);
3163 omp_context *ctx = (omp_context *) wi->info;
3165 if (gimple_has_location (stmt))
3166 input_location = gimple_location (stmt);
3168 /* Check the nesting restrictions. */
3169 bool remove = false;
3170 if (is_gimple_omp (stmt))
3171 remove = !check_omp_nesting_restrictions (stmt, ctx);
3172 else if (is_gimple_call (stmt))
3174 tree fndecl = gimple_call_fndecl (stmt);
3175 if (fndecl)
3177 if (setjmp_or_longjmp_p (fndecl)
3178 && ctx
3179 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3180 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3182 remove = true;
3183 error_at (gimple_location (stmt),
3184 "setjmp/longjmp inside simd construct");
3186 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3187 switch (DECL_FUNCTION_CODE (fndecl))
3189 case BUILT_IN_GOMP_BARRIER:
3190 case BUILT_IN_GOMP_CANCEL:
3191 case BUILT_IN_GOMP_CANCELLATION_POINT:
3192 case BUILT_IN_GOMP_TASKYIELD:
3193 case BUILT_IN_GOMP_TASKWAIT:
3194 case BUILT_IN_GOMP_TASKGROUP_START:
3195 case BUILT_IN_GOMP_TASKGROUP_END:
3196 remove = !check_omp_nesting_restrictions (stmt, ctx);
3197 break;
3198 default:
3199 break;
3203 if (remove)
3205 stmt = gimple_build_nop ();
3206 gsi_replace (gsi, stmt, false);
3209 *handled_ops_p = true;
3211 switch (gimple_code (stmt))
3213 case GIMPLE_OMP_PARALLEL:
3214 taskreg_nesting_level++;
3215 scan_omp_parallel (gsi, ctx);
3216 taskreg_nesting_level--;
3217 break;
3219 case GIMPLE_OMP_TASK:
3220 taskreg_nesting_level++;
3221 scan_omp_task (gsi, ctx);
3222 taskreg_nesting_level--;
3223 break;
3225 case GIMPLE_OMP_FOR:
3226 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3227 break;
3229 case GIMPLE_OMP_SECTIONS:
3230 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3231 break;
3233 case GIMPLE_OMP_SINGLE:
3234 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3235 break;
3237 case GIMPLE_OMP_SECTION:
3238 case GIMPLE_OMP_MASTER:
3239 case GIMPLE_OMP_TASKGROUP:
3240 case GIMPLE_OMP_ORDERED:
3241 case GIMPLE_OMP_CRITICAL:
3242 ctx = new_omp_context (stmt, ctx);
3243 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3244 break;
3246 case GIMPLE_OMP_TARGET:
3247 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3248 break;
3250 case GIMPLE_OMP_TEAMS:
3251 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3252 break;
3254 case GIMPLE_BIND:
3256 tree var;
3258 *handled_ops_p = false;
3259 if (ctx)
3260 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3261 var ;
3262 var = DECL_CHAIN (var))
3263 insert_decl_map (&ctx->cb, var, var);
3265 break;
3266 default:
3267 *handled_ops_p = false;
3268 break;
3271 return NULL_TREE;
3275 /* Scan all the statements starting at the current statement. CTX
3276 contains context information about the OMP directives and
3277 clauses found during the scan. */
3279 static void
3280 scan_omp (gimple_seq *body_p, omp_context *ctx)
3282 location_t saved_location;
3283 struct walk_stmt_info wi;
3285 memset (&wi, 0, sizeof (wi));
3286 wi.info = ctx;
3287 wi.want_locations = true;
3289 saved_location = input_location;
3290 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3291 input_location = saved_location;
3294 /* Re-gimplification and code generation routines. */
3296 /* Build a call to GOMP_barrier. */
3298 static gimple
3299 build_omp_barrier (tree lhs)
3301 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3302 : BUILT_IN_GOMP_BARRIER);
3303 gcall *g = gimple_build_call (fndecl, 0);
3304 if (lhs)
3305 gimple_call_set_lhs (g, lhs);
3306 return g;
3309 /* If a context was created for STMT when it was scanned, return it. */
3311 static omp_context *
3312 maybe_lookup_ctx (gimple stmt)
3314 splay_tree_node n;
3315 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3316 return n ? (omp_context *) n->value : NULL;
3320 /* Find the mapping for DECL in CTX or the immediately enclosing
3321 context that has a mapping for DECL.
3323 If CTX is a nested parallel directive, we may have to use the decl
3324 mappings created in CTX's parent context. Suppose that we have the
3325 following parallel nesting (variable UIDs showed for clarity):
3327 iD.1562 = 0;
3328 #omp parallel shared(iD.1562) -> outer parallel
3329 iD.1562 = iD.1562 + 1;
3331 #omp parallel shared (iD.1562) -> inner parallel
3332 iD.1562 = iD.1562 - 1;
3334 Each parallel structure will create a distinct .omp_data_s structure
3335 for copying iD.1562 in/out of the directive:
3337 outer parallel .omp_data_s.1.i -> iD.1562
3338 inner parallel .omp_data_s.2.i -> iD.1562
3340 A shared variable mapping will produce a copy-out operation before
3341 the parallel directive and a copy-in operation after it. So, in
3342 this case we would have:
3344 iD.1562 = 0;
3345 .omp_data_o.1.i = iD.1562;
3346 #omp parallel shared(iD.1562) -> outer parallel
3347 .omp_data_i.1 = &.omp_data_o.1
3348 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3350 .omp_data_o.2.i = iD.1562; -> **
3351 #omp parallel shared(iD.1562) -> inner parallel
3352 .omp_data_i.2 = &.omp_data_o.2
3353 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3356 ** This is a problem. The symbol iD.1562 cannot be referenced
3357 inside the body of the outer parallel region. But since we are
3358 emitting this copy operation while expanding the inner parallel
3359 directive, we need to access the CTX structure of the outer
3360 parallel directive to get the correct mapping:
3362 .omp_data_o.2.i = .omp_data_i.1->i
3364 Since there may be other workshare or parallel directives enclosing
3365 the parallel directive, it may be necessary to walk up the context
3366 parent chain. This is not a problem in general because nested
3367 parallelism happens only rarely. */
3369 static tree
3370 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3372 tree t;
3373 omp_context *up;
3375 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3376 t = maybe_lookup_decl (decl, up);
3378 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3380 return t ? t : decl;
3384 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3385 in outer contexts. */
3387 static tree
3388 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3390 tree t = NULL;
3391 omp_context *up;
3393 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3394 t = maybe_lookup_decl (decl, up);
3396 return t ? t : decl;
3400 /* Construct the initialization value for reduction CLAUSE. */
3402 tree
3403 omp_reduction_init (tree clause, tree type)
3405 location_t loc = OMP_CLAUSE_LOCATION (clause);
3406 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3408 case PLUS_EXPR:
3409 case MINUS_EXPR:
3410 case BIT_IOR_EXPR:
3411 case BIT_XOR_EXPR:
3412 case TRUTH_OR_EXPR:
3413 case TRUTH_ORIF_EXPR:
3414 case TRUTH_XOR_EXPR:
3415 case NE_EXPR:
3416 return build_zero_cst (type);
3418 case MULT_EXPR:
3419 case TRUTH_AND_EXPR:
3420 case TRUTH_ANDIF_EXPR:
3421 case EQ_EXPR:
3422 return fold_convert_loc (loc, type, integer_one_node);
3424 case BIT_AND_EXPR:
3425 return fold_convert_loc (loc, type, integer_minus_one_node);
3427 case MAX_EXPR:
3428 if (SCALAR_FLOAT_TYPE_P (type))
3430 REAL_VALUE_TYPE max, min;
3431 if (HONOR_INFINITIES (type))
3433 real_inf (&max);
3434 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3436 else
3437 real_maxval (&min, 1, TYPE_MODE (type));
3438 return build_real (type, min);
3440 else
3442 gcc_assert (INTEGRAL_TYPE_P (type));
3443 return TYPE_MIN_VALUE (type);
3446 case MIN_EXPR:
3447 if (SCALAR_FLOAT_TYPE_P (type))
3449 REAL_VALUE_TYPE max;
3450 if (HONOR_INFINITIES (type))
3451 real_inf (&max);
3452 else
3453 real_maxval (&max, 0, TYPE_MODE (type));
3454 return build_real (type, max);
3456 else
3458 gcc_assert (INTEGRAL_TYPE_P (type));
3459 return TYPE_MAX_VALUE (type);
3462 default:
3463 gcc_unreachable ();
3467 /* Return alignment to be assumed for var in CLAUSE, which should be
3468 OMP_CLAUSE_ALIGNED. */
3470 static tree
3471 omp_clause_aligned_alignment (tree clause)
3473 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3474 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3476 /* Otherwise return implementation defined alignment. */
3477 unsigned int al = 1;
3478 machine_mode mode, vmode;
3479 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3480 if (vs)
3481 vs = 1 << floor_log2 (vs);
3482 static enum mode_class classes[]
3483 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3484 for (int i = 0; i < 4; i += 2)
3485 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3486 mode != VOIDmode;
3487 mode = GET_MODE_WIDER_MODE (mode))
3489 vmode = targetm.vectorize.preferred_simd_mode (mode);
3490 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3491 continue;
3492 while (vs
3493 && GET_MODE_SIZE (vmode) < vs
3494 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3495 vmode = GET_MODE_2XWIDER_MODE (vmode);
3497 tree type = lang_hooks.types.type_for_mode (mode, 1);
3498 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3499 continue;
3500 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3501 / GET_MODE_SIZE (mode));
3502 if (TYPE_MODE (type) != vmode)
3503 continue;
3504 if (TYPE_ALIGN_UNIT (type) > al)
3505 al = TYPE_ALIGN_UNIT (type);
3507 return build_int_cst (integer_type_node, al);
3510 /* Return maximum possible vectorization factor for the target. */
3512 static int
3513 omp_max_vf (void)
3515 if (!optimize
3516 || optimize_debug
3517 || !flag_tree_loop_optimize
3518 || (!flag_tree_loop_vectorize
3519 && (global_options_set.x_flag_tree_loop_vectorize
3520 || global_options_set.x_flag_tree_vectorize)))
3521 return 1;
3523 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3524 if (vs)
3526 vs = 1 << floor_log2 (vs);
3527 return vs;
3529 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3530 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3531 return GET_MODE_NUNITS (vqimode);
3532 return 1;
3535 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3536 privatization. */
3538 static bool
3539 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3540 tree &idx, tree &lane, tree &ivar, tree &lvar)
3542 if (max_vf == 0)
3544 max_vf = omp_max_vf ();
3545 if (max_vf > 1)
3547 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3548 OMP_CLAUSE_SAFELEN);
3549 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3550 max_vf = 1;
3551 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3552 max_vf) == -1)
3553 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3555 if (max_vf > 1)
3557 idx = create_tmp_var (unsigned_type_node);
3558 lane = create_tmp_var (unsigned_type_node);
3561 if (max_vf == 1)
3562 return false;
3564 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3565 tree avar = create_tmp_var_raw (atype);
3566 if (TREE_ADDRESSABLE (new_var))
3567 TREE_ADDRESSABLE (avar) = 1;
3568 DECL_ATTRIBUTES (avar)
3569 = tree_cons (get_identifier ("omp simd array"), NULL,
3570 DECL_ATTRIBUTES (avar));
3571 gimple_add_tmp_var (avar);
3572 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3573 NULL_TREE, NULL_TREE);
3574 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3575 NULL_TREE, NULL_TREE);
3576 if (DECL_P (new_var))
3578 SET_DECL_VALUE_EXPR (new_var, lvar);
3579 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3581 return true;
3584 /* Helper function of lower_rec_input_clauses. For a reference
3585 in simd reduction, add an underlying variable it will reference. */
3587 static void
3588 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3590 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3591 if (TREE_CONSTANT (z))
3593 const char *name = NULL;
3594 if (DECL_NAME (new_vard))
3595 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3597 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3598 gimple_add_tmp_var (z);
3599 TREE_ADDRESSABLE (z) = 1;
3600 z = build_fold_addr_expr_loc (loc, z);
3601 gimplify_assign (new_vard, z, ilist);
3605 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3606 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3607 private variables. Initialization statements go in ILIST, while calls
3608 to destructors go in DLIST. */
3610 static void
3611 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3612 omp_context *ctx, struct omp_for_data *fd)
3614 tree c, dtor, copyin_seq, x, ptr;
3615 bool copyin_by_ref = false;
3616 bool lastprivate_firstprivate = false;
3617 bool reduction_omp_orig_ref = false;
3618 int pass;
3619 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3620 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3621 int max_vf = 0;
3622 tree lane = NULL_TREE, idx = NULL_TREE;
3623 tree ivar = NULL_TREE, lvar = NULL_TREE;
3624 gimple_seq llist[2] = { NULL, NULL };
3626 copyin_seq = NULL;
3628 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3629 with data sharing clauses referencing variable sized vars. That
3630 is unnecessarily hard to support and very unlikely to result in
3631 vectorized code anyway. */
3632 if (is_simd)
3633 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3634 switch (OMP_CLAUSE_CODE (c))
3636 case OMP_CLAUSE_LINEAR:
3637 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3638 max_vf = 1;
3639 /* FALLTHRU */
3640 case OMP_CLAUSE_REDUCTION:
3641 case OMP_CLAUSE_PRIVATE:
3642 case OMP_CLAUSE_FIRSTPRIVATE:
3643 case OMP_CLAUSE_LASTPRIVATE:
3644 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3645 max_vf = 1;
3646 break;
3647 default:
3648 continue;
3651 /* Do all the fixed sized types in the first pass, and the variable sized
3652 types in the second pass. This makes sure that the scalar arguments to
3653 the variable sized types are processed before we use them in the
3654 variable sized operations. */
3655 for (pass = 0; pass < 2; ++pass)
3657 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3659 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3660 tree var, new_var;
3661 bool by_ref;
3662 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3664 switch (c_kind)
3666 case OMP_CLAUSE_PRIVATE:
3667 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3668 continue;
3669 break;
3670 case OMP_CLAUSE_SHARED:
3671 /* Ignore shared directives in teams construct. */
3672 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3673 continue;
3674 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3676 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3677 continue;
3679 case OMP_CLAUSE_FIRSTPRIVATE:
3680 case OMP_CLAUSE_COPYIN:
3681 case OMP_CLAUSE_LINEAR:
3682 break;
3683 case OMP_CLAUSE_REDUCTION:
3684 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3685 reduction_omp_orig_ref = true;
3686 break;
3687 case OMP_CLAUSE__LOOPTEMP_:
3688 /* Handle _looptemp_ clauses only on parallel. */
3689 if (fd)
3690 continue;
3691 break;
3692 case OMP_CLAUSE_LASTPRIVATE:
3693 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3695 lastprivate_firstprivate = true;
3696 if (pass != 0)
3697 continue;
3699 /* Even without corresponding firstprivate, if
3700 decl is Fortran allocatable, it needs outer var
3701 reference. */
3702 else if (pass == 0
3703 && lang_hooks.decls.omp_private_outer_ref
3704 (OMP_CLAUSE_DECL (c)))
3705 lastprivate_firstprivate = true;
3706 break;
3707 case OMP_CLAUSE_ALIGNED:
3708 if (pass == 0)
3709 continue;
3710 var = OMP_CLAUSE_DECL (c);
3711 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3712 && !is_global_var (var))
3714 new_var = maybe_lookup_decl (var, ctx);
3715 if (new_var == NULL_TREE)
3716 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3717 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3718 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3719 omp_clause_aligned_alignment (c));
3720 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3721 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3722 gimplify_and_add (x, ilist);
3724 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3725 && is_global_var (var))
3727 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3728 new_var = lookup_decl (var, ctx);
3729 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3730 t = build_fold_addr_expr_loc (clause_loc, t);
3731 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3732 t = build_call_expr_loc (clause_loc, t2, 2, t,
3733 omp_clause_aligned_alignment (c));
3734 t = fold_convert_loc (clause_loc, ptype, t);
3735 x = create_tmp_var (ptype);
3736 t = build2 (MODIFY_EXPR, ptype, x, t);
3737 gimplify_and_add (t, ilist);
3738 t = build_simple_mem_ref_loc (clause_loc, x);
3739 SET_DECL_VALUE_EXPR (new_var, t);
3740 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3742 continue;
3743 default:
3744 continue;
3747 new_var = var = OMP_CLAUSE_DECL (c);
3748 if (c_kind != OMP_CLAUSE_COPYIN)
3749 new_var = lookup_decl (var, ctx);
3751 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3753 if (pass != 0)
3754 continue;
3756 else if (is_variable_sized (var))
3758 /* For variable sized types, we need to allocate the
3759 actual storage here. Call alloca and store the
3760 result in the pointer decl that we created elsewhere. */
3761 if (pass == 0)
3762 continue;
3764 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3766 gcall *stmt;
3767 tree tmp, atmp;
3769 ptr = DECL_VALUE_EXPR (new_var);
3770 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3771 ptr = TREE_OPERAND (ptr, 0);
3772 gcc_assert (DECL_P (ptr));
3773 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3775 /* void *tmp = __builtin_alloca */
3776 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3777 stmt = gimple_build_call (atmp, 1, x);
3778 tmp = create_tmp_var_raw (ptr_type_node);
3779 gimple_add_tmp_var (tmp);
3780 gimple_call_set_lhs (stmt, tmp);
3782 gimple_seq_add_stmt (ilist, stmt);
3784 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3785 gimplify_assign (ptr, x, ilist);
3788 else if (is_reference (var))
3790 /* For references that are being privatized for Fortran,
3791 allocate new backing storage for the new pointer
3792 variable. This allows us to avoid changing all the
3793 code that expects a pointer to something that expects
3794 a direct variable. */
3795 if (pass == 0)
3796 continue;
3798 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3799 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3801 x = build_receiver_ref (var, false, ctx);
3802 x = build_fold_addr_expr_loc (clause_loc, x);
3804 else if (TREE_CONSTANT (x))
3806 /* For reduction in SIMD loop, defer adding the
3807 initialization of the reference, because if we decide
3808 to use SIMD array for it, the initilization could cause
3809 expansion ICE. */
3810 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3811 x = NULL_TREE;
3812 else
3814 const char *name = NULL;
3815 if (DECL_NAME (var))
3816 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3818 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3819 name);
3820 gimple_add_tmp_var (x);
3821 TREE_ADDRESSABLE (x) = 1;
3822 x = build_fold_addr_expr_loc (clause_loc, x);
3825 else
3827 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3828 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3831 if (x)
3833 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3834 gimplify_assign (new_var, x, ilist);
3837 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3839 else if (c_kind == OMP_CLAUSE_REDUCTION
3840 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3842 if (pass == 0)
3843 continue;
3845 else if (pass != 0)
3846 continue;
3848 switch (OMP_CLAUSE_CODE (c))
3850 case OMP_CLAUSE_SHARED:
3851 /* Ignore shared directives in teams construct. */
3852 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3853 continue;
3854 /* Shared global vars are just accessed directly. */
3855 if (is_global_var (new_var))
3856 break;
3857 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3858 needs to be delayed until after fixup_child_record_type so
3859 that we get the correct type during the dereference. */
3860 by_ref = use_pointer_for_field (var, ctx);
3861 x = build_receiver_ref (var, by_ref, ctx);
3862 SET_DECL_VALUE_EXPR (new_var, x);
3863 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3865 /* ??? If VAR is not passed by reference, and the variable
3866 hasn't been initialized yet, then we'll get a warning for
3867 the store into the omp_data_s structure. Ideally, we'd be
3868 able to notice this and not store anything at all, but
3869 we're generating code too early. Suppress the warning. */
3870 if (!by_ref)
3871 TREE_NO_WARNING (var) = 1;
3872 break;
3874 case OMP_CLAUSE_LASTPRIVATE:
3875 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3876 break;
3877 /* FALLTHRU */
3879 case OMP_CLAUSE_PRIVATE:
3880 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3881 x = build_outer_var_ref (var, ctx);
3882 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3884 if (is_task_ctx (ctx))
3885 x = build_receiver_ref (var, false, ctx);
3886 else
3887 x = build_outer_var_ref (var, ctx);
3889 else
3890 x = NULL;
3891 do_private:
3892 tree nx;
3893 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3894 if (is_simd)
3896 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3897 if ((TREE_ADDRESSABLE (new_var) || nx || y
3898 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3899 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3900 idx, lane, ivar, lvar))
3902 if (nx)
3903 x = lang_hooks.decls.omp_clause_default_ctor
3904 (c, unshare_expr (ivar), x);
3905 if (nx && x)
3906 gimplify_and_add (x, &llist[0]);
3907 if (y)
3909 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3910 if (y)
3912 gimple_seq tseq = NULL;
3914 dtor = y;
3915 gimplify_stmt (&dtor, &tseq);
3916 gimple_seq_add_seq (&llist[1], tseq);
3919 break;
3922 if (nx)
3923 gimplify_and_add (nx, ilist);
3924 /* FALLTHRU */
3926 do_dtor:
3927 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3928 if (x)
3930 gimple_seq tseq = NULL;
3932 dtor = x;
3933 gimplify_stmt (&dtor, &tseq);
3934 gimple_seq_add_seq (dlist, tseq);
3936 break;
3938 case OMP_CLAUSE_LINEAR:
3939 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3940 goto do_firstprivate;
3941 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3942 x = NULL;
3943 else
3944 x = build_outer_var_ref (var, ctx);
3945 goto do_private;
3947 case OMP_CLAUSE_FIRSTPRIVATE:
3948 if (is_task_ctx (ctx))
3950 if (is_reference (var) || is_variable_sized (var))
3951 goto do_dtor;
3952 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3953 ctx))
3954 || use_pointer_for_field (var, NULL))
3956 x = build_receiver_ref (var, false, ctx);
3957 SET_DECL_VALUE_EXPR (new_var, x);
3958 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3959 goto do_dtor;
3962 do_firstprivate:
3963 x = build_outer_var_ref (var, ctx);
3964 if (is_simd)
3966 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3967 && gimple_omp_for_combined_into_p (ctx->stmt))
3969 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3970 tree stept = TREE_TYPE (t);
3971 tree ct = find_omp_clause (clauses,
3972 OMP_CLAUSE__LOOPTEMP_);
3973 gcc_assert (ct);
3974 tree l = OMP_CLAUSE_DECL (ct);
3975 tree n1 = fd->loop.n1;
3976 tree step = fd->loop.step;
3977 tree itype = TREE_TYPE (l);
3978 if (POINTER_TYPE_P (itype))
3979 itype = signed_type_for (itype);
3980 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3981 if (TYPE_UNSIGNED (itype)
3982 && fd->loop.cond_code == GT_EXPR)
3983 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3984 fold_build1 (NEGATE_EXPR, itype, l),
3985 fold_build1 (NEGATE_EXPR,
3986 itype, step));
3987 else
3988 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3989 t = fold_build2 (MULT_EXPR, stept,
3990 fold_convert (stept, l), t);
3992 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3994 x = lang_hooks.decls.omp_clause_linear_ctor
3995 (c, new_var, x, t);
3996 gimplify_and_add (x, ilist);
3997 goto do_dtor;
4000 if (POINTER_TYPE_P (TREE_TYPE (x)))
4001 x = fold_build2 (POINTER_PLUS_EXPR,
4002 TREE_TYPE (x), x, t);
4003 else
4004 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4007 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4008 || TREE_ADDRESSABLE (new_var))
4009 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4010 idx, lane, ivar, lvar))
4012 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4014 tree iv = create_tmp_var (TREE_TYPE (new_var));
4015 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4016 gimplify_and_add (x, ilist);
4017 gimple_stmt_iterator gsi
4018 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4019 gassign *g
4020 = gimple_build_assign (unshare_expr (lvar), iv);
4021 gsi_insert_before_without_update (&gsi, g,
4022 GSI_SAME_STMT);
4023 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4024 enum tree_code code = PLUS_EXPR;
4025 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4026 code = POINTER_PLUS_EXPR;
4027 g = gimple_build_assign (iv, code, iv, t);
4028 gsi_insert_before_without_update (&gsi, g,
4029 GSI_SAME_STMT);
4030 break;
4032 x = lang_hooks.decls.omp_clause_copy_ctor
4033 (c, unshare_expr (ivar), x);
4034 gimplify_and_add (x, &llist[0]);
4035 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4036 if (x)
4038 gimple_seq tseq = NULL;
4040 dtor = x;
4041 gimplify_stmt (&dtor, &tseq);
4042 gimple_seq_add_seq (&llist[1], tseq);
4044 break;
4047 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4048 gimplify_and_add (x, ilist);
4049 goto do_dtor;
4051 case OMP_CLAUSE__LOOPTEMP_:
4052 gcc_assert (is_parallel_ctx (ctx));
4053 x = build_outer_var_ref (var, ctx);
4054 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4055 gimplify_and_add (x, ilist);
4056 break;
4058 case OMP_CLAUSE_COPYIN:
4059 by_ref = use_pointer_for_field (var, NULL);
4060 x = build_receiver_ref (var, by_ref, ctx);
4061 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4062 append_to_statement_list (x, &copyin_seq);
4063 copyin_by_ref |= by_ref;
4064 break;
4066 case OMP_CLAUSE_REDUCTION:
4067 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4069 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4070 gimple tseq;
4071 x = build_outer_var_ref (var, ctx);
4073 if (is_reference (var)
4074 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4075 TREE_TYPE (x)))
4076 x = build_fold_addr_expr_loc (clause_loc, x);
4077 SET_DECL_VALUE_EXPR (placeholder, x);
4078 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4079 tree new_vard = new_var;
4080 if (is_reference (var))
4082 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4083 new_vard = TREE_OPERAND (new_var, 0);
4084 gcc_assert (DECL_P (new_vard));
4086 if (is_simd
4087 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4088 idx, lane, ivar, lvar))
4090 if (new_vard == new_var)
4092 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4093 SET_DECL_VALUE_EXPR (new_var, ivar);
4095 else
4097 SET_DECL_VALUE_EXPR (new_vard,
4098 build_fold_addr_expr (ivar));
4099 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4101 x = lang_hooks.decls.omp_clause_default_ctor
4102 (c, unshare_expr (ivar),
4103 build_outer_var_ref (var, ctx));
4104 if (x)
4105 gimplify_and_add (x, &llist[0]);
4106 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4108 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4109 lower_omp (&tseq, ctx);
4110 gimple_seq_add_seq (&llist[0], tseq);
4112 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4113 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4114 lower_omp (&tseq, ctx);
4115 gimple_seq_add_seq (&llist[1], tseq);
4116 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4117 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4118 if (new_vard == new_var)
4119 SET_DECL_VALUE_EXPR (new_var, lvar);
4120 else
4121 SET_DECL_VALUE_EXPR (new_vard,
4122 build_fold_addr_expr (lvar));
4123 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4124 if (x)
4126 tseq = NULL;
4127 dtor = x;
4128 gimplify_stmt (&dtor, &tseq);
4129 gimple_seq_add_seq (&llist[1], tseq);
4131 break;
4133 /* If this is a reference to constant size reduction var
4134 with placeholder, we haven't emitted the initializer
4135 for it because it is undesirable if SIMD arrays are used.
4136 But if they aren't used, we need to emit the deferred
4137 initialization now. */
4138 else if (is_reference (var) && is_simd)
4139 handle_simd_reference (clause_loc, new_vard, ilist);
4140 x = lang_hooks.decls.omp_clause_default_ctor
4141 (c, unshare_expr (new_var),
4142 build_outer_var_ref (var, ctx));
4143 if (x)
4144 gimplify_and_add (x, ilist);
4145 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4147 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4148 lower_omp (&tseq, ctx);
4149 gimple_seq_add_seq (ilist, tseq);
4151 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4152 if (is_simd)
4154 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4155 lower_omp (&tseq, ctx);
4156 gimple_seq_add_seq (dlist, tseq);
4157 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4159 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4160 goto do_dtor;
4162 else
4164 x = omp_reduction_init (c, TREE_TYPE (new_var));
4165 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4166 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4168 /* reduction(-:var) sums up the partial results, so it
4169 acts identically to reduction(+:var). */
4170 if (code == MINUS_EXPR)
4171 code = PLUS_EXPR;
4173 tree new_vard = new_var;
4174 if (is_simd && is_reference (var))
4176 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4177 new_vard = TREE_OPERAND (new_var, 0);
4178 gcc_assert (DECL_P (new_vard));
4180 if (is_simd
4181 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4182 idx, lane, ivar, lvar))
4184 tree ref = build_outer_var_ref (var, ctx);
4186 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4188 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4189 ref = build_outer_var_ref (var, ctx);
4190 gimplify_assign (ref, x, &llist[1]);
4192 if (new_vard != new_var)
4194 SET_DECL_VALUE_EXPR (new_vard,
4195 build_fold_addr_expr (lvar));
4196 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4199 else
4201 if (is_reference (var) && is_simd)
4202 handle_simd_reference (clause_loc, new_vard, ilist);
4203 gimplify_assign (new_var, x, ilist);
4204 if (is_simd)
4206 tree ref = build_outer_var_ref (var, ctx);
4208 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4209 ref = build_outer_var_ref (var, ctx);
4210 gimplify_assign (ref, x, dlist);
4214 break;
4216 default:
4217 gcc_unreachable ();
4222 if (lane)
4224 tree uid = create_tmp_var (ptr_type_node, "simduid");
4225 /* Don't want uninit warnings on simduid, it is always uninitialized,
4226 but we use it not for the value, but for the DECL_UID only. */
4227 TREE_NO_WARNING (uid) = 1;
4228 gimple g
4229 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4230 gimple_call_set_lhs (g, lane);
4231 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4232 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4233 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4234 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4235 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4236 gimple_omp_for_set_clauses (ctx->stmt, c);
4237 g = gimple_build_assign (lane, INTEGER_CST,
4238 build_int_cst (unsigned_type_node, 0));
4239 gimple_seq_add_stmt (ilist, g);
4240 for (int i = 0; i < 2; i++)
4241 if (llist[i])
4243 tree vf = create_tmp_var (unsigned_type_node);
4244 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4245 gimple_call_set_lhs (g, vf);
4246 gimple_seq *seq = i == 0 ? ilist : dlist;
4247 gimple_seq_add_stmt (seq, g);
4248 tree t = build_int_cst (unsigned_type_node, 0);
4249 g = gimple_build_assign (idx, INTEGER_CST, t);
4250 gimple_seq_add_stmt (seq, g);
4251 tree body = create_artificial_label (UNKNOWN_LOCATION);
4252 tree header = create_artificial_label (UNKNOWN_LOCATION);
4253 tree end = create_artificial_label (UNKNOWN_LOCATION);
4254 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4255 gimple_seq_add_stmt (seq, gimple_build_label (body));
4256 gimple_seq_add_seq (seq, llist[i]);
4257 t = build_int_cst (unsigned_type_node, 1);
4258 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4259 gimple_seq_add_stmt (seq, g);
4260 gimple_seq_add_stmt (seq, gimple_build_label (header));
4261 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4262 gimple_seq_add_stmt (seq, g);
4263 gimple_seq_add_stmt (seq, gimple_build_label (end));
4267 /* The copyin sequence is not to be executed by the main thread, since
4268 that would result in self-copies. Perhaps not visible to scalars,
4269 but it certainly is to C++ operator=. */
4270 if (copyin_seq)
4272 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4274 x = build2 (NE_EXPR, boolean_type_node, x,
4275 build_int_cst (TREE_TYPE (x), 0));
4276 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4277 gimplify_and_add (x, ilist);
4280 /* If any copyin variable is passed by reference, we must ensure the
4281 master thread doesn't modify it before it is copied over in all
4282 threads. Similarly for variables in both firstprivate and
4283 lastprivate clauses we need to ensure the lastprivate copying
4284 happens after firstprivate copying in all threads. And similarly
4285 for UDRs if initializer expression refers to omp_orig. */
4286 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4288 /* Don't add any barrier for #pragma omp simd or
4289 #pragma omp distribute. */
4290 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4291 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4292 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4295 /* If max_vf is non-zero, then we can use only a vectorization factor
4296 up to the max_vf we chose. So stick it into the safelen clause. */
4297 if (max_vf)
4299 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4300 OMP_CLAUSE_SAFELEN);
4301 if (c == NULL_TREE
4302 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4303 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4304 max_vf) == 1))
4306 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4307 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4308 max_vf);
4309 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4310 gimple_omp_for_set_clauses (ctx->stmt, c);
4316 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4317 both parallel and workshare constructs. PREDICATE may be NULL if it's
4318 always true. */
4320 static void
4321 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4322 omp_context *ctx)
4324 tree x, c, label = NULL, orig_clauses = clauses;
4325 bool par_clauses = false;
4326 tree simduid = NULL, lastlane = NULL;
4328 /* Early exit if there are no lastprivate or linear clauses. */
4329 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4330 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4331 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4332 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4333 break;
4334 if (clauses == NULL)
4336 /* If this was a workshare clause, see if it had been combined
4337 with its parallel. In that case, look for the clauses on the
4338 parallel statement itself. */
4339 if (is_parallel_ctx (ctx))
4340 return;
4342 ctx = ctx->outer;
4343 if (ctx == NULL || !is_parallel_ctx (ctx))
4344 return;
4346 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4347 OMP_CLAUSE_LASTPRIVATE);
4348 if (clauses == NULL)
4349 return;
4350 par_clauses = true;
4353 if (predicate)
4355 gcond *stmt;
4356 tree label_true, arm1, arm2;
4358 label = create_artificial_label (UNKNOWN_LOCATION);
4359 label_true = create_artificial_label (UNKNOWN_LOCATION);
4360 arm1 = TREE_OPERAND (predicate, 0);
4361 arm2 = TREE_OPERAND (predicate, 1);
4362 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4363 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4364 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4365 label_true, label);
4366 gimple_seq_add_stmt (stmt_list, stmt);
4367 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4370 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4371 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4373 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4374 if (simduid)
4375 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4378 for (c = clauses; c ;)
4380 tree var, new_var;
4381 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4383 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4384 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4385 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4387 var = OMP_CLAUSE_DECL (c);
4388 new_var = lookup_decl (var, ctx);
4390 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4392 tree val = DECL_VALUE_EXPR (new_var);
4393 if (TREE_CODE (val) == ARRAY_REF
4394 && VAR_P (TREE_OPERAND (val, 0))
4395 && lookup_attribute ("omp simd array",
4396 DECL_ATTRIBUTES (TREE_OPERAND (val,
4397 0))))
4399 if (lastlane == NULL)
4401 lastlane = create_tmp_var (unsigned_type_node);
4402 gcall *g
4403 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4404 2, simduid,
4405 TREE_OPERAND (val, 1));
4406 gimple_call_set_lhs (g, lastlane);
4407 gimple_seq_add_stmt (stmt_list, g);
4409 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4410 TREE_OPERAND (val, 0), lastlane,
4411 NULL_TREE, NULL_TREE);
4415 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4416 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4418 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4419 gimple_seq_add_seq (stmt_list,
4420 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4421 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4423 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4424 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4426 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4427 gimple_seq_add_seq (stmt_list,
4428 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4429 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4432 x = build_outer_var_ref (var, ctx);
4433 if (is_reference (var))
4434 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4435 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4436 gimplify_and_add (x, stmt_list);
4438 c = OMP_CLAUSE_CHAIN (c);
4439 if (c == NULL && !par_clauses)
4441 /* If this was a workshare clause, see if it had been combined
4442 with its parallel. In that case, continue looking for the
4443 clauses also on the parallel statement itself. */
4444 if (is_parallel_ctx (ctx))
4445 break;
4447 ctx = ctx->outer;
4448 if (ctx == NULL || !is_parallel_ctx (ctx))
4449 break;
4451 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4452 OMP_CLAUSE_LASTPRIVATE);
4453 par_clauses = true;
4457 if (label)
4458 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4461 static void
4462 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4463 tree tid, tree var, tree new_var)
4465 /* The atomic add at the end of the sum creates unnecessary
4466 write contention on accelerators. To work around this,
4467 create an array to store the partial reductions. Later, in
4468 lower_omp_for (for openacc), the values of array will be
4469 combined. */
4471 tree t = NULL_TREE, array, x;
4472 tree type = get_base_type (var);
4473 gimple stmt;
4475 /* Now insert the partial reductions into the array. */
4477 /* Find the reduction array. */
4479 tree ptype = build_pointer_type (type);
4481 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4482 t = build_receiver_ref (t, false, ctx->outer);
4484 array = create_tmp_var (ptype);
4485 gimplify_assign (array, t, stmt_seqp);
4487 tree ptr = create_tmp_var (TREE_TYPE (array));
4489 /* Find the reduction array. */
4491 /* testing a unary conversion. */
4492 tree offset = create_tmp_var (sizetype);
4493 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4494 stmt_seqp);
4495 t = create_tmp_var (sizetype);
4496 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4497 stmt_seqp);
4498 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4499 gimple_seq_add_stmt (stmt_seqp, stmt);
4501 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4502 of adding sizeof(var) to the array? */
4503 ptr = create_tmp_var (ptype);
4504 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4505 offset);
4506 gimple_seq_add_stmt (stmt_seqp, stmt);
4508 /* Move the local sum to gfc$sum[i]. */
4509 x = unshare_expr (build_simple_mem_ref (ptr));
4510 stmt = gimplify_assign (x, new_var, stmt_seqp);
4513 /* Generate code to implement the REDUCTION clauses. */
4515 static void
4516 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4518 gimple_seq sub_seq = NULL;
4519 gimple stmt;
4520 tree x, c, tid = NULL_TREE;
4521 int count = 0;
4523 /* SIMD reductions are handled in lower_rec_input_clauses. */
4524 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4525 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4526 return;
4528 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4529 update in that case, otherwise use a lock. */
4530 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4531 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4533 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4535 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4536 count = -1;
4537 break;
4539 count++;
4542 if (count == 0)
4543 return;
4545 /* Initialize thread info for OpenACC. */
4546 if (is_gimple_omp_oacc (ctx->stmt))
4548 /* Get the current thread id. */
4549 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4550 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4551 gimple stmt = gimple_build_call (call, 0);
4552 gimple_call_set_lhs (stmt, tid);
4553 gimple_seq_add_stmt (stmt_seqp, stmt);
4556 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4558 tree var, ref, new_var;
4559 enum tree_code code;
4560 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4562 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4563 continue;
4565 var = OMP_CLAUSE_DECL (c);
4566 new_var = lookup_decl (var, ctx);
4567 if (is_reference (var))
4568 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4569 ref = build_outer_var_ref (var, ctx);
4570 code = OMP_CLAUSE_REDUCTION_CODE (c);
4572 /* reduction(-:var) sums up the partial results, so it acts
4573 identically to reduction(+:var). */
4574 if (code == MINUS_EXPR)
4575 code = PLUS_EXPR;
4577 if (is_gimple_omp_oacc (ctx->stmt))
4579 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4581 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4583 else if (count == 1)
4585 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4587 addr = save_expr (addr);
4588 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4589 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4590 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4591 gimplify_and_add (x, stmt_seqp);
4592 return;
4594 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4596 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4598 if (is_reference (var)
4599 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4600 TREE_TYPE (ref)))
4601 ref = build_fold_addr_expr_loc (clause_loc, ref);
4602 SET_DECL_VALUE_EXPR (placeholder, ref);
4603 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4604 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4605 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4606 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4607 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4609 else
4611 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4612 ref = build_outer_var_ref (var, ctx);
4613 gimplify_assign (ref, x, &sub_seq);
4617 if (is_gimple_omp_oacc (ctx->stmt))
4618 return;
4620 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4622 gimple_seq_add_stmt (stmt_seqp, stmt);
4624 gimple_seq_add_seq (stmt_seqp, sub_seq);
4626 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4628 gimple_seq_add_stmt (stmt_seqp, stmt);
4632 /* Generate code to implement the COPYPRIVATE clauses. */
4634 static void
4635 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4636 omp_context *ctx)
4638 tree c;
4640 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4642 tree var, new_var, ref, x;
4643 bool by_ref;
4644 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4646 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4647 continue;
4649 var = OMP_CLAUSE_DECL (c);
4650 by_ref = use_pointer_for_field (var, NULL);
4652 ref = build_sender_ref (var, ctx);
4653 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4654 if (by_ref)
4656 x = build_fold_addr_expr_loc (clause_loc, new_var);
4657 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4659 gimplify_assign (ref, x, slist);
4661 ref = build_receiver_ref (var, false, ctx);
4662 if (by_ref)
4664 ref = fold_convert_loc (clause_loc,
4665 build_pointer_type (TREE_TYPE (new_var)),
4666 ref);
4667 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4669 if (is_reference (var))
4671 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4672 ref = build_simple_mem_ref_loc (clause_loc, ref);
4673 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4675 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4676 gimplify_and_add (x, rlist);
4681 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4682 and REDUCTION from the sender (aka parent) side. */
4684 static void
4685 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4686 omp_context *ctx)
4688 tree c;
4690 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4692 tree val, ref, x, var;
4693 bool by_ref, do_in = false, do_out = false;
4694 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4696 switch (OMP_CLAUSE_CODE (c))
4698 case OMP_CLAUSE_PRIVATE:
4699 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4700 break;
4701 continue;
4702 case OMP_CLAUSE_FIRSTPRIVATE:
4703 case OMP_CLAUSE_COPYIN:
4704 case OMP_CLAUSE_LASTPRIVATE:
4705 case OMP_CLAUSE_REDUCTION:
4706 case OMP_CLAUSE__LOOPTEMP_:
4707 break;
4708 default:
4709 continue;
4712 val = OMP_CLAUSE_DECL (c);
4713 var = lookup_decl_in_outer_ctx (val, ctx);
4715 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4716 && is_global_var (var))
4717 continue;
4718 if (is_variable_sized (val))
4719 continue;
4720 by_ref = use_pointer_for_field (val, NULL);
4722 switch (OMP_CLAUSE_CODE (c))
4724 case OMP_CLAUSE_PRIVATE:
4725 case OMP_CLAUSE_FIRSTPRIVATE:
4726 case OMP_CLAUSE_COPYIN:
4727 case OMP_CLAUSE__LOOPTEMP_:
4728 do_in = true;
4729 break;
4731 case OMP_CLAUSE_LASTPRIVATE:
4732 if (by_ref || is_reference (val))
4734 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4735 continue;
4736 do_in = true;
4738 else
4740 do_out = true;
4741 if (lang_hooks.decls.omp_private_outer_ref (val))
4742 do_in = true;
4744 break;
4746 case OMP_CLAUSE_REDUCTION:
4747 do_in = true;
4748 do_out = !(by_ref || is_reference (val));
4749 break;
4751 default:
4752 gcc_unreachable ();
4755 if (do_in)
4757 ref = build_sender_ref (val, ctx);
4758 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4759 gimplify_assign (ref, x, ilist);
4760 if (is_task_ctx (ctx))
4761 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4764 if (do_out)
4766 ref = build_sender_ref (val, ctx);
4767 gimplify_assign (var, ref, olist);
4772 /* Generate code to implement SHARED from the sender (aka parent)
4773 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4774 list things that got automatically shared. */
4776 static void
4777 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4779 tree var, ovar, nvar, f, x, record_type;
4781 if (ctx->record_type == NULL)
4782 return;
4784 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4785 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4787 ovar = DECL_ABSTRACT_ORIGIN (f);
4788 nvar = maybe_lookup_decl (ovar, ctx);
4789 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4790 continue;
4792 /* If CTX is a nested parallel directive. Find the immediately
4793 enclosing parallel or workshare construct that contains a
4794 mapping for OVAR. */
4795 var = lookup_decl_in_outer_ctx (ovar, ctx);
4797 if (use_pointer_for_field (ovar, ctx))
4799 x = build_sender_ref (ovar, ctx);
4800 var = build_fold_addr_expr (var);
4801 gimplify_assign (x, var, ilist);
4803 else
4805 x = build_sender_ref (ovar, ctx);
4806 gimplify_assign (x, var, ilist);
4808 if (!TREE_READONLY (var)
4809 /* We don't need to receive a new reference to a result
4810 or parm decl. In fact we may not store to it as we will
4811 invalidate any pending RSO and generate wrong gimple
4812 during inlining. */
4813 && !((TREE_CODE (var) == RESULT_DECL
4814 || TREE_CODE (var) == PARM_DECL)
4815 && DECL_BY_REFERENCE (var)))
4817 x = build_sender_ref (ovar, ctx);
4818 gimplify_assign (var, x, olist);
4825 /* A convenience function to build an empty GIMPLE_COND with just the
4826 condition. */
4828 static gcond *
4829 gimple_build_cond_empty (tree cond)
4831 enum tree_code pred_code;
4832 tree lhs, rhs;
4834 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4835 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4839 /* Build the function calls to GOMP_parallel_start etc to actually
4840 generate the parallel operation. REGION is the parallel region
4841 being expanded. BB is the block where to insert the code. WS_ARGS
4842 will be set if this is a call to a combined parallel+workshare
4843 construct, it contains the list of additional arguments needed by
4844 the workshare construct. */
4846 static void
4847 expand_parallel_call (struct omp_region *region, basic_block bb,
4848 gomp_parallel *entry_stmt,
4849 vec<tree, va_gc> *ws_args)
4851 tree t, t1, t2, val, cond, c, clauses, flags;
4852 gimple_stmt_iterator gsi;
4853 gimple stmt;
4854 enum built_in_function start_ix;
4855 int start_ix2;
4856 location_t clause_loc;
4857 vec<tree, va_gc> *args;
4859 clauses = gimple_omp_parallel_clauses (entry_stmt);
4861 /* Determine what flavor of GOMP_parallel we will be
4862 emitting. */
4863 start_ix = BUILT_IN_GOMP_PARALLEL;
4864 if (is_combined_parallel (region))
4866 switch (region->inner->type)
4868 case GIMPLE_OMP_FOR:
4869 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4870 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4871 + (region->inner->sched_kind
4872 == OMP_CLAUSE_SCHEDULE_RUNTIME
4873 ? 3 : region->inner->sched_kind));
4874 start_ix = (enum built_in_function)start_ix2;
4875 break;
4876 case GIMPLE_OMP_SECTIONS:
4877 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4878 break;
4879 default:
4880 gcc_unreachable ();
4884 /* By default, the value of NUM_THREADS is zero (selected at run time)
4885 and there is no conditional. */
4886 cond = NULL_TREE;
4887 val = build_int_cst (unsigned_type_node, 0);
4888 flags = build_int_cst (unsigned_type_node, 0);
4890 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4891 if (c)
4892 cond = OMP_CLAUSE_IF_EXPR (c);
4894 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4895 if (c)
4897 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4898 clause_loc = OMP_CLAUSE_LOCATION (c);
4900 else
4901 clause_loc = gimple_location (entry_stmt);
4903 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4904 if (c)
4905 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4907 /* Ensure 'val' is of the correct type. */
4908 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4910 /* If we found the clause 'if (cond)', build either
4911 (cond != 0) or (cond ? val : 1u). */
4912 if (cond)
4914 cond = gimple_boolify (cond);
4916 if (integer_zerop (val))
4917 val = fold_build2_loc (clause_loc,
4918 EQ_EXPR, unsigned_type_node, cond,
4919 build_int_cst (TREE_TYPE (cond), 0));
4920 else
4922 basic_block cond_bb, then_bb, else_bb;
4923 edge e, e_then, e_else;
4924 tree tmp_then, tmp_else, tmp_join, tmp_var;
4926 tmp_var = create_tmp_var (TREE_TYPE (val));
4927 if (gimple_in_ssa_p (cfun))
4929 tmp_then = make_ssa_name (tmp_var);
4930 tmp_else = make_ssa_name (tmp_var);
4931 tmp_join = make_ssa_name (tmp_var);
4933 else
4935 tmp_then = tmp_var;
4936 tmp_else = tmp_var;
4937 tmp_join = tmp_var;
4940 e = split_block_after_labels (bb);
4941 cond_bb = e->src;
4942 bb = e->dest;
4943 remove_edge (e);
4945 then_bb = create_empty_bb (cond_bb);
4946 else_bb = create_empty_bb (then_bb);
4947 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4948 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4950 stmt = gimple_build_cond_empty (cond);
4951 gsi = gsi_start_bb (cond_bb);
4952 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4954 gsi = gsi_start_bb (then_bb);
4955 stmt = gimple_build_assign (tmp_then, val);
4956 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4958 gsi = gsi_start_bb (else_bb);
4959 stmt = gimple_build_assign
4960 (tmp_else, build_int_cst (unsigned_type_node, 1));
4961 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4963 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4964 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4965 add_bb_to_loop (then_bb, cond_bb->loop_father);
4966 add_bb_to_loop (else_bb, cond_bb->loop_father);
4967 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4968 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4970 if (gimple_in_ssa_p (cfun))
4972 gphi *phi = create_phi_node (tmp_join, bb);
4973 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4974 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4977 val = tmp_join;
4980 gsi = gsi_start_bb (bb);
4981 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4982 false, GSI_CONTINUE_LINKING);
4985 gsi = gsi_last_bb (bb);
4986 t = gimple_omp_parallel_data_arg (entry_stmt);
4987 if (t == NULL)
4988 t1 = null_pointer_node;
4989 else
4990 t1 = build_fold_addr_expr (t);
4991 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4993 vec_alloc (args, 4 + vec_safe_length (ws_args));
4994 args->quick_push (t2);
4995 args->quick_push (t1);
4996 args->quick_push (val);
4997 if (ws_args)
4998 args->splice (*ws_args);
4999 args->quick_push (flags);
5001 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
5002 builtin_decl_explicit (start_ix), args);
5004 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5005 false, GSI_CONTINUE_LINKING);
5008 /* Insert a function call whose name is FUNC_NAME with the information from
5009 ENTRY_STMT into the basic_block BB. */
5011 static void
5012 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
5013 vec <tree, va_gc> *ws_args)
5015 tree t, t1, t2;
5016 gimple_stmt_iterator gsi;
5017 vec <tree, va_gc> *args;
5019 gcc_assert (vec_safe_length (ws_args) == 2);
5020 tree func_name = (*ws_args)[0];
5021 tree grain = (*ws_args)[1];
5023 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5024 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5025 gcc_assert (count != NULL_TREE);
5026 count = OMP_CLAUSE_OPERAND (count, 0);
5028 gsi = gsi_last_bb (bb);
5029 t = gimple_omp_parallel_data_arg (entry_stmt);
5030 if (t == NULL)
5031 t1 = null_pointer_node;
5032 else
5033 t1 = build_fold_addr_expr (t);
5034 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5036 vec_alloc (args, 4);
5037 args->quick_push (t2);
5038 args->quick_push (t1);
5039 args->quick_push (count);
5040 args->quick_push (grain);
5041 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5043 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5044 GSI_CONTINUE_LINKING);
5047 /* Build the function call to GOMP_task to actually
5048 generate the task operation. BB is the block where to insert the code. */
5050 static void
5051 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5053 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5054 gimple_stmt_iterator gsi;
5055 location_t loc = gimple_location (entry_stmt);
5057 clauses = gimple_omp_task_clauses (entry_stmt);
5059 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5060 if (c)
5061 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5062 else
5063 cond = boolean_true_node;
5065 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5066 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5067 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5068 flags = build_int_cst (unsigned_type_node,
5069 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5071 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5072 if (c)
5074 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5075 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5076 build_int_cst (unsigned_type_node, 2),
5077 build_int_cst (unsigned_type_node, 0));
5078 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5080 if (depend)
5081 depend = OMP_CLAUSE_DECL (depend);
5082 else
5083 depend = build_int_cst (ptr_type_node, 0);
5085 gsi = gsi_last_bb (bb);
5086 t = gimple_omp_task_data_arg (entry_stmt);
5087 if (t == NULL)
5088 t2 = null_pointer_node;
5089 else
5090 t2 = build_fold_addr_expr_loc (loc, t);
5091 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5092 t = gimple_omp_task_copy_fn (entry_stmt);
5093 if (t == NULL)
5094 t3 = null_pointer_node;
5095 else
5096 t3 = build_fold_addr_expr_loc (loc, t);
5098 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5099 8, t1, t2, t3,
5100 gimple_omp_task_arg_size (entry_stmt),
5101 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5102 depend);
5104 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5105 false, GSI_CONTINUE_LINKING);
5109 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5110 catch handler and return it. This prevents programs from violating the
5111 structured block semantics with throws. */
5113 static gimple_seq
5114 maybe_catch_exception (gimple_seq body)
5116 gimple g;
5117 tree decl;
5119 if (!flag_exceptions)
5120 return body;
5122 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5123 decl = lang_hooks.eh_protect_cleanup_actions ();
5124 else
5125 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5127 g = gimple_build_eh_must_not_throw (decl);
5128 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5129 GIMPLE_TRY_CATCH);
5131 return gimple_seq_alloc_with_stmt (g);
5134 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5136 static tree
5137 vec2chain (vec<tree, va_gc> *v)
5139 tree chain = NULL_TREE, t;
5140 unsigned ix;
5142 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5144 DECL_CHAIN (t) = chain;
5145 chain = t;
5148 return chain;
5152 /* Remove barriers in REGION->EXIT's block. Note that this is only
5153 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5154 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5155 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5156 removed. */
5158 static void
5159 remove_exit_barrier (struct omp_region *region)
5161 gimple_stmt_iterator gsi;
5162 basic_block exit_bb;
5163 edge_iterator ei;
5164 edge e;
5165 gimple stmt;
5166 int any_addressable_vars = -1;
5168 exit_bb = region->exit;
5170 /* If the parallel region doesn't return, we don't have REGION->EXIT
5171 block at all. */
5172 if (! exit_bb)
5173 return;
5175 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5176 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5177 statements that can appear in between are extremely limited -- no
5178 memory operations at all. Here, we allow nothing at all, so the
5179 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5180 gsi = gsi_last_bb (exit_bb);
5181 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5182 gsi_prev (&gsi);
5183 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5184 return;
5186 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5188 gsi = gsi_last_bb (e->src);
5189 if (gsi_end_p (gsi))
5190 continue;
5191 stmt = gsi_stmt (gsi);
5192 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5193 && !gimple_omp_return_nowait_p (stmt))
5195 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5196 in many cases. If there could be tasks queued, the barrier
5197 might be needed to let the tasks run before some local
5198 variable of the parallel that the task uses as shared
5199 runs out of scope. The task can be spawned either
5200 from within current function (this would be easy to check)
5201 or from some function it calls and gets passed an address
5202 of such a variable. */
5203 if (any_addressable_vars < 0)
5205 gomp_parallel *parallel_stmt
5206 = as_a <gomp_parallel *> (last_stmt (region->entry));
5207 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5208 tree local_decls, block, decl;
5209 unsigned ix;
5211 any_addressable_vars = 0;
5212 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5213 if (TREE_ADDRESSABLE (decl))
5215 any_addressable_vars = 1;
5216 break;
5218 for (block = gimple_block (stmt);
5219 !any_addressable_vars
5220 && block
5221 && TREE_CODE (block) == BLOCK;
5222 block = BLOCK_SUPERCONTEXT (block))
5224 for (local_decls = BLOCK_VARS (block);
5225 local_decls;
5226 local_decls = DECL_CHAIN (local_decls))
5227 if (TREE_ADDRESSABLE (local_decls))
5229 any_addressable_vars = 1;
5230 break;
5232 if (block == gimple_block (parallel_stmt))
5233 break;
5236 if (!any_addressable_vars)
5237 gimple_omp_return_set_nowait (stmt);
5242 static void
5243 remove_exit_barriers (struct omp_region *region)
5245 if (region->type == GIMPLE_OMP_PARALLEL)
5246 remove_exit_barrier (region);
5248 if (region->inner)
5250 region = region->inner;
5251 remove_exit_barriers (region);
5252 while (region->next)
5254 region = region->next;
5255 remove_exit_barriers (region);
5260 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5261 calls. These can't be declared as const functions, but
5262 within one parallel body they are constant, so they can be
5263 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5264 which are declared const. Similarly for task body, except
5265 that in untied task omp_get_thread_num () can change at any task
5266 scheduling point. */
5268 static void
5269 optimize_omp_library_calls (gimple entry_stmt)
5271 basic_block bb;
5272 gimple_stmt_iterator gsi;
5273 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5274 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5275 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5276 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5277 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5278 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5279 OMP_CLAUSE_UNTIED) != NULL);
5281 FOR_EACH_BB_FN (bb, cfun)
5282 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5284 gimple call = gsi_stmt (gsi);
5285 tree decl;
5287 if (is_gimple_call (call)
5288 && (decl = gimple_call_fndecl (call))
5289 && DECL_EXTERNAL (decl)
5290 && TREE_PUBLIC (decl)
5291 && DECL_INITIAL (decl) == NULL)
5293 tree built_in;
5295 if (DECL_NAME (decl) == thr_num_id)
5297 /* In #pragma omp task untied omp_get_thread_num () can change
5298 during the execution of the task region. */
5299 if (untied_task)
5300 continue;
5301 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5303 else if (DECL_NAME (decl) == num_thr_id)
5304 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5305 else
5306 continue;
5308 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5309 || gimple_call_num_args (call) != 0)
5310 continue;
5312 if (flag_exceptions && !TREE_NOTHROW (decl))
5313 continue;
5315 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5316 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5317 TREE_TYPE (TREE_TYPE (built_in))))
5318 continue;
5320 gimple_call_set_fndecl (call, built_in);
5325 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5326 regimplified. */
5328 static tree
5329 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5331 tree t = *tp;
5333 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5334 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5335 return t;
5337 if (TREE_CODE (t) == ADDR_EXPR)
5338 recompute_tree_invariant_for_addr_expr (t);
5340 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5341 return NULL_TREE;
5344 /* Prepend TO = FROM assignment before *GSI_P. */
5346 static void
5347 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5349 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5350 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5351 true, GSI_SAME_STMT);
5352 gimple stmt = gimple_build_assign (to, from);
5353 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5354 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5355 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5357 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5358 gimple_regimplify_operands (stmt, &gsi);
5362 /* Expand the OpenMP parallel or task directive starting at REGION. */
5364 static void
5365 expand_omp_taskreg (struct omp_region *region)
5367 basic_block entry_bb, exit_bb, new_bb;
5368 struct function *child_cfun;
5369 tree child_fn, block, t;
5370 gimple_stmt_iterator gsi;
5371 gimple entry_stmt, stmt;
5372 edge e;
5373 vec<tree, va_gc> *ws_args;
5375 entry_stmt = last_stmt (region->entry);
5376 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5377 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5379 entry_bb = region->entry;
5380 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
5381 exit_bb = region->cont;
5382 else
5383 exit_bb = region->exit;
5385 bool is_cilk_for
5386 = (flag_cilkplus
5387 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5388 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5389 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5391 if (is_cilk_for)
5392 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5393 and the inner statement contains the name of the built-in function
5394 and grain. */
5395 ws_args = region->inner->ws_args;
5396 else if (is_combined_parallel (region))
5397 ws_args = region->ws_args;
5398 else
5399 ws_args = NULL;
5401 if (child_cfun->cfg)
5403 /* Due to inlining, it may happen that we have already outlined
5404 the region, in which case all we need to do is make the
5405 sub-graph unreachable and emit the parallel call. */
5406 edge entry_succ_e, exit_succ_e;
5408 entry_succ_e = single_succ_edge (entry_bb);
5410 gsi = gsi_last_bb (entry_bb);
5411 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5412 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5413 gsi_remove (&gsi, true);
5415 new_bb = entry_bb;
5416 if (exit_bb)
5418 exit_succ_e = single_succ_edge (exit_bb);
5419 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5421 remove_edge_and_dominated_blocks (entry_succ_e);
5423 else
5425 unsigned srcidx, dstidx, num;
5427 /* If the parallel region needs data sent from the parent
5428 function, then the very first statement (except possible
5429 tree profile counter updates) of the parallel body
5430 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5431 &.OMP_DATA_O is passed as an argument to the child function,
5432 we need to replace it with the argument as seen by the child
5433 function.
5435 In most cases, this will end up being the identity assignment
5436 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5437 a function call that has been inlined, the original PARM_DECL
5438 .OMP_DATA_I may have been converted into a different local
5439 variable. In which case, we need to keep the assignment. */
5440 if (gimple_omp_taskreg_data_arg (entry_stmt))
5442 basic_block entry_succ_bb
5443 = single_succ_p (entry_bb) ? single_succ (entry_bb)
5444 : FALLTHRU_EDGE (entry_bb)->dest;
5445 tree arg, narg;
5446 gimple parcopy_stmt = NULL;
5448 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5450 gimple stmt;
5452 gcc_assert (!gsi_end_p (gsi));
5453 stmt = gsi_stmt (gsi);
5454 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5455 continue;
5457 if (gimple_num_ops (stmt) == 2)
5459 tree arg = gimple_assign_rhs1 (stmt);
5461 /* We're ignore the subcode because we're
5462 effectively doing a STRIP_NOPS. */
5464 if (TREE_CODE (arg) == ADDR_EXPR
5465 && TREE_OPERAND (arg, 0)
5466 == gimple_omp_taskreg_data_arg (entry_stmt))
5468 parcopy_stmt = stmt;
5469 break;
5474 gcc_assert (parcopy_stmt != NULL);
5475 arg = DECL_ARGUMENTS (child_fn);
5477 if (!gimple_in_ssa_p (cfun))
5479 if (gimple_assign_lhs (parcopy_stmt) == arg)
5480 gsi_remove (&gsi, true);
5481 else
5483 /* ?? Is setting the subcode really necessary ?? */
5484 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5485 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5488 else
5490 /* If we are in ssa form, we must load the value from the default
5491 definition of the argument. That should not be defined now,
5492 since the argument is not used uninitialized. */
5493 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5494 narg = make_ssa_name (arg, gimple_build_nop ());
5495 set_ssa_default_def (cfun, arg, narg);
5496 /* ?? Is setting the subcode really necessary ?? */
5497 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5498 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5499 update_stmt (parcopy_stmt);
5503 /* Declare local variables needed in CHILD_CFUN. */
5504 block = DECL_INITIAL (child_fn);
5505 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5506 /* The gimplifier could record temporaries in parallel/task block
5507 rather than in containing function's local_decls chain,
5508 which would mean cgraph missed finalizing them. Do it now. */
5509 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5510 if (TREE_CODE (t) == VAR_DECL
5511 && TREE_STATIC (t)
5512 && !DECL_EXTERNAL (t))
5513 varpool_node::finalize_decl (t);
5514 DECL_SAVED_TREE (child_fn) = NULL;
5515 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5516 gimple_set_body (child_fn, NULL);
5517 TREE_USED (block) = 1;
5519 /* Reset DECL_CONTEXT on function arguments. */
5520 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5521 DECL_CONTEXT (t) = child_fn;
5523 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5524 so that it can be moved to the child function. */
5525 gsi = gsi_last_bb (entry_bb);
5526 stmt = gsi_stmt (gsi);
5527 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5528 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5529 e = split_block (entry_bb, stmt);
5530 gsi_remove (&gsi, true);
5531 entry_bb = e->dest;
5532 edge e2 = NULL;
5533 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5534 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5535 else
5537 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
5538 gcc_assert (e2->dest == region->exit);
5539 remove_edge (BRANCH_EDGE (entry_bb));
5540 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
5541 gsi = gsi_last_bb (region->exit);
5542 gcc_assert (!gsi_end_p (gsi)
5543 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5544 gsi_remove (&gsi, true);
5547 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5548 if (exit_bb)
5550 gsi = gsi_last_bb (exit_bb);
5551 gcc_assert (!gsi_end_p (gsi)
5552 && (gimple_code (gsi_stmt (gsi))
5553 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
5554 stmt = gimple_build_return (NULL);
5555 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5556 gsi_remove (&gsi, true);
5559 /* Move the parallel region into CHILD_CFUN. */
5561 if (gimple_in_ssa_p (cfun))
5563 init_tree_ssa (child_cfun);
5564 init_ssa_operands (child_cfun);
5565 child_cfun->gimple_df->in_ssa_p = true;
5566 block = NULL_TREE;
5568 else
5569 block = gimple_block (entry_stmt);
5571 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5572 if (exit_bb)
5573 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5574 if (e2)
5576 basic_block dest_bb = e2->dest;
5577 if (!exit_bb)
5578 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
5579 remove_edge (e2);
5580 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
5582 /* When the OMP expansion process cannot guarantee an up-to-date
5583 loop tree arrange for the child function to fixup loops. */
5584 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5585 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5587 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5588 num = vec_safe_length (child_cfun->local_decls);
5589 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5591 t = (*child_cfun->local_decls)[srcidx];
5592 if (DECL_CONTEXT (t) == cfun->decl)
5593 continue;
5594 if (srcidx != dstidx)
5595 (*child_cfun->local_decls)[dstidx] = t;
5596 dstidx++;
5598 if (dstidx != num)
5599 vec_safe_truncate (child_cfun->local_decls, dstidx);
5601 /* Inform the callgraph about the new function. */
5602 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5603 cgraph_node::add_new_function (child_fn, true);
5604 cgraph_node::get (child_fn)->parallelized_function = 1;
5606 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5607 fixed in a following pass. */
5608 push_cfun (child_cfun);
5609 if (optimize)
5610 optimize_omp_library_calls (entry_stmt);
5611 cgraph_edge::rebuild_edges ();
5613 /* Some EH regions might become dead, see PR34608. If
5614 pass_cleanup_cfg isn't the first pass to happen with the
5615 new child, these dead EH edges might cause problems.
5616 Clean them up now. */
5617 if (flag_exceptions)
5619 basic_block bb;
5620 bool changed = false;
5622 FOR_EACH_BB_FN (bb, cfun)
5623 changed |= gimple_purge_dead_eh_edges (bb);
5624 if (changed)
5625 cleanup_tree_cfg ();
5627 if (gimple_in_ssa_p (cfun))
5628 update_ssa (TODO_update_ssa);
5629 pop_cfun ();
5632 /* Emit a library call to launch the children threads. */
5633 if (is_cilk_for)
5634 expand_cilk_for_call (new_bb,
5635 as_a <gomp_parallel *> (entry_stmt), ws_args);
5636 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5637 expand_parallel_call (region, new_bb,
5638 as_a <gomp_parallel *> (entry_stmt), ws_args);
5639 else
5640 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5641 if (gimple_in_ssa_p (cfun))
5642 update_ssa (TODO_update_ssa_only_virtuals);
5646 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5647 of the combined collapse > 1 loop constructs, generate code like:
5648 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5649 if (cond3 is <)
5650 adj = STEP3 - 1;
5651 else
5652 adj = STEP3 + 1;
5653 count3 = (adj + N32 - N31) / STEP3;
5654 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5655 if (cond2 is <)
5656 adj = STEP2 - 1;
5657 else
5658 adj = STEP2 + 1;
5659 count2 = (adj + N22 - N21) / STEP2;
5660 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5661 if (cond1 is <)
5662 adj = STEP1 - 1;
5663 else
5664 adj = STEP1 + 1;
5665 count1 = (adj + N12 - N11) / STEP1;
5666 count = count1 * count2 * count3;
5667 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5668 count = 0;
5669 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5670 of the combined loop constructs, just initialize COUNTS array
5671 from the _looptemp_ clauses. */
5673 /* NOTE: It *could* be better to moosh all of the BBs together,
5674 creating one larger BB with all the computation and the unexpected
5675 jump at the end. I.e.
5677 bool zero3, zero2, zero1, zero;
5679 zero3 = N32 c3 N31;
5680 count3 = (N32 - N31) /[cl] STEP3;
5681 zero2 = N22 c2 N21;
5682 count2 = (N22 - N21) /[cl] STEP2;
5683 zero1 = N12 c1 N11;
5684 count1 = (N12 - N11) /[cl] STEP1;
5685 zero = zero3 || zero2 || zero1;
5686 count = count1 * count2 * count3;
5687 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5689 After all, we expect the zero=false, and thus we expect to have to
5690 evaluate all of the comparison expressions, so short-circuiting
5691 oughtn't be a win. Since the condition isn't protecting a
5692 denominator, we're not concerned about divide-by-zero, so we can
5693 fully evaluate count even if a numerator turned out to be wrong.
5695 It seems like putting this all together would create much better
5696 scheduling opportunities, and less pressure on the chip's branch
5697 predictor. */
5699 static void
5700 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5701 basic_block &entry_bb, tree *counts,
5702 basic_block &zero_iter_bb, int &first_zero_iter,
5703 basic_block &l2_dom_bb)
5705 tree t, type = TREE_TYPE (fd->loop.v);
5706 edge e, ne;
5707 int i;
5709 /* Collapsed loops need work for expansion into SSA form. */
5710 gcc_assert (!gimple_in_ssa_p (cfun));
5712 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5713 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5715 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5716 isn't supposed to be handled, as the inner loop doesn't
5717 use it. */
5718 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5719 OMP_CLAUSE__LOOPTEMP_);
5720 gcc_assert (innerc);
5721 for (i = 0; i < fd->collapse; i++)
5723 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5724 OMP_CLAUSE__LOOPTEMP_);
5725 gcc_assert (innerc);
5726 if (i)
5727 counts[i] = OMP_CLAUSE_DECL (innerc);
5728 else
5729 counts[0] = NULL_TREE;
5731 return;
5734 for (i = 0; i < fd->collapse; i++)
5736 tree itype = TREE_TYPE (fd->loops[i].v);
5738 if (SSA_VAR_P (fd->loop.n2)
5739 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5740 fold_convert (itype, fd->loops[i].n1),
5741 fold_convert (itype, fd->loops[i].n2)))
5742 == NULL_TREE || !integer_onep (t)))
5744 gcond *cond_stmt;
5745 tree n1, n2;
5746 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5747 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5748 true, GSI_SAME_STMT);
5749 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5750 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5751 true, GSI_SAME_STMT);
5752 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5753 NULL_TREE, NULL_TREE);
5754 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5755 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5756 expand_omp_regimplify_p, NULL, NULL)
5757 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5758 expand_omp_regimplify_p, NULL, NULL))
5760 *gsi = gsi_for_stmt (cond_stmt);
5761 gimple_regimplify_operands (cond_stmt, gsi);
5763 e = split_block (entry_bb, cond_stmt);
5764 if (zero_iter_bb == NULL)
5766 gassign *assign_stmt;
5767 first_zero_iter = i;
5768 zero_iter_bb = create_empty_bb (entry_bb);
5769 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5770 *gsi = gsi_after_labels (zero_iter_bb);
5771 assign_stmt = gimple_build_assign (fd->loop.n2,
5772 build_zero_cst (type));
5773 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5774 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5775 entry_bb);
5777 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5778 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5779 e->flags = EDGE_TRUE_VALUE;
5780 e->probability = REG_BR_PROB_BASE - ne->probability;
5781 if (l2_dom_bb == NULL)
5782 l2_dom_bb = entry_bb;
5783 entry_bb = e->dest;
5784 *gsi = gsi_last_bb (entry_bb);
5787 if (POINTER_TYPE_P (itype))
5788 itype = signed_type_for (itype);
5789 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5790 ? -1 : 1));
5791 t = fold_build2 (PLUS_EXPR, itype,
5792 fold_convert (itype, fd->loops[i].step), t);
5793 t = fold_build2 (PLUS_EXPR, itype, t,
5794 fold_convert (itype, fd->loops[i].n2));
5795 t = fold_build2 (MINUS_EXPR, itype, t,
5796 fold_convert (itype, fd->loops[i].n1));
5797 /* ?? We could probably use CEIL_DIV_EXPR instead of
5798 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5799 generate the same code in the end because generically we
5800 don't know that the values involved must be negative for
5801 GT?? */
5802 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5803 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5804 fold_build1 (NEGATE_EXPR, itype, t),
5805 fold_build1 (NEGATE_EXPR, itype,
5806 fold_convert (itype,
5807 fd->loops[i].step)));
5808 else
5809 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5810 fold_convert (itype, fd->loops[i].step));
5811 t = fold_convert (type, t);
5812 if (TREE_CODE (t) == INTEGER_CST)
5813 counts[i] = t;
5814 else
5816 counts[i] = create_tmp_reg (type, ".count");
5817 expand_omp_build_assign (gsi, counts[i], t);
5819 if (SSA_VAR_P (fd->loop.n2))
5821 if (i == 0)
5822 t = counts[0];
5823 else
5824 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5825 expand_omp_build_assign (gsi, fd->loop.n2, t);
5831 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5832 T = V;
5833 V3 = N31 + (T % count3) * STEP3;
5834 T = T / count3;
5835 V2 = N21 + (T % count2) * STEP2;
5836 T = T / count2;
5837 V1 = N11 + T * STEP1;
5838 if this loop doesn't have an inner loop construct combined with it.
5839 If it does have an inner loop construct combined with it and the
5840 iteration count isn't known constant, store values from counts array
5841 into its _looptemp_ temporaries instead. */
5843 static void
5844 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5845 tree *counts, gimple inner_stmt, tree startvar)
5847 int i;
5848 if (gimple_omp_for_combined_p (fd->for_stmt))
5850 /* If fd->loop.n2 is constant, then no propagation of the counts
5851 is needed, they are constant. */
5852 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5853 return;
5855 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5856 ? gimple_omp_parallel_clauses (inner_stmt)
5857 : gimple_omp_for_clauses (inner_stmt);
5858 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5859 isn't supposed to be handled, as the inner loop doesn't
5860 use it. */
5861 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5862 gcc_assert (innerc);
5863 for (i = 0; i < fd->collapse; i++)
5865 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5866 OMP_CLAUSE__LOOPTEMP_);
5867 gcc_assert (innerc);
5868 if (i)
5870 tree tem = OMP_CLAUSE_DECL (innerc);
5871 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5872 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5873 false, GSI_CONTINUE_LINKING);
5874 gassign *stmt = gimple_build_assign (tem, t);
5875 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5878 return;
5881 tree type = TREE_TYPE (fd->loop.v);
5882 tree tem = create_tmp_reg (type, ".tem");
5883 gassign *stmt = gimple_build_assign (tem, startvar);
5884 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5886 for (i = fd->collapse - 1; i >= 0; i--)
5888 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5889 itype = vtype;
5890 if (POINTER_TYPE_P (vtype))
5891 itype = signed_type_for (vtype);
5892 if (i != 0)
5893 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5894 else
5895 t = tem;
5896 t = fold_convert (itype, t);
5897 t = fold_build2 (MULT_EXPR, itype, t,
5898 fold_convert (itype, fd->loops[i].step));
5899 if (POINTER_TYPE_P (vtype))
5900 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5901 else
5902 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5903 t = force_gimple_operand_gsi (gsi, t,
5904 DECL_P (fd->loops[i].v)
5905 && TREE_ADDRESSABLE (fd->loops[i].v),
5906 NULL_TREE, false,
5907 GSI_CONTINUE_LINKING);
5908 stmt = gimple_build_assign (fd->loops[i].v, t);
5909 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5910 if (i != 0)
5912 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5913 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5914 false, GSI_CONTINUE_LINKING);
5915 stmt = gimple_build_assign (tem, t);
5916 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5922 /* Helper function for expand_omp_for_*. Generate code like:
5923 L10:
5924 V3 += STEP3;
5925 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5926 L11:
5927 V3 = N31;
5928 V2 += STEP2;
5929 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5930 L12:
5931 V2 = N21;
5932 V1 += STEP1;
5933 goto BODY_BB; */
5935 static basic_block
5936 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5937 basic_block body_bb)
5939 basic_block last_bb, bb, collapse_bb = NULL;
5940 int i;
5941 gimple_stmt_iterator gsi;
5942 edge e;
5943 tree t;
5944 gimple stmt;
5946 last_bb = cont_bb;
5947 for (i = fd->collapse - 1; i >= 0; i--)
5949 tree vtype = TREE_TYPE (fd->loops[i].v);
5951 bb = create_empty_bb (last_bb);
5952 add_bb_to_loop (bb, last_bb->loop_father);
5953 gsi = gsi_start_bb (bb);
5955 if (i < fd->collapse - 1)
5957 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5958 e->probability = REG_BR_PROB_BASE / 8;
5960 t = fd->loops[i + 1].n1;
5961 t = force_gimple_operand_gsi (&gsi, t,
5962 DECL_P (fd->loops[i + 1].v)
5963 && TREE_ADDRESSABLE (fd->loops[i
5964 + 1].v),
5965 NULL_TREE, false,
5966 GSI_CONTINUE_LINKING);
5967 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5968 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5970 else
5971 collapse_bb = bb;
5973 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5975 if (POINTER_TYPE_P (vtype))
5976 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5977 else
5978 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5979 t = force_gimple_operand_gsi (&gsi, t,
5980 DECL_P (fd->loops[i].v)
5981 && TREE_ADDRESSABLE (fd->loops[i].v),
5982 NULL_TREE, false, GSI_CONTINUE_LINKING);
5983 stmt = gimple_build_assign (fd->loops[i].v, t);
5984 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5986 if (i > 0)
5988 t = fd->loops[i].n2;
5989 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5990 false, GSI_CONTINUE_LINKING);
5991 tree v = fd->loops[i].v;
5992 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5993 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5994 false, GSI_CONTINUE_LINKING);
5995 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5996 stmt = gimple_build_cond_empty (t);
5997 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5998 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5999 e->probability = REG_BR_PROB_BASE * 7 / 8;
6001 else
6002 make_edge (bb, body_bb, EDGE_FALLTHRU);
6003 last_bb = bb;
6006 return collapse_bb;
6010 /* A subroutine of expand_omp_for. Generate code for a parallel
6011 loop with any schedule. Given parameters:
6013 for (V = N1; V cond N2; V += STEP) BODY;
6015 where COND is "<" or ">", we generate pseudocode
6017 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
6018 if (more) goto L0; else goto L3;
6020 V = istart0;
6021 iend = iend0;
6023 BODY;
6024 V += STEP;
6025 if (V cond iend) goto L1; else goto L2;
6027 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6030 If this is a combined omp parallel loop, instead of the call to
6031 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6032 If this is gimple_omp_for_combined_p loop, then instead of assigning
6033 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6034 inner GIMPLE_OMP_FOR and V += STEP; and
6035 if (V cond iend) goto L1; else goto L2; are removed.
6037 For collapsed loops, given parameters:
6038 collapse(3)
6039 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6040 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6041 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6042 BODY;
6044 we generate pseudocode
6046 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6047 if (cond3 is <)
6048 adj = STEP3 - 1;
6049 else
6050 adj = STEP3 + 1;
6051 count3 = (adj + N32 - N31) / STEP3;
6052 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6053 if (cond2 is <)
6054 adj = STEP2 - 1;
6055 else
6056 adj = STEP2 + 1;
6057 count2 = (adj + N22 - N21) / STEP2;
6058 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6059 if (cond1 is <)
6060 adj = STEP1 - 1;
6061 else
6062 adj = STEP1 + 1;
6063 count1 = (adj + N12 - N11) / STEP1;
6064 count = count1 * count2 * count3;
6065 goto Z1;
6067 count = 0;
6069 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6070 if (more) goto L0; else goto L3;
6072 V = istart0;
6073 T = V;
6074 V3 = N31 + (T % count3) * STEP3;
6075 T = T / count3;
6076 V2 = N21 + (T % count2) * STEP2;
6077 T = T / count2;
6078 V1 = N11 + T * STEP1;
6079 iend = iend0;
6081 BODY;
6082 V += 1;
6083 if (V < iend) goto L10; else goto L2;
6084 L10:
6085 V3 += STEP3;
6086 if (V3 cond3 N32) goto L1; else goto L11;
6087 L11:
6088 V3 = N31;
6089 V2 += STEP2;
6090 if (V2 cond2 N22) goto L1; else goto L12;
6091 L12:
6092 V2 = N21;
6093 V1 += STEP1;
6094 goto L1;
6096 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6101 static void
6102 expand_omp_for_generic (struct omp_region *region,
6103 struct omp_for_data *fd,
6104 enum built_in_function start_fn,
6105 enum built_in_function next_fn,
6106 gimple inner_stmt)
6108 tree type, istart0, iend0, iend;
6109 tree t, vmain, vback, bias = NULL_TREE;
6110 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6111 basic_block l2_bb = NULL, l3_bb = NULL;
6112 gimple_stmt_iterator gsi;
6113 gassign *assign_stmt;
6114 bool in_combined_parallel = is_combined_parallel (region);
6115 bool broken_loop = region->cont == NULL;
6116 edge e, ne;
6117 tree *counts = NULL;
6118 int i;
6120 gcc_assert (!broken_loop || !in_combined_parallel);
6121 gcc_assert (fd->iter_type == long_integer_type_node
6122 || !in_combined_parallel);
6124 type = TREE_TYPE (fd->loop.v);
6125 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6126 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6127 TREE_ADDRESSABLE (istart0) = 1;
6128 TREE_ADDRESSABLE (iend0) = 1;
6130 /* See if we need to bias by LLONG_MIN. */
6131 if (fd->iter_type == long_long_unsigned_type_node
6132 && TREE_CODE (type) == INTEGER_TYPE
6133 && !TYPE_UNSIGNED (type))
6135 tree n1, n2;
6137 if (fd->loop.cond_code == LT_EXPR)
6139 n1 = fd->loop.n1;
6140 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6142 else
6144 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6145 n2 = fd->loop.n1;
6147 if (TREE_CODE (n1) != INTEGER_CST
6148 || TREE_CODE (n2) != INTEGER_CST
6149 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6150 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6153 entry_bb = region->entry;
6154 cont_bb = region->cont;
6155 collapse_bb = NULL;
6156 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6157 gcc_assert (broken_loop
6158 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6159 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6160 l1_bb = single_succ (l0_bb);
6161 if (!broken_loop)
6163 l2_bb = create_empty_bb (cont_bb);
6164 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6165 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6167 else
6168 l2_bb = NULL;
6169 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6170 exit_bb = region->exit;
6172 gsi = gsi_last_bb (entry_bb);
6174 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6175 if (fd->collapse > 1)
6177 int first_zero_iter = -1;
6178 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6180 counts = XALLOCAVEC (tree, fd->collapse);
6181 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6182 zero_iter_bb, first_zero_iter,
6183 l2_dom_bb);
6185 if (zero_iter_bb)
6187 /* Some counts[i] vars might be uninitialized if
6188 some loop has zero iterations. But the body shouldn't
6189 be executed in that case, so just avoid uninit warnings. */
6190 for (i = first_zero_iter; i < fd->collapse; i++)
6191 if (SSA_VAR_P (counts[i]))
6192 TREE_NO_WARNING (counts[i]) = 1;
6193 gsi_prev (&gsi);
6194 e = split_block (entry_bb, gsi_stmt (gsi));
6195 entry_bb = e->dest;
6196 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6197 gsi = gsi_last_bb (entry_bb);
6198 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6199 get_immediate_dominator (CDI_DOMINATORS,
6200 zero_iter_bb));
6203 if (in_combined_parallel)
6205 /* In a combined parallel loop, emit a call to
6206 GOMP_loop_foo_next. */
6207 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6208 build_fold_addr_expr (istart0),
6209 build_fold_addr_expr (iend0));
6211 else
6213 tree t0, t1, t2, t3, t4;
6214 /* If this is not a combined parallel loop, emit a call to
6215 GOMP_loop_foo_start in ENTRY_BB. */
6216 t4 = build_fold_addr_expr (iend0);
6217 t3 = build_fold_addr_expr (istart0);
6218 t2 = fold_convert (fd->iter_type, fd->loop.step);
6219 t1 = fd->loop.n2;
6220 t0 = fd->loop.n1;
6221 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6223 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6224 OMP_CLAUSE__LOOPTEMP_);
6225 gcc_assert (innerc);
6226 t0 = OMP_CLAUSE_DECL (innerc);
6227 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6228 OMP_CLAUSE__LOOPTEMP_);
6229 gcc_assert (innerc);
6230 t1 = OMP_CLAUSE_DECL (innerc);
6232 if (POINTER_TYPE_P (TREE_TYPE (t0))
6233 && TYPE_PRECISION (TREE_TYPE (t0))
6234 != TYPE_PRECISION (fd->iter_type))
6236 /* Avoid casting pointers to integer of a different size. */
6237 tree itype = signed_type_for (type);
6238 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6239 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6241 else
6243 t1 = fold_convert (fd->iter_type, t1);
6244 t0 = fold_convert (fd->iter_type, t0);
6246 if (bias)
6248 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6249 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6251 if (fd->iter_type == long_integer_type_node)
6253 if (fd->chunk_size)
6255 t = fold_convert (fd->iter_type, fd->chunk_size);
6256 t = build_call_expr (builtin_decl_explicit (start_fn),
6257 6, t0, t1, t2, t, t3, t4);
6259 else
6260 t = build_call_expr (builtin_decl_explicit (start_fn),
6261 5, t0, t1, t2, t3, t4);
6263 else
6265 tree t5;
6266 tree c_bool_type;
6267 tree bfn_decl;
6269 /* The GOMP_loop_ull_*start functions have additional boolean
6270 argument, true for < loops and false for > loops.
6271 In Fortran, the C bool type can be different from
6272 boolean_type_node. */
6273 bfn_decl = builtin_decl_explicit (start_fn);
6274 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6275 t5 = build_int_cst (c_bool_type,
6276 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6277 if (fd->chunk_size)
6279 tree bfn_decl = builtin_decl_explicit (start_fn);
6280 t = fold_convert (fd->iter_type, fd->chunk_size);
6281 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6283 else
6284 t = build_call_expr (builtin_decl_explicit (start_fn),
6285 6, t5, t0, t1, t2, t3, t4);
6288 if (TREE_TYPE (t) != boolean_type_node)
6289 t = fold_build2 (NE_EXPR, boolean_type_node,
6290 t, build_int_cst (TREE_TYPE (t), 0));
6291 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6292 true, GSI_SAME_STMT);
6293 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6295 /* Remove the GIMPLE_OMP_FOR statement. */
6296 gsi_remove (&gsi, true);
6298 /* Iteration setup for sequential loop goes in L0_BB. */
6299 tree startvar = fd->loop.v;
6300 tree endvar = NULL_TREE;
6302 if (gimple_omp_for_combined_p (fd->for_stmt))
6304 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6305 && gimple_omp_for_kind (inner_stmt)
6306 == GF_OMP_FOR_KIND_SIMD);
6307 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6308 OMP_CLAUSE__LOOPTEMP_);
6309 gcc_assert (innerc);
6310 startvar = OMP_CLAUSE_DECL (innerc);
6311 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6312 OMP_CLAUSE__LOOPTEMP_);
6313 gcc_assert (innerc);
6314 endvar = OMP_CLAUSE_DECL (innerc);
6317 gsi = gsi_start_bb (l0_bb);
6318 t = istart0;
6319 if (bias)
6320 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6321 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6322 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6323 t = fold_convert (TREE_TYPE (startvar), t);
6324 t = force_gimple_operand_gsi (&gsi, t,
6325 DECL_P (startvar)
6326 && TREE_ADDRESSABLE (startvar),
6327 NULL_TREE, false, GSI_CONTINUE_LINKING);
6328 assign_stmt = gimple_build_assign (startvar, t);
6329 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6331 t = iend0;
6332 if (bias)
6333 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6334 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6335 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6336 t = fold_convert (TREE_TYPE (startvar), t);
6337 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6338 false, GSI_CONTINUE_LINKING);
6339 if (endvar)
6341 assign_stmt = gimple_build_assign (endvar, iend);
6342 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6343 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6344 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6345 else
6346 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6347 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6349 if (fd->collapse > 1)
6350 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6352 if (!broken_loop)
6354 /* Code to control the increment and predicate for the sequential
6355 loop goes in the CONT_BB. */
6356 gsi = gsi_last_bb (cont_bb);
6357 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6358 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6359 vmain = gimple_omp_continue_control_use (cont_stmt);
6360 vback = gimple_omp_continue_control_def (cont_stmt);
6362 if (!gimple_omp_for_combined_p (fd->for_stmt))
6364 if (POINTER_TYPE_P (type))
6365 t = fold_build_pointer_plus (vmain, fd->loop.step);
6366 else
6367 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6368 t = force_gimple_operand_gsi (&gsi, t,
6369 DECL_P (vback)
6370 && TREE_ADDRESSABLE (vback),
6371 NULL_TREE, true, GSI_SAME_STMT);
6372 assign_stmt = gimple_build_assign (vback, t);
6373 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6375 t = build2 (fd->loop.cond_code, boolean_type_node,
6376 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6377 iend);
6378 gcond *cond_stmt = gimple_build_cond_empty (t);
6379 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6382 /* Remove GIMPLE_OMP_CONTINUE. */
6383 gsi_remove (&gsi, true);
6385 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6386 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6388 /* Emit code to get the next parallel iteration in L2_BB. */
6389 gsi = gsi_start_bb (l2_bb);
6391 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6392 build_fold_addr_expr (istart0),
6393 build_fold_addr_expr (iend0));
6394 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6395 false, GSI_CONTINUE_LINKING);
6396 if (TREE_TYPE (t) != boolean_type_node)
6397 t = fold_build2 (NE_EXPR, boolean_type_node,
6398 t, build_int_cst (TREE_TYPE (t), 0));
6399 gcond *cond_stmt = gimple_build_cond_empty (t);
6400 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6403 /* Add the loop cleanup function. */
6404 gsi = gsi_last_bb (exit_bb);
6405 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6406 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6407 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6408 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6409 else
6410 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6411 gcall *call_stmt = gimple_build_call (t, 0);
6412 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6413 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6414 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6415 gsi_remove (&gsi, true);
6417 /* Connect the new blocks. */
6418 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6419 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6421 if (!broken_loop)
6423 gimple_seq phis;
6425 e = find_edge (cont_bb, l3_bb);
6426 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6428 phis = phi_nodes (l3_bb);
6429 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6431 gimple phi = gsi_stmt (gsi);
6432 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6433 PHI_ARG_DEF_FROM_EDGE (phi, e));
6435 remove_edge (e);
6437 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6438 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6439 e = find_edge (cont_bb, l1_bb);
6440 if (gimple_omp_for_combined_p (fd->for_stmt))
6442 remove_edge (e);
6443 e = NULL;
6445 else if (fd->collapse > 1)
6447 remove_edge (e);
6448 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6450 else
6451 e->flags = EDGE_TRUE_VALUE;
6452 if (e)
6454 e->probability = REG_BR_PROB_BASE * 7 / 8;
6455 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6457 else
6459 e = find_edge (cont_bb, l2_bb);
6460 e->flags = EDGE_FALLTHRU;
6462 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6464 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6465 recompute_dominator (CDI_DOMINATORS, l2_bb));
6466 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6467 recompute_dominator (CDI_DOMINATORS, l3_bb));
6468 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6469 recompute_dominator (CDI_DOMINATORS, l0_bb));
6470 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6471 recompute_dominator (CDI_DOMINATORS, l1_bb));
6473 struct loop *outer_loop = alloc_loop ();
6474 outer_loop->header = l0_bb;
6475 outer_loop->latch = l2_bb;
6476 add_loop (outer_loop, l0_bb->loop_father);
6478 if (!gimple_omp_for_combined_p (fd->for_stmt))
6480 struct loop *loop = alloc_loop ();
6481 loop->header = l1_bb;
6482 /* The loop may have multiple latches. */
6483 add_loop (loop, outer_loop);
6489 /* A subroutine of expand_omp_for. Generate code for a parallel
6490 loop with static schedule and no specified chunk size. Given
6491 parameters:
6493 for (V = N1; V cond N2; V += STEP) BODY;
6495 where COND is "<" or ">", we generate pseudocode
6497 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6498 if (cond is <)
6499 adj = STEP - 1;
6500 else
6501 adj = STEP + 1;
6502 if ((__typeof (V)) -1 > 0 && cond is >)
6503 n = -(adj + N2 - N1) / -STEP;
6504 else
6505 n = (adj + N2 - N1) / STEP;
6506 q = n / nthreads;
6507 tt = n % nthreads;
6508 if (threadid < tt) goto L3; else goto L4;
6510 tt = 0;
6511 q = q + 1;
6513 s0 = q * threadid + tt;
6514 e0 = s0 + q;
6515 V = s0 * STEP + N1;
6516 if (s0 >= e0) goto L2; else goto L0;
6518 e = e0 * STEP + N1;
6520 BODY;
6521 V += STEP;
6522 if (V cond e) goto L1;
6526 static void
6527 expand_omp_for_static_nochunk (struct omp_region *region,
6528 struct omp_for_data *fd,
6529 gimple inner_stmt)
6531 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6532 tree type, itype, vmain, vback;
6533 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6534 basic_block body_bb, cont_bb, collapse_bb = NULL;
6535 basic_block fin_bb;
6536 gimple_stmt_iterator gsi;
6537 edge ep;
6538 bool broken_loop = region->cont == NULL;
6539 tree *counts = NULL;
6540 tree n1, n2, step;
6542 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6543 != GF_OMP_FOR_KIND_OACC_LOOP)
6544 || !inner_stmt);
6546 itype = type = TREE_TYPE (fd->loop.v);
6547 if (POINTER_TYPE_P (type))
6548 itype = signed_type_for (type);
6550 entry_bb = region->entry;
6551 cont_bb = region->cont;
6552 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6553 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6554 gcc_assert (broken_loop
6555 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6556 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6557 body_bb = single_succ (seq_start_bb);
6558 if (!broken_loop)
6560 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6561 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6563 exit_bb = region->exit;
6565 /* Iteration space partitioning goes in ENTRY_BB. */
6566 gsi = gsi_last_bb (entry_bb);
6567 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6569 if (fd->collapse > 1)
6571 int first_zero_iter = -1;
6572 basic_block l2_dom_bb = NULL;
6574 counts = XALLOCAVEC (tree, fd->collapse);
6575 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6576 fin_bb, first_zero_iter,
6577 l2_dom_bb);
6578 t = NULL_TREE;
6580 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6581 t = integer_one_node;
6582 else
6583 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6584 fold_convert (type, fd->loop.n1),
6585 fold_convert (type, fd->loop.n2));
6586 if (fd->collapse == 1
6587 && TYPE_UNSIGNED (type)
6588 && (t == NULL_TREE || !integer_onep (t)))
6590 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6591 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6592 true, GSI_SAME_STMT);
6593 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6594 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6595 true, GSI_SAME_STMT);
6596 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6597 NULL_TREE, NULL_TREE);
6598 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6599 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6600 expand_omp_regimplify_p, NULL, NULL)
6601 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6602 expand_omp_regimplify_p, NULL, NULL))
6604 gsi = gsi_for_stmt (cond_stmt);
6605 gimple_regimplify_operands (cond_stmt, &gsi);
6607 ep = split_block (entry_bb, cond_stmt);
6608 ep->flags = EDGE_TRUE_VALUE;
6609 entry_bb = ep->dest;
6610 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6611 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6612 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6613 if (gimple_in_ssa_p (cfun))
6615 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6616 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6617 !gsi_end_p (gpi); gsi_next (&gpi))
6619 gphi *phi = gpi.phi ();
6620 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6621 ep, UNKNOWN_LOCATION);
6624 gsi = gsi_last_bb (entry_bb);
6627 switch (gimple_omp_for_kind (fd->for_stmt))
6629 case GF_OMP_FOR_KIND_FOR:
6630 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6631 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6632 break;
6633 case GF_OMP_FOR_KIND_DISTRIBUTE:
6634 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6635 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6636 break;
6637 case GF_OMP_FOR_KIND_OACC_LOOP:
6638 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6639 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6640 break;
6641 default:
6642 gcc_unreachable ();
6644 nthreads = build_call_expr (nthreads, 0);
6645 nthreads = fold_convert (itype, nthreads);
6646 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6647 true, GSI_SAME_STMT);
6648 threadid = build_call_expr (threadid, 0);
6649 threadid = fold_convert (itype, threadid);
6650 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6651 true, GSI_SAME_STMT);
6653 n1 = fd->loop.n1;
6654 n2 = fd->loop.n2;
6655 step = fd->loop.step;
6656 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6658 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6659 OMP_CLAUSE__LOOPTEMP_);
6660 gcc_assert (innerc);
6661 n1 = OMP_CLAUSE_DECL (innerc);
6662 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6663 OMP_CLAUSE__LOOPTEMP_);
6664 gcc_assert (innerc);
6665 n2 = OMP_CLAUSE_DECL (innerc);
6667 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6668 true, NULL_TREE, true, GSI_SAME_STMT);
6669 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6670 true, NULL_TREE, true, GSI_SAME_STMT);
6671 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6672 true, NULL_TREE, true, GSI_SAME_STMT);
6674 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6675 t = fold_build2 (PLUS_EXPR, itype, step, t);
6676 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6677 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6678 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6679 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6680 fold_build1 (NEGATE_EXPR, itype, t),
6681 fold_build1 (NEGATE_EXPR, itype, step));
6682 else
6683 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6684 t = fold_convert (itype, t);
6685 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6687 q = create_tmp_reg (itype, "q");
6688 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6689 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6690 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6692 tt = create_tmp_reg (itype, "tt");
6693 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6694 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6695 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6697 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6698 gcond *cond_stmt = gimple_build_cond_empty (t);
6699 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6701 second_bb = split_block (entry_bb, cond_stmt)->dest;
6702 gsi = gsi_last_bb (second_bb);
6703 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6705 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6706 GSI_SAME_STMT);
6707 gassign *assign_stmt
6708 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6709 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6711 third_bb = split_block (second_bb, assign_stmt)->dest;
6712 gsi = gsi_last_bb (third_bb);
6713 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6715 t = build2 (MULT_EXPR, itype, q, threadid);
6716 t = build2 (PLUS_EXPR, itype, t, tt);
6717 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6719 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6720 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6722 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6723 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6725 /* Remove the GIMPLE_OMP_FOR statement. */
6726 gsi_remove (&gsi, true);
6728 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6729 gsi = gsi_start_bb (seq_start_bb);
6731 tree startvar = fd->loop.v;
6732 tree endvar = NULL_TREE;
6734 if (gimple_omp_for_combined_p (fd->for_stmt))
6736 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6737 ? gimple_omp_parallel_clauses (inner_stmt)
6738 : gimple_omp_for_clauses (inner_stmt);
6739 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6740 gcc_assert (innerc);
6741 startvar = OMP_CLAUSE_DECL (innerc);
6742 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6743 OMP_CLAUSE__LOOPTEMP_);
6744 gcc_assert (innerc);
6745 endvar = OMP_CLAUSE_DECL (innerc);
6747 t = fold_convert (itype, s0);
6748 t = fold_build2 (MULT_EXPR, itype, t, step);
6749 if (POINTER_TYPE_P (type))
6750 t = fold_build_pointer_plus (n1, t);
6751 else
6752 t = fold_build2 (PLUS_EXPR, type, t, n1);
6753 t = fold_convert (TREE_TYPE (startvar), t);
6754 t = force_gimple_operand_gsi (&gsi, t,
6755 DECL_P (startvar)
6756 && TREE_ADDRESSABLE (startvar),
6757 NULL_TREE, false, GSI_CONTINUE_LINKING);
6758 assign_stmt = gimple_build_assign (startvar, t);
6759 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6761 t = fold_convert (itype, e0);
6762 t = fold_build2 (MULT_EXPR, itype, t, step);
6763 if (POINTER_TYPE_P (type))
6764 t = fold_build_pointer_plus (n1, t);
6765 else
6766 t = fold_build2 (PLUS_EXPR, type, t, n1);
6767 t = fold_convert (TREE_TYPE (startvar), t);
6768 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6769 false, GSI_CONTINUE_LINKING);
6770 if (endvar)
6772 assign_stmt = gimple_build_assign (endvar, e);
6773 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6774 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6775 assign_stmt = gimple_build_assign (fd->loop.v, e);
6776 else
6777 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6778 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6780 if (fd->collapse > 1)
6781 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6783 if (!broken_loop)
6785 /* The code controlling the sequential loop replaces the
6786 GIMPLE_OMP_CONTINUE. */
6787 gsi = gsi_last_bb (cont_bb);
6788 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6789 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6790 vmain = gimple_omp_continue_control_use (cont_stmt);
6791 vback = gimple_omp_continue_control_def (cont_stmt);
6793 if (!gimple_omp_for_combined_p (fd->for_stmt))
6795 if (POINTER_TYPE_P (type))
6796 t = fold_build_pointer_plus (vmain, step);
6797 else
6798 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6799 t = force_gimple_operand_gsi (&gsi, t,
6800 DECL_P (vback)
6801 && TREE_ADDRESSABLE (vback),
6802 NULL_TREE, true, GSI_SAME_STMT);
6803 assign_stmt = gimple_build_assign (vback, t);
6804 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6806 t = build2 (fd->loop.cond_code, boolean_type_node,
6807 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6808 ? t : vback, e);
6809 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6812 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6813 gsi_remove (&gsi, true);
6815 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6816 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6819 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6820 gsi = gsi_last_bb (exit_bb);
6821 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6823 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6824 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6825 gcc_checking_assert (t == NULL_TREE);
6826 else
6827 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6829 gsi_remove (&gsi, true);
6831 /* Connect all the blocks. */
6832 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6833 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6834 ep = find_edge (entry_bb, second_bb);
6835 ep->flags = EDGE_TRUE_VALUE;
6836 ep->probability = REG_BR_PROB_BASE / 4;
6837 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6838 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6840 if (!broken_loop)
6842 ep = find_edge (cont_bb, body_bb);
6843 if (gimple_omp_for_combined_p (fd->for_stmt))
6845 remove_edge (ep);
6846 ep = NULL;
6848 else if (fd->collapse > 1)
6850 remove_edge (ep);
6851 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6853 else
6854 ep->flags = EDGE_TRUE_VALUE;
6855 find_edge (cont_bb, fin_bb)->flags
6856 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6859 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6860 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6861 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6863 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6864 recompute_dominator (CDI_DOMINATORS, body_bb));
6865 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6866 recompute_dominator (CDI_DOMINATORS, fin_bb));
6868 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6870 struct loop *loop = alloc_loop ();
6871 loop->header = body_bb;
6872 if (collapse_bb == NULL)
6873 loop->latch = cont_bb;
6874 add_loop (loop, body_bb->loop_father);
6879 /* A subroutine of expand_omp_for. Generate code for a parallel
6880 loop with static schedule and a specified chunk size. Given
6881 parameters:
6883 for (V = N1; V cond N2; V += STEP) BODY;
6885 where COND is "<" or ">", we generate pseudocode
6887 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6888 if (cond is <)
6889 adj = STEP - 1;
6890 else
6891 adj = STEP + 1;
6892 if ((__typeof (V)) -1 > 0 && cond is >)
6893 n = -(adj + N2 - N1) / -STEP;
6894 else
6895 n = (adj + N2 - N1) / STEP;
6896 trip = 0;
6897 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6898 here so that V is defined
6899 if the loop is not entered
6901 s0 = (trip * nthreads + threadid) * CHUNK;
6902 e0 = min(s0 + CHUNK, n);
6903 if (s0 < n) goto L1; else goto L4;
6905 V = s0 * STEP + N1;
6906 e = e0 * STEP + N1;
6908 BODY;
6909 V += STEP;
6910 if (V cond e) goto L2; else goto L3;
6912 trip += 1;
6913 goto L0;
6917 static void
6918 expand_omp_for_static_chunk (struct omp_region *region,
6919 struct omp_for_data *fd, gimple inner_stmt)
6921 tree n, s0, e0, e, t;
6922 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6923 tree type, itype, vmain, vback, vextra;
6924 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6925 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6926 gimple_stmt_iterator gsi;
6927 edge se;
6928 bool broken_loop = region->cont == NULL;
6929 tree *counts = NULL;
6930 tree n1, n2, step;
6932 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6933 != GF_OMP_FOR_KIND_OACC_LOOP)
6934 || !inner_stmt);
6936 itype = type = TREE_TYPE (fd->loop.v);
6937 if (POINTER_TYPE_P (type))
6938 itype = signed_type_for (type);
6940 entry_bb = region->entry;
6941 se = split_block (entry_bb, last_stmt (entry_bb));
6942 entry_bb = se->src;
6943 iter_part_bb = se->dest;
6944 cont_bb = region->cont;
6945 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6946 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6947 gcc_assert (broken_loop
6948 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6949 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6950 body_bb = single_succ (seq_start_bb);
6951 if (!broken_loop)
6953 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6954 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6955 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6957 exit_bb = region->exit;
6959 /* Trip and adjustment setup goes in ENTRY_BB. */
6960 gsi = gsi_last_bb (entry_bb);
6961 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6963 if (fd->collapse > 1)
6965 int first_zero_iter = -1;
6966 basic_block l2_dom_bb = NULL;
6968 counts = XALLOCAVEC (tree, fd->collapse);
6969 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6970 fin_bb, first_zero_iter,
6971 l2_dom_bb);
6972 t = NULL_TREE;
6974 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6975 t = integer_one_node;
6976 else
6977 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6978 fold_convert (type, fd->loop.n1),
6979 fold_convert (type, fd->loop.n2));
6980 if (fd->collapse == 1
6981 && TYPE_UNSIGNED (type)
6982 && (t == NULL_TREE || !integer_onep (t)))
6984 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6985 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6986 true, GSI_SAME_STMT);
6987 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6988 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6989 true, GSI_SAME_STMT);
6990 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6991 NULL_TREE, NULL_TREE);
6992 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6993 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6994 expand_omp_regimplify_p, NULL, NULL)
6995 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6996 expand_omp_regimplify_p, NULL, NULL))
6998 gsi = gsi_for_stmt (cond_stmt);
6999 gimple_regimplify_operands (cond_stmt, &gsi);
7001 se = split_block (entry_bb, cond_stmt);
7002 se->flags = EDGE_TRUE_VALUE;
7003 entry_bb = se->dest;
7004 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
7005 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
7006 se->probability = REG_BR_PROB_BASE / 2000 - 1;
7007 if (gimple_in_ssa_p (cfun))
7009 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
7010 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
7011 !gsi_end_p (gpi); gsi_next (&gpi))
7013 gphi *phi = gpi.phi ();
7014 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
7015 se, UNKNOWN_LOCATION);
7018 gsi = gsi_last_bb (entry_bb);
7021 switch (gimple_omp_for_kind (fd->for_stmt))
7023 case GF_OMP_FOR_KIND_FOR:
7024 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7025 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7026 break;
7027 case GF_OMP_FOR_KIND_DISTRIBUTE:
7028 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7029 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7030 break;
7031 case GF_OMP_FOR_KIND_OACC_LOOP:
7032 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7033 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7034 break;
7035 default:
7036 gcc_unreachable ();
7038 nthreads = build_call_expr (nthreads, 0);
7039 nthreads = fold_convert (itype, nthreads);
7040 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7041 true, GSI_SAME_STMT);
7042 threadid = build_call_expr (threadid, 0);
7043 threadid = fold_convert (itype, threadid);
7044 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7045 true, GSI_SAME_STMT);
7047 n1 = fd->loop.n1;
7048 n2 = fd->loop.n2;
7049 step = fd->loop.step;
7050 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7052 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7053 OMP_CLAUSE__LOOPTEMP_);
7054 gcc_assert (innerc);
7055 n1 = OMP_CLAUSE_DECL (innerc);
7056 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7057 OMP_CLAUSE__LOOPTEMP_);
7058 gcc_assert (innerc);
7059 n2 = OMP_CLAUSE_DECL (innerc);
7061 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7062 true, NULL_TREE, true, GSI_SAME_STMT);
7063 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7064 true, NULL_TREE, true, GSI_SAME_STMT);
7065 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7066 true, NULL_TREE, true, GSI_SAME_STMT);
7067 fd->chunk_size
7068 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7069 true, NULL_TREE, true, GSI_SAME_STMT);
7071 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7072 t = fold_build2 (PLUS_EXPR, itype, step, t);
7073 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7074 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7075 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7076 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7077 fold_build1 (NEGATE_EXPR, itype, t),
7078 fold_build1 (NEGATE_EXPR, itype, step));
7079 else
7080 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7081 t = fold_convert (itype, t);
7082 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7083 true, GSI_SAME_STMT);
7085 trip_var = create_tmp_reg (itype, ".trip");
7086 if (gimple_in_ssa_p (cfun))
7088 trip_init = make_ssa_name (trip_var);
7089 trip_main = make_ssa_name (trip_var);
7090 trip_back = make_ssa_name (trip_var);
7092 else
7094 trip_init = trip_var;
7095 trip_main = trip_var;
7096 trip_back = trip_var;
7099 gassign *assign_stmt
7100 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7101 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7103 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7104 t = fold_build2 (MULT_EXPR, itype, t, step);
7105 if (POINTER_TYPE_P (type))
7106 t = fold_build_pointer_plus (n1, t);
7107 else
7108 t = fold_build2 (PLUS_EXPR, type, t, n1);
7109 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7110 true, GSI_SAME_STMT);
7112 /* Remove the GIMPLE_OMP_FOR. */
7113 gsi_remove (&gsi, true);
7115 /* Iteration space partitioning goes in ITER_PART_BB. */
7116 gsi = gsi_last_bb (iter_part_bb);
7118 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7119 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7120 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7121 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7122 false, GSI_CONTINUE_LINKING);
7124 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7125 t = fold_build2 (MIN_EXPR, itype, t, n);
7126 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7127 false, GSI_CONTINUE_LINKING);
7129 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7130 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7132 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7133 gsi = gsi_start_bb (seq_start_bb);
7135 tree startvar = fd->loop.v;
7136 tree endvar = NULL_TREE;
7138 if (gimple_omp_for_combined_p (fd->for_stmt))
7140 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7141 ? gimple_omp_parallel_clauses (inner_stmt)
7142 : gimple_omp_for_clauses (inner_stmt);
7143 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7144 gcc_assert (innerc);
7145 startvar = OMP_CLAUSE_DECL (innerc);
7146 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7147 OMP_CLAUSE__LOOPTEMP_);
7148 gcc_assert (innerc);
7149 endvar = OMP_CLAUSE_DECL (innerc);
7152 t = fold_convert (itype, s0);
7153 t = fold_build2 (MULT_EXPR, itype, t, step);
7154 if (POINTER_TYPE_P (type))
7155 t = fold_build_pointer_plus (n1, t);
7156 else
7157 t = fold_build2 (PLUS_EXPR, type, t, n1);
7158 t = fold_convert (TREE_TYPE (startvar), t);
7159 t = force_gimple_operand_gsi (&gsi, t,
7160 DECL_P (startvar)
7161 && TREE_ADDRESSABLE (startvar),
7162 NULL_TREE, false, GSI_CONTINUE_LINKING);
7163 assign_stmt = gimple_build_assign (startvar, t);
7164 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7166 t = fold_convert (itype, e0);
7167 t = fold_build2 (MULT_EXPR, itype, t, step);
7168 if (POINTER_TYPE_P (type))
7169 t = fold_build_pointer_plus (n1, t);
7170 else
7171 t = fold_build2 (PLUS_EXPR, type, t, n1);
7172 t = fold_convert (TREE_TYPE (startvar), t);
7173 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7174 false, GSI_CONTINUE_LINKING);
7175 if (endvar)
7177 assign_stmt = gimple_build_assign (endvar, e);
7178 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7179 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7180 assign_stmt = gimple_build_assign (fd->loop.v, e);
7181 else
7182 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7183 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7185 if (fd->collapse > 1)
7186 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7188 if (!broken_loop)
7190 /* The code controlling the sequential loop goes in CONT_BB,
7191 replacing the GIMPLE_OMP_CONTINUE. */
7192 gsi = gsi_last_bb (cont_bb);
7193 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7194 vmain = gimple_omp_continue_control_use (cont_stmt);
7195 vback = gimple_omp_continue_control_def (cont_stmt);
7197 if (!gimple_omp_for_combined_p (fd->for_stmt))
7199 if (POINTER_TYPE_P (type))
7200 t = fold_build_pointer_plus (vmain, step);
7201 else
7202 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7203 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7204 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7205 true, GSI_SAME_STMT);
7206 assign_stmt = gimple_build_assign (vback, t);
7207 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7209 t = build2 (fd->loop.cond_code, boolean_type_node,
7210 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7211 ? t : vback, e);
7212 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7215 /* Remove GIMPLE_OMP_CONTINUE. */
7216 gsi_remove (&gsi, true);
7218 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7219 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7221 /* Trip update code goes into TRIP_UPDATE_BB. */
7222 gsi = gsi_start_bb (trip_update_bb);
7224 t = build_int_cst (itype, 1);
7225 t = build2 (PLUS_EXPR, itype, trip_main, t);
7226 assign_stmt = gimple_build_assign (trip_back, t);
7227 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7230 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7231 gsi = gsi_last_bb (exit_bb);
7232 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7234 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7235 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7236 gcc_checking_assert (t == NULL_TREE);
7237 else
7238 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7240 gsi_remove (&gsi, true);
7242 /* Connect the new blocks. */
7243 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7244 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7246 if (!broken_loop)
7248 se = find_edge (cont_bb, body_bb);
7249 if (gimple_omp_for_combined_p (fd->for_stmt))
7251 remove_edge (se);
7252 se = NULL;
7254 else if (fd->collapse > 1)
7256 remove_edge (se);
7257 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7259 else
7260 se->flags = EDGE_TRUE_VALUE;
7261 find_edge (cont_bb, trip_update_bb)->flags
7262 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7264 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7267 if (gimple_in_ssa_p (cfun))
7269 gphi_iterator psi;
7270 gphi *phi;
7271 edge re, ene;
7272 edge_var_map *vm;
7273 size_t i;
7275 gcc_assert (fd->collapse == 1 && !broken_loop);
7277 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7278 remove arguments of the phi nodes in fin_bb. We need to create
7279 appropriate phi nodes in iter_part_bb instead. */
7280 se = single_pred_edge (fin_bb);
7281 re = single_succ_edge (trip_update_bb);
7282 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7283 ene = single_succ_edge (entry_bb);
7285 psi = gsi_start_phis (fin_bb);
7286 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7287 gsi_next (&psi), ++i)
7289 gphi *nphi;
7290 source_location locus;
7292 phi = psi.phi ();
7293 t = gimple_phi_result (phi);
7294 gcc_assert (t == redirect_edge_var_map_result (vm));
7295 nphi = create_phi_node (t, iter_part_bb);
7297 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7298 locus = gimple_phi_arg_location_from_edge (phi, se);
7300 /* A special case -- fd->loop.v is not yet computed in
7301 iter_part_bb, we need to use vextra instead. */
7302 if (t == fd->loop.v)
7303 t = vextra;
7304 add_phi_arg (nphi, t, ene, locus);
7305 locus = redirect_edge_var_map_location (vm);
7306 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7308 gcc_assert (gsi_end_p (psi) && i == head->length ());
7309 redirect_edge_var_map_clear (re);
7310 while (1)
7312 psi = gsi_start_phis (fin_bb);
7313 if (gsi_end_p (psi))
7314 break;
7315 remove_phi_node (&psi, false);
7318 /* Make phi node for trip. */
7319 phi = create_phi_node (trip_main, iter_part_bb);
7320 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7321 UNKNOWN_LOCATION);
7322 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7323 UNKNOWN_LOCATION);
7326 if (!broken_loop)
7327 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7328 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7329 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7330 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7331 recompute_dominator (CDI_DOMINATORS, fin_bb));
7332 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7333 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7334 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7335 recompute_dominator (CDI_DOMINATORS, body_bb));
7337 if (!broken_loop)
7339 struct loop *trip_loop = alloc_loop ();
7340 trip_loop->header = iter_part_bb;
7341 trip_loop->latch = trip_update_bb;
7342 add_loop (trip_loop, iter_part_bb->loop_father);
7344 if (!gimple_omp_for_combined_p (fd->for_stmt))
7346 struct loop *loop = alloc_loop ();
7347 loop->header = body_bb;
7348 if (collapse_bb == NULL)
7349 loop->latch = cont_bb;
7350 add_loop (loop, trip_loop);
7355 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7356 Given parameters:
7357 for (V = N1; V cond N2; V += STEP) BODY;
7359 where COND is "<" or ">" or "!=", we generate pseudocode
7361 for (ind_var = low; ind_var < high; ind_var++)
7363 V = n1 + (ind_var * STEP)
7365 <BODY>
7368 In the above pseudocode, low and high are function parameters of the
7369 child function. In the function below, we are inserting a temp.
7370 variable that will be making a call to two OMP functions that will not be
7371 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7372 with _Cilk_for). These functions are replaced with low and high
7373 by the function that handles taskreg. */
7376 static void
7377 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7379 bool broken_loop = region->cont == NULL;
7380 basic_block entry_bb = region->entry;
7381 basic_block cont_bb = region->cont;
7383 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7384 gcc_assert (broken_loop
7385 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7386 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7387 basic_block l1_bb, l2_bb;
7389 if (!broken_loop)
7391 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7392 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7393 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7394 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7396 else
7398 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7399 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7400 l2_bb = single_succ (l1_bb);
7402 basic_block exit_bb = region->exit;
7403 basic_block l2_dom_bb = NULL;
7405 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7407 /* Below statements until the "tree high_val = ..." are pseudo statements
7408 used to pass information to be used by expand_omp_taskreg.
7409 low_val and high_val will be replaced by the __low and __high
7410 parameter from the child function.
7412 The call_exprs part is a place-holder, it is mainly used
7413 to distinctly identify to the top-level part that this is
7414 where we should put low and high (reasoning given in header
7415 comment). */
7417 tree child_fndecl
7418 = gimple_omp_parallel_child_fn (
7419 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7420 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7421 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7423 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7424 high_val = t;
7425 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7426 low_val = t;
7428 gcc_assert (low_val && high_val);
7430 tree type = TREE_TYPE (low_val);
7431 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7432 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7434 /* Not needed in SSA form right now. */
7435 gcc_assert (!gimple_in_ssa_p (cfun));
7436 if (l2_dom_bb == NULL)
7437 l2_dom_bb = l1_bb;
7439 tree n1 = low_val;
7440 tree n2 = high_val;
7442 gimple stmt = gimple_build_assign (ind_var, n1);
7444 /* Replace the GIMPLE_OMP_FOR statement. */
7445 gsi_replace (&gsi, stmt, true);
7447 if (!broken_loop)
7449 /* Code to control the increment goes in the CONT_BB. */
7450 gsi = gsi_last_bb (cont_bb);
7451 stmt = gsi_stmt (gsi);
7452 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7453 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7454 build_one_cst (type));
7456 /* Replace GIMPLE_OMP_CONTINUE. */
7457 gsi_replace (&gsi, stmt, true);
7460 /* Emit the condition in L1_BB. */
7461 gsi = gsi_after_labels (l1_bb);
7462 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7463 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7464 fd->loop.step);
7465 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7466 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7467 fd->loop.n1, fold_convert (sizetype, t));
7468 else
7469 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7470 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7471 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7472 expand_omp_build_assign (&gsi, fd->loop.v, t);
7474 /* The condition is always '<' since the runtime will fill in the low
7475 and high values. */
7476 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7477 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7479 /* Remove GIMPLE_OMP_RETURN. */
7480 gsi = gsi_last_bb (exit_bb);
7481 gsi_remove (&gsi, true);
7483 /* Connect the new blocks. */
7484 remove_edge (FALLTHRU_EDGE (entry_bb));
7486 edge e, ne;
7487 if (!broken_loop)
7489 remove_edge (BRANCH_EDGE (entry_bb));
7490 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7492 e = BRANCH_EDGE (l1_bb);
7493 ne = FALLTHRU_EDGE (l1_bb);
7494 e->flags = EDGE_TRUE_VALUE;
7496 else
7498 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7500 ne = single_succ_edge (l1_bb);
7501 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7504 ne->flags = EDGE_FALSE_VALUE;
7505 e->probability = REG_BR_PROB_BASE * 7 / 8;
7506 ne->probability = REG_BR_PROB_BASE / 8;
7508 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7509 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7510 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7512 if (!broken_loop)
7514 struct loop *loop = alloc_loop ();
7515 loop->header = l1_bb;
7516 loop->latch = cont_bb;
7517 add_loop (loop, l1_bb->loop_father);
7518 loop->safelen = INT_MAX;
7521 /* Pick the correct library function based on the precision of the
7522 induction variable type. */
7523 tree lib_fun = NULL_TREE;
7524 if (TYPE_PRECISION (type) == 32)
7525 lib_fun = cilk_for_32_fndecl;
7526 else if (TYPE_PRECISION (type) == 64)
7527 lib_fun = cilk_for_64_fndecl;
7528 else
7529 gcc_unreachable ();
7531 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7533 /* WS_ARGS contains the library function flavor to call:
7534 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7535 user-defined grain value. If the user does not define one, then zero
7536 is passed in by the parser. */
7537 vec_alloc (region->ws_args, 2);
7538 region->ws_args->quick_push (lib_fun);
7539 region->ws_args->quick_push (fd->chunk_size);
7542 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7543 loop. Given parameters:
7545 for (V = N1; V cond N2; V += STEP) BODY;
7547 where COND is "<" or ">", we generate pseudocode
7549 V = N1;
7550 goto L1;
7552 BODY;
7553 V += STEP;
7555 if (V cond N2) goto L0; else goto L2;
7558 For collapsed loops, given parameters:
7559 collapse(3)
7560 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7561 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7562 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7563 BODY;
7565 we generate pseudocode
7567 if (cond3 is <)
7568 adj = STEP3 - 1;
7569 else
7570 adj = STEP3 + 1;
7571 count3 = (adj + N32 - N31) / STEP3;
7572 if (cond2 is <)
7573 adj = STEP2 - 1;
7574 else
7575 adj = STEP2 + 1;
7576 count2 = (adj + N22 - N21) / STEP2;
7577 if (cond1 is <)
7578 adj = STEP1 - 1;
7579 else
7580 adj = STEP1 + 1;
7581 count1 = (adj + N12 - N11) / STEP1;
7582 count = count1 * count2 * count3;
7583 V = 0;
7584 V1 = N11;
7585 V2 = N21;
7586 V3 = N31;
7587 goto L1;
7589 BODY;
7590 V += 1;
7591 V3 += STEP3;
7592 V2 += (V3 cond3 N32) ? 0 : STEP2;
7593 V3 = (V3 cond3 N32) ? V3 : N31;
7594 V1 += (V2 cond2 N22) ? 0 : STEP1;
7595 V2 = (V2 cond2 N22) ? V2 : N21;
7597 if (V < count) goto L0; else goto L2;
7602 static void
7603 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7605 tree type, t;
7606 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7607 gimple_stmt_iterator gsi;
7608 gimple stmt;
7609 gcond *cond_stmt;
7610 bool broken_loop = region->cont == NULL;
7611 edge e, ne;
7612 tree *counts = NULL;
7613 int i;
7614 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7615 OMP_CLAUSE_SAFELEN);
7616 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7617 OMP_CLAUSE__SIMDUID_);
7618 tree n1, n2;
7620 type = TREE_TYPE (fd->loop.v);
7621 entry_bb = region->entry;
7622 cont_bb = region->cont;
7623 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7624 gcc_assert (broken_loop
7625 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7626 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7627 if (!broken_loop)
7629 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7630 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7631 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7632 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7634 else
7636 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7637 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7638 l2_bb = single_succ (l1_bb);
7640 exit_bb = region->exit;
7641 l2_dom_bb = NULL;
7643 gsi = gsi_last_bb (entry_bb);
7645 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7646 /* Not needed in SSA form right now. */
7647 gcc_assert (!gimple_in_ssa_p (cfun));
7648 if (fd->collapse > 1)
7650 int first_zero_iter = -1;
7651 basic_block zero_iter_bb = l2_bb;
7653 counts = XALLOCAVEC (tree, fd->collapse);
7654 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7655 zero_iter_bb, first_zero_iter,
7656 l2_dom_bb);
7658 if (l2_dom_bb == NULL)
7659 l2_dom_bb = l1_bb;
7661 n1 = fd->loop.n1;
7662 n2 = fd->loop.n2;
7663 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7665 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7666 OMP_CLAUSE__LOOPTEMP_);
7667 gcc_assert (innerc);
7668 n1 = OMP_CLAUSE_DECL (innerc);
7669 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7670 OMP_CLAUSE__LOOPTEMP_);
7671 gcc_assert (innerc);
7672 n2 = OMP_CLAUSE_DECL (innerc);
7673 expand_omp_build_assign (&gsi, fd->loop.v,
7674 fold_convert (type, n1));
7675 if (fd->collapse > 1)
7677 gsi_prev (&gsi);
7678 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7679 gsi_next (&gsi);
7682 else
7684 expand_omp_build_assign (&gsi, fd->loop.v,
7685 fold_convert (type, fd->loop.n1));
7686 if (fd->collapse > 1)
7687 for (i = 0; i < fd->collapse; i++)
7689 tree itype = TREE_TYPE (fd->loops[i].v);
7690 if (POINTER_TYPE_P (itype))
7691 itype = signed_type_for (itype);
7692 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7693 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7697 /* Remove the GIMPLE_OMP_FOR statement. */
7698 gsi_remove (&gsi, true);
7700 if (!broken_loop)
7702 /* Code to control the increment goes in the CONT_BB. */
7703 gsi = gsi_last_bb (cont_bb);
7704 stmt = gsi_stmt (gsi);
7705 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7707 if (POINTER_TYPE_P (type))
7708 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7709 else
7710 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7711 expand_omp_build_assign (&gsi, fd->loop.v, t);
7713 if (fd->collapse > 1)
7715 i = fd->collapse - 1;
7716 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7718 t = fold_convert (sizetype, fd->loops[i].step);
7719 t = fold_build_pointer_plus (fd->loops[i].v, t);
7721 else
7723 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7724 fd->loops[i].step);
7725 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7726 fd->loops[i].v, t);
7728 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7730 for (i = fd->collapse - 1; i > 0; i--)
7732 tree itype = TREE_TYPE (fd->loops[i].v);
7733 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7734 if (POINTER_TYPE_P (itype2))
7735 itype2 = signed_type_for (itype2);
7736 t = build3 (COND_EXPR, itype2,
7737 build2 (fd->loops[i].cond_code, boolean_type_node,
7738 fd->loops[i].v,
7739 fold_convert (itype, fd->loops[i].n2)),
7740 build_int_cst (itype2, 0),
7741 fold_convert (itype2, fd->loops[i - 1].step));
7742 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7743 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7744 else
7745 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7746 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7748 t = build3 (COND_EXPR, itype,
7749 build2 (fd->loops[i].cond_code, boolean_type_node,
7750 fd->loops[i].v,
7751 fold_convert (itype, fd->loops[i].n2)),
7752 fd->loops[i].v,
7753 fold_convert (itype, fd->loops[i].n1));
7754 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7758 /* Remove GIMPLE_OMP_CONTINUE. */
7759 gsi_remove (&gsi, true);
7762 /* Emit the condition in L1_BB. */
7763 gsi = gsi_start_bb (l1_bb);
7765 t = fold_convert (type, n2);
7766 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7767 false, GSI_CONTINUE_LINKING);
7768 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7769 cond_stmt = gimple_build_cond_empty (t);
7770 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7771 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7772 NULL, NULL)
7773 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7774 NULL, NULL))
7776 gsi = gsi_for_stmt (cond_stmt);
7777 gimple_regimplify_operands (cond_stmt, &gsi);
7780 /* Remove GIMPLE_OMP_RETURN. */
7781 gsi = gsi_last_bb (exit_bb);
7782 gsi_remove (&gsi, true);
7784 /* Connect the new blocks. */
7785 remove_edge (FALLTHRU_EDGE (entry_bb));
7787 if (!broken_loop)
7789 remove_edge (BRANCH_EDGE (entry_bb));
7790 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7792 e = BRANCH_EDGE (l1_bb);
7793 ne = FALLTHRU_EDGE (l1_bb);
7794 e->flags = EDGE_TRUE_VALUE;
7796 else
7798 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7800 ne = single_succ_edge (l1_bb);
7801 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7804 ne->flags = EDGE_FALSE_VALUE;
7805 e->probability = REG_BR_PROB_BASE * 7 / 8;
7806 ne->probability = REG_BR_PROB_BASE / 8;
7808 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7809 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7810 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7812 if (!broken_loop)
7814 struct loop *loop = alloc_loop ();
7815 loop->header = l1_bb;
7816 loop->latch = cont_bb;
7817 add_loop (loop, l1_bb->loop_father);
7818 if (safelen == NULL_TREE)
7819 loop->safelen = INT_MAX;
7820 else
7822 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7823 if (TREE_CODE (safelen) != INTEGER_CST)
7824 loop->safelen = 0;
7825 else if (!tree_fits_uhwi_p (safelen)
7826 || tree_to_uhwi (safelen) > INT_MAX)
7827 loop->safelen = INT_MAX;
7828 else
7829 loop->safelen = tree_to_uhwi (safelen);
7830 if (loop->safelen == 1)
7831 loop->safelen = 0;
7833 if (simduid)
7835 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7836 cfun->has_simduid_loops = true;
7838 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7839 the loop. */
7840 if ((flag_tree_loop_vectorize
7841 || (!global_options_set.x_flag_tree_loop_vectorize
7842 && !global_options_set.x_flag_tree_vectorize))
7843 && flag_tree_loop_optimize
7844 && loop->safelen > 1)
7846 loop->force_vectorize = true;
7847 cfun->has_force_vectorize_loops = true;
7853 /* Expand the OMP loop defined by REGION. */
7855 static void
7856 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7858 struct omp_for_data fd;
7859 struct omp_for_data_loop *loops;
7861 loops
7862 = (struct omp_for_data_loop *)
7863 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7864 * sizeof (struct omp_for_data_loop));
7865 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7866 &fd, loops);
7867 region->sched_kind = fd.sched_kind;
7869 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7870 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7871 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7872 if (region->cont)
7874 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7875 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7876 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7878 else
7879 /* If there isn't a continue then this is a degerate case where
7880 the introduction of abnormal edges during lowering will prevent
7881 original loops from being detected. Fix that up. */
7882 loops_state_set (LOOPS_NEED_FIXUP);
7884 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7885 expand_omp_simd (region, &fd);
7886 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7887 expand_cilk_for (region, &fd);
7888 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7889 && !fd.have_ordered)
7891 if (fd.chunk_size == NULL)
7892 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7893 else
7894 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7896 else
7898 int fn_index, start_ix, next_ix;
7900 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7901 == GF_OMP_FOR_KIND_FOR);
7902 if (fd.chunk_size == NULL
7903 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7904 fd.chunk_size = integer_zero_node;
7905 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7906 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7907 ? 3 : fd.sched_kind;
7908 fn_index += fd.have_ordered * 4;
7909 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7910 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7911 if (fd.iter_type == long_long_unsigned_type_node)
7913 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7914 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7915 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7916 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7918 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7919 (enum built_in_function) next_ix, inner_stmt);
7922 if (gimple_in_ssa_p (cfun))
7923 update_ssa (TODO_update_ssa_only_virtuals);
7927 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7929 v = GOMP_sections_start (n);
7931 switch (v)
7933 case 0:
7934 goto L2;
7935 case 1:
7936 section 1;
7937 goto L1;
7938 case 2:
7940 case n:
7942 default:
7943 abort ();
7946 v = GOMP_sections_next ();
7947 goto L0;
7949 reduction;
7951 If this is a combined parallel sections, replace the call to
7952 GOMP_sections_start with call to GOMP_sections_next. */
7954 static void
7955 expand_omp_sections (struct omp_region *region)
7957 tree t, u, vin = NULL, vmain, vnext, l2;
7958 unsigned len;
7959 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7960 gimple_stmt_iterator si, switch_si;
7961 gomp_sections *sections_stmt;
7962 gimple stmt;
7963 gomp_continue *cont;
7964 edge_iterator ei;
7965 edge e;
7966 struct omp_region *inner;
7967 unsigned i, casei;
7968 bool exit_reachable = region->cont != NULL;
7970 gcc_assert (region->exit != NULL);
7971 entry_bb = region->entry;
7972 l0_bb = single_succ (entry_bb);
7973 l1_bb = region->cont;
7974 l2_bb = region->exit;
7975 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7976 l2 = gimple_block_label (l2_bb);
7977 else
7979 /* This can happen if there are reductions. */
7980 len = EDGE_COUNT (l0_bb->succs);
7981 gcc_assert (len > 0);
7982 e = EDGE_SUCC (l0_bb, len - 1);
7983 si = gsi_last_bb (e->dest);
7984 l2 = NULL_TREE;
7985 if (gsi_end_p (si)
7986 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7987 l2 = gimple_block_label (e->dest);
7988 else
7989 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7991 si = gsi_last_bb (e->dest);
7992 if (gsi_end_p (si)
7993 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7995 l2 = gimple_block_label (e->dest);
7996 break;
8000 if (exit_reachable)
8001 default_bb = create_empty_bb (l1_bb->prev_bb);
8002 else
8003 default_bb = create_empty_bb (l0_bb);
8005 /* We will build a switch() with enough cases for all the
8006 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
8007 and a default case to abort if something goes wrong. */
8008 len = EDGE_COUNT (l0_bb->succs);
8010 /* Use vec::quick_push on label_vec throughout, since we know the size
8011 in advance. */
8012 auto_vec<tree> label_vec (len);
8014 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
8015 GIMPLE_OMP_SECTIONS statement. */
8016 si = gsi_last_bb (entry_bb);
8017 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
8018 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8019 vin = gimple_omp_sections_control (sections_stmt);
8020 if (!is_combined_parallel (region))
8022 /* If we are not inside a combined parallel+sections region,
8023 call GOMP_sections_start. */
8024 t = build_int_cst (unsigned_type_node, len - 1);
8025 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
8026 stmt = gimple_build_call (u, 1, t);
8028 else
8030 /* Otherwise, call GOMP_sections_next. */
8031 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8032 stmt = gimple_build_call (u, 0);
8034 gimple_call_set_lhs (stmt, vin);
8035 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8036 gsi_remove (&si, true);
8038 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8039 L0_BB. */
8040 switch_si = gsi_last_bb (l0_bb);
8041 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8042 if (exit_reachable)
8044 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8045 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8046 vmain = gimple_omp_continue_control_use (cont);
8047 vnext = gimple_omp_continue_control_def (cont);
8049 else
8051 vmain = vin;
8052 vnext = NULL_TREE;
8055 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8056 label_vec.quick_push (t);
8057 i = 1;
8059 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8060 for (inner = region->inner, casei = 1;
8061 inner;
8062 inner = inner->next, i++, casei++)
8064 basic_block s_entry_bb, s_exit_bb;
8066 /* Skip optional reduction region. */
8067 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8069 --i;
8070 --casei;
8071 continue;
8074 s_entry_bb = inner->entry;
8075 s_exit_bb = inner->exit;
8077 t = gimple_block_label (s_entry_bb);
8078 u = build_int_cst (unsigned_type_node, casei);
8079 u = build_case_label (u, NULL, t);
8080 label_vec.quick_push (u);
8082 si = gsi_last_bb (s_entry_bb);
8083 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8084 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8085 gsi_remove (&si, true);
8086 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8088 if (s_exit_bb == NULL)
8089 continue;
8091 si = gsi_last_bb (s_exit_bb);
8092 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8093 gsi_remove (&si, true);
8095 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8098 /* Error handling code goes in DEFAULT_BB. */
8099 t = gimple_block_label (default_bb);
8100 u = build_case_label (NULL, NULL, t);
8101 make_edge (l0_bb, default_bb, 0);
8102 add_bb_to_loop (default_bb, current_loops->tree_root);
8104 stmt = gimple_build_switch (vmain, u, label_vec);
8105 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8106 gsi_remove (&switch_si, true);
8108 si = gsi_start_bb (default_bb);
8109 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8110 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8112 if (exit_reachable)
8114 tree bfn_decl;
8116 /* Code to get the next section goes in L1_BB. */
8117 si = gsi_last_bb (l1_bb);
8118 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8120 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8121 stmt = gimple_build_call (bfn_decl, 0);
8122 gimple_call_set_lhs (stmt, vnext);
8123 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8124 gsi_remove (&si, true);
8126 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8129 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8130 si = gsi_last_bb (l2_bb);
8131 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8132 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8133 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8134 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8135 else
8136 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8137 stmt = gimple_build_call (t, 0);
8138 if (gimple_omp_return_lhs (gsi_stmt (si)))
8139 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8140 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8141 gsi_remove (&si, true);
8143 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8147 /* Expand code for an OpenMP single directive. We've already expanded
8148 much of the code, here we simply place the GOMP_barrier call. */
8150 static void
8151 expand_omp_single (struct omp_region *region)
8153 basic_block entry_bb, exit_bb;
8154 gimple_stmt_iterator si;
8156 entry_bb = region->entry;
8157 exit_bb = region->exit;
8159 si = gsi_last_bb (entry_bb);
8160 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8161 gsi_remove (&si, true);
8162 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8164 si = gsi_last_bb (exit_bb);
8165 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8167 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8168 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8170 gsi_remove (&si, true);
8171 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8175 /* Generic expansion for OpenMP synchronization directives: master,
8176 ordered and critical. All we need to do here is remove the entry
8177 and exit markers for REGION. */
8179 static void
8180 expand_omp_synch (struct omp_region *region)
8182 basic_block entry_bb, exit_bb;
8183 gimple_stmt_iterator si;
8185 entry_bb = region->entry;
8186 exit_bb = region->exit;
8188 si = gsi_last_bb (entry_bb);
8189 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8190 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8191 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8192 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8193 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8194 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8195 gsi_remove (&si, true);
8196 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8198 if (exit_bb)
8200 si = gsi_last_bb (exit_bb);
8201 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8202 gsi_remove (&si, true);
8203 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8207 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8208 operation as a normal volatile load. */
8210 static bool
8211 expand_omp_atomic_load (basic_block load_bb, tree addr,
8212 tree loaded_val, int index)
8214 enum built_in_function tmpbase;
8215 gimple_stmt_iterator gsi;
8216 basic_block store_bb;
8217 location_t loc;
8218 gimple stmt;
8219 tree decl, call, type, itype;
8221 gsi = gsi_last_bb (load_bb);
8222 stmt = gsi_stmt (gsi);
8223 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8224 loc = gimple_location (stmt);
8226 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8227 is smaller than word size, then expand_atomic_load assumes that the load
8228 is atomic. We could avoid the builtin entirely in this case. */
8230 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8231 decl = builtin_decl_explicit (tmpbase);
8232 if (decl == NULL_TREE)
8233 return false;
8235 type = TREE_TYPE (loaded_val);
8236 itype = TREE_TYPE (TREE_TYPE (decl));
8238 call = build_call_expr_loc (loc, decl, 2, addr,
8239 build_int_cst (NULL,
8240 gimple_omp_atomic_seq_cst_p (stmt)
8241 ? MEMMODEL_SEQ_CST
8242 : MEMMODEL_RELAXED));
8243 if (!useless_type_conversion_p (type, itype))
8244 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8245 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8247 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8248 gsi_remove (&gsi, true);
8250 store_bb = single_succ (load_bb);
8251 gsi = gsi_last_bb (store_bb);
8252 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8253 gsi_remove (&gsi, true);
8255 if (gimple_in_ssa_p (cfun))
8256 update_ssa (TODO_update_ssa_no_phi);
8258 return true;
8261 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8262 operation as a normal volatile store. */
8264 static bool
8265 expand_omp_atomic_store (basic_block load_bb, tree addr,
8266 tree loaded_val, tree stored_val, int index)
8268 enum built_in_function tmpbase;
8269 gimple_stmt_iterator gsi;
8270 basic_block store_bb = single_succ (load_bb);
8271 location_t loc;
8272 gimple stmt;
8273 tree decl, call, type, itype;
8274 machine_mode imode;
8275 bool exchange;
8277 gsi = gsi_last_bb (load_bb);
8278 stmt = gsi_stmt (gsi);
8279 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8281 /* If the load value is needed, then this isn't a store but an exchange. */
8282 exchange = gimple_omp_atomic_need_value_p (stmt);
8284 gsi = gsi_last_bb (store_bb);
8285 stmt = gsi_stmt (gsi);
8286 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8287 loc = gimple_location (stmt);
8289 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8290 is smaller than word size, then expand_atomic_store assumes that the store
8291 is atomic. We could avoid the builtin entirely in this case. */
8293 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8294 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8295 decl = builtin_decl_explicit (tmpbase);
8296 if (decl == NULL_TREE)
8297 return false;
8299 type = TREE_TYPE (stored_val);
8301 /* Dig out the type of the function's second argument. */
8302 itype = TREE_TYPE (decl);
8303 itype = TYPE_ARG_TYPES (itype);
8304 itype = TREE_CHAIN (itype);
8305 itype = TREE_VALUE (itype);
8306 imode = TYPE_MODE (itype);
8308 if (exchange && !can_atomic_exchange_p (imode, true))
8309 return false;
8311 if (!useless_type_conversion_p (itype, type))
8312 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8313 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8314 build_int_cst (NULL,
8315 gimple_omp_atomic_seq_cst_p (stmt)
8316 ? MEMMODEL_SEQ_CST
8317 : MEMMODEL_RELAXED));
8318 if (exchange)
8320 if (!useless_type_conversion_p (type, itype))
8321 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8322 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8325 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8326 gsi_remove (&gsi, true);
8328 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8329 gsi = gsi_last_bb (load_bb);
8330 gsi_remove (&gsi, true);
8332 if (gimple_in_ssa_p (cfun))
8333 update_ssa (TODO_update_ssa_no_phi);
8335 return true;
8338 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8339 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8340 size of the data type, and thus usable to find the index of the builtin
8341 decl. Returns false if the expression is not of the proper form. */
8343 static bool
8344 expand_omp_atomic_fetch_op (basic_block load_bb,
8345 tree addr, tree loaded_val,
8346 tree stored_val, int index)
8348 enum built_in_function oldbase, newbase, tmpbase;
8349 tree decl, itype, call;
8350 tree lhs, rhs;
8351 basic_block store_bb = single_succ (load_bb);
8352 gimple_stmt_iterator gsi;
8353 gimple stmt;
8354 location_t loc;
8355 enum tree_code code;
8356 bool need_old, need_new;
8357 machine_mode imode;
8358 bool seq_cst;
8360 /* We expect to find the following sequences:
8362 load_bb:
8363 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8365 store_bb:
8366 val = tmp OP something; (or: something OP tmp)
8367 GIMPLE_OMP_STORE (val)
8369 ???FIXME: Allow a more flexible sequence.
8370 Perhaps use data flow to pick the statements.
8374 gsi = gsi_after_labels (store_bb);
8375 stmt = gsi_stmt (gsi);
8376 loc = gimple_location (stmt);
8377 if (!is_gimple_assign (stmt))
8378 return false;
8379 gsi_next (&gsi);
8380 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8381 return false;
8382 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8383 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8384 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8385 gcc_checking_assert (!need_old || !need_new);
8387 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8388 return false;
8390 /* Check for one of the supported fetch-op operations. */
8391 code = gimple_assign_rhs_code (stmt);
8392 switch (code)
8394 case PLUS_EXPR:
8395 case POINTER_PLUS_EXPR:
8396 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8397 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8398 break;
8399 case MINUS_EXPR:
8400 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8401 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8402 break;
8403 case BIT_AND_EXPR:
8404 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8405 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8406 break;
8407 case BIT_IOR_EXPR:
8408 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8409 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8410 break;
8411 case BIT_XOR_EXPR:
8412 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8413 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8414 break;
8415 default:
8416 return false;
8419 /* Make sure the expression is of the proper form. */
8420 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8421 rhs = gimple_assign_rhs2 (stmt);
8422 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8423 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8424 rhs = gimple_assign_rhs1 (stmt);
8425 else
8426 return false;
8428 tmpbase = ((enum built_in_function)
8429 ((need_new ? newbase : oldbase) + index + 1));
8430 decl = builtin_decl_explicit (tmpbase);
8431 if (decl == NULL_TREE)
8432 return false;
8433 itype = TREE_TYPE (TREE_TYPE (decl));
8434 imode = TYPE_MODE (itype);
8436 /* We could test all of the various optabs involved, but the fact of the
8437 matter is that (with the exception of i486 vs i586 and xadd) all targets
8438 that support any atomic operaton optab also implements compare-and-swap.
8439 Let optabs.c take care of expanding any compare-and-swap loop. */
8440 if (!can_compare_and_swap_p (imode, true))
8441 return false;
8443 gsi = gsi_last_bb (load_bb);
8444 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8446 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8447 It only requires that the operation happen atomically. Thus we can
8448 use the RELAXED memory model. */
8449 call = build_call_expr_loc (loc, decl, 3, addr,
8450 fold_convert_loc (loc, itype, rhs),
8451 build_int_cst (NULL,
8452 seq_cst ? MEMMODEL_SEQ_CST
8453 : MEMMODEL_RELAXED));
8455 if (need_old || need_new)
8457 lhs = need_old ? loaded_val : stored_val;
8458 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8459 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8461 else
8462 call = fold_convert_loc (loc, void_type_node, call);
8463 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8464 gsi_remove (&gsi, true);
8466 gsi = gsi_last_bb (store_bb);
8467 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8468 gsi_remove (&gsi, true);
8469 gsi = gsi_last_bb (store_bb);
8470 gsi_remove (&gsi, true);
8472 if (gimple_in_ssa_p (cfun))
8473 update_ssa (TODO_update_ssa_no_phi);
8475 return true;
8478 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8480 oldval = *addr;
8481 repeat:
8482 newval = rhs; // with oldval replacing *addr in rhs
8483 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8484 if (oldval != newval)
8485 goto repeat;
8487 INDEX is log2 of the size of the data type, and thus usable to find the
8488 index of the builtin decl. */
8490 static bool
8491 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8492 tree addr, tree loaded_val, tree stored_val,
8493 int index)
8495 tree loadedi, storedi, initial, new_storedi, old_vali;
8496 tree type, itype, cmpxchg, iaddr;
8497 gimple_stmt_iterator si;
8498 basic_block loop_header = single_succ (load_bb);
8499 gimple phi, stmt;
8500 edge e;
8501 enum built_in_function fncode;
8503 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8504 order to use the RELAXED memory model effectively. */
8505 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8506 + index + 1);
8507 cmpxchg = builtin_decl_explicit (fncode);
8508 if (cmpxchg == NULL_TREE)
8509 return false;
8510 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8511 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8513 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8514 return false;
8516 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8517 si = gsi_last_bb (load_bb);
8518 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8520 /* For floating-point values, we'll need to view-convert them to integers
8521 so that we can perform the atomic compare and swap. Simplify the
8522 following code by always setting up the "i"ntegral variables. */
8523 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8525 tree iaddr_val;
8527 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8528 true));
8529 iaddr_val
8530 = force_gimple_operand_gsi (&si,
8531 fold_convert (TREE_TYPE (iaddr), addr),
8532 false, NULL_TREE, true, GSI_SAME_STMT);
8533 stmt = gimple_build_assign (iaddr, iaddr_val);
8534 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8535 loadedi = create_tmp_var (itype);
8536 if (gimple_in_ssa_p (cfun))
8537 loadedi = make_ssa_name (loadedi);
8539 else
8541 iaddr = addr;
8542 loadedi = loaded_val;
8545 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8546 tree loaddecl = builtin_decl_explicit (fncode);
8547 if (loaddecl)
8548 initial
8549 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8550 build_call_expr (loaddecl, 2, iaddr,
8551 build_int_cst (NULL_TREE,
8552 MEMMODEL_RELAXED)));
8553 else
8554 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8555 build_int_cst (TREE_TYPE (iaddr), 0));
8557 initial
8558 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8559 GSI_SAME_STMT);
8561 /* Move the value to the LOADEDI temporary. */
8562 if (gimple_in_ssa_p (cfun))
8564 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8565 phi = create_phi_node (loadedi, loop_header);
8566 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8567 initial);
8569 else
8570 gsi_insert_before (&si,
8571 gimple_build_assign (loadedi, initial),
8572 GSI_SAME_STMT);
8573 if (loadedi != loaded_val)
8575 gimple_stmt_iterator gsi2;
8576 tree x;
8578 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8579 gsi2 = gsi_start_bb (loop_header);
8580 if (gimple_in_ssa_p (cfun))
8582 gassign *stmt;
8583 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8584 true, GSI_SAME_STMT);
8585 stmt = gimple_build_assign (loaded_val, x);
8586 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8588 else
8590 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8591 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8592 true, GSI_SAME_STMT);
8595 gsi_remove (&si, true);
8597 si = gsi_last_bb (store_bb);
8598 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8600 if (iaddr == addr)
8601 storedi = stored_val;
8602 else
8603 storedi =
8604 force_gimple_operand_gsi (&si,
8605 build1 (VIEW_CONVERT_EXPR, itype,
8606 stored_val), true, NULL_TREE, true,
8607 GSI_SAME_STMT);
8609 /* Build the compare&swap statement. */
8610 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8611 new_storedi = force_gimple_operand_gsi (&si,
8612 fold_convert (TREE_TYPE (loadedi),
8613 new_storedi),
8614 true, NULL_TREE,
8615 true, GSI_SAME_STMT);
8617 if (gimple_in_ssa_p (cfun))
8618 old_vali = loadedi;
8619 else
8621 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8622 stmt = gimple_build_assign (old_vali, loadedi);
8623 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8625 stmt = gimple_build_assign (loadedi, new_storedi);
8626 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8629 /* Note that we always perform the comparison as an integer, even for
8630 floating point. This allows the atomic operation to properly
8631 succeed even with NaNs and -0.0. */
8632 stmt = gimple_build_cond_empty
8633 (build2 (NE_EXPR, boolean_type_node,
8634 new_storedi, old_vali));
8635 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8637 /* Update cfg. */
8638 e = single_succ_edge (store_bb);
8639 e->flags &= ~EDGE_FALLTHRU;
8640 e->flags |= EDGE_FALSE_VALUE;
8642 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8644 /* Copy the new value to loadedi (we already did that before the condition
8645 if we are not in SSA). */
8646 if (gimple_in_ssa_p (cfun))
8648 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8649 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8652 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8653 gsi_remove (&si, true);
8655 struct loop *loop = alloc_loop ();
8656 loop->header = loop_header;
8657 loop->latch = store_bb;
8658 add_loop (loop, loop_header->loop_father);
8660 if (gimple_in_ssa_p (cfun))
8661 update_ssa (TODO_update_ssa_no_phi);
8663 return true;
8666 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8668 GOMP_atomic_start ();
8669 *addr = rhs;
8670 GOMP_atomic_end ();
8672 The result is not globally atomic, but works so long as all parallel
8673 references are within #pragma omp atomic directives. According to
8674 responses received from omp@openmp.org, appears to be within spec.
8675 Which makes sense, since that's how several other compilers handle
8676 this situation as well.
8677 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8678 expanding. STORED_VAL is the operand of the matching
8679 GIMPLE_OMP_ATOMIC_STORE.
8681 We replace
8682 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8683 loaded_val = *addr;
8685 and replace
8686 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8687 *addr = stored_val;
8690 static bool
8691 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8692 tree addr, tree loaded_val, tree stored_val)
8694 gimple_stmt_iterator si;
8695 gassign *stmt;
8696 tree t;
8698 si = gsi_last_bb (load_bb);
8699 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8701 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8702 t = build_call_expr (t, 0);
8703 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8705 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8706 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8707 gsi_remove (&si, true);
8709 si = gsi_last_bb (store_bb);
8710 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8712 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8713 stored_val);
8714 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8716 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8717 t = build_call_expr (t, 0);
8718 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8719 gsi_remove (&si, true);
8721 if (gimple_in_ssa_p (cfun))
8722 update_ssa (TODO_update_ssa_no_phi);
8723 return true;
8726 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8727 using expand_omp_atomic_fetch_op. If it failed, we try to
8728 call expand_omp_atomic_pipeline, and if it fails too, the
8729 ultimate fallback is wrapping the operation in a mutex
8730 (expand_omp_atomic_mutex). REGION is the atomic region built
8731 by build_omp_regions_1(). */
8733 static void
8734 expand_omp_atomic (struct omp_region *region)
8736 basic_block load_bb = region->entry, store_bb = region->exit;
8737 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8738 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8739 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8740 tree addr = gimple_omp_atomic_load_rhs (load);
8741 tree stored_val = gimple_omp_atomic_store_val (store);
8742 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8743 HOST_WIDE_INT index;
8745 /* Make sure the type is one of the supported sizes. */
8746 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8747 index = exact_log2 (index);
8748 if (index >= 0 && index <= 4)
8750 unsigned int align = TYPE_ALIGN_UNIT (type);
8752 /* __sync builtins require strict data alignment. */
8753 if (exact_log2 (align) >= index)
8755 /* Atomic load. */
8756 if (loaded_val == stored_val
8757 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8758 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8759 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8760 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8761 return;
8763 /* Atomic store. */
8764 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8765 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8766 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8767 && store_bb == single_succ (load_bb)
8768 && first_stmt (store_bb) == store
8769 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8770 stored_val, index))
8771 return;
8773 /* When possible, use specialized atomic update functions. */
8774 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8775 && store_bb == single_succ (load_bb)
8776 && expand_omp_atomic_fetch_op (load_bb, addr,
8777 loaded_val, stored_val, index))
8778 return;
8780 /* If we don't have specialized __sync builtins, try and implement
8781 as a compare and swap loop. */
8782 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8783 loaded_val, stored_val, index))
8784 return;
8788 /* The ultimate fallback is wrapping the operation in a mutex. */
8789 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8793 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8795 static void
8796 expand_omp_target (struct omp_region *region)
8798 basic_block entry_bb, exit_bb, new_bb;
8799 struct function *child_cfun;
8800 tree child_fn, block, t;
8801 gimple_stmt_iterator gsi;
8802 gomp_target *entry_stmt;
8803 gimple stmt;
8804 edge e;
8805 bool offloaded, data_region;
8807 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8808 new_bb = region->entry;
8810 offloaded = is_gimple_omp_offloaded (entry_stmt);
8811 switch (gimple_omp_target_kind (entry_stmt))
8813 case GF_OMP_TARGET_KIND_REGION:
8814 case GF_OMP_TARGET_KIND_UPDATE:
8815 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8816 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8817 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8818 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8819 data_region = false;
8820 break;
8821 case GF_OMP_TARGET_KIND_DATA:
8822 case GF_OMP_TARGET_KIND_OACC_DATA:
8823 data_region = true;
8824 break;
8825 default:
8826 gcc_unreachable ();
8829 child_fn = NULL_TREE;
8830 child_cfun = NULL;
8831 if (offloaded)
8833 child_fn = gimple_omp_target_child_fn (entry_stmt);
8834 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8837 /* Supported by expand_omp_taskreg, but not here. */
8838 if (child_cfun != NULL)
8839 gcc_checking_assert (!child_cfun->cfg);
8840 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8842 entry_bb = region->entry;
8843 exit_bb = region->exit;
8845 if (offloaded)
8847 unsigned srcidx, dstidx, num;
8849 /* If the offloading region needs data sent from the parent
8850 function, then the very first statement (except possible
8851 tree profile counter updates) of the offloading body
8852 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8853 &.OMP_DATA_O is passed as an argument to the child function,
8854 we need to replace it with the argument as seen by the child
8855 function.
8857 In most cases, this will end up being the identity assignment
8858 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8859 a function call that has been inlined, the original PARM_DECL
8860 .OMP_DATA_I may have been converted into a different local
8861 variable. In which case, we need to keep the assignment. */
8862 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8863 if (data_arg)
8865 basic_block entry_succ_bb = single_succ (entry_bb);
8866 gimple_stmt_iterator gsi;
8867 tree arg;
8868 gimple tgtcopy_stmt = NULL;
8869 tree sender = TREE_VEC_ELT (data_arg, 0);
8871 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8873 gcc_assert (!gsi_end_p (gsi));
8874 stmt = gsi_stmt (gsi);
8875 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8876 continue;
8878 if (gimple_num_ops (stmt) == 2)
8880 tree arg = gimple_assign_rhs1 (stmt);
8882 /* We're ignoring the subcode because we're
8883 effectively doing a STRIP_NOPS. */
8885 if (TREE_CODE (arg) == ADDR_EXPR
8886 && TREE_OPERAND (arg, 0) == sender)
8888 tgtcopy_stmt = stmt;
8889 break;
8894 gcc_assert (tgtcopy_stmt != NULL);
8895 arg = DECL_ARGUMENTS (child_fn);
8897 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8898 gsi_remove (&gsi, true);
8901 /* Declare local variables needed in CHILD_CFUN. */
8902 block = DECL_INITIAL (child_fn);
8903 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8904 /* The gimplifier could record temporaries in the offloading block
8905 rather than in containing function's local_decls chain,
8906 which would mean cgraph missed finalizing them. Do it now. */
8907 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8908 if (TREE_CODE (t) == VAR_DECL
8909 && TREE_STATIC (t)
8910 && !DECL_EXTERNAL (t))
8911 varpool_node::finalize_decl (t);
8912 DECL_SAVED_TREE (child_fn) = NULL;
8913 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8914 gimple_set_body (child_fn, NULL);
8915 TREE_USED (block) = 1;
8917 /* Reset DECL_CONTEXT on function arguments. */
8918 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8919 DECL_CONTEXT (t) = child_fn;
8921 /* Split ENTRY_BB at GIMPLE_*,
8922 so that it can be moved to the child function. */
8923 gsi = gsi_last_bb (entry_bb);
8924 stmt = gsi_stmt (gsi);
8925 gcc_assert (stmt
8926 && gimple_code (stmt) == gimple_code (entry_stmt));
8927 e = split_block (entry_bb, stmt);
8928 gsi_remove (&gsi, true);
8929 entry_bb = e->dest;
8930 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8932 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8933 if (exit_bb)
8935 gsi = gsi_last_bb (exit_bb);
8936 gcc_assert (!gsi_end_p (gsi)
8937 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8938 stmt = gimple_build_return (NULL);
8939 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8940 gsi_remove (&gsi, true);
8943 /* Move the offloading region into CHILD_CFUN. */
8945 block = gimple_block (entry_stmt);
8947 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8948 if (exit_bb)
8949 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8950 /* When the OMP expansion process cannot guarantee an up-to-date
8951 loop tree arrange for the child function to fixup loops. */
8952 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8953 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8955 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8956 num = vec_safe_length (child_cfun->local_decls);
8957 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8959 t = (*child_cfun->local_decls)[srcidx];
8960 if (DECL_CONTEXT (t) == cfun->decl)
8961 continue;
8962 if (srcidx != dstidx)
8963 (*child_cfun->local_decls)[dstidx] = t;
8964 dstidx++;
8966 if (dstidx != num)
8967 vec_safe_truncate (child_cfun->local_decls, dstidx);
8969 /* Inform the callgraph about the new function. */
8970 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8971 cgraph_node::add_new_function (child_fn, true);
8973 #ifdef ENABLE_OFFLOADING
8974 /* Add the new function to the offload table. */
8975 vec_safe_push (offload_funcs, child_fn);
8976 #endif
8978 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8979 fixed in a following pass. */
8980 push_cfun (child_cfun);
8981 cgraph_edge::rebuild_edges ();
8983 #ifdef ENABLE_OFFLOADING
8984 /* Prevent IPA from removing child_fn as unreachable, since there are no
8985 refs from the parent function to child_fn in offload LTO mode. */
8986 struct cgraph_node *node = cgraph_node::get (child_fn);
8987 node->mark_force_output ();
8988 #endif
8990 /* Some EH regions might become dead, see PR34608. If
8991 pass_cleanup_cfg isn't the first pass to happen with the
8992 new child, these dead EH edges might cause problems.
8993 Clean them up now. */
8994 if (flag_exceptions)
8996 basic_block bb;
8997 bool changed = false;
8999 FOR_EACH_BB_FN (bb, cfun)
9000 changed |= gimple_purge_dead_eh_edges (bb);
9001 if (changed)
9002 cleanup_tree_cfg ();
9004 pop_cfun ();
9007 /* Emit a library call to launch the offloading region, or do data
9008 transfers. */
9009 tree t1, t2, t3, t4, device, cond, c, clauses;
9010 enum built_in_function start_ix;
9011 location_t clause_loc;
9013 switch (gimple_omp_target_kind (entry_stmt))
9015 case GF_OMP_TARGET_KIND_REGION:
9016 start_ix = BUILT_IN_GOMP_TARGET;
9017 break;
9018 case GF_OMP_TARGET_KIND_DATA:
9019 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9020 break;
9021 case GF_OMP_TARGET_KIND_UPDATE:
9022 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9023 break;
9024 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9025 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9026 start_ix = BUILT_IN_GOACC_PARALLEL;
9027 break;
9028 case GF_OMP_TARGET_KIND_OACC_DATA:
9029 start_ix = BUILT_IN_GOACC_DATA_START;
9030 break;
9031 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9032 start_ix = BUILT_IN_GOACC_UPDATE;
9033 break;
9034 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9035 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9036 break;
9037 default:
9038 gcc_unreachable ();
9041 clauses = gimple_omp_target_clauses (entry_stmt);
9043 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9044 library choose) and there is no conditional. */
9045 cond = NULL_TREE;
9046 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
9048 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9049 if (c)
9050 cond = OMP_CLAUSE_IF_EXPR (c);
9052 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9053 if (c)
9055 /* Even if we pass it to all library function calls, it is currently only
9056 defined/used for the OpenMP target ones. */
9057 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9058 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9059 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9061 device = OMP_CLAUSE_DEVICE_ID (c);
9062 clause_loc = OMP_CLAUSE_LOCATION (c);
9064 else
9065 clause_loc = gimple_location (entry_stmt);
9067 /* Ensure 'device' is of the correct type. */
9068 device = fold_convert_loc (clause_loc, integer_type_node, device);
9070 /* If we found the clause 'if (cond)', build
9071 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9072 if (cond)
9074 cond = gimple_boolify (cond);
9076 basic_block cond_bb, then_bb, else_bb;
9077 edge e;
9078 tree tmp_var;
9080 tmp_var = create_tmp_var (TREE_TYPE (device));
9081 if (offloaded)
9082 e = split_block_after_labels (new_bb);
9083 else
9085 gsi = gsi_last_bb (new_bb);
9086 gsi_prev (&gsi);
9087 e = split_block (new_bb, gsi_stmt (gsi));
9089 cond_bb = e->src;
9090 new_bb = e->dest;
9091 remove_edge (e);
9093 then_bb = create_empty_bb (cond_bb);
9094 else_bb = create_empty_bb (then_bb);
9095 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9096 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9098 stmt = gimple_build_cond_empty (cond);
9099 gsi = gsi_last_bb (cond_bb);
9100 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9102 gsi = gsi_start_bb (then_bb);
9103 stmt = gimple_build_assign (tmp_var, device);
9104 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9106 gsi = gsi_start_bb (else_bb);
9107 stmt = gimple_build_assign (tmp_var,
9108 build_int_cst (integer_type_node,
9109 GOMP_DEVICE_HOST_FALLBACK));
9110 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9112 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9113 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9114 add_bb_to_loop (then_bb, cond_bb->loop_father);
9115 add_bb_to_loop (else_bb, cond_bb->loop_father);
9116 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9117 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9119 device = tmp_var;
9122 gsi = gsi_last_bb (new_bb);
9123 t = gimple_omp_target_data_arg (entry_stmt);
9124 if (t == NULL)
9126 t1 = size_zero_node;
9127 t2 = build_zero_cst (ptr_type_node);
9128 t3 = t2;
9129 t4 = t2;
9131 else
9133 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9134 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9135 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9136 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9137 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9140 gimple g;
9141 /* The maximum number used by any start_ix, without varargs. */
9142 auto_vec<tree, 11> args;
9143 args.quick_push (device);
9144 if (offloaded)
9145 args.quick_push (build_fold_addr_expr (child_fn));
9146 switch (start_ix)
9148 case BUILT_IN_GOMP_TARGET:
9149 case BUILT_IN_GOMP_TARGET_DATA:
9150 case BUILT_IN_GOMP_TARGET_UPDATE:
9151 /* This const void * is part of the current ABI, but we're not actually
9152 using it. */
9153 args.quick_push (build_zero_cst (ptr_type_node));
9154 break;
9155 case BUILT_IN_GOACC_DATA_START:
9156 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9157 case BUILT_IN_GOACC_PARALLEL:
9158 case BUILT_IN_GOACC_UPDATE:
9159 break;
9160 default:
9161 gcc_unreachable ();
9163 args.quick_push (t1);
9164 args.quick_push (t2);
9165 args.quick_push (t3);
9166 args.quick_push (t4);
9167 switch (start_ix)
9169 case BUILT_IN_GOACC_DATA_START:
9170 case BUILT_IN_GOMP_TARGET:
9171 case BUILT_IN_GOMP_TARGET_DATA:
9172 case BUILT_IN_GOMP_TARGET_UPDATE:
9173 break;
9174 case BUILT_IN_GOACC_PARALLEL:
9176 tree t_num_gangs, t_num_workers, t_vector_length;
9178 /* Default values for num_gangs, num_workers, and vector_length. */
9179 t_num_gangs = t_num_workers = t_vector_length
9180 = fold_convert_loc (gimple_location (entry_stmt),
9181 integer_type_node, integer_one_node);
9182 /* ..., but if present, use the value specified by the respective
9183 clause, making sure that are of the correct type. */
9184 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9185 if (c)
9186 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9187 integer_type_node,
9188 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9189 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9190 if (c)
9191 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9192 integer_type_node,
9193 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9194 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9195 if (c)
9196 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9197 integer_type_node,
9198 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9199 args.quick_push (t_num_gangs);
9200 args.quick_push (t_num_workers);
9201 args.quick_push (t_vector_length);
9203 /* FALLTHRU */
9204 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9205 case BUILT_IN_GOACC_UPDATE:
9207 tree t_async;
9208 int t_wait_idx;
9210 /* Default values for t_async. */
9211 t_async = fold_convert_loc (gimple_location (entry_stmt),
9212 integer_type_node,
9213 build_int_cst (integer_type_node,
9214 GOMP_ASYNC_SYNC));
9215 /* ..., but if present, use the value specified by the respective
9216 clause, making sure that is of the correct type. */
9217 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9218 if (c)
9219 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9220 integer_type_node,
9221 OMP_CLAUSE_ASYNC_EXPR (c));
9223 args.quick_push (t_async);
9224 /* Save the index, and... */
9225 t_wait_idx = args.length ();
9226 /* ... push a default value. */
9227 args.quick_push (fold_convert_loc (gimple_location (entry_stmt),
9228 integer_type_node,
9229 integer_zero_node));
9230 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9231 if (c)
9233 int n = 0;
9235 for (; c; c = OMP_CLAUSE_CHAIN (c))
9237 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9239 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9240 integer_type_node,
9241 OMP_CLAUSE_WAIT_EXPR (c)));
9242 n++;
9246 /* Now that we know the number, replace the default value. */
9247 args.ordered_remove (t_wait_idx);
9248 args.quick_insert (t_wait_idx,
9249 fold_convert_loc (gimple_location (entry_stmt),
9250 integer_type_node,
9251 build_int_cst (integer_type_node, n)));
9254 break;
9255 default:
9256 gcc_unreachable ();
9259 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
9260 gimple_set_location (g, gimple_location (entry_stmt));
9261 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9262 if (!offloaded)
9264 g = gsi_stmt (gsi);
9265 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9266 gsi_remove (&gsi, true);
9268 if (data_region
9269 && region->exit)
9271 gsi = gsi_last_bb (region->exit);
9272 g = gsi_stmt (gsi);
9273 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9274 gsi_remove (&gsi, true);
9279 /* Expand the parallel region tree rooted at REGION. Expansion
9280 proceeds in depth-first order. Innermost regions are expanded
9281 first. This way, parallel regions that require a new function to
9282 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9283 internal dependencies in their body. */
9285 static void
9286 expand_omp (struct omp_region *region)
9288 while (region)
9290 location_t saved_location;
9291 gimple inner_stmt = NULL;
9293 /* First, determine whether this is a combined parallel+workshare
9294 region. */
9295 if (region->type == GIMPLE_OMP_PARALLEL)
9296 determine_parallel_type (region);
9298 if (region->type == GIMPLE_OMP_FOR
9299 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9300 inner_stmt = last_stmt (region->inner->entry);
9302 if (region->inner)
9303 expand_omp (region->inner);
9305 saved_location = input_location;
9306 if (gimple_has_location (last_stmt (region->entry)))
9307 input_location = gimple_location (last_stmt (region->entry));
9309 switch (region->type)
9311 case GIMPLE_OMP_PARALLEL:
9312 case GIMPLE_OMP_TASK:
9313 expand_omp_taskreg (region);
9314 break;
9316 case GIMPLE_OMP_FOR:
9317 expand_omp_for (region, inner_stmt);
9318 break;
9320 case GIMPLE_OMP_SECTIONS:
9321 expand_omp_sections (region);
9322 break;
9324 case GIMPLE_OMP_SECTION:
9325 /* Individual omp sections are handled together with their
9326 parent GIMPLE_OMP_SECTIONS region. */
9327 break;
9329 case GIMPLE_OMP_SINGLE:
9330 expand_omp_single (region);
9331 break;
9333 case GIMPLE_OMP_MASTER:
9334 case GIMPLE_OMP_TASKGROUP:
9335 case GIMPLE_OMP_ORDERED:
9336 case GIMPLE_OMP_CRITICAL:
9337 case GIMPLE_OMP_TEAMS:
9338 expand_omp_synch (region);
9339 break;
9341 case GIMPLE_OMP_ATOMIC_LOAD:
9342 expand_omp_atomic (region);
9343 break;
9345 case GIMPLE_OMP_TARGET:
9346 expand_omp_target (region);
9347 break;
9349 default:
9350 gcc_unreachable ();
9353 input_location = saved_location;
9354 region = region->next;
9359 /* Helper for build_omp_regions. Scan the dominator tree starting at
9360 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9361 true, the function ends once a single tree is built (otherwise, whole
9362 forest of OMP constructs may be built). */
9364 static void
9365 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9366 bool single_tree)
9368 gimple_stmt_iterator gsi;
9369 gimple stmt;
9370 basic_block son;
9372 gsi = gsi_last_bb (bb);
9373 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9375 struct omp_region *region;
9376 enum gimple_code code;
9378 stmt = gsi_stmt (gsi);
9379 code = gimple_code (stmt);
9380 if (code == GIMPLE_OMP_RETURN)
9382 /* STMT is the return point out of region PARENT. Mark it
9383 as the exit point and make PARENT the immediately
9384 enclosing region. */
9385 gcc_assert (parent);
9386 region = parent;
9387 region->exit = bb;
9388 parent = parent->outer;
9390 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9392 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9393 GIMPLE_OMP_RETURN, but matches with
9394 GIMPLE_OMP_ATOMIC_LOAD. */
9395 gcc_assert (parent);
9396 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9397 region = parent;
9398 region->exit = bb;
9399 parent = parent->outer;
9401 else if (code == GIMPLE_OMP_CONTINUE)
9403 gcc_assert (parent);
9404 parent->cont = bb;
9406 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9408 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9409 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9411 else
9413 region = new_omp_region (bb, code, parent);
9414 /* Otherwise... */
9415 if (code == GIMPLE_OMP_TARGET)
9417 switch (gimple_omp_target_kind (stmt))
9419 case GF_OMP_TARGET_KIND_REGION:
9420 case GF_OMP_TARGET_KIND_DATA:
9421 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9422 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9423 case GF_OMP_TARGET_KIND_OACC_DATA:
9424 break;
9425 case GF_OMP_TARGET_KIND_UPDATE:
9426 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9427 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9428 /* ..., other than for those stand-alone directives... */
9429 region = NULL;
9430 break;
9431 default:
9432 gcc_unreachable ();
9435 /* ..., this directive becomes the parent for a new region. */
9436 if (region)
9437 parent = region;
9441 if (single_tree && !parent)
9442 return;
9444 for (son = first_dom_son (CDI_DOMINATORS, bb);
9445 son;
9446 son = next_dom_son (CDI_DOMINATORS, son))
9447 build_omp_regions_1 (son, parent, single_tree);
9450 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9451 root_omp_region. */
9453 static void
9454 build_omp_regions_root (basic_block root)
9456 gcc_assert (root_omp_region == NULL);
9457 build_omp_regions_1 (root, NULL, true);
9458 gcc_assert (root_omp_region != NULL);
9461 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9463 void
9464 omp_expand_local (basic_block head)
9466 build_omp_regions_root (head);
9467 if (dump_file && (dump_flags & TDF_DETAILS))
9469 fprintf (dump_file, "\nOMP region tree\n\n");
9470 dump_omp_region (dump_file, root_omp_region, 0);
9471 fprintf (dump_file, "\n");
9474 remove_exit_barriers (root_omp_region);
9475 expand_omp (root_omp_region);
9477 free_omp_regions ();
9480 /* Scan the CFG and build a tree of OMP regions. Return the root of
9481 the OMP region tree. */
9483 static void
9484 build_omp_regions (void)
9486 gcc_assert (root_omp_region == NULL);
9487 calculate_dominance_info (CDI_DOMINATORS);
9488 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9491 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9493 static unsigned int
9494 execute_expand_omp (void)
9496 build_omp_regions ();
9498 if (!root_omp_region)
9499 return 0;
9501 if (dump_file)
9503 fprintf (dump_file, "\nOMP region tree\n\n");
9504 dump_omp_region (dump_file, root_omp_region, 0);
9505 fprintf (dump_file, "\n");
9508 remove_exit_barriers (root_omp_region);
9510 expand_omp (root_omp_region);
9512 cleanup_tree_cfg ();
9514 free_omp_regions ();
9516 return 0;
9519 /* OMP expansion -- the default pass, run before creation of SSA form. */
9521 namespace {
9523 const pass_data pass_data_expand_omp =
9525 GIMPLE_PASS, /* type */
9526 "ompexp", /* name */
9527 OPTGROUP_NONE, /* optinfo_flags */
9528 TV_NONE, /* tv_id */
9529 PROP_gimple_any, /* properties_required */
9530 PROP_gimple_eomp, /* properties_provided */
9531 0, /* properties_destroyed */
9532 0, /* todo_flags_start */
9533 0, /* todo_flags_finish */
9536 class pass_expand_omp : public gimple_opt_pass
9538 public:
9539 pass_expand_omp (gcc::context *ctxt)
9540 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9543 /* opt_pass methods: */
9544 virtual unsigned int execute (function *)
9546 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9547 || flag_openmp_simd != 0)
9548 && !seen_error ());
9550 /* This pass always runs, to provide PROP_gimple_eomp.
9551 But often, there is nothing to do. */
9552 if (!gate)
9553 return 0;
9555 return execute_expand_omp ();
9558 }; // class pass_expand_omp
9560 } // anon namespace
9562 gimple_opt_pass *
9563 make_pass_expand_omp (gcc::context *ctxt)
9565 return new pass_expand_omp (ctxt);
9568 namespace {
9570 const pass_data pass_data_expand_omp_ssa =
9572 GIMPLE_PASS, /* type */
9573 "ompexpssa", /* name */
9574 OPTGROUP_NONE, /* optinfo_flags */
9575 TV_NONE, /* tv_id */
9576 PROP_cfg | PROP_ssa, /* properties_required */
9577 PROP_gimple_eomp, /* properties_provided */
9578 0, /* properties_destroyed */
9579 0, /* todo_flags_start */
9580 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9583 class pass_expand_omp_ssa : public gimple_opt_pass
9585 public:
9586 pass_expand_omp_ssa (gcc::context *ctxt)
9587 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9590 /* opt_pass methods: */
9591 virtual bool gate (function *fun)
9593 return !(fun->curr_properties & PROP_gimple_eomp);
9595 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9597 }; // class pass_expand_omp_ssa
9599 } // anon namespace
9601 gimple_opt_pass *
9602 make_pass_expand_omp_ssa (gcc::context *ctxt)
9604 return new pass_expand_omp_ssa (ctxt);
9607 /* Routines to lower OMP directives into OMP-GIMPLE. */
9609 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9610 convert it to gimple. */
9611 static void
9612 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9614 gimple stmt;
9616 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9618 stmt = gimple_build_assign (dest, op, dest, src);
9619 gimple_seq_add_stmt (seq, stmt);
9620 return;
9623 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9624 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9625 gimplify_assign (t, rdest, seq);
9626 rdest = t;
9628 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9629 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9630 gimplify_assign (t, idest, seq);
9631 idest = t;
9633 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9634 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9635 gimplify_assign (t, rsrc, seq);
9636 rsrc = t;
9638 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9639 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9640 gimplify_assign (t, isrc, seq);
9641 isrc = t;
9643 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9644 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9645 tree result;
9647 if (op == PLUS_EXPR)
9649 stmt = gimple_build_assign (r, op, rdest, rsrc);
9650 gimple_seq_add_stmt (seq, stmt);
9652 stmt = gimple_build_assign (i, op, idest, isrc);
9653 gimple_seq_add_stmt (seq, stmt);
9655 else if (op == MULT_EXPR)
9657 /* Let x = a + ib = dest, y = c + id = src.
9658 x * y = (ac - bd) + i(ad + bc) */
9659 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9660 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9661 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9662 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9664 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9665 gimple_seq_add_stmt (seq, stmt);
9667 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9668 gimple_seq_add_stmt (seq, stmt);
9670 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9671 gimple_seq_add_stmt (seq, stmt);
9673 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9674 gimple_seq_add_stmt (seq, stmt);
9676 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9677 gimple_seq_add_stmt (seq, stmt);
9679 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9680 gimple_seq_add_stmt (seq, stmt);
9682 else
9683 gcc_unreachable ();
9685 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9686 gimplify_assign (dest, result, seq);
9689 /* Helper function to initialize local data for the reduction arrays.
9690 The reduction arrays need to be placed inside the calling function
9691 for accelerators, or else the host won't be able to preform the final
9692 reduction. */
9694 static void
9695 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9696 gimple_seq *stmt_seqp, omp_context *ctx)
9698 tree c, t, oc;
9699 gimple stmt;
9700 omp_context *octx;
9702 /* Find the innermost OpenACC parallel context. */
9703 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9704 && (gimple_omp_target_kind (ctx->stmt)
9705 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9706 octx = ctx;
9707 else
9708 octx = ctx->outer;
9709 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9710 && (gimple_omp_target_kind (octx->stmt)
9711 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9713 /* Extract the clauses. */
9714 oc = gimple_omp_target_clauses (octx->stmt);
9716 /* Find the last outer clause. */
9717 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9720 /* Allocate arrays for each reduction variable. */
9721 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9723 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9724 continue;
9726 tree var = OMP_CLAUSE_DECL (c);
9727 tree type = get_base_type (var);
9728 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9729 ctx);
9730 tree size, call;
9732 /* Calculate size of the reduction array. */
9733 t = create_tmp_var (TREE_TYPE (nthreads));
9734 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9735 fold_convert (TREE_TYPE (nthreads),
9736 TYPE_SIZE_UNIT (type)));
9737 gimple_seq_add_stmt (stmt_seqp, stmt);
9739 size = create_tmp_var (sizetype);
9740 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9742 /* Now allocate memory for it. */
9743 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9744 stmt = gimple_build_call (call, 1, size);
9745 gimple_call_set_lhs (stmt, array);
9746 gimple_seq_add_stmt (stmt_seqp, stmt);
9748 /* Map this array into the accelerator. */
9750 /* Add the reduction array to the list of clauses. */
9751 tree x = array;
9752 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9753 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9754 OMP_CLAUSE_DECL (t) = x;
9755 OMP_CLAUSE_CHAIN (t) = NULL;
9756 if (oc)
9757 OMP_CLAUSE_CHAIN (oc) = t;
9758 else
9759 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9760 OMP_CLAUSE_SIZE (t) = size;
9761 oc = t;
9765 /* Helper function to process the array of partial reductions. Nthreads
9766 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9767 cannot be used here, because nthreads on the host may be different than
9768 on the accelerator. */
9770 static void
9771 oacc_finalize_reduction_data (tree clauses, tree nthreads,
9772 gimple_seq *stmt_seqp, omp_context *ctx)
9774 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9775 gimple stmt;
9777 /* Create for loop.
9779 let var = the original reduction variable
9780 let array = reduction variable array
9782 for (i = 0; i < nthreads; i++)
9783 var op= array[i]
9786 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9787 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9788 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9790 /* Create and initialize an index variable. */
9791 tree ix = create_tmp_var (sizetype);
9792 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9793 stmt_seqp);
9795 /* Insert the loop header label here. */
9796 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9798 /* Exit loop if ix >= nthreads. */
9799 x = create_tmp_var (sizetype);
9800 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9801 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9802 gimple_seq_add_stmt (stmt_seqp, stmt);
9804 /* Insert the loop body label here. */
9805 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9807 /* Collapse each reduction array, one element at a time. */
9808 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9810 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9811 continue;
9813 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9815 /* reduction(-:var) sums up the partial results, so it acts
9816 identically to reduction(+:var). */
9817 if (reduction_code == MINUS_EXPR)
9818 reduction_code = PLUS_EXPR;
9820 /* Set up reduction variable var. */
9821 var = OMP_CLAUSE_DECL (c);
9822 type = get_base_type (var);
9823 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9824 (OMP_CLAUSE_DECL (c)), ctx);
9826 /* Calculate the array offset. */
9827 tree offset = create_tmp_var (sizetype);
9828 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9829 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9830 gimple_seq_add_stmt (stmt_seqp, stmt);
9832 tree ptr = create_tmp_var (TREE_TYPE (array));
9833 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9834 gimple_seq_add_stmt (stmt_seqp, stmt);
9836 /* Extract array[ix] into mem. */
9837 tree mem = create_tmp_var (type);
9838 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9840 /* Find the original reduction variable. */
9841 if (is_reference (var))
9842 var = build_simple_mem_ref (var);
9844 tree t = create_tmp_var (type);
9846 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9847 gimplify_and_add (unshare_expr(x), stmt_seqp);
9849 /* var = var op mem */
9850 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9852 case TRUTH_ANDIF_EXPR:
9853 case TRUTH_ORIF_EXPR:
9854 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9855 t, mem);
9856 gimplify_and_add (t, stmt_seqp);
9857 break;
9858 default:
9859 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9860 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9861 stmt_seqp);
9864 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9865 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9866 gimplify_and_add (unshare_expr(x), stmt_seqp);
9869 /* Increment the induction variable. */
9870 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9871 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9872 gimple_seq_add_stmt (stmt_seqp, stmt);
9874 /* Go back to the top of the loop. */
9875 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9877 /* Place the loop exit label here. */
9878 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9881 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9882 scan that for reductions. */
9884 static void
9885 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9886 gimple_seq *out_stmt_seqp, omp_context *ctx)
9888 gimple_stmt_iterator gsi;
9889 gimple_seq inner = NULL;
9891 /* A collapse clause may have inserted a new bind block. */
9892 gsi = gsi_start (*body);
9893 while (!gsi_end_p (gsi))
9895 gimple stmt = gsi_stmt (gsi);
9896 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9898 inner = gimple_bind_body (bind_stmt);
9899 body = &inner;
9900 gsi = gsi_start (*body);
9902 else if (dyn_cast <gomp_for *> (stmt))
9903 break;
9904 else
9905 gsi_next (&gsi);
9908 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9910 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9911 enter, exit;
9912 bool reduction_found = false;
9914 gimple stmt = gsi_stmt (gsi);
9916 switch (gimple_code (stmt))
9918 case GIMPLE_OMP_FOR:
9919 clauses = gimple_omp_for_clauses (stmt);
9921 /* Search for a reduction clause. */
9922 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9923 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9925 reduction_found = true;
9926 break;
9929 if (!reduction_found)
9930 break;
9932 ctx = maybe_lookup_ctx (stmt);
9933 t = NULL_TREE;
9935 /* Extract the number of threads. */
9936 nthreads = create_tmp_var (sizetype);
9937 t = oacc_max_threads (ctx);
9938 gimplify_assign (nthreads, t, in_stmt_seqp);
9940 /* Determine if this is kernel will be executed on the host. */
9941 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9942 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9943 stmt = gimple_build_call (call, 0);
9944 gimple_call_set_lhs (stmt, acc_device);
9945 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9947 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9948 acc_device_host = create_tmp_var (integer_type_node,
9949 ".acc_device_host");
9950 gimplify_assign (acc_device_host,
9951 build_int_cst (integer_type_node,
9952 GOMP_DEVICE_HOST),
9953 in_stmt_seqp);
9955 enter = create_artificial_label (UNKNOWN_LOCATION);
9956 exit = create_artificial_label (UNKNOWN_LOCATION);
9958 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9959 enter, exit);
9960 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9961 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9962 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9963 integer_one_node),
9964 in_stmt_seqp);
9965 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9967 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9968 gimplify_assign (acc_device_host,
9969 build_int_cst (integer_type_node,
9970 GOMP_DEVICE_HOST_NONSHM),
9971 in_stmt_seqp);
9973 enter = create_artificial_label (UNKNOWN_LOCATION);
9974 exit = create_artificial_label (UNKNOWN_LOCATION);
9976 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9977 enter, exit);
9978 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9979 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9980 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9981 integer_one_node),
9982 in_stmt_seqp);
9983 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9985 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9986 ctx);
9987 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9988 break;
9989 default:
9990 // Scan for other directives which support reduction here.
9991 break;
9996 /* If ctx is a worksharing context inside of a cancellable parallel
9997 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9998 and conditional branch to parallel's cancel_label to handle
9999 cancellation in the implicit barrier. */
10001 static void
10002 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
10004 gimple omp_return = gimple_seq_last_stmt (*body);
10005 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
10006 if (gimple_omp_return_nowait_p (omp_return))
10007 return;
10008 if (ctx->outer
10009 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
10010 && ctx->outer->cancellable)
10012 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
10013 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
10014 tree lhs = create_tmp_var (c_bool_type);
10015 gimple_omp_return_set_lhs (omp_return, lhs);
10016 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10017 gimple g = gimple_build_cond (NE_EXPR, lhs,
10018 fold_convert (c_bool_type,
10019 boolean_false_node),
10020 ctx->outer->cancel_label, fallthru_label);
10021 gimple_seq_add_stmt (body, g);
10022 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10026 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10027 CTX is the enclosing OMP context for the current statement. */
10029 static void
10030 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10032 tree block, control;
10033 gimple_stmt_iterator tgsi;
10034 gomp_sections *stmt;
10035 gimple t;
10036 gbind *new_stmt, *bind;
10037 gimple_seq ilist, dlist, olist, new_body;
10039 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
10041 push_gimplify_context ();
10043 dlist = NULL;
10044 ilist = NULL;
10045 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10046 &ilist, &dlist, ctx, NULL);
10048 new_body = gimple_omp_body (stmt);
10049 gimple_omp_set_body (stmt, NULL);
10050 tgsi = gsi_start (new_body);
10051 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10053 omp_context *sctx;
10054 gimple sec_start;
10056 sec_start = gsi_stmt (tgsi);
10057 sctx = maybe_lookup_ctx (sec_start);
10058 gcc_assert (sctx);
10060 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10061 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10062 GSI_CONTINUE_LINKING);
10063 gimple_omp_set_body (sec_start, NULL);
10065 if (gsi_one_before_end_p (tgsi))
10067 gimple_seq l = NULL;
10068 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10069 &l, ctx);
10070 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10071 gimple_omp_section_set_last (sec_start);
10074 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10075 GSI_CONTINUE_LINKING);
10078 block = make_node (BLOCK);
10079 bind = gimple_build_bind (NULL, new_body, block);
10081 olist = NULL;
10082 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10084 block = make_node (BLOCK);
10085 new_stmt = gimple_build_bind (NULL, NULL, block);
10086 gsi_replace (gsi_p, new_stmt, true);
10088 pop_gimplify_context (new_stmt);
10089 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10090 BLOCK_VARS (block) = gimple_bind_vars (bind);
10091 if (BLOCK_VARS (block))
10092 TREE_USED (block) = 1;
10094 new_body = NULL;
10095 gimple_seq_add_seq (&new_body, ilist);
10096 gimple_seq_add_stmt (&new_body, stmt);
10097 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10098 gimple_seq_add_stmt (&new_body, bind);
10100 control = create_tmp_var (unsigned_type_node, ".section");
10101 t = gimple_build_omp_continue (control, control);
10102 gimple_omp_sections_set_control (stmt, control);
10103 gimple_seq_add_stmt (&new_body, t);
10105 gimple_seq_add_seq (&new_body, olist);
10106 if (ctx->cancellable)
10107 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10108 gimple_seq_add_seq (&new_body, dlist);
10110 new_body = maybe_catch_exception (new_body);
10112 t = gimple_build_omp_return
10113 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10114 OMP_CLAUSE_NOWAIT));
10115 gimple_seq_add_stmt (&new_body, t);
10116 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10118 gimple_bind_set_body (new_stmt, new_body);
10122 /* A subroutine of lower_omp_single. Expand the simple form of
10123 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10125 if (GOMP_single_start ())
10126 BODY;
10127 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10129 FIXME. It may be better to delay expanding the logic of this until
10130 pass_expand_omp. The expanded logic may make the job more difficult
10131 to a synchronization analysis pass. */
10133 static void
10134 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10136 location_t loc = gimple_location (single_stmt);
10137 tree tlabel = create_artificial_label (loc);
10138 tree flabel = create_artificial_label (loc);
10139 gimple call, cond;
10140 tree lhs, decl;
10142 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10143 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10144 call = gimple_build_call (decl, 0);
10145 gimple_call_set_lhs (call, lhs);
10146 gimple_seq_add_stmt (pre_p, call);
10148 cond = gimple_build_cond (EQ_EXPR, lhs,
10149 fold_convert_loc (loc, TREE_TYPE (lhs),
10150 boolean_true_node),
10151 tlabel, flabel);
10152 gimple_seq_add_stmt (pre_p, cond);
10153 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10154 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10155 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10159 /* A subroutine of lower_omp_single. Expand the simple form of
10160 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10162 #pragma omp single copyprivate (a, b, c)
10164 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10167 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10169 BODY;
10170 copyout.a = a;
10171 copyout.b = b;
10172 copyout.c = c;
10173 GOMP_single_copy_end (&copyout);
10175 else
10177 a = copyout_p->a;
10178 b = copyout_p->b;
10179 c = copyout_p->c;
10181 GOMP_barrier ();
10184 FIXME. It may be better to delay expanding the logic of this until
10185 pass_expand_omp. The expanded logic may make the job more difficult
10186 to a synchronization analysis pass. */
10188 static void
10189 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10190 omp_context *ctx)
10192 tree ptr_type, t, l0, l1, l2, bfn_decl;
10193 gimple_seq copyin_seq;
10194 location_t loc = gimple_location (single_stmt);
10196 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10198 ptr_type = build_pointer_type (ctx->record_type);
10199 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10201 l0 = create_artificial_label (loc);
10202 l1 = create_artificial_label (loc);
10203 l2 = create_artificial_label (loc);
10205 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10206 t = build_call_expr_loc (loc, bfn_decl, 0);
10207 t = fold_convert_loc (loc, ptr_type, t);
10208 gimplify_assign (ctx->receiver_decl, t, pre_p);
10210 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10211 build_int_cst (ptr_type, 0));
10212 t = build3 (COND_EXPR, void_type_node, t,
10213 build_and_jump (&l0), build_and_jump (&l1));
10214 gimplify_and_add (t, pre_p);
10216 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10218 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10220 copyin_seq = NULL;
10221 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10222 &copyin_seq, ctx);
10224 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10225 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10226 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10227 gimplify_and_add (t, pre_p);
10229 t = build_and_jump (&l2);
10230 gimplify_and_add (t, pre_p);
10232 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10234 gimple_seq_add_seq (pre_p, copyin_seq);
10236 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10240 /* Expand code for an OpenMP single directive. */
10242 static void
10243 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10245 tree block;
10246 gimple t;
10247 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10248 gbind *bind;
10249 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10251 push_gimplify_context ();
10253 block = make_node (BLOCK);
10254 bind = gimple_build_bind (NULL, NULL, block);
10255 gsi_replace (gsi_p, bind, true);
10256 bind_body = NULL;
10257 dlist = NULL;
10258 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10259 &bind_body, &dlist, ctx, NULL);
10260 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10262 gimple_seq_add_stmt (&bind_body, single_stmt);
10264 if (ctx->record_type)
10265 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10266 else
10267 lower_omp_single_simple (single_stmt, &bind_body);
10269 gimple_omp_set_body (single_stmt, NULL);
10271 gimple_seq_add_seq (&bind_body, dlist);
10273 bind_body = maybe_catch_exception (bind_body);
10275 t = gimple_build_omp_return
10276 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10277 OMP_CLAUSE_NOWAIT));
10278 gimple_seq_add_stmt (&bind_body_tail, t);
10279 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10280 if (ctx->record_type)
10282 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10283 tree clobber = build_constructor (ctx->record_type, NULL);
10284 TREE_THIS_VOLATILE (clobber) = 1;
10285 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10286 clobber), GSI_SAME_STMT);
10288 gimple_seq_add_seq (&bind_body, bind_body_tail);
10289 gimple_bind_set_body (bind, bind_body);
10291 pop_gimplify_context (bind);
10293 gimple_bind_append_vars (bind, ctx->block_vars);
10294 BLOCK_VARS (block) = ctx->block_vars;
10295 if (BLOCK_VARS (block))
10296 TREE_USED (block) = 1;
10300 /* Expand code for an OpenMP master directive. */
10302 static void
10303 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10305 tree block, lab = NULL, x, bfn_decl;
10306 gimple stmt = gsi_stmt (*gsi_p);
10307 gbind *bind;
10308 location_t loc = gimple_location (stmt);
10309 gimple_seq tseq;
10311 push_gimplify_context ();
10313 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 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10319 x = build_call_expr_loc (loc, bfn_decl, 0);
10320 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10321 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10322 tseq = NULL;
10323 gimplify_and_add (x, &tseq);
10324 gimple_bind_add_seq (bind, tseq);
10326 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10327 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10328 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10329 gimple_omp_set_body (stmt, NULL);
10331 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10333 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10335 pop_gimplify_context (bind);
10337 gimple_bind_append_vars (bind, ctx->block_vars);
10338 BLOCK_VARS (block) = ctx->block_vars;
10342 /* Expand code for an OpenMP taskgroup directive. */
10344 static void
10345 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10347 gimple stmt = gsi_stmt (*gsi_p);
10348 gcall *x;
10349 gbind *bind;
10350 tree block = make_node (BLOCK);
10352 bind = gimple_build_bind (NULL, NULL, block);
10353 gsi_replace (gsi_p, bind, true);
10354 gimple_bind_add_stmt (bind, stmt);
10356 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10358 gimple_bind_add_stmt (bind, x);
10360 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10361 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10362 gimple_omp_set_body (stmt, NULL);
10364 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10366 gimple_bind_append_vars (bind, ctx->block_vars);
10367 BLOCK_VARS (block) = ctx->block_vars;
10371 /* Expand code for an OpenMP ordered directive. */
10373 static void
10374 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10376 tree block;
10377 gimple stmt = gsi_stmt (*gsi_p);
10378 gcall *x;
10379 gbind *bind;
10381 push_gimplify_context ();
10383 block = make_node (BLOCK);
10384 bind = gimple_build_bind (NULL, NULL, block);
10385 gsi_replace (gsi_p, bind, true);
10386 gimple_bind_add_stmt (bind, stmt);
10388 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10390 gimple_bind_add_stmt (bind, x);
10392 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10393 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10394 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10395 gimple_omp_set_body (stmt, NULL);
10397 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10398 gimple_bind_add_stmt (bind, x);
10400 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10402 pop_gimplify_context (bind);
10404 gimple_bind_append_vars (bind, ctx->block_vars);
10405 BLOCK_VARS (block) = gimple_bind_vars (bind);
10409 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10410 substitution of a couple of function calls. But in the NAMED case,
10411 requires that languages coordinate a symbol name. It is therefore
10412 best put here in common code. */
10414 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10416 static void
10417 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10419 tree block;
10420 tree name, lock, unlock;
10421 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10422 gbind *bind;
10423 location_t loc = gimple_location (stmt);
10424 gimple_seq tbody;
10426 name = gimple_omp_critical_name (stmt);
10427 if (name)
10429 tree decl;
10431 if (!critical_name_mutexes)
10432 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10434 tree *n = critical_name_mutexes->get (name);
10435 if (n == NULL)
10437 char *new_str;
10439 decl = create_tmp_var_raw (ptr_type_node);
10441 new_str = ACONCAT ((".gomp_critical_user_",
10442 IDENTIFIER_POINTER (name), NULL));
10443 DECL_NAME (decl) = get_identifier (new_str);
10444 TREE_PUBLIC (decl) = 1;
10445 TREE_STATIC (decl) = 1;
10446 DECL_COMMON (decl) = 1;
10447 DECL_ARTIFICIAL (decl) = 1;
10448 DECL_IGNORED_P (decl) = 1;
10450 varpool_node::finalize_decl (decl);
10452 critical_name_mutexes->put (name, decl);
10454 else
10455 decl = *n;
10457 /* If '#pragma omp critical' is inside offloaded region or
10458 inside function marked as offloadable, the symbol must be
10459 marked as offloadable too. */
10460 omp_context *octx;
10461 if (cgraph_node::get (current_function_decl)->offloadable)
10462 varpool_node::get_create (decl)->offloadable = 1;
10463 else
10464 for (octx = ctx->outer; octx; octx = octx->outer)
10465 if (is_gimple_omp_offloaded (octx->stmt))
10467 varpool_node::get_create (decl)->offloadable = 1;
10468 break;
10471 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10472 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10474 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10475 unlock = build_call_expr_loc (loc, unlock, 1,
10476 build_fold_addr_expr_loc (loc, decl));
10478 else
10480 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10481 lock = build_call_expr_loc (loc, lock, 0);
10483 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10484 unlock = build_call_expr_loc (loc, unlock, 0);
10487 push_gimplify_context ();
10489 block = make_node (BLOCK);
10490 bind = gimple_build_bind (NULL, NULL, block);
10491 gsi_replace (gsi_p, bind, true);
10492 gimple_bind_add_stmt (bind, stmt);
10494 tbody = gimple_bind_body (bind);
10495 gimplify_and_add (lock, &tbody);
10496 gimple_bind_set_body (bind, tbody);
10498 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10499 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10500 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10501 gimple_omp_set_body (stmt, NULL);
10503 tbody = gimple_bind_body (bind);
10504 gimplify_and_add (unlock, &tbody);
10505 gimple_bind_set_body (bind, tbody);
10507 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10509 pop_gimplify_context (bind);
10510 gimple_bind_append_vars (bind, ctx->block_vars);
10511 BLOCK_VARS (block) = gimple_bind_vars (bind);
10515 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10516 for a lastprivate clause. Given a loop control predicate of (V
10517 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10518 is appended to *DLIST, iterator initialization is appended to
10519 *BODY_P. */
10521 static void
10522 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10523 gimple_seq *dlist, struct omp_context *ctx)
10525 tree clauses, cond, vinit;
10526 enum tree_code cond_code;
10527 gimple_seq stmts;
10529 cond_code = fd->loop.cond_code;
10530 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10532 /* When possible, use a strict equality expression. This can let VRP
10533 type optimizations deduce the value and remove a copy. */
10534 if (tree_fits_shwi_p (fd->loop.step))
10536 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10537 if (step == 1 || step == -1)
10538 cond_code = EQ_EXPR;
10541 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
10543 clauses = gimple_omp_for_clauses (fd->for_stmt);
10544 stmts = NULL;
10545 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10546 if (!gimple_seq_empty_p (stmts))
10548 gimple_seq_add_seq (&stmts, *dlist);
10549 *dlist = stmts;
10551 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10552 vinit = fd->loop.n1;
10553 if (cond_code == EQ_EXPR
10554 && tree_fits_shwi_p (fd->loop.n2)
10555 && ! integer_zerop (fd->loop.n2))
10556 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10557 else
10558 vinit = unshare_expr (vinit);
10560 /* Initialize the iterator variable, so that threads that don't execute
10561 any iterations don't execute the lastprivate clauses by accident. */
10562 gimplify_assign (fd->loop.v, vinit, body_p);
10567 /* Lower code for an OMP loop directive. */
10569 static void
10570 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10572 tree *rhs_p, block;
10573 struct omp_for_data fd, *fdp = NULL;
10574 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10575 gbind *new_stmt;
10576 gimple_seq omp_for_body, body, dlist;
10577 size_t i;
10579 push_gimplify_context ();
10581 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10583 block = make_node (BLOCK);
10584 new_stmt = gimple_build_bind (NULL, NULL, block);
10585 /* Replace at gsi right away, so that 'stmt' is no member
10586 of a sequence anymore as we're going to add to to a different
10587 one below. */
10588 gsi_replace (gsi_p, new_stmt, true);
10590 /* Move declaration of temporaries in the loop body before we make
10591 it go away. */
10592 omp_for_body = gimple_omp_body (stmt);
10593 if (!gimple_seq_empty_p (omp_for_body)
10594 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10596 gbind *inner_bind
10597 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10598 tree vars = gimple_bind_vars (inner_bind);
10599 gimple_bind_append_vars (new_stmt, vars);
10600 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10601 keep them on the inner_bind and it's block. */
10602 gimple_bind_set_vars (inner_bind, NULL_TREE);
10603 if (gimple_bind_block (inner_bind))
10604 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10607 if (gimple_omp_for_combined_into_p (stmt))
10609 extract_omp_for_data (stmt, &fd, NULL);
10610 fdp = &fd;
10612 /* We need two temporaries with fd.loop.v type (istart/iend)
10613 and then (fd.collapse - 1) temporaries with the same
10614 type for count2 ... countN-1 vars if not constant. */
10615 size_t count = 2;
10616 tree type = fd.iter_type;
10617 if (fd.collapse > 1
10618 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10619 count += fd.collapse - 1;
10620 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10621 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10622 tree clauses = *pc;
10623 if (parallel_for)
10624 outerc
10625 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10626 OMP_CLAUSE__LOOPTEMP_);
10627 for (i = 0; i < count; i++)
10629 tree temp;
10630 if (parallel_for)
10632 gcc_assert (outerc);
10633 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10634 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10635 OMP_CLAUSE__LOOPTEMP_);
10637 else
10639 temp = create_tmp_var (type);
10640 insert_decl_map (&ctx->outer->cb, temp, temp);
10642 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10643 OMP_CLAUSE_DECL (*pc) = temp;
10644 pc = &OMP_CLAUSE_CHAIN (*pc);
10646 *pc = clauses;
10649 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10650 dlist = NULL;
10651 body = NULL;
10652 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10653 fdp);
10654 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10656 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10658 /* Lower the header expressions. At this point, we can assume that
10659 the header is of the form:
10661 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10663 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10664 using the .omp_data_s mapping, if needed. */
10665 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10667 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10668 if (!is_gimple_min_invariant (*rhs_p))
10669 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10671 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10672 if (!is_gimple_min_invariant (*rhs_p))
10673 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10675 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10676 if (!is_gimple_min_invariant (*rhs_p))
10677 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10680 /* Once lowered, extract the bounds and clauses. */
10681 extract_omp_for_data (stmt, &fd, NULL);
10683 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10685 gimple_seq_add_stmt (&body, stmt);
10686 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10688 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10689 fd.loop.v));
10691 /* After the loop, add exit clauses. */
10692 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10694 if (ctx->cancellable)
10695 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10697 gimple_seq_add_seq (&body, dlist);
10699 body = maybe_catch_exception (body);
10701 /* Region exit marker goes at the end of the loop body. */
10702 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10703 maybe_add_implicit_barrier_cancel (ctx, &body);
10704 pop_gimplify_context (new_stmt);
10706 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10707 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10708 if (BLOCK_VARS (block))
10709 TREE_USED (block) = 1;
10711 gimple_bind_set_body (new_stmt, body);
10712 gimple_omp_set_body (stmt, NULL);
10713 gimple_omp_for_set_pre_body (stmt, NULL);
10716 /* Callback for walk_stmts. Check if the current statement only contains
10717 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10719 static tree
10720 check_combined_parallel (gimple_stmt_iterator *gsi_p,
10721 bool *handled_ops_p,
10722 struct walk_stmt_info *wi)
10724 int *info = (int *) wi->info;
10725 gimple stmt = gsi_stmt (*gsi_p);
10727 *handled_ops_p = true;
10728 switch (gimple_code (stmt))
10730 WALK_SUBSTMTS;
10732 case GIMPLE_OMP_FOR:
10733 case GIMPLE_OMP_SECTIONS:
10734 *info = *info == 0 ? 1 : -1;
10735 break;
10736 default:
10737 *info = -1;
10738 break;
10740 return NULL;
10743 struct omp_taskcopy_context
10745 /* This field must be at the beginning, as we do "inheritance": Some
10746 callback functions for tree-inline.c (e.g., omp_copy_decl)
10747 receive a copy_body_data pointer that is up-casted to an
10748 omp_context pointer. */
10749 copy_body_data cb;
10750 omp_context *ctx;
10753 static tree
10754 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10756 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10758 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10759 return create_tmp_var (TREE_TYPE (var));
10761 return var;
10764 static tree
10765 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10767 tree name, new_fields = NULL, type, f;
10769 type = lang_hooks.types.make_type (RECORD_TYPE);
10770 name = DECL_NAME (TYPE_NAME (orig_type));
10771 name = build_decl (gimple_location (tcctx->ctx->stmt),
10772 TYPE_DECL, name, type);
10773 TYPE_NAME (type) = name;
10775 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10777 tree new_f = copy_node (f);
10778 DECL_CONTEXT (new_f) = type;
10779 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10780 TREE_CHAIN (new_f) = new_fields;
10781 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10782 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10783 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10784 &tcctx->cb, NULL);
10785 new_fields = new_f;
10786 tcctx->cb.decl_map->put (f, new_f);
10788 TYPE_FIELDS (type) = nreverse (new_fields);
10789 layout_type (type);
10790 return type;
10793 /* Create task copyfn. */
10795 static void
10796 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
10798 struct function *child_cfun;
10799 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10800 tree record_type, srecord_type, bind, list;
10801 bool record_needs_remap = false, srecord_needs_remap = false;
10802 splay_tree_node n;
10803 struct omp_taskcopy_context tcctx;
10804 location_t loc = gimple_location (task_stmt);
10806 child_fn = gimple_omp_task_copy_fn (task_stmt);
10807 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10808 gcc_assert (child_cfun->cfg == NULL);
10809 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10811 /* Reset DECL_CONTEXT on function arguments. */
10812 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10813 DECL_CONTEXT (t) = child_fn;
10815 /* Populate the function. */
10816 push_gimplify_context ();
10817 push_cfun (child_cfun);
10819 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10820 TREE_SIDE_EFFECTS (bind) = 1;
10821 list = NULL;
10822 DECL_SAVED_TREE (child_fn) = bind;
10823 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10825 /* Remap src and dst argument types if needed. */
10826 record_type = ctx->record_type;
10827 srecord_type = ctx->srecord_type;
10828 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10829 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10831 record_needs_remap = true;
10832 break;
10834 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10835 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10837 srecord_needs_remap = true;
10838 break;
10841 if (record_needs_remap || srecord_needs_remap)
10843 memset (&tcctx, '\0', sizeof (tcctx));
10844 tcctx.cb.src_fn = ctx->cb.src_fn;
10845 tcctx.cb.dst_fn = child_fn;
10846 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
10847 gcc_checking_assert (tcctx.cb.src_node);
10848 tcctx.cb.dst_node = tcctx.cb.src_node;
10849 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10850 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10851 tcctx.cb.eh_lp_nr = 0;
10852 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10853 tcctx.cb.decl_map = new hash_map<tree, tree>;
10854 tcctx.ctx = ctx;
10856 if (record_needs_remap)
10857 record_type = task_copyfn_remap_type (&tcctx, record_type);
10858 if (srecord_needs_remap)
10859 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10861 else
10862 tcctx.cb.decl_map = NULL;
10864 arg = DECL_ARGUMENTS (child_fn);
10865 TREE_TYPE (arg) = build_pointer_type (record_type);
10866 sarg = DECL_CHAIN (arg);
10867 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10869 /* First pass: initialize temporaries used in record_type and srecord_type
10870 sizes and field offsets. */
10871 if (tcctx.cb.decl_map)
10872 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10873 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10875 tree *p;
10877 decl = OMP_CLAUSE_DECL (c);
10878 p = tcctx.cb.decl_map->get (decl);
10879 if (p == NULL)
10880 continue;
10881 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10882 sf = (tree) n->value;
10883 sf = *tcctx.cb.decl_map->get (sf);
10884 src = build_simple_mem_ref_loc (loc, sarg);
10885 src = omp_build_component_ref (src, sf);
10886 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10887 append_to_statement_list (t, &list);
10890 /* Second pass: copy shared var pointers and copy construct non-VLA
10891 firstprivate vars. */
10892 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10893 switch (OMP_CLAUSE_CODE (c))
10895 case OMP_CLAUSE_SHARED:
10896 decl = OMP_CLAUSE_DECL (c);
10897 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10898 if (n == NULL)
10899 break;
10900 f = (tree) n->value;
10901 if (tcctx.cb.decl_map)
10902 f = *tcctx.cb.decl_map->get (f);
10903 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10904 sf = (tree) n->value;
10905 if (tcctx.cb.decl_map)
10906 sf = *tcctx.cb.decl_map->get (sf);
10907 src = build_simple_mem_ref_loc (loc, sarg);
10908 src = omp_build_component_ref (src, sf);
10909 dst = build_simple_mem_ref_loc (loc, arg);
10910 dst = omp_build_component_ref (dst, f);
10911 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10912 append_to_statement_list (t, &list);
10913 break;
10914 case OMP_CLAUSE_FIRSTPRIVATE:
10915 decl = OMP_CLAUSE_DECL (c);
10916 if (is_variable_sized (decl))
10917 break;
10918 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10919 if (n == NULL)
10920 break;
10921 f = (tree) n->value;
10922 if (tcctx.cb.decl_map)
10923 f = *tcctx.cb.decl_map->get (f);
10924 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10925 if (n != NULL)
10927 sf = (tree) n->value;
10928 if (tcctx.cb.decl_map)
10929 sf = *tcctx.cb.decl_map->get (sf);
10930 src = build_simple_mem_ref_loc (loc, sarg);
10931 src = omp_build_component_ref (src, sf);
10932 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
10933 src = build_simple_mem_ref_loc (loc, src);
10935 else
10936 src = decl;
10937 dst = build_simple_mem_ref_loc (loc, arg);
10938 dst = omp_build_component_ref (dst, f);
10939 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10940 append_to_statement_list (t, &list);
10941 break;
10942 case OMP_CLAUSE_PRIVATE:
10943 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10944 break;
10945 decl = OMP_CLAUSE_DECL (c);
10946 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10947 f = (tree) n->value;
10948 if (tcctx.cb.decl_map)
10949 f = *tcctx.cb.decl_map->get (f);
10950 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10951 if (n != NULL)
10953 sf = (tree) n->value;
10954 if (tcctx.cb.decl_map)
10955 sf = *tcctx.cb.decl_map->get (sf);
10956 src = build_simple_mem_ref_loc (loc, sarg);
10957 src = omp_build_component_ref (src, sf);
10958 if (use_pointer_for_field (decl, NULL))
10959 src = build_simple_mem_ref_loc (loc, src);
10961 else
10962 src = decl;
10963 dst = build_simple_mem_ref_loc (loc, arg);
10964 dst = omp_build_component_ref (dst, f);
10965 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10966 append_to_statement_list (t, &list);
10967 break;
10968 default:
10969 break;
10972 /* Last pass: handle VLA firstprivates. */
10973 if (tcctx.cb.decl_map)
10974 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10975 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10977 tree ind, ptr, df;
10979 decl = OMP_CLAUSE_DECL (c);
10980 if (!is_variable_sized (decl))
10981 continue;
10982 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10983 if (n == NULL)
10984 continue;
10985 f = (tree) n->value;
10986 f = *tcctx.cb.decl_map->get (f);
10987 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10988 ind = DECL_VALUE_EXPR (decl);
10989 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10990 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10991 n = splay_tree_lookup (ctx->sfield_map,
10992 (splay_tree_key) TREE_OPERAND (ind, 0));
10993 sf = (tree) n->value;
10994 sf = *tcctx.cb.decl_map->get (sf);
10995 src = build_simple_mem_ref_loc (loc, sarg);
10996 src = omp_build_component_ref (src, sf);
10997 src = build_simple_mem_ref_loc (loc, src);
10998 dst = build_simple_mem_ref_loc (loc, arg);
10999 dst = omp_build_component_ref (dst, f);
11000 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11001 append_to_statement_list (t, &list);
11002 n = splay_tree_lookup (ctx->field_map,
11003 (splay_tree_key) TREE_OPERAND (ind, 0));
11004 df = (tree) n->value;
11005 df = *tcctx.cb.decl_map->get (df);
11006 ptr = build_simple_mem_ref_loc (loc, arg);
11007 ptr = omp_build_component_ref (ptr, df);
11008 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
11009 build_fold_addr_expr_loc (loc, dst));
11010 append_to_statement_list (t, &list);
11013 t = build1 (RETURN_EXPR, void_type_node, NULL);
11014 append_to_statement_list (t, &list);
11016 if (tcctx.cb.decl_map)
11017 delete tcctx.cb.decl_map;
11018 pop_gimplify_context (NULL);
11019 BIND_EXPR_BODY (bind) = list;
11020 pop_cfun ();
11023 static void
11024 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
11026 tree c, clauses;
11027 gimple g;
11028 size_t n_in = 0, n_out = 0, idx = 2, i;
11030 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11031 OMP_CLAUSE_DEPEND);
11032 gcc_assert (clauses);
11033 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11034 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11035 switch (OMP_CLAUSE_DEPEND_KIND (c))
11037 case OMP_CLAUSE_DEPEND_IN:
11038 n_in++;
11039 break;
11040 case OMP_CLAUSE_DEPEND_OUT:
11041 case OMP_CLAUSE_DEPEND_INOUT:
11042 n_out++;
11043 break;
11044 default:
11045 gcc_unreachable ();
11047 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11048 tree array = create_tmp_var (type);
11049 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11050 NULL_TREE);
11051 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11052 gimple_seq_add_stmt (iseq, g);
11053 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11054 NULL_TREE);
11055 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11056 gimple_seq_add_stmt (iseq, g);
11057 for (i = 0; i < 2; i++)
11059 if ((i ? n_in : n_out) == 0)
11060 continue;
11061 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11062 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11063 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11065 tree t = OMP_CLAUSE_DECL (c);
11066 t = fold_convert (ptr_type_node, t);
11067 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11068 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11069 NULL_TREE, NULL_TREE);
11070 g = gimple_build_assign (r, t);
11071 gimple_seq_add_stmt (iseq, g);
11074 tree *p = gimple_omp_task_clauses_ptr (stmt);
11075 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11076 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11077 OMP_CLAUSE_CHAIN (c) = *p;
11078 *p = c;
11079 tree clobber = build_constructor (type, NULL);
11080 TREE_THIS_VOLATILE (clobber) = 1;
11081 g = gimple_build_assign (array, clobber);
11082 gimple_seq_add_stmt (oseq, g);
11085 /* Lower the OpenMP parallel or task directive in the current statement
11086 in GSI_P. CTX holds context information for the directive. */
11088 static void
11089 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11091 tree clauses;
11092 tree child_fn, t;
11093 gimple stmt = gsi_stmt (*gsi_p);
11094 gbind *par_bind, *bind, *dep_bind = NULL;
11095 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11096 location_t loc = gimple_location (stmt);
11098 clauses = gimple_omp_taskreg_clauses (stmt);
11099 par_bind
11100 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11101 par_body = gimple_bind_body (par_bind);
11102 child_fn = ctx->cb.dst_fn;
11103 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11104 && !gimple_omp_parallel_combined_p (stmt))
11106 struct walk_stmt_info wi;
11107 int ws_num = 0;
11109 memset (&wi, 0, sizeof (wi));
11110 wi.info = &ws_num;
11111 wi.val_only = true;
11112 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11113 if (ws_num == 1)
11114 gimple_omp_parallel_set_combined_p (stmt, true);
11116 gimple_seq dep_ilist = NULL;
11117 gimple_seq dep_olist = NULL;
11118 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11119 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11121 push_gimplify_context ();
11122 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11123 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11126 if (ctx->srecord_type)
11127 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11129 push_gimplify_context ();
11131 par_olist = NULL;
11132 par_ilist = NULL;
11133 par_rlist = NULL;
11134 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11135 lower_omp (&par_body, ctx);
11136 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11137 lower_reduction_clauses (clauses, &par_rlist, ctx);
11139 /* Declare all the variables created by mapping and the variables
11140 declared in the scope of the parallel body. */
11141 record_vars_into (ctx->block_vars, child_fn);
11142 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11144 if (ctx->record_type)
11146 ctx->sender_decl
11147 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11148 : ctx->record_type, ".omp_data_o");
11149 DECL_NAMELESS (ctx->sender_decl) = 1;
11150 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11151 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11154 olist = NULL;
11155 ilist = NULL;
11156 lower_send_clauses (clauses, &ilist, &olist, ctx);
11157 lower_send_shared_vars (&ilist, &olist, ctx);
11159 if (ctx->record_type)
11161 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11162 TREE_THIS_VOLATILE (clobber) = 1;
11163 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11164 clobber));
11167 /* Once all the expansions are done, sequence all the different
11168 fragments inside gimple_omp_body. */
11170 new_body = NULL;
11172 if (ctx->record_type)
11174 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11175 /* fixup_child_record_type might have changed receiver_decl's type. */
11176 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11177 gimple_seq_add_stmt (&new_body,
11178 gimple_build_assign (ctx->receiver_decl, t));
11181 gimple_seq_add_seq (&new_body, par_ilist);
11182 gimple_seq_add_seq (&new_body, par_body);
11183 gimple_seq_add_seq (&new_body, par_rlist);
11184 if (ctx->cancellable)
11185 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11186 gimple_seq_add_seq (&new_body, par_olist);
11187 new_body = maybe_catch_exception (new_body);
11188 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
11189 gimple_seq_add_stmt (&new_body,
11190 gimple_build_omp_continue (integer_zero_node,
11191 integer_zero_node));
11192 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11193 gimple_omp_set_body (stmt, new_body);
11195 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11196 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11197 gimple_bind_add_seq (bind, ilist);
11198 gimple_bind_add_stmt (bind, stmt);
11199 gimple_bind_add_seq (bind, olist);
11201 pop_gimplify_context (NULL);
11203 if (dep_bind)
11205 gimple_bind_add_seq (dep_bind, dep_ilist);
11206 gimple_bind_add_stmt (dep_bind, bind);
11207 gimple_bind_add_seq (dep_bind, dep_olist);
11208 pop_gimplify_context (dep_bind);
11212 /* Lower the GIMPLE_OMP_TARGET in the current statement
11213 in GSI_P. CTX holds context information for the directive. */
11215 static void
11216 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11218 tree clauses;
11219 tree child_fn, t, c;
11220 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11221 gbind *tgt_bind, *bind;
11222 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11223 location_t loc = gimple_location (stmt);
11224 bool offloaded, data_region;
11225 unsigned int map_cnt = 0;
11227 offloaded = is_gimple_omp_offloaded (stmt);
11228 switch (gimple_omp_target_kind (stmt))
11230 case GF_OMP_TARGET_KIND_REGION:
11231 case GF_OMP_TARGET_KIND_UPDATE:
11232 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11233 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11234 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11235 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11236 data_region = false;
11237 break;
11238 case GF_OMP_TARGET_KIND_DATA:
11239 case GF_OMP_TARGET_KIND_OACC_DATA:
11240 data_region = true;
11241 break;
11242 default:
11243 gcc_unreachable ();
11246 clauses = gimple_omp_target_clauses (stmt);
11248 tgt_bind = NULL;
11249 tgt_body = NULL;
11250 if (offloaded)
11252 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11253 tgt_body = gimple_bind_body (tgt_bind);
11255 else if (data_region)
11256 tgt_body = gimple_omp_body (stmt);
11257 child_fn = ctx->cb.dst_fn;
11259 push_gimplify_context ();
11261 irlist = NULL;
11262 orlist = NULL;
11263 if (offloaded
11264 && is_gimple_omp_oacc (stmt))
11265 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11267 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11268 switch (OMP_CLAUSE_CODE (c))
11270 tree var, x;
11272 default:
11273 break;
11274 case OMP_CLAUSE_MAP:
11275 #ifdef ENABLE_CHECKING
11276 /* First check what we're prepared to handle in the following. */
11277 switch (OMP_CLAUSE_MAP_KIND (c))
11279 case GOMP_MAP_ALLOC:
11280 case GOMP_MAP_TO:
11281 case GOMP_MAP_FROM:
11282 case GOMP_MAP_TOFROM:
11283 case GOMP_MAP_POINTER:
11284 case GOMP_MAP_TO_PSET:
11285 break;
11286 case GOMP_MAP_FORCE_ALLOC:
11287 case GOMP_MAP_FORCE_TO:
11288 case GOMP_MAP_FORCE_FROM:
11289 case GOMP_MAP_FORCE_TOFROM:
11290 case GOMP_MAP_FORCE_PRESENT:
11291 case GOMP_MAP_FORCE_DEALLOC:
11292 case GOMP_MAP_FORCE_DEVICEPTR:
11293 gcc_assert (is_gimple_omp_oacc (stmt));
11294 break;
11295 default:
11296 gcc_unreachable ();
11298 #endif
11299 /* FALLTHRU */
11300 case OMP_CLAUSE_TO:
11301 case OMP_CLAUSE_FROM:
11302 var = OMP_CLAUSE_DECL (c);
11303 if (!DECL_P (var))
11305 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11306 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11307 map_cnt++;
11308 continue;
11311 if (DECL_SIZE (var)
11312 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11314 tree var2 = DECL_VALUE_EXPR (var);
11315 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11316 var2 = TREE_OPERAND (var2, 0);
11317 gcc_assert (DECL_P (var2));
11318 var = var2;
11321 if (!maybe_lookup_field (var, ctx))
11322 continue;
11324 if (offloaded)
11326 x = build_receiver_ref (var, true, ctx);
11327 tree new_var = lookup_decl (var, ctx);
11328 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11329 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11330 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11331 x = build_simple_mem_ref (x);
11332 SET_DECL_VALUE_EXPR (new_var, x);
11333 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11335 map_cnt++;
11338 if (offloaded)
11340 target_nesting_level++;
11341 lower_omp (&tgt_body, ctx);
11342 target_nesting_level--;
11344 else if (data_region)
11345 lower_omp (&tgt_body, ctx);
11347 if (offloaded)
11349 /* Declare all the variables created by mapping and the variables
11350 declared in the scope of the target body. */
11351 record_vars_into (ctx->block_vars, child_fn);
11352 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11355 olist = NULL;
11356 ilist = NULL;
11357 if (ctx->record_type)
11359 ctx->sender_decl
11360 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11361 DECL_NAMELESS (ctx->sender_decl) = 1;
11362 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11363 t = make_tree_vec (3);
11364 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11365 TREE_VEC_ELT (t, 1)
11366 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11367 ".omp_data_sizes");
11368 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11369 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11370 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11371 tree tkind_type;
11372 int talign_shift;
11373 if (is_gimple_omp_oacc (stmt))
11375 tkind_type = short_unsigned_type_node;
11376 talign_shift = 8;
11378 else
11380 tkind_type = unsigned_char_type_node;
11381 talign_shift = 3;
11383 TREE_VEC_ELT (t, 2)
11384 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11385 ".omp_data_kinds");
11386 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11387 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11388 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11389 gimple_omp_target_set_data_arg (stmt, t);
11391 vec<constructor_elt, va_gc> *vsize;
11392 vec<constructor_elt, va_gc> *vkind;
11393 vec_alloc (vsize, map_cnt);
11394 vec_alloc (vkind, map_cnt);
11395 unsigned int map_idx = 0;
11397 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11398 switch (OMP_CLAUSE_CODE (c))
11400 tree ovar, nc;
11402 default:
11403 break;
11404 case OMP_CLAUSE_MAP:
11405 case OMP_CLAUSE_TO:
11406 case OMP_CLAUSE_FROM:
11407 nc = c;
11408 ovar = OMP_CLAUSE_DECL (c);
11409 if (!DECL_P (ovar))
11411 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11412 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11414 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11415 == get_base_address (ovar));
11416 nc = OMP_CLAUSE_CHAIN (c);
11417 ovar = OMP_CLAUSE_DECL (nc);
11419 else
11421 tree x = build_sender_ref (ovar, ctx);
11422 tree v
11423 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11424 gimplify_assign (x, v, &ilist);
11425 nc = NULL_TREE;
11428 else
11430 if (DECL_SIZE (ovar)
11431 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11433 tree ovar2 = DECL_VALUE_EXPR (ovar);
11434 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11435 ovar2 = TREE_OPERAND (ovar2, 0);
11436 gcc_assert (DECL_P (ovar2));
11437 ovar = ovar2;
11439 if (!maybe_lookup_field (ovar, ctx))
11440 continue;
11443 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11444 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11445 talign = DECL_ALIGN_UNIT (ovar);
11446 if (nc)
11448 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11449 tree x = build_sender_ref (ovar, ctx);
11450 if (maybe_lookup_oacc_reduction (var, ctx))
11452 gcc_checking_assert (offloaded
11453 && is_gimple_omp_oacc (stmt));
11454 gimplify_assign (x, var, &ilist);
11456 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11457 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11458 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11459 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11461 gcc_assert (offloaded);
11462 tree avar
11463 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11464 mark_addressable (avar);
11465 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11466 talign = DECL_ALIGN_UNIT (avar);
11467 avar = build_fold_addr_expr (avar);
11468 gimplify_assign (x, avar, &ilist);
11470 else if (is_gimple_reg (var))
11472 gcc_assert (offloaded);
11473 tree avar = create_tmp_var (TREE_TYPE (var));
11474 mark_addressable (avar);
11475 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11476 if (GOMP_MAP_COPY_TO_P (map_kind)
11477 || map_kind == GOMP_MAP_POINTER
11478 || map_kind == GOMP_MAP_TO_PSET
11479 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11480 gimplify_assign (avar, var, &ilist);
11481 avar = build_fold_addr_expr (avar);
11482 gimplify_assign (x, avar, &ilist);
11483 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11484 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11485 && !TYPE_READONLY (TREE_TYPE (var)))
11487 x = build_sender_ref (ovar, ctx);
11488 x = build_simple_mem_ref (x);
11489 gimplify_assign (var, x, &olist);
11492 else
11494 var = build_fold_addr_expr (var);
11495 gimplify_assign (x, var, &ilist);
11498 tree s = OMP_CLAUSE_SIZE (c);
11499 if (s == NULL_TREE)
11500 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11501 s = fold_convert (size_type_node, s);
11502 tree purpose = size_int (map_idx++);
11503 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11504 if (TREE_CODE (s) != INTEGER_CST)
11505 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11507 unsigned HOST_WIDE_INT tkind;
11508 switch (OMP_CLAUSE_CODE (c))
11510 case OMP_CLAUSE_MAP:
11511 tkind = OMP_CLAUSE_MAP_KIND (c);
11512 break;
11513 case OMP_CLAUSE_TO:
11514 tkind = GOMP_MAP_TO;
11515 break;
11516 case OMP_CLAUSE_FROM:
11517 tkind = GOMP_MAP_FROM;
11518 break;
11519 default:
11520 gcc_unreachable ();
11522 gcc_checking_assert (tkind
11523 < (HOST_WIDE_INT_C (1U) << talign_shift));
11524 talign = ceil_log2 (talign);
11525 tkind |= talign << talign_shift;
11526 gcc_checking_assert (tkind
11527 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11528 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11529 build_int_cstu (tkind_type, tkind));
11530 if (nc && nc != c)
11531 c = nc;
11534 gcc_assert (map_idx == map_cnt);
11536 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11537 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11538 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11539 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11540 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11542 gimple_seq initlist = NULL;
11543 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11544 TREE_VEC_ELT (t, 1)),
11545 &initlist, true, NULL_TREE);
11546 gimple_seq_add_seq (&ilist, initlist);
11548 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11549 NULL);
11550 TREE_THIS_VOLATILE (clobber) = 1;
11551 gimple_seq_add_stmt (&olist,
11552 gimple_build_assign (TREE_VEC_ELT (t, 1),
11553 clobber));
11556 tree clobber = build_constructor (ctx->record_type, NULL);
11557 TREE_THIS_VOLATILE (clobber) = 1;
11558 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11559 clobber));
11562 /* Once all the expansions are done, sequence all the different
11563 fragments inside gimple_omp_body. */
11565 new_body = NULL;
11567 if (offloaded
11568 && ctx->record_type)
11570 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11571 /* fixup_child_record_type might have changed receiver_decl's type. */
11572 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11573 gimple_seq_add_stmt (&new_body,
11574 gimple_build_assign (ctx->receiver_decl, t));
11577 if (offloaded)
11579 gimple_seq_add_seq (&new_body, tgt_body);
11580 new_body = maybe_catch_exception (new_body);
11582 else if (data_region)
11583 new_body = tgt_body;
11584 if (offloaded || data_region)
11586 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11587 gimple_omp_set_body (stmt, new_body);
11590 bind = gimple_build_bind (NULL, NULL,
11591 tgt_bind ? gimple_bind_block (tgt_bind)
11592 : NULL_TREE);
11593 gsi_replace (gsi_p, bind, true);
11594 gimple_bind_add_seq (bind, irlist);
11595 gimple_bind_add_seq (bind, ilist);
11596 gimple_bind_add_stmt (bind, stmt);
11597 gimple_bind_add_seq (bind, olist);
11598 gimple_bind_add_seq (bind, orlist);
11600 pop_gimplify_context (NULL);
11603 /* Expand code for an OpenMP teams directive. */
11605 static void
11606 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11608 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11609 push_gimplify_context ();
11611 tree block = make_node (BLOCK);
11612 gbind *bind = gimple_build_bind (NULL, NULL, block);
11613 gsi_replace (gsi_p, bind, true);
11614 gimple_seq bind_body = NULL;
11615 gimple_seq dlist = NULL;
11616 gimple_seq olist = NULL;
11618 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11619 OMP_CLAUSE_NUM_TEAMS);
11620 if (num_teams == NULL_TREE)
11621 num_teams = build_int_cst (unsigned_type_node, 0);
11622 else
11624 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11625 num_teams = fold_convert (unsigned_type_node, num_teams);
11626 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11628 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11629 OMP_CLAUSE_THREAD_LIMIT);
11630 if (thread_limit == NULL_TREE)
11631 thread_limit = build_int_cst (unsigned_type_node, 0);
11632 else
11634 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11635 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11636 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11637 fb_rvalue);
11640 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11641 &bind_body, &dlist, ctx, NULL);
11642 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11643 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11644 gimple_seq_add_stmt (&bind_body, teams_stmt);
11646 location_t loc = gimple_location (teams_stmt);
11647 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11648 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11649 gimple_set_location (call, loc);
11650 gimple_seq_add_stmt (&bind_body, call);
11652 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11653 gimple_omp_set_body (teams_stmt, NULL);
11654 gimple_seq_add_seq (&bind_body, olist);
11655 gimple_seq_add_seq (&bind_body, dlist);
11656 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11657 gimple_bind_set_body (bind, bind_body);
11659 pop_gimplify_context (bind);
11661 gimple_bind_append_vars (bind, ctx->block_vars);
11662 BLOCK_VARS (block) = ctx->block_vars;
11663 if (BLOCK_VARS (block))
11664 TREE_USED (block) = 1;
11668 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11669 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11670 of OMP context, but with task_shared_vars set. */
11672 static tree
11673 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11674 void *data)
11676 tree t = *tp;
11678 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11679 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11680 return t;
11682 if (task_shared_vars
11683 && DECL_P (t)
11684 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11685 return t;
11687 /* If a global variable has been privatized, TREE_CONSTANT on
11688 ADDR_EXPR might be wrong. */
11689 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11690 recompute_tree_invariant_for_addr_expr (t);
11692 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11693 return NULL_TREE;
11696 static void
11697 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11699 gimple stmt = gsi_stmt (*gsi_p);
11700 struct walk_stmt_info wi;
11701 gcall *call_stmt;
11703 if (gimple_has_location (stmt))
11704 input_location = gimple_location (stmt);
11706 if (task_shared_vars)
11707 memset (&wi, '\0', sizeof (wi));
11709 /* If we have issued syntax errors, avoid doing any heavy lifting.
11710 Just replace the OMP directives with a NOP to avoid
11711 confusing RTL expansion. */
11712 if (seen_error () && is_gimple_omp (stmt))
11714 gsi_replace (gsi_p, gimple_build_nop (), true);
11715 return;
11718 switch (gimple_code (stmt))
11720 case GIMPLE_COND:
11722 gcond *cond_stmt = as_a <gcond *> (stmt);
11723 if ((ctx || task_shared_vars)
11724 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11725 lower_omp_regimplify_p,
11726 ctx ? NULL : &wi, NULL)
11727 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11728 lower_omp_regimplify_p,
11729 ctx ? NULL : &wi, NULL)))
11730 gimple_regimplify_operands (cond_stmt, gsi_p);
11732 break;
11733 case GIMPLE_CATCH:
11734 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
11735 break;
11736 case GIMPLE_EH_FILTER:
11737 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
11738 break;
11739 case GIMPLE_TRY:
11740 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11741 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
11742 break;
11743 case GIMPLE_TRANSACTION:
11744 lower_omp (gimple_transaction_body_ptr (
11745 as_a <gtransaction *> (stmt)),
11746 ctx);
11747 break;
11748 case GIMPLE_BIND:
11749 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
11750 break;
11751 case GIMPLE_OMP_PARALLEL:
11752 case GIMPLE_OMP_TASK:
11753 ctx = maybe_lookup_ctx (stmt);
11754 gcc_assert (ctx);
11755 if (ctx->cancellable)
11756 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11757 lower_omp_taskreg (gsi_p, ctx);
11758 break;
11759 case GIMPLE_OMP_FOR:
11760 ctx = maybe_lookup_ctx (stmt);
11761 gcc_assert (ctx);
11762 if (ctx->cancellable)
11763 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11764 lower_omp_for (gsi_p, ctx);
11765 break;
11766 case GIMPLE_OMP_SECTIONS:
11767 ctx = maybe_lookup_ctx (stmt);
11768 gcc_assert (ctx);
11769 if (ctx->cancellable)
11770 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11771 lower_omp_sections (gsi_p, ctx);
11772 break;
11773 case GIMPLE_OMP_SINGLE:
11774 ctx = maybe_lookup_ctx (stmt);
11775 gcc_assert (ctx);
11776 lower_omp_single (gsi_p, ctx);
11777 break;
11778 case GIMPLE_OMP_MASTER:
11779 ctx = maybe_lookup_ctx (stmt);
11780 gcc_assert (ctx);
11781 lower_omp_master (gsi_p, ctx);
11782 break;
11783 case GIMPLE_OMP_TASKGROUP:
11784 ctx = maybe_lookup_ctx (stmt);
11785 gcc_assert (ctx);
11786 lower_omp_taskgroup (gsi_p, ctx);
11787 break;
11788 case GIMPLE_OMP_ORDERED:
11789 ctx = maybe_lookup_ctx (stmt);
11790 gcc_assert (ctx);
11791 lower_omp_ordered (gsi_p, ctx);
11792 break;
11793 case GIMPLE_OMP_CRITICAL:
11794 ctx = maybe_lookup_ctx (stmt);
11795 gcc_assert (ctx);
11796 lower_omp_critical (gsi_p, ctx);
11797 break;
11798 case GIMPLE_OMP_ATOMIC_LOAD:
11799 if ((ctx || task_shared_vars)
11800 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11801 as_a <gomp_atomic_load *> (stmt)),
11802 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11803 gimple_regimplify_operands (stmt, gsi_p);
11804 break;
11805 case GIMPLE_OMP_TARGET:
11806 ctx = maybe_lookup_ctx (stmt);
11807 gcc_assert (ctx);
11808 lower_omp_target (gsi_p, ctx);
11809 break;
11810 case GIMPLE_OMP_TEAMS:
11811 ctx = maybe_lookup_ctx (stmt);
11812 gcc_assert (ctx);
11813 lower_omp_teams (gsi_p, ctx);
11814 break;
11815 case GIMPLE_CALL:
11816 tree fndecl;
11817 call_stmt = as_a <gcall *> (stmt);
11818 fndecl = gimple_call_fndecl (call_stmt);
11819 if (fndecl
11820 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11821 switch (DECL_FUNCTION_CODE (fndecl))
11823 case BUILT_IN_GOMP_BARRIER:
11824 if (ctx == NULL)
11825 break;
11826 /* FALLTHRU */
11827 case BUILT_IN_GOMP_CANCEL:
11828 case BUILT_IN_GOMP_CANCELLATION_POINT:
11829 omp_context *cctx;
11830 cctx = ctx;
11831 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11832 cctx = cctx->outer;
11833 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
11834 if (!cctx->cancellable)
11836 if (DECL_FUNCTION_CODE (fndecl)
11837 == BUILT_IN_GOMP_CANCELLATION_POINT)
11839 stmt = gimple_build_nop ();
11840 gsi_replace (gsi_p, stmt, false);
11842 break;
11844 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11846 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
11847 gimple_call_set_fndecl (call_stmt, fndecl);
11848 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
11850 tree lhs;
11851 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
11852 gimple_call_set_lhs (call_stmt, lhs);
11853 tree fallthru_label;
11854 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11855 gimple g;
11856 g = gimple_build_label (fallthru_label);
11857 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11858 g = gimple_build_cond (NE_EXPR, lhs,
11859 fold_convert (TREE_TYPE (lhs),
11860 boolean_false_node),
11861 cctx->cancel_label, fallthru_label);
11862 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11863 break;
11864 default:
11865 break;
11867 /* FALLTHRU */
11868 default:
11869 if ((ctx || task_shared_vars)
11870 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11871 ctx ? NULL : &wi))
11873 /* Just remove clobbers, this should happen only if we have
11874 "privatized" local addressable variables in SIMD regions,
11875 the clobber isn't needed in that case and gimplifying address
11876 of the ARRAY_REF into a pointer and creating MEM_REF based
11877 clobber would create worse code than we get with the clobber
11878 dropped. */
11879 if (gimple_clobber_p (stmt))
11881 gsi_replace (gsi_p, gimple_build_nop (), true);
11882 break;
11884 gimple_regimplify_operands (stmt, gsi_p);
11886 break;
11890 static void
11891 lower_omp (gimple_seq *body, omp_context *ctx)
11893 location_t saved_location = input_location;
11894 gimple_stmt_iterator gsi;
11895 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11896 lower_omp_1 (&gsi, ctx);
11897 /* During gimplification, we haven't folded statments inside offloading
11898 regions (gimplify.c:maybe_fold_stmt); do that now. */
11899 if (target_nesting_level)
11900 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11901 fold_stmt (&gsi);
11902 input_location = saved_location;
11905 /* Main entry point. */
11907 static unsigned int
11908 execute_lower_omp (void)
11910 gimple_seq body;
11911 int i;
11912 omp_context *ctx;
11914 /* This pass always runs, to provide PROP_gimple_lomp.
11915 But often, there is nothing to do. */
11916 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11917 && flag_openmp_simd == 0)
11918 return 0;
11920 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11921 delete_omp_context);
11923 body = gimple_body (current_function_decl);
11924 scan_omp (&body, NULL);
11925 gcc_assert (taskreg_nesting_level == 0);
11926 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11927 finish_taskreg_scan (ctx);
11928 taskreg_contexts.release ();
11930 if (all_contexts->root)
11932 if (task_shared_vars)
11933 push_gimplify_context ();
11934 lower_omp (&body, NULL);
11935 if (task_shared_vars)
11936 pop_gimplify_context (NULL);
11939 if (all_contexts)
11941 splay_tree_delete (all_contexts);
11942 all_contexts = NULL;
11944 BITMAP_FREE (task_shared_vars);
11945 return 0;
11948 namespace {
11950 const pass_data pass_data_lower_omp =
11952 GIMPLE_PASS, /* type */
11953 "omplower", /* name */
11954 OPTGROUP_NONE, /* optinfo_flags */
11955 TV_NONE, /* tv_id */
11956 PROP_gimple_any, /* properties_required */
11957 PROP_gimple_lomp, /* properties_provided */
11958 0, /* properties_destroyed */
11959 0, /* todo_flags_start */
11960 0, /* todo_flags_finish */
11963 class pass_lower_omp : public gimple_opt_pass
11965 public:
11966 pass_lower_omp (gcc::context *ctxt)
11967 : gimple_opt_pass (pass_data_lower_omp, ctxt)
11970 /* opt_pass methods: */
11971 virtual unsigned int execute (function *) { return execute_lower_omp (); }
11973 }; // class pass_lower_omp
11975 } // anon namespace
11977 gimple_opt_pass *
11978 make_pass_lower_omp (gcc::context *ctxt)
11980 return new pass_lower_omp (ctxt);
11983 /* The following is a utility to diagnose structured block violations.
11984 It is not part of the "omplower" pass, as that's invoked too late. It
11985 should be invoked by the respective front ends after gimplification. */
11987 static splay_tree all_labels;
11989 /* Check for mismatched contexts and generate an error if needed. Return
11990 true if an error is detected. */
11992 static bool
11993 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
11994 gimple branch_ctx, gimple label_ctx)
11996 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
11997 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
11999 if (label_ctx == branch_ctx)
12000 return false;
12002 const char* kind = NULL;
12004 if (flag_cilkplus)
12006 if ((branch_ctx
12007 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12008 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12009 || (label_ctx
12010 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12011 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12012 kind = "Cilk Plus";
12014 if (flag_openacc)
12016 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
12017 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
12019 gcc_checking_assert (kind == NULL);
12020 kind = "OpenACC";
12023 if (kind == NULL)
12025 gcc_checking_assert (flag_openmp);
12026 kind = "OpenMP";
12030 Previously we kept track of the label's entire context in diagnose_sb_[12]
12031 so we could traverse it and issue a correct "exit" or "enter" error
12032 message upon a structured block violation.
12034 We built the context by building a list with tree_cons'ing, but there is
12035 no easy counterpart in gimple tuples. It seems like far too much work
12036 for issuing exit/enter error messages. If someone really misses the
12037 distinct error message... patches welcome.
12040 #if 0
12041 /* Try to avoid confusing the user by producing and error message
12042 with correct "exit" or "enter" verbiage. We prefer "exit"
12043 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12044 if (branch_ctx == NULL)
12045 exit_p = false;
12046 else
12048 while (label_ctx)
12050 if (TREE_VALUE (label_ctx) == branch_ctx)
12052 exit_p = false;
12053 break;
12055 label_ctx = TREE_CHAIN (label_ctx);
12059 if (exit_p)
12060 error ("invalid exit from %s structured block", kind);
12061 else
12062 error ("invalid entry to %s structured block", kind);
12063 #endif
12065 /* If it's obvious we have an invalid entry, be specific about the error. */
12066 if (branch_ctx == NULL)
12067 error ("invalid entry to %s structured block", kind);
12068 else
12070 /* Otherwise, be vague and lazy, but efficient. */
12071 error ("invalid branch to/from %s structured block", kind);
12074 gsi_replace (gsi_p, gimple_build_nop (), false);
12075 return true;
12078 /* Pass 1: Create a minimal tree of structured blocks, and record
12079 where each label is found. */
12081 static tree
12082 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12083 struct walk_stmt_info *wi)
12085 gimple context = (gimple) wi->info;
12086 gimple inner_context;
12087 gimple stmt = gsi_stmt (*gsi_p);
12089 *handled_ops_p = true;
12091 switch (gimple_code (stmt))
12093 WALK_SUBSTMTS;
12095 case GIMPLE_OMP_PARALLEL:
12096 case GIMPLE_OMP_TASK:
12097 case GIMPLE_OMP_SECTIONS:
12098 case GIMPLE_OMP_SINGLE:
12099 case GIMPLE_OMP_SECTION:
12100 case GIMPLE_OMP_MASTER:
12101 case GIMPLE_OMP_ORDERED:
12102 case GIMPLE_OMP_CRITICAL:
12103 case GIMPLE_OMP_TARGET:
12104 case GIMPLE_OMP_TEAMS:
12105 case GIMPLE_OMP_TASKGROUP:
12106 /* The minimal context here is just the current OMP construct. */
12107 inner_context = stmt;
12108 wi->info = inner_context;
12109 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12110 wi->info = context;
12111 break;
12113 case GIMPLE_OMP_FOR:
12114 inner_context = stmt;
12115 wi->info = inner_context;
12116 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12117 walk them. */
12118 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12119 diagnose_sb_1, NULL, wi);
12120 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12121 wi->info = context;
12122 break;
12124 case GIMPLE_LABEL:
12125 splay_tree_insert (all_labels,
12126 (splay_tree_key) gimple_label_label (
12127 as_a <glabel *> (stmt)),
12128 (splay_tree_value) context);
12129 break;
12131 default:
12132 break;
12135 return NULL_TREE;
12138 /* Pass 2: Check each branch and see if its context differs from that of
12139 the destination label's context. */
12141 static tree
12142 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12143 struct walk_stmt_info *wi)
12145 gimple context = (gimple) wi->info;
12146 splay_tree_node n;
12147 gimple stmt = gsi_stmt (*gsi_p);
12149 *handled_ops_p = true;
12151 switch (gimple_code (stmt))
12153 WALK_SUBSTMTS;
12155 case GIMPLE_OMP_PARALLEL:
12156 case GIMPLE_OMP_TASK:
12157 case GIMPLE_OMP_SECTIONS:
12158 case GIMPLE_OMP_SINGLE:
12159 case GIMPLE_OMP_SECTION:
12160 case GIMPLE_OMP_MASTER:
12161 case GIMPLE_OMP_ORDERED:
12162 case GIMPLE_OMP_CRITICAL:
12163 case GIMPLE_OMP_TARGET:
12164 case GIMPLE_OMP_TEAMS:
12165 case GIMPLE_OMP_TASKGROUP:
12166 wi->info = stmt;
12167 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12168 wi->info = context;
12169 break;
12171 case GIMPLE_OMP_FOR:
12172 wi->info = stmt;
12173 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12174 walk them. */
12175 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12176 diagnose_sb_2, NULL, wi);
12177 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12178 wi->info = context;
12179 break;
12181 case GIMPLE_COND:
12183 gcond *cond_stmt = as_a <gcond *> (stmt);
12184 tree lab = gimple_cond_true_label (cond_stmt);
12185 if (lab)
12187 n = splay_tree_lookup (all_labels,
12188 (splay_tree_key) lab);
12189 diagnose_sb_0 (gsi_p, context,
12190 n ? (gimple) n->value : NULL);
12192 lab = gimple_cond_false_label (cond_stmt);
12193 if (lab)
12195 n = splay_tree_lookup (all_labels,
12196 (splay_tree_key) lab);
12197 diagnose_sb_0 (gsi_p, context,
12198 n ? (gimple) n->value : NULL);
12201 break;
12203 case GIMPLE_GOTO:
12205 tree lab = gimple_goto_dest (stmt);
12206 if (TREE_CODE (lab) != LABEL_DECL)
12207 break;
12209 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12210 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
12212 break;
12214 case GIMPLE_SWITCH:
12216 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12217 unsigned int i;
12218 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12220 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12221 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12222 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
12223 break;
12226 break;
12228 case GIMPLE_RETURN:
12229 diagnose_sb_0 (gsi_p, context, NULL);
12230 break;
12232 default:
12233 break;
12236 return NULL_TREE;
12239 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12240 GIMPLE_* codes. */
12241 bool
12242 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12243 int *region_idx)
12245 gimple last = last_stmt (bb);
12246 enum gimple_code code = gimple_code (last);
12247 struct omp_region *cur_region = *region;
12248 bool fallthru = false;
12250 switch (code)
12252 case GIMPLE_OMP_PARALLEL:
12253 case GIMPLE_OMP_TASK:
12254 case GIMPLE_OMP_FOR:
12255 case GIMPLE_OMP_SINGLE:
12256 case GIMPLE_OMP_TEAMS:
12257 case GIMPLE_OMP_MASTER:
12258 case GIMPLE_OMP_TASKGROUP:
12259 case GIMPLE_OMP_ORDERED:
12260 case GIMPLE_OMP_CRITICAL:
12261 case GIMPLE_OMP_SECTION:
12262 cur_region = new_omp_region (bb, code, cur_region);
12263 fallthru = true;
12264 break;
12266 case GIMPLE_OMP_TARGET:
12267 cur_region = new_omp_region (bb, code, cur_region);
12268 fallthru = true;
12269 switch (gimple_omp_target_kind (last))
12271 case GF_OMP_TARGET_KIND_REGION:
12272 case GF_OMP_TARGET_KIND_DATA:
12273 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12274 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12275 case GF_OMP_TARGET_KIND_OACC_DATA:
12276 break;
12277 case GF_OMP_TARGET_KIND_UPDATE:
12278 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12279 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12280 cur_region = cur_region->outer;
12281 break;
12282 default:
12283 gcc_unreachable ();
12285 break;
12287 case GIMPLE_OMP_SECTIONS:
12288 cur_region = new_omp_region (bb, code, cur_region);
12289 fallthru = true;
12290 break;
12292 case GIMPLE_OMP_SECTIONS_SWITCH:
12293 fallthru = false;
12294 break;
12296 case GIMPLE_OMP_ATOMIC_LOAD:
12297 case GIMPLE_OMP_ATOMIC_STORE:
12298 fallthru = true;
12299 break;
12301 case GIMPLE_OMP_RETURN:
12302 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12303 somewhere other than the next block. This will be
12304 created later. */
12305 cur_region->exit = bb;
12306 if (cur_region->type == GIMPLE_OMP_TASK)
12307 /* Add an edge corresponding to not scheduling the task
12308 immediately. */
12309 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
12310 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12311 cur_region = cur_region->outer;
12312 break;
12314 case GIMPLE_OMP_CONTINUE:
12315 cur_region->cont = bb;
12316 switch (cur_region->type)
12318 case GIMPLE_OMP_FOR:
12319 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12320 succs edges as abnormal to prevent splitting
12321 them. */
12322 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12323 /* Make the loopback edge. */
12324 make_edge (bb, single_succ (cur_region->entry),
12325 EDGE_ABNORMAL);
12327 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12328 corresponds to the case that the body of the loop
12329 is not executed at all. */
12330 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12331 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12332 fallthru = false;
12333 break;
12335 case GIMPLE_OMP_SECTIONS:
12336 /* Wire up the edges into and out of the nested sections. */
12338 basic_block switch_bb = single_succ (cur_region->entry);
12340 struct omp_region *i;
12341 for (i = cur_region->inner; i ; i = i->next)
12343 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12344 make_edge (switch_bb, i->entry, 0);
12345 make_edge (i->exit, bb, EDGE_FALLTHRU);
12348 /* Make the loopback edge to the block with
12349 GIMPLE_OMP_SECTIONS_SWITCH. */
12350 make_edge (bb, switch_bb, 0);
12352 /* Make the edge from the switch to exit. */
12353 make_edge (switch_bb, bb->next_bb, 0);
12354 fallthru = false;
12356 break;
12358 case GIMPLE_OMP_TASK:
12359 fallthru = true;
12360 break;
12362 default:
12363 gcc_unreachable ();
12365 break;
12367 default:
12368 gcc_unreachable ();
12371 if (*region != cur_region)
12373 *region = cur_region;
12374 if (cur_region)
12375 *region_idx = cur_region->entry->index;
12376 else
12377 *region_idx = 0;
12380 return fallthru;
12383 static unsigned int
12384 diagnose_omp_structured_block_errors (void)
12386 struct walk_stmt_info wi;
12387 gimple_seq body = gimple_body (current_function_decl);
12389 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12391 memset (&wi, 0, sizeof (wi));
12392 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12394 memset (&wi, 0, sizeof (wi));
12395 wi.want_locations = true;
12396 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12398 gimple_set_body (current_function_decl, body);
12400 splay_tree_delete (all_labels);
12401 all_labels = NULL;
12403 return 0;
12406 namespace {
12408 const pass_data pass_data_diagnose_omp_blocks =
12410 GIMPLE_PASS, /* type */
12411 "*diagnose_omp_blocks", /* name */
12412 OPTGROUP_NONE, /* optinfo_flags */
12413 TV_NONE, /* tv_id */
12414 PROP_gimple_any, /* properties_required */
12415 0, /* properties_provided */
12416 0, /* properties_destroyed */
12417 0, /* todo_flags_start */
12418 0, /* todo_flags_finish */
12421 class pass_diagnose_omp_blocks : public gimple_opt_pass
12423 public:
12424 pass_diagnose_omp_blocks (gcc::context *ctxt)
12425 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12428 /* opt_pass methods: */
12429 virtual bool gate (function *)
12431 return flag_cilkplus || flag_openacc || flag_openmp;
12433 virtual unsigned int execute (function *)
12435 return diagnose_omp_structured_block_errors ();
12438 }; // class pass_diagnose_omp_blocks
12440 } // anon namespace
12442 gimple_opt_pass *
12443 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12445 return new pass_diagnose_omp_blocks (ctxt);
12448 /* SIMD clone supporting code. */
12450 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12451 of arguments to reserve space for. */
12453 static struct cgraph_simd_clone *
12454 simd_clone_struct_alloc (int nargs)
12456 struct cgraph_simd_clone *clone_info;
12457 size_t len = (sizeof (struct cgraph_simd_clone)
12458 + nargs * sizeof (struct cgraph_simd_clone_arg));
12459 clone_info = (struct cgraph_simd_clone *)
12460 ggc_internal_cleared_alloc (len);
12461 return clone_info;
12464 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12466 static inline void
12467 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12468 struct cgraph_simd_clone *from)
12470 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12471 + ((from->nargs - from->inbranch)
12472 * sizeof (struct cgraph_simd_clone_arg))));
12475 /* Return vector of parameter types of function FNDECL. This uses
12476 TYPE_ARG_TYPES if available, otherwise falls back to types of
12477 DECL_ARGUMENTS types. */
12479 vec<tree>
12480 simd_clone_vector_of_formal_parm_types (tree fndecl)
12482 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12483 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12484 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12485 unsigned int i;
12486 tree arg;
12487 FOR_EACH_VEC_ELT (args, i, arg)
12488 args[i] = TREE_TYPE (args[i]);
12489 return args;
12492 /* Given a simd function in NODE, extract the simd specific
12493 information from the OMP clauses passed in CLAUSES, and return
12494 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12495 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12496 otherwise set to FALSE. */
12498 static struct cgraph_simd_clone *
12499 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12500 bool *inbranch_specified)
12502 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12503 tree t;
12504 int n;
12505 *inbranch_specified = false;
12507 n = args.length ();
12508 if (n > 0 && args.last () == void_type_node)
12509 n--;
12511 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12512 be cloned have a distinctive artificial label in addition to "omp
12513 declare simd". */
12514 bool cilk_clone
12515 = (flag_cilkplus
12516 && lookup_attribute ("cilk simd function",
12517 DECL_ATTRIBUTES (node->decl)));
12519 /* Allocate one more than needed just in case this is an in-branch
12520 clone which will require a mask argument. */
12521 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12522 clone_info->nargs = n;
12523 clone_info->cilk_elemental = cilk_clone;
12525 if (!clauses)
12527 args.release ();
12528 return clone_info;
12530 clauses = TREE_VALUE (clauses);
12531 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12532 return clone_info;
12534 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12536 switch (OMP_CLAUSE_CODE (t))
12538 case OMP_CLAUSE_INBRANCH:
12539 clone_info->inbranch = 1;
12540 *inbranch_specified = true;
12541 break;
12542 case OMP_CLAUSE_NOTINBRANCH:
12543 clone_info->inbranch = 0;
12544 *inbranch_specified = true;
12545 break;
12546 case OMP_CLAUSE_SIMDLEN:
12547 clone_info->simdlen
12548 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12549 break;
12550 case OMP_CLAUSE_LINEAR:
12552 tree decl = OMP_CLAUSE_DECL (t);
12553 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12554 int argno = TREE_INT_CST_LOW (decl);
12555 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12557 clone_info->args[argno].arg_type
12558 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12559 clone_info->args[argno].linear_step = tree_to_shwi (step);
12560 gcc_assert (clone_info->args[argno].linear_step >= 0
12561 && clone_info->args[argno].linear_step < n);
12563 else
12565 if (POINTER_TYPE_P (args[argno]))
12566 step = fold_convert (ssizetype, step);
12567 if (!tree_fits_shwi_p (step))
12569 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12570 "ignoring large linear step");
12571 args.release ();
12572 return NULL;
12574 else if (integer_zerop (step))
12576 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12577 "ignoring zero linear step");
12578 args.release ();
12579 return NULL;
12581 else
12583 clone_info->args[argno].arg_type
12584 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12585 clone_info->args[argno].linear_step = tree_to_shwi (step);
12588 break;
12590 case OMP_CLAUSE_UNIFORM:
12592 tree decl = OMP_CLAUSE_DECL (t);
12593 int argno = tree_to_uhwi (decl);
12594 clone_info->args[argno].arg_type
12595 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12596 break;
12598 case OMP_CLAUSE_ALIGNED:
12600 tree decl = OMP_CLAUSE_DECL (t);
12601 int argno = tree_to_uhwi (decl);
12602 clone_info->args[argno].alignment
12603 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12604 break;
12606 default:
12607 break;
12610 args.release ();
12611 return clone_info;
12614 /* Given a SIMD clone in NODE, calculate the characteristic data
12615 type and return the coresponding type. The characteristic data
12616 type is computed as described in the Intel Vector ABI. */
12618 static tree
12619 simd_clone_compute_base_data_type (struct cgraph_node *node,
12620 struct cgraph_simd_clone *clone_info)
12622 tree type = integer_type_node;
12623 tree fndecl = node->decl;
12625 /* a) For non-void function, the characteristic data type is the
12626 return type. */
12627 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12628 type = TREE_TYPE (TREE_TYPE (fndecl));
12630 /* b) If the function has any non-uniform, non-linear parameters,
12631 then the characteristic data type is the type of the first
12632 such parameter. */
12633 else
12635 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12636 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12637 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12639 type = map[i];
12640 break;
12642 map.release ();
12645 /* c) If the characteristic data type determined by a) or b) above
12646 is struct, union, or class type which is pass-by-value (except
12647 for the type that maps to the built-in complex data type), the
12648 characteristic data type is int. */
12649 if (RECORD_OR_UNION_TYPE_P (type)
12650 && !aggregate_value_p (type, NULL)
12651 && TREE_CODE (type) != COMPLEX_TYPE)
12652 return integer_type_node;
12654 /* d) If none of the above three classes is applicable, the
12655 characteristic data type is int. */
12657 return type;
12659 /* e) For Intel Xeon Phi native and offload compilation, if the
12660 resulting characteristic data type is 8-bit or 16-bit integer
12661 data type, the characteristic data type is int. */
12662 /* Well, we don't handle Xeon Phi yet. */
12665 static tree
12666 simd_clone_mangle (struct cgraph_node *node,
12667 struct cgraph_simd_clone *clone_info)
12669 char vecsize_mangle = clone_info->vecsize_mangle;
12670 char mask = clone_info->inbranch ? 'M' : 'N';
12671 unsigned int simdlen = clone_info->simdlen;
12672 unsigned int n;
12673 pretty_printer pp;
12675 gcc_assert (vecsize_mangle && simdlen);
12677 pp_string (&pp, "_ZGV");
12678 pp_character (&pp, vecsize_mangle);
12679 pp_character (&pp, mask);
12680 pp_decimal_int (&pp, simdlen);
12682 for (n = 0; n < clone_info->nargs; ++n)
12684 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12686 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12687 pp_character (&pp, 'u');
12688 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12690 gcc_assert (arg.linear_step != 0);
12691 pp_character (&pp, 'l');
12692 if (arg.linear_step > 1)
12693 pp_unsigned_wide_integer (&pp, arg.linear_step);
12694 else if (arg.linear_step < 0)
12696 pp_character (&pp, 'n');
12697 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12698 arg.linear_step));
12701 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12703 pp_character (&pp, 's');
12704 pp_unsigned_wide_integer (&pp, arg.linear_step);
12706 else
12707 pp_character (&pp, 'v');
12708 if (arg.alignment)
12710 pp_character (&pp, 'a');
12711 pp_decimal_int (&pp, arg.alignment);
12715 pp_underscore (&pp);
12716 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12717 if (*str == '*')
12718 ++str;
12719 pp_string (&pp, str);
12720 str = pp_formatted_text (&pp);
12722 /* If there already is a SIMD clone with the same mangled name, don't
12723 add another one. This can happen e.g. for
12724 #pragma omp declare simd
12725 #pragma omp declare simd simdlen(8)
12726 int foo (int, int);
12727 if the simdlen is assumed to be 8 for the first one, etc. */
12728 for (struct cgraph_node *clone = node->simd_clones; clone;
12729 clone = clone->simdclone->next_clone)
12730 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12731 str) == 0)
12732 return NULL_TREE;
12734 return get_identifier (str);
12737 /* Create a simd clone of OLD_NODE and return it. */
12739 static struct cgraph_node *
12740 simd_clone_create (struct cgraph_node *old_node)
12742 struct cgraph_node *new_node;
12743 if (old_node->definition)
12745 if (!old_node->has_gimple_body_p ())
12746 return NULL;
12747 old_node->get_body ();
12748 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12749 false, NULL, NULL,
12750 "simdclone");
12752 else
12754 tree old_decl = old_node->decl;
12755 tree new_decl = copy_node (old_node->decl);
12756 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12757 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12758 SET_DECL_RTL (new_decl, NULL);
12759 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12760 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
12761 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
12762 symtab->call_cgraph_insertion_hooks (new_node);
12764 if (new_node == NULL)
12765 return new_node;
12767 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12769 /* The function cgraph_function_versioning () will force the new
12770 symbol local. Undo this, and inherit external visability from
12771 the old node. */
12772 new_node->local.local = old_node->local.local;
12773 new_node->externally_visible = old_node->externally_visible;
12775 return new_node;
12778 /* Adjust the return type of the given function to its appropriate
12779 vector counterpart. Returns a simd array to be used throughout the
12780 function as a return value. */
12782 static tree
12783 simd_clone_adjust_return_type (struct cgraph_node *node)
12785 tree fndecl = node->decl;
12786 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12787 unsigned int veclen;
12788 tree t;
12790 /* Adjust the function return type. */
12791 if (orig_rettype == void_type_node)
12792 return NULL_TREE;
12793 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
12794 t = TREE_TYPE (TREE_TYPE (fndecl));
12795 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
12796 veclen = node->simdclone->vecsize_int;
12797 else
12798 veclen = node->simdclone->vecsize_float;
12799 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
12800 if (veclen > node->simdclone->simdlen)
12801 veclen = node->simdclone->simdlen;
12802 if (POINTER_TYPE_P (t))
12803 t = pointer_sized_int_node;
12804 if (veclen == node->simdclone->simdlen)
12805 t = build_vector_type (t, node->simdclone->simdlen);
12806 else
12808 t = build_vector_type (t, veclen);
12809 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
12811 TREE_TYPE (TREE_TYPE (fndecl)) = t;
12812 if (!node->definition)
12813 return NULL_TREE;
12815 t = DECL_RESULT (fndecl);
12816 /* Adjust the DECL_RESULT. */
12817 gcc_assert (TREE_TYPE (t) != void_type_node);
12818 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12819 relayout_decl (t);
12821 tree atype = build_array_type_nelts (orig_rettype,
12822 node->simdclone->simdlen);
12823 if (veclen != node->simdclone->simdlen)
12824 return build1 (VIEW_CONVERT_EXPR, atype, t);
12826 /* Set up a SIMD array to use as the return value. */
12827 tree retval = create_tmp_var_raw (atype, "retval");
12828 gimple_add_tmp_var (retval);
12829 return retval;
12832 /* Each vector argument has a corresponding array to be used locally
12833 as part of the eventual loop. Create such temporary array and
12834 return it.
12836 PREFIX is the prefix to be used for the temporary.
12838 TYPE is the inner element type.
12840 SIMDLEN is the number of elements. */
12842 static tree
12843 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12845 tree atype = build_array_type_nelts (type, simdlen);
12846 tree avar = create_tmp_var_raw (atype, prefix);
12847 gimple_add_tmp_var (avar);
12848 return avar;
12851 /* Modify the function argument types to their corresponding vector
12852 counterparts if appropriate. Also, create one array for each simd
12853 argument to be used locally when using the function arguments as
12854 part of the loop.
12856 NODE is the function whose arguments are to be adjusted.
12858 Returns an adjustment vector that will be filled describing how the
12859 argument types will be adjusted. */
12861 static ipa_parm_adjustment_vec
12862 simd_clone_adjust_argument_types (struct cgraph_node *node)
12864 vec<tree> args;
12865 ipa_parm_adjustment_vec adjustments;
12867 if (node->definition)
12868 args = ipa_get_vector_of_formal_parms (node->decl);
12869 else
12870 args = simd_clone_vector_of_formal_parm_types (node->decl);
12871 adjustments.create (args.length ());
12872 unsigned i, j, veclen;
12873 struct ipa_parm_adjustment adj;
12874 for (i = 0; i < node->simdclone->nargs; ++i)
12876 memset (&adj, 0, sizeof (adj));
12877 tree parm = args[i];
12878 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12879 adj.base_index = i;
12880 adj.base = parm;
12882 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12883 node->simdclone->args[i].orig_type = parm_type;
12885 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12887 /* No adjustment necessary for scalar arguments. */
12888 adj.op = IPA_PARM_OP_COPY;
12890 else
12892 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12893 veclen = node->simdclone->vecsize_int;
12894 else
12895 veclen = node->simdclone->vecsize_float;
12896 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12897 if (veclen > node->simdclone->simdlen)
12898 veclen = node->simdclone->simdlen;
12899 adj.arg_prefix = "simd";
12900 if (POINTER_TYPE_P (parm_type))
12901 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12902 else
12903 adj.type = build_vector_type (parm_type, veclen);
12904 node->simdclone->args[i].vector_type = adj.type;
12905 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12907 adjustments.safe_push (adj);
12908 if (j == veclen)
12910 memset (&adj, 0, sizeof (adj));
12911 adj.op = IPA_PARM_OP_NEW;
12912 adj.arg_prefix = "simd";
12913 adj.base_index = i;
12914 adj.type = node->simdclone->args[i].vector_type;
12918 if (node->definition)
12919 node->simdclone->args[i].simd_array
12920 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12921 parm_type, node->simdclone->simdlen);
12923 adjustments.safe_push (adj);
12926 if (node->simdclone->inbranch)
12928 tree base_type
12929 = simd_clone_compute_base_data_type (node->simdclone->origin,
12930 node->simdclone);
12932 memset (&adj, 0, sizeof (adj));
12933 adj.op = IPA_PARM_OP_NEW;
12934 adj.arg_prefix = "mask";
12936 adj.base_index = i;
12937 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12938 veclen = node->simdclone->vecsize_int;
12939 else
12940 veclen = node->simdclone->vecsize_float;
12941 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12942 if (veclen > node->simdclone->simdlen)
12943 veclen = node->simdclone->simdlen;
12944 if (POINTER_TYPE_P (base_type))
12945 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12946 else
12947 adj.type = build_vector_type (base_type, veclen);
12948 adjustments.safe_push (adj);
12950 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12951 adjustments.safe_push (adj);
12953 /* We have previously allocated one extra entry for the mask. Use
12954 it and fill it. */
12955 struct cgraph_simd_clone *sc = node->simdclone;
12956 sc->nargs++;
12957 if (node->definition)
12959 sc->args[i].orig_arg
12960 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12961 sc->args[i].simd_array
12962 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12964 sc->args[i].orig_type = base_type;
12965 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12968 if (node->definition)
12969 ipa_modify_formal_parameters (node->decl, adjustments);
12970 else
12972 tree new_arg_types = NULL_TREE, new_reversed;
12973 bool last_parm_void = false;
12974 if (args.length () > 0 && args.last () == void_type_node)
12975 last_parm_void = true;
12977 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12978 j = adjustments.length ();
12979 for (i = 0; i < j; i++)
12981 struct ipa_parm_adjustment *adj = &adjustments[i];
12982 tree ptype;
12983 if (adj->op == IPA_PARM_OP_COPY)
12984 ptype = args[adj->base_index];
12985 else
12986 ptype = adj->type;
12987 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12989 new_reversed = nreverse (new_arg_types);
12990 if (last_parm_void)
12992 if (new_reversed)
12993 TREE_CHAIN (new_arg_types) = void_list_node;
12994 else
12995 new_reversed = void_list_node;
12998 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
12999 TYPE_ARG_TYPES (new_type) = new_reversed;
13000 TREE_TYPE (node->decl) = new_type;
13002 adjustments.release ();
13004 args.release ();
13005 return adjustments;
13008 /* Initialize and copy the function arguments in NODE to their
13009 corresponding local simd arrays. Returns a fresh gimple_seq with
13010 the instruction sequence generated. */
13012 static gimple_seq
13013 simd_clone_init_simd_arrays (struct cgraph_node *node,
13014 ipa_parm_adjustment_vec adjustments)
13016 gimple_seq seq = NULL;
13017 unsigned i = 0, j = 0, k;
13019 for (tree arg = DECL_ARGUMENTS (node->decl);
13020 arg;
13021 arg = DECL_CHAIN (arg), i++, j++)
13023 if (adjustments[j].op == IPA_PARM_OP_COPY)
13024 continue;
13026 node->simdclone->args[i].vector_arg = arg;
13028 tree array = node->simdclone->args[i].simd_array;
13029 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13031 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13032 tree ptr = build_fold_addr_expr (array);
13033 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13034 build_int_cst (ptype, 0));
13035 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13036 gimplify_and_add (t, &seq);
13038 else
13040 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13041 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13042 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13044 tree ptr = build_fold_addr_expr (array);
13045 int elemsize;
13046 if (k)
13048 arg = DECL_CHAIN (arg);
13049 j++;
13051 elemsize
13052 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13053 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13054 build_int_cst (ptype, k * elemsize));
13055 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13056 gimplify_and_add (t, &seq);
13060 return seq;
13063 /* Callback info for ipa_simd_modify_stmt_ops below. */
13065 struct modify_stmt_info {
13066 ipa_parm_adjustment_vec adjustments;
13067 gimple stmt;
13068 /* True if the parent statement was modified by
13069 ipa_simd_modify_stmt_ops. */
13070 bool modified;
13073 /* Callback for walk_gimple_op.
13075 Adjust operands from a given statement as specified in the
13076 adjustments vector in the callback data. */
13078 static tree
13079 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13081 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13082 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13083 tree *orig_tp = tp;
13084 if (TREE_CODE (*tp) == ADDR_EXPR)
13085 tp = &TREE_OPERAND (*tp, 0);
13086 struct ipa_parm_adjustment *cand = NULL;
13087 if (TREE_CODE (*tp) == PARM_DECL)
13088 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13089 else
13091 if (TYPE_P (*tp))
13092 *walk_subtrees = 0;
13095 tree repl = NULL_TREE;
13096 if (cand)
13097 repl = unshare_expr (cand->new_decl);
13098 else
13100 if (tp != orig_tp)
13102 *walk_subtrees = 0;
13103 bool modified = info->modified;
13104 info->modified = false;
13105 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13106 if (!info->modified)
13108 info->modified = modified;
13109 return NULL_TREE;
13111 info->modified = modified;
13112 repl = *tp;
13114 else
13115 return NULL_TREE;
13118 if (tp != orig_tp)
13120 repl = build_fold_addr_expr (repl);
13121 gimple stmt;
13122 if (is_gimple_debug (info->stmt))
13124 tree vexpr = make_node (DEBUG_EXPR_DECL);
13125 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13126 DECL_ARTIFICIAL (vexpr) = 1;
13127 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13128 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13129 repl = vexpr;
13131 else
13133 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13134 repl = gimple_assign_lhs (stmt);
13136 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13137 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13138 *orig_tp = repl;
13140 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13142 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13143 *tp = vce;
13145 else
13146 *tp = repl;
13148 info->modified = true;
13149 return NULL_TREE;
13152 /* Traverse the function body and perform all modifications as
13153 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13154 modified such that the replacement/reduction value will now be an
13155 offset into the corresponding simd_array.
13157 This function will replace all function argument uses with their
13158 corresponding simd array elements, and ajust the return values
13159 accordingly. */
13161 static void
13162 ipa_simd_modify_function_body (struct cgraph_node *node,
13163 ipa_parm_adjustment_vec adjustments,
13164 tree retval_array, tree iter)
13166 basic_block bb;
13167 unsigned int i, j, l;
13169 /* Re-use the adjustments array, but this time use it to replace
13170 every function argument use to an offset into the corresponding
13171 simd_array. */
13172 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13174 if (!node->simdclone->args[i].vector_arg)
13175 continue;
13177 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13178 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13179 adjustments[j].new_decl
13180 = build4 (ARRAY_REF,
13181 basetype,
13182 node->simdclone->args[i].simd_array,
13183 iter,
13184 NULL_TREE, NULL_TREE);
13185 if (adjustments[j].op == IPA_PARM_OP_NONE
13186 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13187 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13190 l = adjustments.length ();
13191 for (i = 1; i < num_ssa_names; i++)
13193 tree name = ssa_name (i);
13194 if (name
13195 && SSA_NAME_VAR (name)
13196 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13198 for (j = 0; j < l; j++)
13199 if (SSA_NAME_VAR (name) == adjustments[j].base
13200 && adjustments[j].new_decl)
13202 tree base_var;
13203 if (adjustments[j].new_ssa_base == NULL_TREE)
13205 base_var
13206 = copy_var_decl (adjustments[j].base,
13207 DECL_NAME (adjustments[j].base),
13208 TREE_TYPE (adjustments[j].base));
13209 adjustments[j].new_ssa_base = base_var;
13211 else
13212 base_var = adjustments[j].new_ssa_base;
13213 if (SSA_NAME_IS_DEFAULT_DEF (name))
13215 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13216 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13217 tree new_decl = unshare_expr (adjustments[j].new_decl);
13218 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13219 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13220 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13221 gimple stmt = gimple_build_assign (name, new_decl);
13222 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13224 else
13225 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13230 struct modify_stmt_info info;
13231 info.adjustments = adjustments;
13233 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13235 gimple_stmt_iterator gsi;
13237 gsi = gsi_start_bb (bb);
13238 while (!gsi_end_p (gsi))
13240 gimple stmt = gsi_stmt (gsi);
13241 info.stmt = stmt;
13242 struct walk_stmt_info wi;
13244 memset (&wi, 0, sizeof (wi));
13245 info.modified = false;
13246 wi.info = &info;
13247 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13249 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13251 tree retval = gimple_return_retval (return_stmt);
13252 if (!retval)
13254 gsi_remove (&gsi, true);
13255 continue;
13258 /* Replace `return foo' with `retval_array[iter] = foo'. */
13259 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13260 retval_array, iter, NULL, NULL);
13261 stmt = gimple_build_assign (ref, retval);
13262 gsi_replace (&gsi, stmt, true);
13263 info.modified = true;
13266 if (info.modified)
13268 update_stmt (stmt);
13269 if (maybe_clean_eh_stmt (stmt))
13270 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13272 gsi_next (&gsi);
13277 /* Adjust the argument types in NODE to their appropriate vector
13278 counterparts. */
13280 static void
13281 simd_clone_adjust (struct cgraph_node *node)
13283 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13285 targetm.simd_clone.adjust (node);
13287 tree retval = simd_clone_adjust_return_type (node);
13288 ipa_parm_adjustment_vec adjustments
13289 = simd_clone_adjust_argument_types (node);
13291 push_gimplify_context ();
13293 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13295 /* Adjust all uses of vector arguments accordingly. Adjust all
13296 return values accordingly. */
13297 tree iter = create_tmp_var (unsigned_type_node, "iter");
13298 tree iter1 = make_ssa_name (iter);
13299 tree iter2 = make_ssa_name (iter);
13300 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13302 /* Initialize the iteration variable. */
13303 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13304 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13305 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13306 /* Insert the SIMD array and iv initialization at function
13307 entry. */
13308 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13310 pop_gimplify_context (NULL);
13312 /* Create a new BB right before the original exit BB, to hold the
13313 iteration increment and the condition/branch. */
13314 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13315 basic_block incr_bb = create_empty_bb (orig_exit);
13316 add_bb_to_loop (incr_bb, body_bb->loop_father);
13317 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13318 flag. Set it now to be a FALLTHRU_EDGE. */
13319 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13320 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13321 for (unsigned i = 0;
13322 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13324 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13325 redirect_edge_succ (e, incr_bb);
13327 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13328 e->probability = REG_BR_PROB_BASE;
13329 gsi = gsi_last_bb (incr_bb);
13330 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13331 build_int_cst (unsigned_type_node, 1));
13332 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13334 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13335 struct loop *loop = alloc_loop ();
13336 cfun->has_force_vectorize_loops = true;
13337 loop->safelen = node->simdclone->simdlen;
13338 loop->force_vectorize = true;
13339 loop->header = body_bb;
13341 /* Branch around the body if the mask applies. */
13342 if (node->simdclone->inbranch)
13344 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13345 tree mask_array
13346 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13347 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13348 tree aref = build4 (ARRAY_REF,
13349 TREE_TYPE (TREE_TYPE (mask_array)),
13350 mask_array, iter1,
13351 NULL, NULL);
13352 g = gimple_build_assign (mask, aref);
13353 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13354 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13355 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13357 aref = build1 (VIEW_CONVERT_EXPR,
13358 build_nonstandard_integer_type (bitsize, 0), mask);
13359 mask = make_ssa_name (TREE_TYPE (aref));
13360 g = gimple_build_assign (mask, aref);
13361 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13364 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13365 NULL, NULL);
13366 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13367 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13368 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13371 /* Generate the condition. */
13372 g = gimple_build_cond (LT_EXPR,
13373 iter2,
13374 build_int_cst (unsigned_type_node,
13375 node->simdclone->simdlen),
13376 NULL, NULL);
13377 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13378 e = split_block (incr_bb, gsi_stmt (gsi));
13379 basic_block latch_bb = e->dest;
13380 basic_block new_exit_bb;
13381 new_exit_bb = split_block_after_labels (latch_bb)->dest;
13382 loop->latch = latch_bb;
13384 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13386 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13387 /* The successor of incr_bb is already pointing to latch_bb; just
13388 change the flags.
13389 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13390 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13392 gphi *phi = create_phi_node (iter1, body_bb);
13393 edge preheader_edge = find_edge (entry_bb, body_bb);
13394 edge latch_edge = single_succ_edge (latch_bb);
13395 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13396 UNKNOWN_LOCATION);
13397 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13399 /* Generate the new return. */
13400 gsi = gsi_last_bb (new_exit_bb);
13401 if (retval
13402 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13403 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13404 retval = TREE_OPERAND (retval, 0);
13405 else if (retval)
13407 retval = build1 (VIEW_CONVERT_EXPR,
13408 TREE_TYPE (TREE_TYPE (node->decl)),
13409 retval);
13410 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13411 false, GSI_CONTINUE_LINKING);
13413 g = gimple_build_return (retval);
13414 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13416 /* Handle aligned clauses by replacing default defs of the aligned
13417 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13418 lhs. Handle linear by adding PHIs. */
13419 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13420 if (node->simdclone->args[i].alignment
13421 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13422 && (node->simdclone->args[i].alignment
13423 & (node->simdclone->args[i].alignment - 1)) == 0
13424 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13425 == POINTER_TYPE)
13427 unsigned int alignment = node->simdclone->args[i].alignment;
13428 tree orig_arg = node->simdclone->args[i].orig_arg;
13429 tree def = ssa_default_def (cfun, orig_arg);
13430 if (def && !has_zero_uses (def))
13432 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13433 gimple_seq seq = NULL;
13434 bool need_cvt = false;
13435 gcall *call
13436 = gimple_build_call (fn, 2, def, size_int (alignment));
13437 g = call;
13438 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13439 ptr_type_node))
13440 need_cvt = true;
13441 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13442 gimple_call_set_lhs (g, t);
13443 gimple_seq_add_stmt_without_update (&seq, g);
13444 if (need_cvt)
13446 t = make_ssa_name (orig_arg);
13447 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13448 gimple_seq_add_stmt_without_update (&seq, g);
13450 gsi_insert_seq_on_edge_immediate
13451 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13453 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13454 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13455 entry_bb);
13456 node->create_edge (cgraph_node::get_create (fn),
13457 call, entry_bb->count, freq);
13459 imm_use_iterator iter;
13460 use_operand_p use_p;
13461 gimple use_stmt;
13462 tree repl = gimple_get_lhs (g);
13463 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13464 if (is_gimple_debug (use_stmt) || use_stmt == call)
13465 continue;
13466 else
13467 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13468 SET_USE (use_p, repl);
13471 else if (node->simdclone->args[i].arg_type
13472 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13474 tree orig_arg = node->simdclone->args[i].orig_arg;
13475 tree def = ssa_default_def (cfun, orig_arg);
13476 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13477 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13478 if (def && !has_zero_uses (def))
13480 iter1 = make_ssa_name (orig_arg);
13481 iter2 = make_ssa_name (orig_arg);
13482 phi = create_phi_node (iter1, body_bb);
13483 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13484 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13485 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13486 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13487 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13488 ? TREE_TYPE (orig_arg) : sizetype;
13489 tree addcst
13490 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13491 g = gimple_build_assign (iter2, code, iter1, addcst);
13492 gsi = gsi_last_bb (incr_bb);
13493 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13495 imm_use_iterator iter;
13496 use_operand_p use_p;
13497 gimple use_stmt;
13498 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13499 if (use_stmt == phi)
13500 continue;
13501 else
13502 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13503 SET_USE (use_p, iter1);
13507 calculate_dominance_info (CDI_DOMINATORS);
13508 add_loop (loop, loop->header->loop_father);
13509 update_ssa (TODO_update_ssa);
13511 pop_cfun ();
13514 /* If the function in NODE is tagged as an elemental SIMD function,
13515 create the appropriate SIMD clones. */
13517 static void
13518 expand_simd_clones (struct cgraph_node *node)
13520 tree attr = lookup_attribute ("omp declare simd",
13521 DECL_ATTRIBUTES (node->decl));
13522 if (attr == NULL_TREE
13523 || node->global.inlined_to
13524 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13525 return;
13527 /* Ignore
13528 #pragma omp declare simd
13529 extern int foo ();
13530 in C, there we don't know the argument types at all. */
13531 if (!node->definition
13532 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13533 return;
13537 /* Start with parsing the "omp declare simd" attribute(s). */
13538 bool inbranch_clause_specified;
13539 struct cgraph_simd_clone *clone_info
13540 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13541 &inbranch_clause_specified);
13542 if (clone_info == NULL)
13543 continue;
13545 int orig_simdlen = clone_info->simdlen;
13546 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13547 /* The target can return 0 (no simd clones should be created),
13548 1 (just one ISA of simd clones should be created) or higher
13549 count of ISA variants. In that case, clone_info is initialized
13550 for the first ISA variant. */
13551 int count
13552 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13553 base_type, 0);
13554 if (count == 0)
13555 continue;
13557 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13558 also create one inbranch and one !inbranch clone of it. */
13559 for (int i = 0; i < count * 2; i++)
13561 struct cgraph_simd_clone *clone = clone_info;
13562 if (inbranch_clause_specified && (i & 1) != 0)
13563 continue;
13565 if (i != 0)
13567 clone = simd_clone_struct_alloc (clone_info->nargs
13568 + ((i & 1) != 0));
13569 simd_clone_struct_copy (clone, clone_info);
13570 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13571 and simd_clone_adjust_argument_types did to the first
13572 clone's info. */
13573 clone->nargs -= clone_info->inbranch;
13574 clone->simdlen = orig_simdlen;
13575 /* And call the target hook again to get the right ISA. */
13576 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13577 base_type,
13578 i / 2);
13579 if ((i & 1) != 0)
13580 clone->inbranch = 1;
13583 /* simd_clone_mangle might fail if such a clone has been created
13584 already. */
13585 tree id = simd_clone_mangle (node, clone);
13586 if (id == NULL_TREE)
13587 continue;
13589 /* Only when we are sure we want to create the clone actually
13590 clone the function (or definitions) or create another
13591 extern FUNCTION_DECL (for prototypes without definitions). */
13592 struct cgraph_node *n = simd_clone_create (node);
13593 if (n == NULL)
13594 continue;
13596 n->simdclone = clone;
13597 clone->origin = node;
13598 clone->next_clone = NULL;
13599 if (node->simd_clones == NULL)
13601 clone->prev_clone = n;
13602 node->simd_clones = n;
13604 else
13606 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13607 clone->prev_clone->simdclone->next_clone = n;
13608 node->simd_clones->simdclone->prev_clone = n;
13610 symtab->change_decl_assembler_name (n->decl, id);
13611 /* And finally adjust the return type, parameters and for
13612 definitions also function body. */
13613 if (node->definition)
13614 simd_clone_adjust (n);
13615 else
13617 simd_clone_adjust_return_type (n);
13618 simd_clone_adjust_argument_types (n);
13622 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13625 /* Entry point for IPA simd clone creation pass. */
13627 static unsigned int
13628 ipa_omp_simd_clone (void)
13630 struct cgraph_node *node;
13631 FOR_EACH_FUNCTION (node)
13632 expand_simd_clones (node);
13633 return 0;
13636 namespace {
13638 const pass_data pass_data_omp_simd_clone =
13640 SIMPLE_IPA_PASS, /* type */
13641 "simdclone", /* name */
13642 OPTGROUP_NONE, /* optinfo_flags */
13643 TV_NONE, /* tv_id */
13644 ( PROP_ssa | PROP_cfg ), /* properties_required */
13645 0, /* properties_provided */
13646 0, /* properties_destroyed */
13647 0, /* todo_flags_start */
13648 0, /* todo_flags_finish */
13651 class pass_omp_simd_clone : public simple_ipa_opt_pass
13653 public:
13654 pass_omp_simd_clone(gcc::context *ctxt)
13655 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13658 /* opt_pass methods: */
13659 virtual bool gate (function *);
13660 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
13663 bool
13664 pass_omp_simd_clone::gate (function *)
13666 return ((flag_openmp || flag_openmp_simd
13667 || flag_cilkplus
13668 || (in_lto_p && !flag_wpa))
13669 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13672 } // anon namespace
13674 simple_ipa_opt_pass *
13675 make_pass_omp_simd_clone (gcc::context *ctxt)
13677 return new pass_omp_simd_clone (ctxt);
13680 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13681 adds their addresses and sizes to constructor-vector V_CTOR. */
13682 static void
13683 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13684 vec<constructor_elt, va_gc> *v_ctor)
13686 unsigned len = vec_safe_length (v_decls);
13687 for (unsigned i = 0; i < len; i++)
13689 tree it = (*v_decls)[i];
13690 bool is_function = TREE_CODE (it) != VAR_DECL;
13692 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13693 if (!is_function)
13694 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13695 fold_convert (const_ptr_type_node,
13696 DECL_SIZE_UNIT (it)));
13700 /* Create new symbols containing (address, size) pairs for global variables,
13701 marked with "omp declare target" attribute, as well as addresses for the
13702 functions, which are outlined offloading regions. */
13703 void
13704 omp_finish_file (void)
13706 unsigned num_funcs = vec_safe_length (offload_funcs);
13707 unsigned num_vars = vec_safe_length (offload_vars);
13709 if (num_funcs == 0 && num_vars == 0)
13710 return;
13712 if (targetm_common.have_named_sections)
13714 vec<constructor_elt, va_gc> *v_f, *v_v;
13715 vec_alloc (v_f, num_funcs);
13716 vec_alloc (v_v, num_vars * 2);
13718 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13719 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13721 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13722 num_vars * 2);
13723 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13724 num_funcs);
13725 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13726 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13727 tree ctor_v = build_constructor (vars_decl_type, v_v);
13728 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13729 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13730 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13731 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13732 get_identifier (".offload_func_table"),
13733 funcs_decl_type);
13734 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13735 get_identifier (".offload_var_table"),
13736 vars_decl_type);
13737 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13738 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13739 otherwise a joint table in a binary will contain padding between
13740 tables from multiple object files. */
13741 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13742 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13743 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13744 DECL_INITIAL (funcs_decl) = ctor_f;
13745 DECL_INITIAL (vars_decl) = ctor_v;
13746 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13747 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13749 varpool_node::finalize_decl (vars_decl);
13750 varpool_node::finalize_decl (funcs_decl);
13752 else
13754 for (unsigned i = 0; i < num_funcs; i++)
13756 tree it = (*offload_funcs)[i];
13757 targetm.record_offload_symbol (it);
13759 for (unsigned i = 0; i < num_vars; i++)
13761 tree it = (*offload_vars)[i];
13762 targetm.record_offload_symbol (it);
13767 #include "gt-omp-low.h"