PR target/66563
[official-gcc.git] / gcc / omp-low.c
blob415a2c88a0b9dfa7ef3465a349052ca6cf43f1b8
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 "alias.h"
30 #include "symtab.h"
31 #include "tree.h"
32 #include "fold-const.h"
33 #include "stringpool.h"
34 #include "stor-layout.h"
35 #include "rtl.h"
36 #include "predict.h"
37 #include "hard-reg-set.h"
38 #include "function.h"
39 #include "dominance.h"
40 #include "cfg.h"
41 #include "cfganal.h"
42 #include "basic-block.h"
43 #include "tree-ssa-alias.h"
44 #include "internal-fn.h"
45 #include "gimple-fold.h"
46 #include "gimple-expr.h"
47 #include "gimple.h"
48 #include "gimplify.h"
49 #include "gimple-iterator.h"
50 #include "gimplify-me.h"
51 #include "gimple-walk.h"
52 #include "tree-iterator.h"
53 #include "tree-inline.h"
54 #include "langhooks.h"
55 #include "diagnostic-core.h"
56 #include "gimple-ssa.h"
57 #include "plugin-api.h"
58 #include "ipa-ref.h"
59 #include "cgraph.h"
60 #include "tree-cfg.h"
61 #include "tree-phinodes.h"
62 #include "ssa-iterators.h"
63 #include "tree-ssanames.h"
64 #include "tree-into-ssa.h"
65 #include "flags.h"
66 #include "insn-config.h"
67 #include "expmed.h"
68 #include "dojump.h"
69 #include "explow.h"
70 #include "calls.h"
71 #include "emit-rtl.h"
72 #include "varasm.h"
73 #include "stmt.h"
74 #include "expr.h"
75 #include "tree-dfa.h"
76 #include "tree-ssa.h"
77 #include "tree-pass.h"
78 #include "except.h"
79 #include "splay-tree.h"
80 #include "insn-codes.h"
81 #include "optabs.h"
82 #include "cfgloop.h"
83 #include "target.h"
84 #include "common/common-target.h"
85 #include "omp-low.h"
86 #include "gimple-low.h"
87 #include "tree-cfgcleanup.h"
88 #include "pretty-print.h"
89 #include "alloc-pool.h"
90 #include "symbol-summary.h"
91 #include "ipa-prop.h"
92 #include "tree-nested.h"
93 #include "tree-eh.h"
94 #include "cilk.h"
95 #include "context.h"
96 #include "lto-section-names.h"
97 #include "gomp-constants.h"
100 /* Lowering of OMP parallel and workshare constructs proceeds in two
101 phases. The first phase scans the function looking for OMP statements
102 and then for variables that must be replaced to satisfy data sharing
103 clauses. The second phase expands code for the constructs, as well as
104 re-gimplifying things when variables have been replaced with complex
105 expressions.
107 Final code generation is done by pass_expand_omp. The flowgraph is
108 scanned for regions which are then moved to a new
109 function, to be invoked by the thread library, or offloaded. */
111 /* OMP region information. Every parallel and workshare
112 directive is enclosed between two markers, the OMP_* directive
113 and a corresponding OMP_RETURN statement. */
115 struct omp_region
117 /* The enclosing region. */
118 struct omp_region *outer;
120 /* First child region. */
121 struct omp_region *inner;
123 /* Next peer region. */
124 struct omp_region *next;
126 /* Block containing the omp directive as its last stmt. */
127 basic_block entry;
129 /* Block containing the OMP_RETURN as its last stmt. */
130 basic_block exit;
132 /* Block containing the OMP_CONTINUE as its last stmt. */
133 basic_block cont;
135 /* If this is a combined parallel+workshare region, this is a list
136 of additional arguments needed by the combined parallel+workshare
137 library call. */
138 vec<tree, va_gc> *ws_args;
140 /* The code for the omp directive of this region. */
141 enum gimple_code type;
143 /* Schedule kind, only used for OMP_FOR type regions. */
144 enum omp_clause_schedule_kind sched_kind;
146 /* True if this is a combined parallel+workshare region. */
147 bool is_combined_parallel;
150 /* Levels of parallelism as defined by OpenACC. Increasing numbers
151 correspond to deeper loop nesting levels. */
152 #define MASK_GANG 1
153 #define MASK_WORKER 2
154 #define MASK_VECTOR 4
156 /* Context structure. Used to store information about each parallel
157 directive in the code. */
159 typedef struct omp_context
161 /* This field must be at the beginning, as we do "inheritance": Some
162 callback functions for tree-inline.c (e.g., omp_copy_decl)
163 receive a copy_body_data pointer that is up-casted to an
164 omp_context pointer. */
165 copy_body_data cb;
167 /* The tree of contexts corresponding to the encountered constructs. */
168 struct omp_context *outer;
169 gimple stmt;
171 /* Map variables to fields in a structure that allows communication
172 between sending and receiving threads. */
173 splay_tree field_map;
174 tree record_type;
175 tree sender_decl;
176 tree receiver_decl;
178 /* These are used just by task contexts, if task firstprivate fn is
179 needed. srecord_type is used to communicate from the thread
180 that encountered the task construct to task firstprivate fn,
181 record_type is allocated by GOMP_task, initialized by task firstprivate
182 fn and passed to the task body fn. */
183 splay_tree sfield_map;
184 tree srecord_type;
186 /* A chain of variables to add to the top-level block surrounding the
187 construct. In the case of a parallel, this is in the child function. */
188 tree block_vars;
190 /* A map of reduction pointer variables. For accelerators, each
191 reduction variable is replaced with an array. Each thread, in turn,
192 is assigned to a slot on that array. */
193 splay_tree reduction_map;
195 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
196 barriers should jump to during omplower pass. */
197 tree cancel_label;
199 /* What to do with variables with implicitly determined sharing
200 attributes. */
201 enum omp_clause_default_kind default_kind;
203 /* Nesting depth of this context. Used to beautify error messages re
204 invalid gotos. The outermost ctx is depth 1, with depth 0 being
205 reserved for the main body of the function. */
206 int depth;
208 /* True if this parallel directive is nested within another. */
209 bool is_nested;
211 /* True if this construct can be cancelled. */
212 bool cancellable;
214 /* For OpenACC loops, a mask of gang, worker and vector used at
215 levels below this one. */
216 int gwv_below;
217 /* For OpenACC loops, a mask of gang, worker and vector used at
218 this level and above. For parallel and kernels clauses, a mask
219 indicating which of num_gangs/num_workers/num_vectors was used. */
220 int gwv_this;
221 } omp_context;
223 /* A structure holding the elements of:
224 for (V = N1; V cond N2; V += STEP) [...] */
226 struct omp_for_data_loop
228 tree v, n1, n2, step;
229 enum tree_code cond_code;
232 /* A structure describing the main elements of a parallel loop. */
234 struct omp_for_data
236 struct omp_for_data_loop loop;
237 tree chunk_size;
238 gomp_for *for_stmt;
239 tree pre, iter_type;
240 int collapse;
241 bool have_nowait, have_ordered;
242 enum omp_clause_schedule_kind sched_kind;
243 struct omp_for_data_loop *loops;
247 static splay_tree all_contexts;
248 static int taskreg_nesting_level;
249 static int target_nesting_level;
250 static struct omp_region *root_omp_region;
251 static bitmap task_shared_vars;
252 static vec<omp_context *> taskreg_contexts;
254 static void scan_omp (gimple_seq *, omp_context *);
255 static tree scan_omp_1_op (tree *, int *, void *);
257 #define WALK_SUBSTMTS \
258 case GIMPLE_BIND: \
259 case GIMPLE_TRY: \
260 case GIMPLE_CATCH: \
261 case GIMPLE_EH_FILTER: \
262 case GIMPLE_TRANSACTION: \
263 /* The sub-statements for these should be walked. */ \
264 *handled_ops_p = false; \
265 break;
267 /* Helper function to get the name of the array containing the partial
268 reductions for OpenACC reductions. */
269 static const char *
270 oacc_get_reduction_array_id (tree node)
272 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
273 int len = strlen ("OACC") + strlen (id);
274 char *temp_name = XALLOCAVEC (char, len + 1);
275 snprintf (temp_name, len + 1, "OACC%s", id);
276 return IDENTIFIER_POINTER (get_identifier (temp_name));
279 /* Determine the number of threads OpenACC threads used to determine the
280 size of the array of partial reductions. Currently, this is num_gangs
281 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
282 because it is independed of the device used. */
284 static tree
285 oacc_max_threads (omp_context *ctx)
287 tree nthreads, vector_length, gangs, clauses;
289 gangs = fold_convert (sizetype, integer_one_node);
290 vector_length = gangs;
292 /* The reduction clause may be nested inside a loop directive.
293 Scan for the innermost vector_length clause. */
294 for (omp_context *oc = ctx; oc; oc = oc->outer)
296 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
297 || (gimple_omp_target_kind (oc->stmt)
298 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
299 continue;
301 clauses = gimple_omp_target_clauses (oc->stmt);
303 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
304 if (vector_length)
305 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
306 sizetype,
307 OMP_CLAUSE_VECTOR_LENGTH_EXPR
308 (vector_length));
309 else
310 vector_length = fold_convert (sizetype, integer_one_node);
312 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
313 if (gangs)
314 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
315 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
316 else
317 gangs = fold_convert (sizetype, integer_one_node);
319 break;
322 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
324 return nthreads;
327 /* Holds offload tables with decls. */
328 vec<tree, va_gc> *offload_funcs, *offload_vars;
330 /* Convenience function for calling scan_omp_1_op on tree operands. */
332 static inline tree
333 scan_omp_op (tree *tp, omp_context *ctx)
335 struct walk_stmt_info wi;
337 memset (&wi, 0, sizeof (wi));
338 wi.info = ctx;
339 wi.want_locations = true;
341 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
344 static void lower_omp (gimple_seq *, omp_context *);
345 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
346 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
348 /* Find an OMP clause of type KIND within CLAUSES. */
350 tree
351 find_omp_clause (tree clauses, enum omp_clause_code kind)
353 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
354 if (OMP_CLAUSE_CODE (clauses) == kind)
355 return clauses;
357 return NULL_TREE;
360 /* Return true if CTX is for an omp parallel. */
362 static inline bool
363 is_parallel_ctx (omp_context *ctx)
365 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
369 /* Return true if CTX is for an omp task. */
371 static inline bool
372 is_task_ctx (omp_context *ctx)
374 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
378 /* Return true if CTX is for an omp parallel or omp task. */
380 static inline bool
381 is_taskreg_ctx (omp_context *ctx)
383 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
384 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
388 /* Return true if REGION is a combined parallel+workshare region. */
390 static inline bool
391 is_combined_parallel (struct omp_region *region)
393 return region->is_combined_parallel;
397 /* Extract the header elements of parallel loop FOR_STMT and store
398 them into *FD. */
400 static void
401 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
402 struct omp_for_data_loop *loops)
404 tree t, var, *collapse_iter, *collapse_count;
405 tree count = NULL_TREE, iter_type = long_integer_type_node;
406 struct omp_for_data_loop *loop;
407 int i;
408 struct omp_for_data_loop dummy_loop;
409 location_t loc = gimple_location (for_stmt);
410 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
411 bool distribute = gimple_omp_for_kind (for_stmt)
412 == GF_OMP_FOR_KIND_DISTRIBUTE;
414 fd->for_stmt = for_stmt;
415 fd->pre = NULL;
416 fd->collapse = gimple_omp_for_collapse (for_stmt);
417 if (fd->collapse > 1)
418 fd->loops = loops;
419 else
420 fd->loops = &fd->loop;
422 fd->have_nowait = distribute || simd;
423 fd->have_ordered = false;
424 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
425 fd->chunk_size = NULL_TREE;
426 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
427 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
428 collapse_iter = NULL;
429 collapse_count = NULL;
431 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
432 switch (OMP_CLAUSE_CODE (t))
434 case OMP_CLAUSE_NOWAIT:
435 fd->have_nowait = true;
436 break;
437 case OMP_CLAUSE_ORDERED:
438 fd->have_ordered = true;
439 break;
440 case OMP_CLAUSE_SCHEDULE:
441 gcc_assert (!distribute);
442 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
443 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
444 break;
445 case OMP_CLAUSE_DIST_SCHEDULE:
446 gcc_assert (distribute);
447 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
448 break;
449 case OMP_CLAUSE_COLLAPSE:
450 if (fd->collapse > 1)
452 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
453 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
455 break;
456 default:
457 break;
460 /* FIXME: for now map schedule(auto) to schedule(static).
461 There should be analysis to determine whether all iterations
462 are approximately the same amount of work (then schedule(static)
463 is best) or if it varies (then schedule(dynamic,N) is better). */
464 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
466 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
467 gcc_assert (fd->chunk_size == NULL);
469 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
470 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
471 gcc_assert (fd->chunk_size == NULL);
472 else if (fd->chunk_size == NULL)
474 /* We only need to compute a default chunk size for ordered
475 static loops and dynamic loops. */
476 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
477 || fd->have_ordered)
478 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
479 ? integer_zero_node : integer_one_node;
482 for (i = 0; i < fd->collapse; i++)
484 if (fd->collapse == 1)
485 loop = &fd->loop;
486 else if (loops != NULL)
487 loop = loops + i;
488 else
489 loop = &dummy_loop;
491 loop->v = gimple_omp_for_index (for_stmt, i);
492 gcc_assert (SSA_VAR_P (loop->v));
493 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
494 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
495 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
496 loop->n1 = gimple_omp_for_initial (for_stmt, i);
498 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
499 loop->n2 = gimple_omp_for_final (for_stmt, i);
500 switch (loop->cond_code)
502 case LT_EXPR:
503 case GT_EXPR:
504 break;
505 case NE_EXPR:
506 gcc_assert (gimple_omp_for_kind (for_stmt)
507 == GF_OMP_FOR_KIND_CILKSIMD
508 || (gimple_omp_for_kind (for_stmt)
509 == GF_OMP_FOR_KIND_CILKFOR));
510 break;
511 case LE_EXPR:
512 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
513 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
514 else
515 loop->n2 = fold_build2_loc (loc,
516 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
517 build_int_cst (TREE_TYPE (loop->n2), 1));
518 loop->cond_code = LT_EXPR;
519 break;
520 case GE_EXPR:
521 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
522 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
523 else
524 loop->n2 = fold_build2_loc (loc,
525 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
526 build_int_cst (TREE_TYPE (loop->n2), 1));
527 loop->cond_code = GT_EXPR;
528 break;
529 default:
530 gcc_unreachable ();
533 t = gimple_omp_for_incr (for_stmt, i);
534 gcc_assert (TREE_OPERAND (t, 0) == var);
535 switch (TREE_CODE (t))
537 case PLUS_EXPR:
538 loop->step = TREE_OPERAND (t, 1);
539 break;
540 case POINTER_PLUS_EXPR:
541 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
542 break;
543 case MINUS_EXPR:
544 loop->step = TREE_OPERAND (t, 1);
545 loop->step = fold_build1_loc (loc,
546 NEGATE_EXPR, TREE_TYPE (loop->step),
547 loop->step);
548 break;
549 default:
550 gcc_unreachable ();
553 if (simd
554 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
555 && !fd->have_ordered))
557 if (fd->collapse == 1)
558 iter_type = TREE_TYPE (loop->v);
559 else if (i == 0
560 || TYPE_PRECISION (iter_type)
561 < TYPE_PRECISION (TREE_TYPE (loop->v)))
562 iter_type
563 = build_nonstandard_integer_type
564 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
566 else if (iter_type != long_long_unsigned_type_node)
568 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
569 iter_type = long_long_unsigned_type_node;
570 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
571 && TYPE_PRECISION (TREE_TYPE (loop->v))
572 >= TYPE_PRECISION (iter_type))
574 tree n;
576 if (loop->cond_code == LT_EXPR)
577 n = fold_build2_loc (loc,
578 PLUS_EXPR, TREE_TYPE (loop->v),
579 loop->n2, loop->step);
580 else
581 n = loop->n1;
582 if (TREE_CODE (n) != INTEGER_CST
583 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
584 iter_type = long_long_unsigned_type_node;
586 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
587 > TYPE_PRECISION (iter_type))
589 tree n1, n2;
591 if (loop->cond_code == LT_EXPR)
593 n1 = loop->n1;
594 n2 = fold_build2_loc (loc,
595 PLUS_EXPR, TREE_TYPE (loop->v),
596 loop->n2, loop->step);
598 else
600 n1 = fold_build2_loc (loc,
601 MINUS_EXPR, TREE_TYPE (loop->v),
602 loop->n2, loop->step);
603 n2 = loop->n1;
605 if (TREE_CODE (n1) != INTEGER_CST
606 || TREE_CODE (n2) != INTEGER_CST
607 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
608 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
609 iter_type = long_long_unsigned_type_node;
613 if (collapse_count && *collapse_count == NULL)
615 t = fold_binary (loop->cond_code, boolean_type_node,
616 fold_convert (TREE_TYPE (loop->v), loop->n1),
617 fold_convert (TREE_TYPE (loop->v), loop->n2));
618 if (t && integer_zerop (t))
619 count = build_zero_cst (long_long_unsigned_type_node);
620 else if ((i == 0 || count != NULL_TREE)
621 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
622 && TREE_CONSTANT (loop->n1)
623 && TREE_CONSTANT (loop->n2)
624 && TREE_CODE (loop->step) == INTEGER_CST)
626 tree itype = TREE_TYPE (loop->v);
628 if (POINTER_TYPE_P (itype))
629 itype = signed_type_for (itype);
630 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
631 t = fold_build2_loc (loc,
632 PLUS_EXPR, itype,
633 fold_convert_loc (loc, itype, loop->step), t);
634 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
635 fold_convert_loc (loc, itype, loop->n2));
636 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
637 fold_convert_loc (loc, itype, loop->n1));
638 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
639 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
640 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
641 fold_build1_loc (loc, NEGATE_EXPR, itype,
642 fold_convert_loc (loc, itype,
643 loop->step)));
644 else
645 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
646 fold_convert_loc (loc, itype, loop->step));
647 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
648 if (count != NULL_TREE)
649 count = fold_build2_loc (loc,
650 MULT_EXPR, long_long_unsigned_type_node,
651 count, t);
652 else
653 count = t;
654 if (TREE_CODE (count) != INTEGER_CST)
655 count = NULL_TREE;
657 else if (count && !integer_zerop (count))
658 count = NULL_TREE;
662 if (count
663 && !simd
664 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
665 || fd->have_ordered))
667 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
668 iter_type = long_long_unsigned_type_node;
669 else
670 iter_type = long_integer_type_node;
672 else if (collapse_iter && *collapse_iter != NULL)
673 iter_type = TREE_TYPE (*collapse_iter);
674 fd->iter_type = iter_type;
675 if (collapse_iter && *collapse_iter == NULL)
676 *collapse_iter = create_tmp_var (iter_type, ".iter");
677 if (collapse_count && *collapse_count == NULL)
679 if (count)
680 *collapse_count = fold_convert_loc (loc, iter_type, count);
681 else
682 *collapse_count = create_tmp_var (iter_type, ".count");
685 if (fd->collapse > 1)
687 fd->loop.v = *collapse_iter;
688 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
689 fd->loop.n2 = *collapse_count;
690 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
691 fd->loop.cond_code = LT_EXPR;
694 /* For OpenACC loops, force a chunk size of one, as this avoids the default
695 scheduling where several subsequent iterations are being executed by the
696 same thread. */
697 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
699 gcc_assert (fd->chunk_size == NULL_TREE);
700 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
705 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
706 is the immediate dominator of PAR_ENTRY_BB, return true if there
707 are no data dependencies that would prevent expanding the parallel
708 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
710 When expanding a combined parallel+workshare region, the call to
711 the child function may need additional arguments in the case of
712 GIMPLE_OMP_FOR regions. In some cases, these arguments are
713 computed out of variables passed in from the parent to the child
714 via 'struct .omp_data_s'. For instance:
716 #pragma omp parallel for schedule (guided, i * 4)
717 for (j ...)
719 Is lowered into:
721 # BLOCK 2 (PAR_ENTRY_BB)
722 .omp_data_o.i = i;
723 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
725 # BLOCK 3 (WS_ENTRY_BB)
726 .omp_data_i = &.omp_data_o;
727 D.1667 = .omp_data_i->i;
728 D.1598 = D.1667 * 4;
729 #pragma omp for schedule (guided, D.1598)
731 When we outline the parallel region, the call to the child function
732 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
733 that value is computed *after* the call site. So, in principle we
734 cannot do the transformation.
736 To see whether the code in WS_ENTRY_BB blocks the combined
737 parallel+workshare call, we collect all the variables used in the
738 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
739 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
740 call.
742 FIXME. If we had the SSA form built at this point, we could merely
743 hoist the code in block 3 into block 2 and be done with it. But at
744 this point we don't have dataflow information and though we could
745 hack something up here, it is really not worth the aggravation. */
747 static bool
748 workshare_safe_to_combine_p (basic_block ws_entry_bb)
750 struct omp_for_data fd;
751 gimple ws_stmt = last_stmt (ws_entry_bb);
753 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
754 return true;
756 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
758 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
760 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
761 return false;
762 if (fd.iter_type != long_integer_type_node)
763 return false;
765 /* FIXME. We give up too easily here. If any of these arguments
766 are not constants, they will likely involve variables that have
767 been mapped into fields of .omp_data_s for sharing with the child
768 function. With appropriate data flow, it would be possible to
769 see through this. */
770 if (!is_gimple_min_invariant (fd.loop.n1)
771 || !is_gimple_min_invariant (fd.loop.n2)
772 || !is_gimple_min_invariant (fd.loop.step)
773 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
774 return false;
776 return true;
780 /* Collect additional arguments needed to emit a combined
781 parallel+workshare call. WS_STMT is the workshare directive being
782 expanded. */
784 static vec<tree, va_gc> *
785 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
787 tree t;
788 location_t loc = gimple_location (ws_stmt);
789 vec<tree, va_gc> *ws_args;
791 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
793 struct omp_for_data fd;
794 tree n1, n2;
796 extract_omp_for_data (for_stmt, &fd, NULL);
797 n1 = fd.loop.n1;
798 n2 = fd.loop.n2;
800 if (gimple_omp_for_combined_into_p (for_stmt))
802 tree innerc
803 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
804 OMP_CLAUSE__LOOPTEMP_);
805 gcc_assert (innerc);
806 n1 = OMP_CLAUSE_DECL (innerc);
807 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
808 OMP_CLAUSE__LOOPTEMP_);
809 gcc_assert (innerc);
810 n2 = OMP_CLAUSE_DECL (innerc);
813 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
815 t = fold_convert_loc (loc, long_integer_type_node, n1);
816 ws_args->quick_push (t);
818 t = fold_convert_loc (loc, long_integer_type_node, n2);
819 ws_args->quick_push (t);
821 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
822 ws_args->quick_push (t);
824 if (fd.chunk_size)
826 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
827 ws_args->quick_push (t);
830 return ws_args;
832 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
834 /* Number of sections is equal to the number of edges from the
835 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
836 the exit of the sections region. */
837 basic_block bb = single_succ (gimple_bb (ws_stmt));
838 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
839 vec_alloc (ws_args, 1);
840 ws_args->quick_push (t);
841 return ws_args;
844 gcc_unreachable ();
848 /* Discover whether REGION is a combined parallel+workshare region. */
850 static void
851 determine_parallel_type (struct omp_region *region)
853 basic_block par_entry_bb, par_exit_bb;
854 basic_block ws_entry_bb, ws_exit_bb;
856 if (region == NULL || region->inner == NULL
857 || region->exit == NULL || region->inner->exit == NULL
858 || region->inner->cont == NULL)
859 return;
861 /* We only support parallel+for and parallel+sections. */
862 if (region->type != GIMPLE_OMP_PARALLEL
863 || (region->inner->type != GIMPLE_OMP_FOR
864 && region->inner->type != GIMPLE_OMP_SECTIONS))
865 return;
867 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
868 WS_EXIT_BB -> PAR_EXIT_BB. */
869 par_entry_bb = region->entry;
870 par_exit_bb = region->exit;
871 ws_entry_bb = region->inner->entry;
872 ws_exit_bb = region->inner->exit;
874 if (single_succ (par_entry_bb) == ws_entry_bb
875 && single_succ (ws_exit_bb) == par_exit_bb
876 && workshare_safe_to_combine_p (ws_entry_bb)
877 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
878 || (last_and_only_stmt (ws_entry_bb)
879 && last_and_only_stmt (par_exit_bb))))
881 gimple par_stmt = last_stmt (par_entry_bb);
882 gimple ws_stmt = last_stmt (ws_entry_bb);
884 if (region->inner->type == GIMPLE_OMP_FOR)
886 /* If this is a combined parallel loop, we need to determine
887 whether or not to use the combined library calls. There
888 are two cases where we do not apply the transformation:
889 static loops and any kind of ordered loop. In the first
890 case, we already open code the loop so there is no need
891 to do anything else. In the latter case, the combined
892 parallel loop call would still need extra synchronization
893 to implement ordered semantics, so there would not be any
894 gain in using the combined call. */
895 tree clauses = gimple_omp_for_clauses (ws_stmt);
896 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
897 if (c == NULL
898 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
899 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
901 region->is_combined_parallel = false;
902 region->inner->is_combined_parallel = false;
903 return;
907 region->is_combined_parallel = true;
908 region->inner->is_combined_parallel = true;
909 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
914 /* Return true if EXPR is variable sized. */
916 static inline bool
917 is_variable_sized (const_tree expr)
919 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
922 /* Return true if DECL is a reference type. */
924 static inline bool
925 is_reference (tree decl)
927 return lang_hooks.decls.omp_privatize_by_reference (decl);
930 /* Return the type of a decl. If the decl is reference type,
931 return its base type. */
932 static inline tree
933 get_base_type (tree decl)
935 tree type = TREE_TYPE (decl);
936 if (is_reference (decl))
937 type = TREE_TYPE (type);
938 return type;
941 /* Lookup variables. The "maybe" form
942 allows for the variable form to not have been entered, otherwise we
943 assert that the variable must have been entered. */
945 static inline tree
946 lookup_decl (tree var, omp_context *ctx)
948 tree *n = ctx->cb.decl_map->get (var);
949 return *n;
952 static inline tree
953 maybe_lookup_decl (const_tree var, omp_context *ctx)
955 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
956 return n ? *n : NULL_TREE;
959 static inline tree
960 lookup_field (tree var, omp_context *ctx)
962 splay_tree_node n;
963 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
964 return (tree) n->value;
967 static inline tree
968 lookup_sfield (tree var, omp_context *ctx)
970 splay_tree_node n;
971 n = splay_tree_lookup (ctx->sfield_map
972 ? ctx->sfield_map : ctx->field_map,
973 (splay_tree_key) var);
974 return (tree) n->value;
977 static inline tree
978 maybe_lookup_field (tree var, omp_context *ctx)
980 splay_tree_node n;
981 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
982 return n ? (tree) n->value : NULL_TREE;
985 static inline tree
986 lookup_oacc_reduction (const char *id, omp_context *ctx)
988 splay_tree_node n;
989 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
990 return (tree) n->value;
993 static inline tree
994 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
996 splay_tree_node n = NULL;
997 if (ctx->reduction_map)
998 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
999 return n ? (tree) n->value : NULL_TREE;
1002 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1003 the parallel context if DECL is to be shared. */
1005 static bool
1006 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1008 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1009 return true;
1011 /* We can only use copy-in/copy-out semantics for shared variables
1012 when we know the value is not accessible from an outer scope. */
1013 if (shared_ctx)
1015 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1017 /* ??? Trivially accessible from anywhere. But why would we even
1018 be passing an address in this case? Should we simply assert
1019 this to be false, or should we have a cleanup pass that removes
1020 these from the list of mappings? */
1021 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1022 return true;
1024 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1025 without analyzing the expression whether or not its location
1026 is accessible to anyone else. In the case of nested parallel
1027 regions it certainly may be. */
1028 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1029 return true;
1031 /* Do not use copy-in/copy-out for variables that have their
1032 address taken. */
1033 if (TREE_ADDRESSABLE (decl))
1034 return true;
1036 /* lower_send_shared_vars only uses copy-in, but not copy-out
1037 for these. */
1038 if (TREE_READONLY (decl)
1039 || ((TREE_CODE (decl) == RESULT_DECL
1040 || TREE_CODE (decl) == PARM_DECL)
1041 && DECL_BY_REFERENCE (decl)))
1042 return false;
1044 /* Disallow copy-in/out in nested parallel if
1045 decl is shared in outer parallel, otherwise
1046 each thread could store the shared variable
1047 in its own copy-in location, making the
1048 variable no longer really shared. */
1049 if (shared_ctx->is_nested)
1051 omp_context *up;
1053 for (up = shared_ctx->outer; up; up = up->outer)
1054 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1055 break;
1057 if (up)
1059 tree c;
1061 for (c = gimple_omp_taskreg_clauses (up->stmt);
1062 c; c = OMP_CLAUSE_CHAIN (c))
1063 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1064 && OMP_CLAUSE_DECL (c) == decl)
1065 break;
1067 if (c)
1068 goto maybe_mark_addressable_and_ret;
1072 /* For tasks avoid using copy-in/out. As tasks can be
1073 deferred or executed in different thread, when GOMP_task
1074 returns, the task hasn't necessarily terminated. */
1075 if (is_task_ctx (shared_ctx))
1077 tree outer;
1078 maybe_mark_addressable_and_ret:
1079 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1080 if (is_gimple_reg (outer))
1082 /* Taking address of OUTER in lower_send_shared_vars
1083 might need regimplification of everything that uses the
1084 variable. */
1085 if (!task_shared_vars)
1086 task_shared_vars = BITMAP_ALLOC (NULL);
1087 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1088 TREE_ADDRESSABLE (outer) = 1;
1090 return true;
1094 return false;
1097 /* Construct a new automatic decl similar to VAR. */
1099 static tree
1100 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1102 tree copy = copy_var_decl (var, name, type);
1104 DECL_CONTEXT (copy) = current_function_decl;
1105 DECL_CHAIN (copy) = ctx->block_vars;
1106 ctx->block_vars = copy;
1108 return copy;
1111 static tree
1112 omp_copy_decl_1 (tree var, omp_context *ctx)
1114 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1117 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1118 as appropriate. */
1119 static tree
1120 omp_build_component_ref (tree obj, tree field)
1122 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1123 if (TREE_THIS_VOLATILE (field))
1124 TREE_THIS_VOLATILE (ret) |= 1;
1125 if (TREE_READONLY (field))
1126 TREE_READONLY (ret) |= 1;
1127 return ret;
1130 /* Build tree nodes to access the field for VAR on the receiver side. */
1132 static tree
1133 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1135 tree x, field = lookup_field (var, ctx);
1137 /* If the receiver record type was remapped in the child function,
1138 remap the field into the new record type. */
1139 x = maybe_lookup_field (field, ctx);
1140 if (x != NULL)
1141 field = x;
1143 x = build_simple_mem_ref (ctx->receiver_decl);
1144 x = omp_build_component_ref (x, field);
1145 if (by_ref)
1146 x = build_simple_mem_ref (x);
1148 return x;
1151 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1152 of a parallel, this is a component reference; for workshare constructs
1153 this is some variable. */
1155 static tree
1156 build_outer_var_ref (tree var, omp_context *ctx)
1158 tree x;
1160 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1161 x = var;
1162 else if (is_variable_sized (var))
1164 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1165 x = build_outer_var_ref (x, ctx);
1166 x = build_simple_mem_ref (x);
1168 else if (is_taskreg_ctx (ctx))
1170 bool by_ref = use_pointer_for_field (var, NULL);
1171 x = build_receiver_ref (var, by_ref, ctx);
1173 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1174 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1176 /* #pragma omp simd isn't a worksharing construct, and can reference even
1177 private vars in its linear etc. clauses. */
1178 x = NULL_TREE;
1179 if (ctx->outer && is_taskreg_ctx (ctx))
1180 x = lookup_decl (var, ctx->outer);
1181 else if (ctx->outer)
1182 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1183 if (x == NULL_TREE)
1184 x = var;
1186 else if (ctx->outer)
1187 x = lookup_decl (var, ctx->outer);
1188 else if (is_reference (var))
1189 /* This can happen with orphaned constructs. If var is reference, it is
1190 possible it is shared and as such valid. */
1191 x = var;
1192 else
1193 gcc_unreachable ();
1195 if (is_reference (var))
1196 x = build_simple_mem_ref (x);
1198 return x;
1201 /* Build tree nodes to access the field for VAR on the sender side. */
1203 static tree
1204 build_sender_ref (tree var, omp_context *ctx)
1206 tree field = lookup_sfield (var, ctx);
1207 return omp_build_component_ref (ctx->sender_decl, field);
1210 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1212 static void
1213 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1215 tree field, type, sfield = NULL_TREE;
1217 gcc_assert ((mask & 1) == 0
1218 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1219 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1220 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1221 gcc_assert ((mask & 3) == 3
1222 || !is_gimple_omp_oacc (ctx->stmt));
1224 type = TREE_TYPE (var);
1225 if (mask & 4)
1227 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1228 type = build_pointer_type (build_pointer_type (type));
1230 else if (by_ref)
1231 type = build_pointer_type (type);
1232 else if ((mask & 3) == 1 && is_reference (var))
1233 type = TREE_TYPE (type);
1235 field = build_decl (DECL_SOURCE_LOCATION (var),
1236 FIELD_DECL, DECL_NAME (var), type);
1238 /* Remember what variable this field was created for. This does have a
1239 side effect of making dwarf2out ignore this member, so for helpful
1240 debugging we clear it later in delete_omp_context. */
1241 DECL_ABSTRACT_ORIGIN (field) = var;
1242 if (type == TREE_TYPE (var))
1244 DECL_ALIGN (field) = DECL_ALIGN (var);
1245 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1246 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1248 else
1249 DECL_ALIGN (field) = TYPE_ALIGN (type);
1251 if ((mask & 3) == 3)
1253 insert_field_into_struct (ctx->record_type, field);
1254 if (ctx->srecord_type)
1256 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1257 FIELD_DECL, DECL_NAME (var), type);
1258 DECL_ABSTRACT_ORIGIN (sfield) = var;
1259 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1260 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1261 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1262 insert_field_into_struct (ctx->srecord_type, sfield);
1265 else
1267 if (ctx->srecord_type == NULL_TREE)
1269 tree t;
1271 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1272 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1273 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1275 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1276 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1277 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1278 insert_field_into_struct (ctx->srecord_type, sfield);
1279 splay_tree_insert (ctx->sfield_map,
1280 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1281 (splay_tree_value) sfield);
1284 sfield = field;
1285 insert_field_into_struct ((mask & 1) ? ctx->record_type
1286 : ctx->srecord_type, field);
1289 if (mask & 1)
1290 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1291 (splay_tree_value) field);
1292 if ((mask & 2) && ctx->sfield_map)
1293 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1294 (splay_tree_value) sfield);
1297 static tree
1298 install_var_local (tree var, omp_context *ctx)
1300 tree new_var = omp_copy_decl_1 (var, ctx);
1301 insert_decl_map (&ctx->cb, var, new_var);
1302 return new_var;
1305 /* Adjust the replacement for DECL in CTX for the new context. This means
1306 copying the DECL_VALUE_EXPR, and fixing up the type. */
1308 static void
1309 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1311 tree new_decl, size;
1313 new_decl = lookup_decl (decl, ctx);
1315 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1317 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1318 && DECL_HAS_VALUE_EXPR_P (decl))
1320 tree ve = DECL_VALUE_EXPR (decl);
1321 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1322 SET_DECL_VALUE_EXPR (new_decl, ve);
1323 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1326 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1328 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1329 if (size == error_mark_node)
1330 size = TYPE_SIZE (TREE_TYPE (new_decl));
1331 DECL_SIZE (new_decl) = size;
1333 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1334 if (size == error_mark_node)
1335 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1336 DECL_SIZE_UNIT (new_decl) = size;
1340 /* The callback for remap_decl. Search all containing contexts for a
1341 mapping of the variable; this avoids having to duplicate the splay
1342 tree ahead of time. We know a mapping doesn't already exist in the
1343 given context. Create new mappings to implement default semantics. */
1345 static tree
1346 omp_copy_decl (tree var, copy_body_data *cb)
1348 omp_context *ctx = (omp_context *) cb;
1349 tree new_var;
1351 if (TREE_CODE (var) == LABEL_DECL)
1353 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1354 DECL_CONTEXT (new_var) = current_function_decl;
1355 insert_decl_map (&ctx->cb, var, new_var);
1356 return new_var;
1359 while (!is_taskreg_ctx (ctx))
1361 ctx = ctx->outer;
1362 if (ctx == NULL)
1363 return var;
1364 new_var = maybe_lookup_decl (var, ctx);
1365 if (new_var)
1366 return new_var;
1369 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1370 return var;
1372 return error_mark_node;
1376 /* Debugging dumps for parallel regions. */
1377 void dump_omp_region (FILE *, struct omp_region *, int);
1378 void debug_omp_region (struct omp_region *);
1379 void debug_all_omp_regions (void);
1381 /* Dump the parallel region tree rooted at REGION. */
1383 void
1384 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1386 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1387 gimple_code_name[region->type]);
1389 if (region->inner)
1390 dump_omp_region (file, region->inner, indent + 4);
1392 if (region->cont)
1394 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1395 region->cont->index);
1398 if (region->exit)
1399 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1400 region->exit->index);
1401 else
1402 fprintf (file, "%*s[no exit marker]\n", indent, "");
1404 if (region->next)
1405 dump_omp_region (file, region->next, indent);
1408 DEBUG_FUNCTION void
1409 debug_omp_region (struct omp_region *region)
1411 dump_omp_region (stderr, region, 0);
1414 DEBUG_FUNCTION void
1415 debug_all_omp_regions (void)
1417 dump_omp_region (stderr, root_omp_region, 0);
1421 /* Create a new parallel region starting at STMT inside region PARENT. */
1423 static struct omp_region *
1424 new_omp_region (basic_block bb, enum gimple_code type,
1425 struct omp_region *parent)
1427 struct omp_region *region = XCNEW (struct omp_region);
1429 region->outer = parent;
1430 region->entry = bb;
1431 region->type = type;
1433 if (parent)
1435 /* This is a nested region. Add it to the list of inner
1436 regions in PARENT. */
1437 region->next = parent->inner;
1438 parent->inner = region;
1440 else
1442 /* This is a toplevel region. Add it to the list of toplevel
1443 regions in ROOT_OMP_REGION. */
1444 region->next = root_omp_region;
1445 root_omp_region = region;
1448 return region;
1451 /* Release the memory associated with the region tree rooted at REGION. */
1453 static void
1454 free_omp_region_1 (struct omp_region *region)
1456 struct omp_region *i, *n;
1458 for (i = region->inner; i ; i = n)
1460 n = i->next;
1461 free_omp_region_1 (i);
1464 free (region);
1467 /* Release the memory for the entire omp region tree. */
1469 void
1470 free_omp_regions (void)
1472 struct omp_region *r, *n;
1473 for (r = root_omp_region; r ; r = n)
1475 n = r->next;
1476 free_omp_region_1 (r);
1478 root_omp_region = NULL;
1482 /* Create a new context, with OUTER_CTX being the surrounding context. */
1484 static omp_context *
1485 new_omp_context (gimple stmt, omp_context *outer_ctx)
1487 omp_context *ctx = XCNEW (omp_context);
1489 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1490 (splay_tree_value) ctx);
1491 ctx->stmt = stmt;
1493 if (outer_ctx)
1495 ctx->outer = outer_ctx;
1496 ctx->cb = outer_ctx->cb;
1497 ctx->cb.block = NULL;
1498 ctx->depth = outer_ctx->depth + 1;
1499 ctx->reduction_map = outer_ctx->reduction_map;
1501 else
1503 ctx->cb.src_fn = current_function_decl;
1504 ctx->cb.dst_fn = current_function_decl;
1505 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1506 gcc_checking_assert (ctx->cb.src_node);
1507 ctx->cb.dst_node = ctx->cb.src_node;
1508 ctx->cb.src_cfun = cfun;
1509 ctx->cb.copy_decl = omp_copy_decl;
1510 ctx->cb.eh_lp_nr = 0;
1511 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1512 ctx->depth = 1;
1515 ctx->cb.decl_map = new hash_map<tree, tree>;
1517 return ctx;
1520 static gimple_seq maybe_catch_exception (gimple_seq);
1522 /* Finalize task copyfn. */
1524 static void
1525 finalize_task_copyfn (gomp_task *task_stmt)
1527 struct function *child_cfun;
1528 tree child_fn;
1529 gimple_seq seq = NULL, new_seq;
1530 gbind *bind;
1532 child_fn = gimple_omp_task_copy_fn (task_stmt);
1533 if (child_fn == NULL_TREE)
1534 return;
1536 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1537 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1539 push_cfun (child_cfun);
1540 bind = gimplify_body (child_fn, false);
1541 gimple_seq_add_stmt (&seq, bind);
1542 new_seq = maybe_catch_exception (seq);
1543 if (new_seq != seq)
1545 bind = gimple_build_bind (NULL, new_seq, NULL);
1546 seq = NULL;
1547 gimple_seq_add_stmt (&seq, bind);
1549 gimple_set_body (child_fn, seq);
1550 pop_cfun ();
1552 /* Inform the callgraph about the new function. */
1553 cgraph_node *node = cgraph_node::get_create (child_fn);
1554 node->parallelized_function = 1;
1555 cgraph_node::add_new_function (child_fn, false);
1558 /* Destroy a omp_context data structures. Called through the splay tree
1559 value delete callback. */
1561 static void
1562 delete_omp_context (splay_tree_value value)
1564 omp_context *ctx = (omp_context *) value;
1566 delete ctx->cb.decl_map;
1568 if (ctx->field_map)
1569 splay_tree_delete (ctx->field_map);
1570 if (ctx->sfield_map)
1571 splay_tree_delete (ctx->sfield_map);
1572 /* Reduction map is copied to nested contexts, so only delete it in the
1573 owner. */
1574 if (ctx->reduction_map
1575 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1576 && is_gimple_omp_offloaded (ctx->stmt)
1577 && is_gimple_omp_oacc (ctx->stmt))
1578 splay_tree_delete (ctx->reduction_map);
1580 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1581 it produces corrupt debug information. */
1582 if (ctx->record_type)
1584 tree t;
1585 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1586 DECL_ABSTRACT_ORIGIN (t) = NULL;
1588 if (ctx->srecord_type)
1590 tree t;
1591 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1592 DECL_ABSTRACT_ORIGIN (t) = NULL;
1595 if (is_task_ctx (ctx))
1596 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1598 XDELETE (ctx);
1601 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1602 context. */
1604 static void
1605 fixup_child_record_type (omp_context *ctx)
1607 tree f, type = ctx->record_type;
1609 /* ??? It isn't sufficient to just call remap_type here, because
1610 variably_modified_type_p doesn't work the way we expect for
1611 record types. Testing each field for whether it needs remapping
1612 and creating a new record by hand works, however. */
1613 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1614 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1615 break;
1616 if (f)
1618 tree name, new_fields = NULL;
1620 type = lang_hooks.types.make_type (RECORD_TYPE);
1621 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1622 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1623 TYPE_DECL, name, type);
1624 TYPE_NAME (type) = name;
1626 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1628 tree new_f = copy_node (f);
1629 DECL_CONTEXT (new_f) = type;
1630 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1631 DECL_CHAIN (new_f) = new_fields;
1632 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1633 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1634 &ctx->cb, NULL);
1635 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1636 &ctx->cb, NULL);
1637 new_fields = new_f;
1639 /* Arrange to be able to look up the receiver field
1640 given the sender field. */
1641 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1642 (splay_tree_value) new_f);
1644 TYPE_FIELDS (type) = nreverse (new_fields);
1645 layout_type (type);
1648 TREE_TYPE (ctx->receiver_decl)
1649 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1652 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1653 specified by CLAUSES. */
1655 static void
1656 scan_sharing_clauses (tree clauses, omp_context *ctx)
1658 tree c, decl;
1659 bool scan_array_reductions = false;
1661 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1663 bool by_ref;
1665 switch (OMP_CLAUSE_CODE (c))
1667 case OMP_CLAUSE_PRIVATE:
1668 decl = OMP_CLAUSE_DECL (c);
1669 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1670 goto do_private;
1671 else if (!is_variable_sized (decl))
1672 install_var_local (decl, ctx);
1673 break;
1675 case OMP_CLAUSE_SHARED:
1676 decl = OMP_CLAUSE_DECL (c);
1677 /* Ignore shared directives in teams construct. */
1678 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1680 /* Global variables don't need to be copied,
1681 the receiver side will use them directly. */
1682 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1683 if (is_global_var (odecl))
1684 break;
1685 insert_decl_map (&ctx->cb, decl, odecl);
1686 break;
1688 gcc_assert (is_taskreg_ctx (ctx));
1689 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1690 || !is_variable_sized (decl));
1691 /* Global variables don't need to be copied,
1692 the receiver side will use them directly. */
1693 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1694 break;
1695 by_ref = use_pointer_for_field (decl, ctx);
1696 if (! TREE_READONLY (decl)
1697 || TREE_ADDRESSABLE (decl)
1698 || by_ref
1699 || is_reference (decl))
1701 install_var_field (decl, by_ref, 3, ctx);
1702 install_var_local (decl, ctx);
1703 break;
1705 /* We don't need to copy const scalar vars back. */
1706 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1707 goto do_private;
1709 case OMP_CLAUSE_LASTPRIVATE:
1710 /* Let the corresponding firstprivate clause create
1711 the variable. */
1712 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1713 break;
1714 /* FALLTHRU */
1716 case OMP_CLAUSE_FIRSTPRIVATE:
1717 if (is_gimple_omp_oacc (ctx->stmt))
1719 sorry ("clause not supported yet");
1720 break;
1722 /* FALLTHRU */
1723 case OMP_CLAUSE_REDUCTION:
1724 case OMP_CLAUSE_LINEAR:
1725 decl = OMP_CLAUSE_DECL (c);
1726 do_private:
1727 if (is_variable_sized (decl))
1729 if (is_task_ctx (ctx))
1730 install_var_field (decl, false, 1, ctx);
1731 break;
1733 else if (is_taskreg_ctx (ctx))
1735 bool global
1736 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1737 by_ref = use_pointer_for_field (decl, NULL);
1739 if (is_task_ctx (ctx)
1740 && (global || by_ref || is_reference (decl)))
1742 install_var_field (decl, false, 1, ctx);
1743 if (!global)
1744 install_var_field (decl, by_ref, 2, ctx);
1746 else if (!global)
1747 install_var_field (decl, by_ref, 3, ctx);
1749 install_var_local (decl, ctx);
1750 if (is_gimple_omp_oacc (ctx->stmt)
1751 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1753 /* Create a decl for the reduction array. */
1754 tree var = OMP_CLAUSE_DECL (c);
1755 tree type = get_base_type (var);
1756 tree ptype = build_pointer_type (type);
1757 tree array = create_tmp_var (ptype,
1758 oacc_get_reduction_array_id (var));
1759 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1760 install_var_field (array, true, 3, c);
1761 install_var_local (array, c);
1763 /* Insert it into the current context. */
1764 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1765 oacc_get_reduction_array_id (var),
1766 (splay_tree_value) array);
1767 splay_tree_insert (ctx->reduction_map,
1768 (splay_tree_key) array,
1769 (splay_tree_value) array);
1771 break;
1773 case OMP_CLAUSE__LOOPTEMP_:
1774 gcc_assert (is_parallel_ctx (ctx));
1775 decl = OMP_CLAUSE_DECL (c);
1776 install_var_field (decl, false, 3, ctx);
1777 install_var_local (decl, ctx);
1778 break;
1780 case OMP_CLAUSE_COPYPRIVATE:
1781 case OMP_CLAUSE_COPYIN:
1782 decl = OMP_CLAUSE_DECL (c);
1783 by_ref = use_pointer_for_field (decl, NULL);
1784 install_var_field (decl, by_ref, 3, ctx);
1785 break;
1787 case OMP_CLAUSE_DEFAULT:
1788 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1789 break;
1791 case OMP_CLAUSE_FINAL:
1792 case OMP_CLAUSE_IF:
1793 case OMP_CLAUSE_NUM_THREADS:
1794 case OMP_CLAUSE_NUM_TEAMS:
1795 case OMP_CLAUSE_THREAD_LIMIT:
1796 case OMP_CLAUSE_DEVICE:
1797 case OMP_CLAUSE_SCHEDULE:
1798 case OMP_CLAUSE_DIST_SCHEDULE:
1799 case OMP_CLAUSE_DEPEND:
1800 case OMP_CLAUSE__CILK_FOR_COUNT_:
1801 case OMP_CLAUSE_NUM_GANGS:
1802 case OMP_CLAUSE_NUM_WORKERS:
1803 case OMP_CLAUSE_VECTOR_LENGTH:
1804 if (ctx->outer)
1805 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1806 break;
1808 case OMP_CLAUSE_TO:
1809 case OMP_CLAUSE_FROM:
1810 case OMP_CLAUSE_MAP:
1811 if (ctx->outer)
1812 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1813 decl = OMP_CLAUSE_DECL (c);
1814 /* Global variables with "omp declare target" attribute
1815 don't need to be copied, the receiver side will use them
1816 directly. */
1817 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1818 && DECL_P (decl)
1819 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1820 && varpool_node::get_create (decl)->offloadable)
1821 break;
1822 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1823 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
1825 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1826 not offloaded; there is nothing to map for those. */
1827 if (!is_gimple_omp_offloaded (ctx->stmt)
1828 && !POINTER_TYPE_P (TREE_TYPE (decl))
1829 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
1830 break;
1832 if (DECL_P (decl))
1834 if (DECL_SIZE (decl)
1835 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1837 tree decl2 = DECL_VALUE_EXPR (decl);
1838 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1839 decl2 = TREE_OPERAND (decl2, 0);
1840 gcc_assert (DECL_P (decl2));
1841 install_var_field (decl2, true, 3, ctx);
1842 install_var_local (decl2, ctx);
1843 install_var_local (decl, ctx);
1845 else
1847 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1848 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1849 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1850 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1851 install_var_field (decl, true, 7, ctx);
1852 else
1853 install_var_field (decl, true, 3, ctx);
1854 if (is_gimple_omp_offloaded (ctx->stmt))
1855 install_var_local (decl, ctx);
1858 else
1860 tree base = get_base_address (decl);
1861 tree nc = OMP_CLAUSE_CHAIN (c);
1862 if (DECL_P (base)
1863 && nc != NULL_TREE
1864 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1865 && OMP_CLAUSE_DECL (nc) == base
1866 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1867 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1869 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1870 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1872 else
1874 if (ctx->outer)
1876 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1877 decl = OMP_CLAUSE_DECL (c);
1879 gcc_assert (!splay_tree_lookup (ctx->field_map,
1880 (splay_tree_key) decl));
1881 tree field
1882 = build_decl (OMP_CLAUSE_LOCATION (c),
1883 FIELD_DECL, NULL_TREE, ptr_type_node);
1884 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1885 insert_field_into_struct (ctx->record_type, field);
1886 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1887 (splay_tree_value) field);
1890 break;
1892 case OMP_CLAUSE_NOWAIT:
1893 case OMP_CLAUSE_ORDERED:
1894 case OMP_CLAUSE_COLLAPSE:
1895 case OMP_CLAUSE_UNTIED:
1896 case OMP_CLAUSE_MERGEABLE:
1897 case OMP_CLAUSE_PROC_BIND:
1898 case OMP_CLAUSE_SAFELEN:
1899 case OMP_CLAUSE_ASYNC:
1900 case OMP_CLAUSE_WAIT:
1901 case OMP_CLAUSE_GANG:
1902 case OMP_CLAUSE_WORKER:
1903 case OMP_CLAUSE_VECTOR:
1904 break;
1906 case OMP_CLAUSE_ALIGNED:
1907 decl = OMP_CLAUSE_DECL (c);
1908 if (is_global_var (decl)
1909 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1910 install_var_local (decl, ctx);
1911 break;
1913 case OMP_CLAUSE_DEVICE_RESIDENT:
1914 case OMP_CLAUSE_USE_DEVICE:
1915 case OMP_CLAUSE__CACHE_:
1916 case OMP_CLAUSE_INDEPENDENT:
1917 case OMP_CLAUSE_AUTO:
1918 case OMP_CLAUSE_SEQ:
1919 sorry ("Clause not supported yet");
1920 break;
1922 default:
1923 gcc_unreachable ();
1927 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1929 switch (OMP_CLAUSE_CODE (c))
1931 case OMP_CLAUSE_LASTPRIVATE:
1932 /* Let the corresponding firstprivate clause create
1933 the variable. */
1934 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1935 scan_array_reductions = true;
1936 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1937 break;
1938 /* FALLTHRU */
1940 case OMP_CLAUSE_FIRSTPRIVATE:
1941 if (is_gimple_omp_oacc (ctx->stmt))
1943 sorry ("clause not supported yet");
1944 break;
1946 /* FALLTHRU */
1947 case OMP_CLAUSE_PRIVATE:
1948 case OMP_CLAUSE_REDUCTION:
1949 case OMP_CLAUSE_LINEAR:
1950 decl = OMP_CLAUSE_DECL (c);
1951 if (is_variable_sized (decl))
1952 install_var_local (decl, ctx);
1953 fixup_remapped_decl (decl, ctx,
1954 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1955 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1956 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1957 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1958 scan_array_reductions = true;
1959 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1960 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1961 scan_array_reductions = true;
1962 break;
1964 case OMP_CLAUSE_SHARED:
1965 /* Ignore shared directives in teams construct. */
1966 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1967 break;
1968 decl = OMP_CLAUSE_DECL (c);
1969 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1970 fixup_remapped_decl (decl, ctx, false);
1971 break;
1973 case OMP_CLAUSE_MAP:
1974 if (!is_gimple_omp_offloaded (ctx->stmt))
1975 break;
1976 decl = OMP_CLAUSE_DECL (c);
1977 if (DECL_P (decl)
1978 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1979 && varpool_node::get_create (decl)->offloadable)
1980 break;
1981 if (DECL_P (decl))
1983 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1984 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1985 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1987 tree new_decl = lookup_decl (decl, ctx);
1988 TREE_TYPE (new_decl)
1989 = remap_type (TREE_TYPE (decl), &ctx->cb);
1991 else if (DECL_SIZE (decl)
1992 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1994 tree decl2 = DECL_VALUE_EXPR (decl);
1995 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1996 decl2 = TREE_OPERAND (decl2, 0);
1997 gcc_assert (DECL_P (decl2));
1998 fixup_remapped_decl (decl2, ctx, false);
1999 fixup_remapped_decl (decl, ctx, true);
2001 else
2002 fixup_remapped_decl (decl, ctx, false);
2004 break;
2006 case OMP_CLAUSE_COPYPRIVATE:
2007 case OMP_CLAUSE_COPYIN:
2008 case OMP_CLAUSE_DEFAULT:
2009 case OMP_CLAUSE_IF:
2010 case OMP_CLAUSE_NUM_THREADS:
2011 case OMP_CLAUSE_NUM_TEAMS:
2012 case OMP_CLAUSE_THREAD_LIMIT:
2013 case OMP_CLAUSE_DEVICE:
2014 case OMP_CLAUSE_SCHEDULE:
2015 case OMP_CLAUSE_DIST_SCHEDULE:
2016 case OMP_CLAUSE_NOWAIT:
2017 case OMP_CLAUSE_ORDERED:
2018 case OMP_CLAUSE_COLLAPSE:
2019 case OMP_CLAUSE_UNTIED:
2020 case OMP_CLAUSE_FINAL:
2021 case OMP_CLAUSE_MERGEABLE:
2022 case OMP_CLAUSE_PROC_BIND:
2023 case OMP_CLAUSE_SAFELEN:
2024 case OMP_CLAUSE_ALIGNED:
2025 case OMP_CLAUSE_DEPEND:
2026 case OMP_CLAUSE__LOOPTEMP_:
2027 case OMP_CLAUSE_TO:
2028 case OMP_CLAUSE_FROM:
2029 case OMP_CLAUSE__CILK_FOR_COUNT_:
2030 case OMP_CLAUSE_ASYNC:
2031 case OMP_CLAUSE_WAIT:
2032 case OMP_CLAUSE_NUM_GANGS:
2033 case OMP_CLAUSE_NUM_WORKERS:
2034 case OMP_CLAUSE_VECTOR_LENGTH:
2035 case OMP_CLAUSE_GANG:
2036 case OMP_CLAUSE_WORKER:
2037 case OMP_CLAUSE_VECTOR:
2038 break;
2040 case OMP_CLAUSE_DEVICE_RESIDENT:
2041 case OMP_CLAUSE_USE_DEVICE:
2042 case OMP_CLAUSE__CACHE_:
2043 case OMP_CLAUSE_INDEPENDENT:
2044 case OMP_CLAUSE_AUTO:
2045 case OMP_CLAUSE_SEQ:
2046 sorry ("Clause not supported yet");
2047 break;
2049 default:
2050 gcc_unreachable ();
2054 gcc_checking_assert (!scan_array_reductions
2055 || !is_gimple_omp_oacc (ctx->stmt));
2056 if (scan_array_reductions)
2057 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2058 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2059 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2061 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2062 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2064 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2065 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2066 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2067 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2068 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2069 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2072 /* Create a new name for omp child function. Returns an identifier. If
2073 IS_CILK_FOR is true then the suffix for the child function is
2074 "_cilk_for_fn." */
2076 static tree
2077 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2079 if (is_cilk_for)
2080 return clone_function_name (current_function_decl, "_cilk_for_fn");
2081 return clone_function_name (current_function_decl,
2082 task_copy ? "_omp_cpyfn" : "_omp_fn");
2085 /* Returns the type of the induction variable for the child function for
2086 _Cilk_for and the types for _high and _low variables based on TYPE. */
2088 static tree
2089 cilk_for_check_loop_diff_type (tree type)
2091 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2093 if (TYPE_UNSIGNED (type))
2094 return uint32_type_node;
2095 else
2096 return integer_type_node;
2098 else
2100 if (TYPE_UNSIGNED (type))
2101 return uint64_type_node;
2102 else
2103 return long_long_integer_type_node;
2107 /* Build a decl for the omp child function. It'll not contain a body
2108 yet, just the bare decl. */
2110 static void
2111 create_omp_child_function (omp_context *ctx, bool task_copy)
2113 tree decl, type, name, t;
2115 tree cilk_for_count
2116 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2117 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2118 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2119 tree cilk_var_type = NULL_TREE;
2121 name = create_omp_child_function_name (task_copy,
2122 cilk_for_count != NULL_TREE);
2123 if (task_copy)
2124 type = build_function_type_list (void_type_node, ptr_type_node,
2125 ptr_type_node, NULL_TREE);
2126 else if (cilk_for_count)
2128 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2129 cilk_var_type = cilk_for_check_loop_diff_type (type);
2130 type = build_function_type_list (void_type_node, ptr_type_node,
2131 cilk_var_type, cilk_var_type, NULL_TREE);
2133 else
2134 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2136 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2138 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2139 || !task_copy);
2140 if (!task_copy)
2141 ctx->cb.dst_fn = decl;
2142 else
2143 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2145 TREE_STATIC (decl) = 1;
2146 TREE_USED (decl) = 1;
2147 DECL_ARTIFICIAL (decl) = 1;
2148 DECL_IGNORED_P (decl) = 0;
2149 TREE_PUBLIC (decl) = 0;
2150 DECL_UNINLINABLE (decl) = 1;
2151 DECL_EXTERNAL (decl) = 0;
2152 DECL_CONTEXT (decl) = NULL_TREE;
2153 DECL_INITIAL (decl) = make_node (BLOCK);
2154 if (cgraph_node::get (current_function_decl)->offloadable)
2155 cgraph_node::get_create (decl)->offloadable = 1;
2156 else
2158 omp_context *octx;
2159 for (octx = ctx; octx; octx = octx->outer)
2160 if (is_gimple_omp_offloaded (octx->stmt))
2162 cgraph_node::get_create (decl)->offloadable = 1;
2163 #ifdef ENABLE_OFFLOADING
2164 g->have_offload = true;
2165 #endif
2166 break;
2170 if (cgraph_node::get_create (decl)->offloadable
2171 && !lookup_attribute ("omp declare target",
2172 DECL_ATTRIBUTES (current_function_decl)))
2173 DECL_ATTRIBUTES (decl)
2174 = tree_cons (get_identifier ("omp target entrypoint"),
2175 NULL_TREE, DECL_ATTRIBUTES (decl));
2177 t = build_decl (DECL_SOURCE_LOCATION (decl),
2178 RESULT_DECL, NULL_TREE, void_type_node);
2179 DECL_ARTIFICIAL (t) = 1;
2180 DECL_IGNORED_P (t) = 1;
2181 DECL_CONTEXT (t) = decl;
2182 DECL_RESULT (decl) = t;
2184 /* _Cilk_for's child function requires two extra parameters called
2185 __low and __high that are set the by Cilk runtime when it calls this
2186 function. */
2187 if (cilk_for_count)
2189 t = build_decl (DECL_SOURCE_LOCATION (decl),
2190 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2191 DECL_ARTIFICIAL (t) = 1;
2192 DECL_NAMELESS (t) = 1;
2193 DECL_ARG_TYPE (t) = ptr_type_node;
2194 DECL_CONTEXT (t) = current_function_decl;
2195 TREE_USED (t) = 1;
2196 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2197 DECL_ARGUMENTS (decl) = t;
2199 t = build_decl (DECL_SOURCE_LOCATION (decl),
2200 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2201 DECL_ARTIFICIAL (t) = 1;
2202 DECL_NAMELESS (t) = 1;
2203 DECL_ARG_TYPE (t) = ptr_type_node;
2204 DECL_CONTEXT (t) = current_function_decl;
2205 TREE_USED (t) = 1;
2206 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2207 DECL_ARGUMENTS (decl) = t;
2210 tree data_name = get_identifier (".omp_data_i");
2211 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2212 ptr_type_node);
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 if (cilk_for_count)
2219 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2220 DECL_ARGUMENTS (decl) = t;
2221 if (!task_copy)
2222 ctx->receiver_decl = t;
2223 else
2225 t = build_decl (DECL_SOURCE_LOCATION (decl),
2226 PARM_DECL, get_identifier (".omp_data_o"),
2227 ptr_type_node);
2228 DECL_ARTIFICIAL (t) = 1;
2229 DECL_NAMELESS (t) = 1;
2230 DECL_ARG_TYPE (t) = ptr_type_node;
2231 DECL_CONTEXT (t) = current_function_decl;
2232 TREE_USED (t) = 1;
2233 TREE_ADDRESSABLE (t) = 1;
2234 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2235 DECL_ARGUMENTS (decl) = t;
2238 /* Allocate memory for the function structure. The call to
2239 allocate_struct_function clobbers CFUN, so we need to restore
2240 it afterward. */
2241 push_struct_function (decl);
2242 cfun->function_end_locus = gimple_location (ctx->stmt);
2243 pop_cfun ();
2246 /* Callback for walk_gimple_seq. Check if combined parallel
2247 contains gimple_omp_for_combined_into_p OMP_FOR. */
2249 static tree
2250 find_combined_for (gimple_stmt_iterator *gsi_p,
2251 bool *handled_ops_p,
2252 struct walk_stmt_info *wi)
2254 gimple stmt = gsi_stmt (*gsi_p);
2256 *handled_ops_p = true;
2257 switch (gimple_code (stmt))
2259 WALK_SUBSTMTS;
2261 case GIMPLE_OMP_FOR:
2262 if (gimple_omp_for_combined_into_p (stmt)
2263 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2265 wi->info = stmt;
2266 return integer_zero_node;
2268 break;
2269 default:
2270 break;
2272 return NULL;
2275 /* Scan an OpenMP parallel directive. */
2277 static void
2278 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2280 omp_context *ctx;
2281 tree name;
2282 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2284 /* Ignore parallel directives with empty bodies, unless there
2285 are copyin clauses. */
2286 if (optimize > 0
2287 && empty_body_p (gimple_omp_body (stmt))
2288 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2289 OMP_CLAUSE_COPYIN) == NULL)
2291 gsi_replace (gsi, gimple_build_nop (), false);
2292 return;
2295 if (gimple_omp_parallel_combined_p (stmt))
2297 struct walk_stmt_info wi;
2299 memset (&wi, 0, sizeof (wi));
2300 wi.val_only = true;
2301 walk_gimple_seq (gimple_omp_body (stmt),
2302 find_combined_for, NULL, &wi);
2303 if (wi.info)
2305 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2306 struct omp_for_data fd;
2307 extract_omp_for_data (for_stmt, &fd, NULL);
2308 /* We need two temporaries with fd.loop.v type (istart/iend)
2309 and then (fd.collapse - 1) temporaries with the same
2310 type for count2 ... countN-1 vars if not constant. */
2311 size_t count = 2, i;
2312 tree type = fd.iter_type;
2313 if (fd.collapse > 1
2314 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2315 count += fd.collapse - 1;
2316 for (i = 0; i < count; i++)
2318 tree temp = create_tmp_var (type);
2319 tree c = build_omp_clause (UNKNOWN_LOCATION,
2320 OMP_CLAUSE__LOOPTEMP_);
2321 insert_decl_map (&outer_ctx->cb, temp, temp);
2322 OMP_CLAUSE_DECL (c) = temp;
2323 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2324 gimple_omp_parallel_set_clauses (stmt, c);
2329 ctx = new_omp_context (stmt, outer_ctx);
2330 taskreg_contexts.safe_push (ctx);
2331 if (taskreg_nesting_level > 1)
2332 ctx->is_nested = true;
2333 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2334 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2335 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2336 name = create_tmp_var_name (".omp_data_s");
2337 name = build_decl (gimple_location (stmt),
2338 TYPE_DECL, name, ctx->record_type);
2339 DECL_ARTIFICIAL (name) = 1;
2340 DECL_NAMELESS (name) = 1;
2341 TYPE_NAME (ctx->record_type) = name;
2342 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2343 create_omp_child_function (ctx, false);
2344 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2346 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2347 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2349 if (TYPE_FIELDS (ctx->record_type) == NULL)
2350 ctx->record_type = ctx->receiver_decl = NULL;
2353 /* Scan an OpenMP task directive. */
2355 static void
2356 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2358 omp_context *ctx;
2359 tree name, t;
2360 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2362 /* Ignore task directives with empty bodies. */
2363 if (optimize > 0
2364 && empty_body_p (gimple_omp_body (stmt)))
2366 gsi_replace (gsi, gimple_build_nop (), false);
2367 return;
2370 ctx = new_omp_context (stmt, outer_ctx);
2371 taskreg_contexts.safe_push (ctx);
2372 if (taskreg_nesting_level > 1)
2373 ctx->is_nested = true;
2374 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2375 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2376 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2377 name = create_tmp_var_name (".omp_data_s");
2378 name = build_decl (gimple_location (stmt),
2379 TYPE_DECL, name, ctx->record_type);
2380 DECL_ARTIFICIAL (name) = 1;
2381 DECL_NAMELESS (name) = 1;
2382 TYPE_NAME (ctx->record_type) = name;
2383 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2384 create_omp_child_function (ctx, false);
2385 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2387 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2389 if (ctx->srecord_type)
2391 name = create_tmp_var_name (".omp_data_a");
2392 name = build_decl (gimple_location (stmt),
2393 TYPE_DECL, name, ctx->srecord_type);
2394 DECL_ARTIFICIAL (name) = 1;
2395 DECL_NAMELESS (name) = 1;
2396 TYPE_NAME (ctx->srecord_type) = name;
2397 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2398 create_omp_child_function (ctx, true);
2401 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2403 if (TYPE_FIELDS (ctx->record_type) == NULL)
2405 ctx->record_type = ctx->receiver_decl = NULL;
2406 t = build_int_cst (long_integer_type_node, 0);
2407 gimple_omp_task_set_arg_size (stmt, t);
2408 t = build_int_cst (long_integer_type_node, 1);
2409 gimple_omp_task_set_arg_align (stmt, t);
2414 /* If any decls have been made addressable during scan_omp,
2415 adjust their fields if needed, and layout record types
2416 of parallel/task constructs. */
2418 static void
2419 finish_taskreg_scan (omp_context *ctx)
2421 if (ctx->record_type == NULL_TREE)
2422 return;
2424 /* If any task_shared_vars were needed, verify all
2425 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2426 statements if use_pointer_for_field hasn't changed
2427 because of that. If it did, update field types now. */
2428 if (task_shared_vars)
2430 tree c;
2432 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2433 c; c = OMP_CLAUSE_CHAIN (c))
2434 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2436 tree decl = OMP_CLAUSE_DECL (c);
2438 /* Global variables don't need to be copied,
2439 the receiver side will use them directly. */
2440 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2441 continue;
2442 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2443 || !use_pointer_for_field (decl, ctx))
2444 continue;
2445 tree field = lookup_field (decl, ctx);
2446 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2447 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2448 continue;
2449 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2450 TREE_THIS_VOLATILE (field) = 0;
2451 DECL_USER_ALIGN (field) = 0;
2452 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2453 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2454 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2455 if (ctx->srecord_type)
2457 tree sfield = lookup_sfield (decl, ctx);
2458 TREE_TYPE (sfield) = TREE_TYPE (field);
2459 TREE_THIS_VOLATILE (sfield) = 0;
2460 DECL_USER_ALIGN (sfield) = 0;
2461 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2462 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2463 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2468 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2470 layout_type (ctx->record_type);
2471 fixup_child_record_type (ctx);
2473 else
2475 location_t loc = gimple_location (ctx->stmt);
2476 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2477 /* Move VLA fields to the end. */
2478 p = &TYPE_FIELDS (ctx->record_type);
2479 while (*p)
2480 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2481 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2483 *q = *p;
2484 *p = TREE_CHAIN (*p);
2485 TREE_CHAIN (*q) = NULL_TREE;
2486 q = &TREE_CHAIN (*q);
2488 else
2489 p = &DECL_CHAIN (*p);
2490 *p = vla_fields;
2491 layout_type (ctx->record_type);
2492 fixup_child_record_type (ctx);
2493 if (ctx->srecord_type)
2494 layout_type (ctx->srecord_type);
2495 tree t = fold_convert_loc (loc, long_integer_type_node,
2496 TYPE_SIZE_UNIT (ctx->record_type));
2497 gimple_omp_task_set_arg_size (ctx->stmt, t);
2498 t = build_int_cst (long_integer_type_node,
2499 TYPE_ALIGN_UNIT (ctx->record_type));
2500 gimple_omp_task_set_arg_align (ctx->stmt, t);
2505 static omp_context *
2506 enclosing_target_ctx (omp_context *ctx)
2508 while (ctx != NULL
2509 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2510 ctx = ctx->outer;
2511 gcc_assert (ctx != NULL);
2512 return ctx;
2515 static bool
2516 oacc_loop_or_target_p (gimple stmt)
2518 enum gimple_code outer_type = gimple_code (stmt);
2519 return ((outer_type == GIMPLE_OMP_TARGET
2520 && ((gimple_omp_target_kind (stmt)
2521 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2522 || (gimple_omp_target_kind (stmt)
2523 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2524 || (outer_type == GIMPLE_OMP_FOR
2525 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2528 /* Scan a GIMPLE_OMP_FOR. */
2530 static void
2531 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2533 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
2534 omp_context *ctx;
2535 size_t i;
2536 tree clauses = gimple_omp_for_clauses (stmt);
2538 if (outer_ctx)
2539 outer_type = gimple_code (outer_ctx->stmt);
2541 ctx = new_omp_context (stmt, outer_ctx);
2543 if (is_gimple_omp_oacc (stmt))
2545 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2546 ctx->gwv_this = outer_ctx->gwv_this;
2547 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2549 int val;
2550 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2551 val = MASK_GANG;
2552 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2553 val = MASK_WORKER;
2554 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2555 val = MASK_VECTOR;
2556 else
2557 continue;
2558 ctx->gwv_this |= val;
2559 if (!outer_ctx)
2561 /* Skip; not nested inside a region. */
2562 continue;
2564 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2566 /* Skip; not nested inside an OpenACC region. */
2567 continue;
2569 if (outer_type == GIMPLE_OMP_FOR)
2570 outer_ctx->gwv_below |= val;
2571 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2573 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2574 if (gimple_omp_target_kind (enclosing->stmt)
2575 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2576 error_at (gimple_location (stmt),
2577 "no arguments allowed to gang, worker and vector clauses inside parallel");
2582 scan_sharing_clauses (clauses, ctx);
2584 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2585 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2587 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2588 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2589 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2590 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2592 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2594 if (is_gimple_omp_oacc (stmt))
2596 if (ctx->gwv_this & ctx->gwv_below)
2597 error_at (gimple_location (stmt),
2598 "gang, worker and vector may occur only once in a loop nest");
2599 else if (ctx->gwv_below != 0
2600 && ctx->gwv_this > ctx->gwv_below)
2601 error_at (gimple_location (stmt),
2602 "gang, worker and vector must occur in this order in a loop nest");
2603 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2604 outer_ctx->gwv_below |= ctx->gwv_below;
2608 /* Scan an OpenMP sections directive. */
2610 static void
2611 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2613 omp_context *ctx;
2615 ctx = new_omp_context (stmt, outer_ctx);
2616 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2617 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2620 /* Scan an OpenMP single directive. */
2622 static void
2623 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2625 omp_context *ctx;
2626 tree name;
2628 ctx = new_omp_context (stmt, outer_ctx);
2629 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2630 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2631 name = create_tmp_var_name (".omp_copy_s");
2632 name = build_decl (gimple_location (stmt),
2633 TYPE_DECL, name, ctx->record_type);
2634 TYPE_NAME (ctx->record_type) = name;
2636 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2637 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2639 if (TYPE_FIELDS (ctx->record_type) == NULL)
2640 ctx->record_type = NULL;
2641 else
2642 layout_type (ctx->record_type);
2645 /* Scan a GIMPLE_OMP_TARGET. */
2647 static void
2648 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2650 omp_context *ctx;
2651 tree name;
2652 bool offloaded = is_gimple_omp_offloaded (stmt);
2653 tree clauses = gimple_omp_target_clauses (stmt);
2655 ctx = new_omp_context (stmt, outer_ctx);
2656 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2657 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2658 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2659 name = create_tmp_var_name (".omp_data_t");
2660 name = build_decl (gimple_location (stmt),
2661 TYPE_DECL, name, ctx->record_type);
2662 DECL_ARTIFICIAL (name) = 1;
2663 DECL_NAMELESS (name) = 1;
2664 TYPE_NAME (ctx->record_type) = name;
2665 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2666 if (offloaded)
2668 if (is_gimple_omp_oacc (stmt))
2669 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2670 0, 0);
2672 create_omp_child_function (ctx, false);
2673 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2676 if (is_gimple_omp_oacc (stmt))
2678 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2680 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2681 ctx->gwv_this |= MASK_GANG;
2682 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2683 ctx->gwv_this |= MASK_WORKER;
2684 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2685 ctx->gwv_this |= MASK_VECTOR;
2689 scan_sharing_clauses (clauses, ctx);
2690 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2692 if (TYPE_FIELDS (ctx->record_type) == NULL)
2693 ctx->record_type = ctx->receiver_decl = NULL;
2694 else
2696 TYPE_FIELDS (ctx->record_type)
2697 = nreverse (TYPE_FIELDS (ctx->record_type));
2698 #ifdef ENABLE_CHECKING
2699 tree field;
2700 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2701 for (field = TYPE_FIELDS (ctx->record_type);
2702 field;
2703 field = DECL_CHAIN (field))
2704 gcc_assert (DECL_ALIGN (field) == align);
2705 #endif
2706 layout_type (ctx->record_type);
2707 if (offloaded)
2708 fixup_child_record_type (ctx);
2712 /* Scan an OpenMP teams directive. */
2714 static void
2715 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2717 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2718 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2719 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2722 /* Check nesting restrictions. */
2723 static bool
2724 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2726 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2727 inside an OpenACC CTX. */
2728 if (!(is_gimple_omp (stmt)
2729 && is_gimple_omp_oacc (stmt)))
2731 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2732 if (is_gimple_omp (ctx_->stmt)
2733 && is_gimple_omp_oacc (ctx_->stmt))
2735 error_at (gimple_location (stmt),
2736 "non-OpenACC construct inside of OpenACC region");
2737 return false;
2741 if (ctx != NULL)
2743 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2744 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2746 error_at (gimple_location (stmt),
2747 "OpenMP constructs may not be nested inside simd region");
2748 return false;
2750 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2752 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2753 || (gimple_omp_for_kind (stmt)
2754 != GF_OMP_FOR_KIND_DISTRIBUTE))
2755 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2757 error_at (gimple_location (stmt),
2758 "only distribute or parallel constructs are allowed to "
2759 "be closely nested inside teams construct");
2760 return false;
2764 switch (gimple_code (stmt))
2766 case GIMPLE_OMP_FOR:
2767 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2768 return true;
2769 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2771 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2773 error_at (gimple_location (stmt),
2774 "distribute construct must be closely nested inside "
2775 "teams construct");
2776 return false;
2778 return true;
2780 /* FALLTHRU */
2781 case GIMPLE_CALL:
2782 if (is_gimple_call (stmt)
2783 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2784 == BUILT_IN_GOMP_CANCEL
2785 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2786 == BUILT_IN_GOMP_CANCELLATION_POINT))
2788 const char *bad = NULL;
2789 const char *kind = NULL;
2790 if (ctx == NULL)
2792 error_at (gimple_location (stmt), "orphaned %qs construct",
2793 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2794 == BUILT_IN_GOMP_CANCEL
2795 ? "#pragma omp cancel"
2796 : "#pragma omp cancellation point");
2797 return false;
2799 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2800 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2801 : 0)
2803 case 1:
2804 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2805 bad = "#pragma omp parallel";
2806 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2807 == BUILT_IN_GOMP_CANCEL
2808 && !integer_zerop (gimple_call_arg (stmt, 1)))
2809 ctx->cancellable = true;
2810 kind = "parallel";
2811 break;
2812 case 2:
2813 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2814 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2815 bad = "#pragma omp for";
2816 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2817 == BUILT_IN_GOMP_CANCEL
2818 && !integer_zerop (gimple_call_arg (stmt, 1)))
2820 ctx->cancellable = true;
2821 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2822 OMP_CLAUSE_NOWAIT))
2823 warning_at (gimple_location (stmt), 0,
2824 "%<#pragma omp cancel for%> inside "
2825 "%<nowait%> for construct");
2826 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2827 OMP_CLAUSE_ORDERED))
2828 warning_at (gimple_location (stmt), 0,
2829 "%<#pragma omp cancel for%> inside "
2830 "%<ordered%> for construct");
2832 kind = "for";
2833 break;
2834 case 4:
2835 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2836 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2837 bad = "#pragma omp sections";
2838 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2839 == BUILT_IN_GOMP_CANCEL
2840 && !integer_zerop (gimple_call_arg (stmt, 1)))
2842 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2844 ctx->cancellable = true;
2845 if (find_omp_clause (gimple_omp_sections_clauses
2846 (ctx->stmt),
2847 OMP_CLAUSE_NOWAIT))
2848 warning_at (gimple_location (stmt), 0,
2849 "%<#pragma omp cancel sections%> inside "
2850 "%<nowait%> sections construct");
2852 else
2854 gcc_assert (ctx->outer
2855 && gimple_code (ctx->outer->stmt)
2856 == GIMPLE_OMP_SECTIONS);
2857 ctx->outer->cancellable = true;
2858 if (find_omp_clause (gimple_omp_sections_clauses
2859 (ctx->outer->stmt),
2860 OMP_CLAUSE_NOWAIT))
2861 warning_at (gimple_location (stmt), 0,
2862 "%<#pragma omp cancel sections%> inside "
2863 "%<nowait%> sections construct");
2866 kind = "sections";
2867 break;
2868 case 8:
2869 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2870 bad = "#pragma omp task";
2871 else
2872 ctx->cancellable = true;
2873 kind = "taskgroup";
2874 break;
2875 default:
2876 error_at (gimple_location (stmt), "invalid arguments");
2877 return false;
2879 if (bad)
2881 error_at (gimple_location (stmt),
2882 "%<%s %s%> construct not closely nested inside of %qs",
2883 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2884 == BUILT_IN_GOMP_CANCEL
2885 ? "#pragma omp cancel"
2886 : "#pragma omp cancellation point", kind, bad);
2887 return false;
2890 /* FALLTHRU */
2891 case GIMPLE_OMP_SECTIONS:
2892 case GIMPLE_OMP_SINGLE:
2893 for (; ctx != NULL; ctx = ctx->outer)
2894 switch (gimple_code (ctx->stmt))
2896 case GIMPLE_OMP_FOR:
2897 case GIMPLE_OMP_SECTIONS:
2898 case GIMPLE_OMP_SINGLE:
2899 case GIMPLE_OMP_ORDERED:
2900 case GIMPLE_OMP_MASTER:
2901 case GIMPLE_OMP_TASK:
2902 case GIMPLE_OMP_CRITICAL:
2903 if (is_gimple_call (stmt))
2905 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2906 != BUILT_IN_GOMP_BARRIER)
2907 return true;
2908 error_at (gimple_location (stmt),
2909 "barrier region may not be closely nested inside "
2910 "of work-sharing, critical, ordered, master or "
2911 "explicit task region");
2912 return false;
2914 error_at (gimple_location (stmt),
2915 "work-sharing region may not be closely nested inside "
2916 "of work-sharing, critical, ordered, master or explicit "
2917 "task region");
2918 return false;
2919 case GIMPLE_OMP_PARALLEL:
2920 return true;
2921 default:
2922 break;
2924 break;
2925 case GIMPLE_OMP_MASTER:
2926 for (; ctx != NULL; ctx = ctx->outer)
2927 switch (gimple_code (ctx->stmt))
2929 case GIMPLE_OMP_FOR:
2930 case GIMPLE_OMP_SECTIONS:
2931 case GIMPLE_OMP_SINGLE:
2932 case GIMPLE_OMP_TASK:
2933 error_at (gimple_location (stmt),
2934 "master region may not be closely nested inside "
2935 "of work-sharing or explicit task region");
2936 return false;
2937 case GIMPLE_OMP_PARALLEL:
2938 return true;
2939 default:
2940 break;
2942 break;
2943 case GIMPLE_OMP_ORDERED:
2944 for (; ctx != NULL; ctx = ctx->outer)
2945 switch (gimple_code (ctx->stmt))
2947 case GIMPLE_OMP_CRITICAL:
2948 case GIMPLE_OMP_TASK:
2949 error_at (gimple_location (stmt),
2950 "ordered region may not be closely nested inside "
2951 "of critical or explicit task region");
2952 return false;
2953 case GIMPLE_OMP_FOR:
2954 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2955 OMP_CLAUSE_ORDERED) == NULL)
2957 error_at (gimple_location (stmt),
2958 "ordered region must be closely nested inside "
2959 "a loop region with an ordered clause");
2960 return false;
2962 return true;
2963 case GIMPLE_OMP_PARALLEL:
2964 error_at (gimple_location (stmt),
2965 "ordered region must be closely nested inside "
2966 "a loop region with an ordered clause");
2967 return false;
2968 default:
2969 break;
2971 break;
2972 case GIMPLE_OMP_CRITICAL:
2974 tree this_stmt_name
2975 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2976 for (; ctx != NULL; ctx = ctx->outer)
2977 if (gomp_critical *other_crit
2978 = dyn_cast <gomp_critical *> (ctx->stmt))
2979 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2981 error_at (gimple_location (stmt),
2982 "critical region may not be nested inside a critical "
2983 "region with the same name");
2984 return false;
2987 break;
2988 case GIMPLE_OMP_TEAMS:
2989 if (ctx == NULL
2990 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2991 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2993 error_at (gimple_location (stmt),
2994 "teams construct not closely nested inside of target "
2995 "region");
2996 return false;
2998 break;
2999 case GIMPLE_OMP_TARGET:
3000 for (; ctx != NULL; ctx = ctx->outer)
3002 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3004 if (is_gimple_omp (stmt)
3005 && is_gimple_omp_oacc (stmt)
3006 && is_gimple_omp (ctx->stmt))
3008 error_at (gimple_location (stmt),
3009 "OpenACC construct inside of non-OpenACC region");
3010 return false;
3012 continue;
3015 const char *stmt_name, *ctx_stmt_name;
3016 switch (gimple_omp_target_kind (stmt))
3018 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3019 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3020 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3021 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3022 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3023 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3024 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3025 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3026 default: gcc_unreachable ();
3028 switch (gimple_omp_target_kind (ctx->stmt))
3030 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3031 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3032 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3033 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3034 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3035 default: gcc_unreachable ();
3038 /* OpenACC/OpenMP mismatch? */
3039 if (is_gimple_omp_oacc (stmt)
3040 != is_gimple_omp_oacc (ctx->stmt))
3042 error_at (gimple_location (stmt),
3043 "%s %s construct inside of %s %s region",
3044 (is_gimple_omp_oacc (stmt)
3045 ? "OpenACC" : "OpenMP"), stmt_name,
3046 (is_gimple_omp_oacc (ctx->stmt)
3047 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3048 return false;
3050 if (is_gimple_omp_offloaded (ctx->stmt))
3052 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3053 if (is_gimple_omp_oacc (ctx->stmt))
3055 error_at (gimple_location (stmt),
3056 "%s construct inside of %s region",
3057 stmt_name, ctx_stmt_name);
3058 return false;
3060 else
3062 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3063 warning_at (gimple_location (stmt), 0,
3064 "%s construct inside of %s region",
3065 stmt_name, ctx_stmt_name);
3069 break;
3070 default:
3071 break;
3073 return true;
3077 /* Helper function scan_omp.
3079 Callback for walk_tree or operators in walk_gimple_stmt used to
3080 scan for OMP directives in TP. */
3082 static tree
3083 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3085 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3086 omp_context *ctx = (omp_context *) wi->info;
3087 tree t = *tp;
3089 switch (TREE_CODE (t))
3091 case VAR_DECL:
3092 case PARM_DECL:
3093 case LABEL_DECL:
3094 case RESULT_DECL:
3095 if (ctx)
3096 *tp = remap_decl (t, &ctx->cb);
3097 break;
3099 default:
3100 if (ctx && TYPE_P (t))
3101 *tp = remap_type (t, &ctx->cb);
3102 else if (!DECL_P (t))
3104 *walk_subtrees = 1;
3105 if (ctx)
3107 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3108 if (tem != TREE_TYPE (t))
3110 if (TREE_CODE (t) == INTEGER_CST)
3111 *tp = wide_int_to_tree (tem, t);
3112 else
3113 TREE_TYPE (t) = tem;
3117 break;
3120 return NULL_TREE;
3123 /* Return true if FNDECL is a setjmp or a longjmp. */
3125 static bool
3126 setjmp_or_longjmp_p (const_tree fndecl)
3128 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3129 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3130 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3131 return true;
3133 tree declname = DECL_NAME (fndecl);
3134 if (!declname)
3135 return false;
3136 const char *name = IDENTIFIER_POINTER (declname);
3137 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3141 /* Helper function for scan_omp.
3143 Callback for walk_gimple_stmt used to scan for OMP directives in
3144 the current statement in GSI. */
3146 static tree
3147 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3148 struct walk_stmt_info *wi)
3150 gimple stmt = gsi_stmt (*gsi);
3151 omp_context *ctx = (omp_context *) wi->info;
3153 if (gimple_has_location (stmt))
3154 input_location = gimple_location (stmt);
3156 /* Check the nesting restrictions. */
3157 bool remove = false;
3158 if (is_gimple_omp (stmt))
3159 remove = !check_omp_nesting_restrictions (stmt, ctx);
3160 else if (is_gimple_call (stmt))
3162 tree fndecl = gimple_call_fndecl (stmt);
3163 if (fndecl)
3165 if (setjmp_or_longjmp_p (fndecl)
3166 && ctx
3167 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3168 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3170 remove = true;
3171 error_at (gimple_location (stmt),
3172 "setjmp/longjmp inside simd construct");
3174 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3175 switch (DECL_FUNCTION_CODE (fndecl))
3177 case BUILT_IN_GOMP_BARRIER:
3178 case BUILT_IN_GOMP_CANCEL:
3179 case BUILT_IN_GOMP_CANCELLATION_POINT:
3180 case BUILT_IN_GOMP_TASKYIELD:
3181 case BUILT_IN_GOMP_TASKWAIT:
3182 case BUILT_IN_GOMP_TASKGROUP_START:
3183 case BUILT_IN_GOMP_TASKGROUP_END:
3184 remove = !check_omp_nesting_restrictions (stmt, ctx);
3185 break;
3186 default:
3187 break;
3191 if (remove)
3193 stmt = gimple_build_nop ();
3194 gsi_replace (gsi, stmt, false);
3197 *handled_ops_p = true;
3199 switch (gimple_code (stmt))
3201 case GIMPLE_OMP_PARALLEL:
3202 taskreg_nesting_level++;
3203 scan_omp_parallel (gsi, ctx);
3204 taskreg_nesting_level--;
3205 break;
3207 case GIMPLE_OMP_TASK:
3208 taskreg_nesting_level++;
3209 scan_omp_task (gsi, ctx);
3210 taskreg_nesting_level--;
3211 break;
3213 case GIMPLE_OMP_FOR:
3214 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3215 break;
3217 case GIMPLE_OMP_SECTIONS:
3218 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3219 break;
3221 case GIMPLE_OMP_SINGLE:
3222 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3223 break;
3225 case GIMPLE_OMP_SECTION:
3226 case GIMPLE_OMP_MASTER:
3227 case GIMPLE_OMP_TASKGROUP:
3228 case GIMPLE_OMP_ORDERED:
3229 case GIMPLE_OMP_CRITICAL:
3230 ctx = new_omp_context (stmt, ctx);
3231 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3232 break;
3234 case GIMPLE_OMP_TARGET:
3235 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3236 break;
3238 case GIMPLE_OMP_TEAMS:
3239 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3240 break;
3242 case GIMPLE_BIND:
3244 tree var;
3246 *handled_ops_p = false;
3247 if (ctx)
3248 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3249 var ;
3250 var = DECL_CHAIN (var))
3251 insert_decl_map (&ctx->cb, var, var);
3253 break;
3254 default:
3255 *handled_ops_p = false;
3256 break;
3259 return NULL_TREE;
3263 /* Scan all the statements starting at the current statement. CTX
3264 contains context information about the OMP directives and
3265 clauses found during the scan. */
3267 static void
3268 scan_omp (gimple_seq *body_p, omp_context *ctx)
3270 location_t saved_location;
3271 struct walk_stmt_info wi;
3273 memset (&wi, 0, sizeof (wi));
3274 wi.info = ctx;
3275 wi.want_locations = true;
3277 saved_location = input_location;
3278 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3279 input_location = saved_location;
3282 /* Re-gimplification and code generation routines. */
3284 /* Build a call to GOMP_barrier. */
3286 static gimple
3287 build_omp_barrier (tree lhs)
3289 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3290 : BUILT_IN_GOMP_BARRIER);
3291 gcall *g = gimple_build_call (fndecl, 0);
3292 if (lhs)
3293 gimple_call_set_lhs (g, lhs);
3294 return g;
3297 /* If a context was created for STMT when it was scanned, return it. */
3299 static omp_context *
3300 maybe_lookup_ctx (gimple stmt)
3302 splay_tree_node n;
3303 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3304 return n ? (omp_context *) n->value : NULL;
3308 /* Find the mapping for DECL in CTX or the immediately enclosing
3309 context that has a mapping for DECL.
3311 If CTX is a nested parallel directive, we may have to use the decl
3312 mappings created in CTX's parent context. Suppose that we have the
3313 following parallel nesting (variable UIDs showed for clarity):
3315 iD.1562 = 0;
3316 #omp parallel shared(iD.1562) -> outer parallel
3317 iD.1562 = iD.1562 + 1;
3319 #omp parallel shared (iD.1562) -> inner parallel
3320 iD.1562 = iD.1562 - 1;
3322 Each parallel structure will create a distinct .omp_data_s structure
3323 for copying iD.1562 in/out of the directive:
3325 outer parallel .omp_data_s.1.i -> iD.1562
3326 inner parallel .omp_data_s.2.i -> iD.1562
3328 A shared variable mapping will produce a copy-out operation before
3329 the parallel directive and a copy-in operation after it. So, in
3330 this case we would have:
3332 iD.1562 = 0;
3333 .omp_data_o.1.i = iD.1562;
3334 #omp parallel shared(iD.1562) -> outer parallel
3335 .omp_data_i.1 = &.omp_data_o.1
3336 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3338 .omp_data_o.2.i = iD.1562; -> **
3339 #omp parallel shared(iD.1562) -> inner parallel
3340 .omp_data_i.2 = &.omp_data_o.2
3341 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3344 ** This is a problem. The symbol iD.1562 cannot be referenced
3345 inside the body of the outer parallel region. But since we are
3346 emitting this copy operation while expanding the inner parallel
3347 directive, we need to access the CTX structure of the outer
3348 parallel directive to get the correct mapping:
3350 .omp_data_o.2.i = .omp_data_i.1->i
3352 Since there may be other workshare or parallel directives enclosing
3353 the parallel directive, it may be necessary to walk up the context
3354 parent chain. This is not a problem in general because nested
3355 parallelism happens only rarely. */
3357 static tree
3358 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3360 tree t;
3361 omp_context *up;
3363 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3364 t = maybe_lookup_decl (decl, up);
3366 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3368 return t ? t : decl;
3372 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3373 in outer contexts. */
3375 static tree
3376 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3378 tree t = NULL;
3379 omp_context *up;
3381 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3382 t = maybe_lookup_decl (decl, up);
3384 return t ? t : decl;
3388 /* Construct the initialization value for reduction CLAUSE. */
3390 tree
3391 omp_reduction_init (tree clause, tree type)
3393 location_t loc = OMP_CLAUSE_LOCATION (clause);
3394 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3396 case PLUS_EXPR:
3397 case MINUS_EXPR:
3398 case BIT_IOR_EXPR:
3399 case BIT_XOR_EXPR:
3400 case TRUTH_OR_EXPR:
3401 case TRUTH_ORIF_EXPR:
3402 case TRUTH_XOR_EXPR:
3403 case NE_EXPR:
3404 return build_zero_cst (type);
3406 case MULT_EXPR:
3407 case TRUTH_AND_EXPR:
3408 case TRUTH_ANDIF_EXPR:
3409 case EQ_EXPR:
3410 return fold_convert_loc (loc, type, integer_one_node);
3412 case BIT_AND_EXPR:
3413 return fold_convert_loc (loc, type, integer_minus_one_node);
3415 case MAX_EXPR:
3416 if (SCALAR_FLOAT_TYPE_P (type))
3418 REAL_VALUE_TYPE max, min;
3419 if (HONOR_INFINITIES (type))
3421 real_inf (&max);
3422 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3424 else
3425 real_maxval (&min, 1, TYPE_MODE (type));
3426 return build_real (type, min);
3428 else
3430 gcc_assert (INTEGRAL_TYPE_P (type));
3431 return TYPE_MIN_VALUE (type);
3434 case MIN_EXPR:
3435 if (SCALAR_FLOAT_TYPE_P (type))
3437 REAL_VALUE_TYPE max;
3438 if (HONOR_INFINITIES (type))
3439 real_inf (&max);
3440 else
3441 real_maxval (&max, 0, TYPE_MODE (type));
3442 return build_real (type, max);
3444 else
3446 gcc_assert (INTEGRAL_TYPE_P (type));
3447 return TYPE_MAX_VALUE (type);
3450 default:
3451 gcc_unreachable ();
3455 /* Return alignment to be assumed for var in CLAUSE, which should be
3456 OMP_CLAUSE_ALIGNED. */
3458 static tree
3459 omp_clause_aligned_alignment (tree clause)
3461 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3462 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3464 /* Otherwise return implementation defined alignment. */
3465 unsigned int al = 1;
3466 machine_mode mode, vmode;
3467 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3468 if (vs)
3469 vs = 1 << floor_log2 (vs);
3470 static enum mode_class classes[]
3471 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3472 for (int i = 0; i < 4; i += 2)
3473 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3474 mode != VOIDmode;
3475 mode = GET_MODE_WIDER_MODE (mode))
3477 vmode = targetm.vectorize.preferred_simd_mode (mode);
3478 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3479 continue;
3480 while (vs
3481 && GET_MODE_SIZE (vmode) < vs
3482 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3483 vmode = GET_MODE_2XWIDER_MODE (vmode);
3485 tree type = lang_hooks.types.type_for_mode (mode, 1);
3486 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3487 continue;
3488 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3489 / GET_MODE_SIZE (mode));
3490 if (TYPE_MODE (type) != vmode)
3491 continue;
3492 if (TYPE_ALIGN_UNIT (type) > al)
3493 al = TYPE_ALIGN_UNIT (type);
3495 return build_int_cst (integer_type_node, al);
3498 /* Return maximum possible vectorization factor for the target. */
3500 static int
3501 omp_max_vf (void)
3503 if (!optimize
3504 || optimize_debug
3505 || !flag_tree_loop_optimize
3506 || (!flag_tree_loop_vectorize
3507 && (global_options_set.x_flag_tree_loop_vectorize
3508 || global_options_set.x_flag_tree_vectorize)))
3509 return 1;
3511 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3512 if (vs)
3514 vs = 1 << floor_log2 (vs);
3515 return vs;
3517 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3518 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3519 return GET_MODE_NUNITS (vqimode);
3520 return 1;
3523 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3524 privatization. */
3526 static bool
3527 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3528 tree &idx, tree &lane, tree &ivar, tree &lvar)
3530 if (max_vf == 0)
3532 max_vf = omp_max_vf ();
3533 if (max_vf > 1)
3535 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3536 OMP_CLAUSE_SAFELEN);
3537 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3538 max_vf = 1;
3539 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3540 max_vf) == -1)
3541 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3543 if (max_vf > 1)
3545 idx = create_tmp_var (unsigned_type_node);
3546 lane = create_tmp_var (unsigned_type_node);
3549 if (max_vf == 1)
3550 return false;
3552 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3553 tree avar = create_tmp_var_raw (atype);
3554 if (TREE_ADDRESSABLE (new_var))
3555 TREE_ADDRESSABLE (avar) = 1;
3556 DECL_ATTRIBUTES (avar)
3557 = tree_cons (get_identifier ("omp simd array"), NULL,
3558 DECL_ATTRIBUTES (avar));
3559 gimple_add_tmp_var (avar);
3560 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3561 NULL_TREE, NULL_TREE);
3562 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3563 NULL_TREE, NULL_TREE);
3564 if (DECL_P (new_var))
3566 SET_DECL_VALUE_EXPR (new_var, lvar);
3567 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3569 return true;
3572 /* Helper function of lower_rec_input_clauses. For a reference
3573 in simd reduction, add an underlying variable it will reference. */
3575 static void
3576 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3578 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3579 if (TREE_CONSTANT (z))
3581 const char *name = NULL;
3582 if (DECL_NAME (new_vard))
3583 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3585 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3586 gimple_add_tmp_var (z);
3587 TREE_ADDRESSABLE (z) = 1;
3588 z = build_fold_addr_expr_loc (loc, z);
3589 gimplify_assign (new_vard, z, ilist);
3593 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3594 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3595 private variables. Initialization statements go in ILIST, while calls
3596 to destructors go in DLIST. */
3598 static void
3599 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3600 omp_context *ctx, struct omp_for_data *fd)
3602 tree c, dtor, copyin_seq, x, ptr;
3603 bool copyin_by_ref = false;
3604 bool lastprivate_firstprivate = false;
3605 bool reduction_omp_orig_ref = false;
3606 int pass;
3607 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3608 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3609 int max_vf = 0;
3610 tree lane = NULL_TREE, idx = NULL_TREE;
3611 tree ivar = NULL_TREE, lvar = NULL_TREE;
3612 gimple_seq llist[2] = { NULL, NULL };
3614 copyin_seq = NULL;
3616 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3617 with data sharing clauses referencing variable sized vars. That
3618 is unnecessarily hard to support and very unlikely to result in
3619 vectorized code anyway. */
3620 if (is_simd)
3621 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3622 switch (OMP_CLAUSE_CODE (c))
3624 case OMP_CLAUSE_LINEAR:
3625 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3626 max_vf = 1;
3627 /* FALLTHRU */
3628 case OMP_CLAUSE_REDUCTION:
3629 case OMP_CLAUSE_PRIVATE:
3630 case OMP_CLAUSE_FIRSTPRIVATE:
3631 case OMP_CLAUSE_LASTPRIVATE:
3632 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3633 max_vf = 1;
3634 break;
3635 default:
3636 continue;
3639 /* Do all the fixed sized types in the first pass, and the variable sized
3640 types in the second pass. This makes sure that the scalar arguments to
3641 the variable sized types are processed before we use them in the
3642 variable sized operations. */
3643 for (pass = 0; pass < 2; ++pass)
3645 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3647 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3648 tree var, new_var;
3649 bool by_ref;
3650 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3652 switch (c_kind)
3654 case OMP_CLAUSE_PRIVATE:
3655 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3656 continue;
3657 break;
3658 case OMP_CLAUSE_SHARED:
3659 /* Ignore shared directives in teams construct. */
3660 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3661 continue;
3662 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3664 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3665 continue;
3667 case OMP_CLAUSE_FIRSTPRIVATE:
3668 case OMP_CLAUSE_COPYIN:
3669 case OMP_CLAUSE_LINEAR:
3670 break;
3671 case OMP_CLAUSE_REDUCTION:
3672 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3673 reduction_omp_orig_ref = true;
3674 break;
3675 case OMP_CLAUSE__LOOPTEMP_:
3676 /* Handle _looptemp_ clauses only on parallel. */
3677 if (fd)
3678 continue;
3679 break;
3680 case OMP_CLAUSE_LASTPRIVATE:
3681 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3683 lastprivate_firstprivate = true;
3684 if (pass != 0)
3685 continue;
3687 /* Even without corresponding firstprivate, if
3688 decl is Fortran allocatable, it needs outer var
3689 reference. */
3690 else if (pass == 0
3691 && lang_hooks.decls.omp_private_outer_ref
3692 (OMP_CLAUSE_DECL (c)))
3693 lastprivate_firstprivate = true;
3694 break;
3695 case OMP_CLAUSE_ALIGNED:
3696 if (pass == 0)
3697 continue;
3698 var = OMP_CLAUSE_DECL (c);
3699 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3700 && !is_global_var (var))
3702 new_var = maybe_lookup_decl (var, ctx);
3703 if (new_var == NULL_TREE)
3704 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3705 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3706 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3707 omp_clause_aligned_alignment (c));
3708 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3709 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3710 gimplify_and_add (x, ilist);
3712 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3713 && is_global_var (var))
3715 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3716 new_var = lookup_decl (var, ctx);
3717 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3718 t = build_fold_addr_expr_loc (clause_loc, t);
3719 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3720 t = build_call_expr_loc (clause_loc, t2, 2, t,
3721 omp_clause_aligned_alignment (c));
3722 t = fold_convert_loc (clause_loc, ptype, t);
3723 x = create_tmp_var (ptype);
3724 t = build2 (MODIFY_EXPR, ptype, x, t);
3725 gimplify_and_add (t, ilist);
3726 t = build_simple_mem_ref_loc (clause_loc, x);
3727 SET_DECL_VALUE_EXPR (new_var, t);
3728 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3730 continue;
3731 default:
3732 continue;
3735 new_var = var = OMP_CLAUSE_DECL (c);
3736 if (c_kind != OMP_CLAUSE_COPYIN)
3737 new_var = lookup_decl (var, ctx);
3739 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3741 if (pass != 0)
3742 continue;
3744 else if (is_variable_sized (var))
3746 /* For variable sized types, we need to allocate the
3747 actual storage here. Call alloca and store the
3748 result in the pointer decl that we created elsewhere. */
3749 if (pass == 0)
3750 continue;
3752 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3754 gcall *stmt;
3755 tree tmp, atmp;
3757 ptr = DECL_VALUE_EXPR (new_var);
3758 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3759 ptr = TREE_OPERAND (ptr, 0);
3760 gcc_assert (DECL_P (ptr));
3761 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3763 /* void *tmp = __builtin_alloca */
3764 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3765 stmt = gimple_build_call (atmp, 1, x);
3766 tmp = create_tmp_var_raw (ptr_type_node);
3767 gimple_add_tmp_var (tmp);
3768 gimple_call_set_lhs (stmt, tmp);
3770 gimple_seq_add_stmt (ilist, stmt);
3772 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3773 gimplify_assign (ptr, x, ilist);
3776 else if (is_reference (var))
3778 /* For references that are being privatized for Fortran,
3779 allocate new backing storage for the new pointer
3780 variable. This allows us to avoid changing all the
3781 code that expects a pointer to something that expects
3782 a direct variable. */
3783 if (pass == 0)
3784 continue;
3786 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3787 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3789 x = build_receiver_ref (var, false, ctx);
3790 x = build_fold_addr_expr_loc (clause_loc, x);
3792 else if (TREE_CONSTANT (x))
3794 /* For reduction in SIMD loop, defer adding the
3795 initialization of the reference, because if we decide
3796 to use SIMD array for it, the initilization could cause
3797 expansion ICE. */
3798 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3799 x = NULL_TREE;
3800 else
3802 const char *name = NULL;
3803 if (DECL_NAME (var))
3804 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3806 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3807 name);
3808 gimple_add_tmp_var (x);
3809 TREE_ADDRESSABLE (x) = 1;
3810 x = build_fold_addr_expr_loc (clause_loc, x);
3813 else
3815 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3816 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3819 if (x)
3821 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3822 gimplify_assign (new_var, x, ilist);
3825 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3827 else if (c_kind == OMP_CLAUSE_REDUCTION
3828 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3830 if (pass == 0)
3831 continue;
3833 else if (pass != 0)
3834 continue;
3836 switch (OMP_CLAUSE_CODE (c))
3838 case OMP_CLAUSE_SHARED:
3839 /* Ignore shared directives in teams construct. */
3840 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3841 continue;
3842 /* Shared global vars are just accessed directly. */
3843 if (is_global_var (new_var))
3844 break;
3845 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3846 needs to be delayed until after fixup_child_record_type so
3847 that we get the correct type during the dereference. */
3848 by_ref = use_pointer_for_field (var, ctx);
3849 x = build_receiver_ref (var, by_ref, ctx);
3850 SET_DECL_VALUE_EXPR (new_var, x);
3851 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3853 /* ??? If VAR is not passed by reference, and the variable
3854 hasn't been initialized yet, then we'll get a warning for
3855 the store into the omp_data_s structure. Ideally, we'd be
3856 able to notice this and not store anything at all, but
3857 we're generating code too early. Suppress the warning. */
3858 if (!by_ref)
3859 TREE_NO_WARNING (var) = 1;
3860 break;
3862 case OMP_CLAUSE_LASTPRIVATE:
3863 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3864 break;
3865 /* FALLTHRU */
3867 case OMP_CLAUSE_PRIVATE:
3868 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3869 x = build_outer_var_ref (var, ctx);
3870 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3872 if (is_task_ctx (ctx))
3873 x = build_receiver_ref (var, false, ctx);
3874 else
3875 x = build_outer_var_ref (var, ctx);
3877 else
3878 x = NULL;
3879 do_private:
3880 tree nx;
3881 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3882 if (is_simd)
3884 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3885 if ((TREE_ADDRESSABLE (new_var) || nx || y
3886 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3887 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3888 idx, lane, ivar, lvar))
3890 if (nx)
3891 x = lang_hooks.decls.omp_clause_default_ctor
3892 (c, unshare_expr (ivar), x);
3893 if (nx && x)
3894 gimplify_and_add (x, &llist[0]);
3895 if (y)
3897 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3898 if (y)
3900 gimple_seq tseq = NULL;
3902 dtor = y;
3903 gimplify_stmt (&dtor, &tseq);
3904 gimple_seq_add_seq (&llist[1], tseq);
3907 break;
3910 if (nx)
3911 gimplify_and_add (nx, ilist);
3912 /* FALLTHRU */
3914 do_dtor:
3915 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3916 if (x)
3918 gimple_seq tseq = NULL;
3920 dtor = x;
3921 gimplify_stmt (&dtor, &tseq);
3922 gimple_seq_add_seq (dlist, tseq);
3924 break;
3926 case OMP_CLAUSE_LINEAR:
3927 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3928 goto do_firstprivate;
3929 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3930 x = NULL;
3931 else
3932 x = build_outer_var_ref (var, ctx);
3933 goto do_private;
3935 case OMP_CLAUSE_FIRSTPRIVATE:
3936 if (is_task_ctx (ctx))
3938 if (is_reference (var) || is_variable_sized (var))
3939 goto do_dtor;
3940 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3941 ctx))
3942 || use_pointer_for_field (var, NULL))
3944 x = build_receiver_ref (var, false, ctx);
3945 SET_DECL_VALUE_EXPR (new_var, x);
3946 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3947 goto do_dtor;
3950 do_firstprivate:
3951 x = build_outer_var_ref (var, ctx);
3952 if (is_simd)
3954 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3955 && gimple_omp_for_combined_into_p (ctx->stmt))
3957 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3958 tree stept = TREE_TYPE (t);
3959 tree ct = find_omp_clause (clauses,
3960 OMP_CLAUSE__LOOPTEMP_);
3961 gcc_assert (ct);
3962 tree l = OMP_CLAUSE_DECL (ct);
3963 tree n1 = fd->loop.n1;
3964 tree step = fd->loop.step;
3965 tree itype = TREE_TYPE (l);
3966 if (POINTER_TYPE_P (itype))
3967 itype = signed_type_for (itype);
3968 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3969 if (TYPE_UNSIGNED (itype)
3970 && fd->loop.cond_code == GT_EXPR)
3971 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3972 fold_build1 (NEGATE_EXPR, itype, l),
3973 fold_build1 (NEGATE_EXPR,
3974 itype, step));
3975 else
3976 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3977 t = fold_build2 (MULT_EXPR, stept,
3978 fold_convert (stept, l), t);
3980 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3982 x = lang_hooks.decls.omp_clause_linear_ctor
3983 (c, new_var, x, t);
3984 gimplify_and_add (x, ilist);
3985 goto do_dtor;
3988 if (POINTER_TYPE_P (TREE_TYPE (x)))
3989 x = fold_build2 (POINTER_PLUS_EXPR,
3990 TREE_TYPE (x), x, t);
3991 else
3992 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3995 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3996 || TREE_ADDRESSABLE (new_var))
3997 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3998 idx, lane, ivar, lvar))
4000 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4002 tree iv = create_tmp_var (TREE_TYPE (new_var));
4003 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4004 gimplify_and_add (x, ilist);
4005 gimple_stmt_iterator gsi
4006 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4007 gassign *g
4008 = gimple_build_assign (unshare_expr (lvar), iv);
4009 gsi_insert_before_without_update (&gsi, g,
4010 GSI_SAME_STMT);
4011 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4012 enum tree_code code = PLUS_EXPR;
4013 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4014 code = POINTER_PLUS_EXPR;
4015 g = gimple_build_assign (iv, code, iv, t);
4016 gsi_insert_before_without_update (&gsi, g,
4017 GSI_SAME_STMT);
4018 break;
4020 x = lang_hooks.decls.omp_clause_copy_ctor
4021 (c, unshare_expr (ivar), x);
4022 gimplify_and_add (x, &llist[0]);
4023 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4024 if (x)
4026 gimple_seq tseq = NULL;
4028 dtor = x;
4029 gimplify_stmt (&dtor, &tseq);
4030 gimple_seq_add_seq (&llist[1], tseq);
4032 break;
4035 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4036 gimplify_and_add (x, ilist);
4037 goto do_dtor;
4039 case OMP_CLAUSE__LOOPTEMP_:
4040 gcc_assert (is_parallel_ctx (ctx));
4041 x = build_outer_var_ref (var, ctx);
4042 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4043 gimplify_and_add (x, ilist);
4044 break;
4046 case OMP_CLAUSE_COPYIN:
4047 by_ref = use_pointer_for_field (var, NULL);
4048 x = build_receiver_ref (var, by_ref, ctx);
4049 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4050 append_to_statement_list (x, &copyin_seq);
4051 copyin_by_ref |= by_ref;
4052 break;
4054 case OMP_CLAUSE_REDUCTION:
4055 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4057 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4058 gimple tseq;
4059 x = build_outer_var_ref (var, ctx);
4061 if (is_reference (var)
4062 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4063 TREE_TYPE (x)))
4064 x = build_fold_addr_expr_loc (clause_loc, x);
4065 SET_DECL_VALUE_EXPR (placeholder, x);
4066 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4067 tree new_vard = new_var;
4068 if (is_reference (var))
4070 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4071 new_vard = TREE_OPERAND (new_var, 0);
4072 gcc_assert (DECL_P (new_vard));
4074 if (is_simd
4075 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4076 idx, lane, ivar, lvar))
4078 if (new_vard == new_var)
4080 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4081 SET_DECL_VALUE_EXPR (new_var, ivar);
4083 else
4085 SET_DECL_VALUE_EXPR (new_vard,
4086 build_fold_addr_expr (ivar));
4087 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4089 x = lang_hooks.decls.omp_clause_default_ctor
4090 (c, unshare_expr (ivar),
4091 build_outer_var_ref (var, ctx));
4092 if (x)
4093 gimplify_and_add (x, &llist[0]);
4094 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4096 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4097 lower_omp (&tseq, ctx);
4098 gimple_seq_add_seq (&llist[0], tseq);
4100 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4101 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4102 lower_omp (&tseq, ctx);
4103 gimple_seq_add_seq (&llist[1], tseq);
4104 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4105 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4106 if (new_vard == new_var)
4107 SET_DECL_VALUE_EXPR (new_var, lvar);
4108 else
4109 SET_DECL_VALUE_EXPR (new_vard,
4110 build_fold_addr_expr (lvar));
4111 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4112 if (x)
4114 tseq = NULL;
4115 dtor = x;
4116 gimplify_stmt (&dtor, &tseq);
4117 gimple_seq_add_seq (&llist[1], tseq);
4119 break;
4121 /* If this is a reference to constant size reduction var
4122 with placeholder, we haven't emitted the initializer
4123 for it because it is undesirable if SIMD arrays are used.
4124 But if they aren't used, we need to emit the deferred
4125 initialization now. */
4126 else if (is_reference (var) && is_simd)
4127 handle_simd_reference (clause_loc, new_vard, ilist);
4128 x = lang_hooks.decls.omp_clause_default_ctor
4129 (c, unshare_expr (new_var),
4130 build_outer_var_ref (var, ctx));
4131 if (x)
4132 gimplify_and_add (x, ilist);
4133 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4135 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4136 lower_omp (&tseq, ctx);
4137 gimple_seq_add_seq (ilist, tseq);
4139 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4140 if (is_simd)
4142 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4143 lower_omp (&tseq, ctx);
4144 gimple_seq_add_seq (dlist, tseq);
4145 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4147 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4148 goto do_dtor;
4150 else
4152 x = omp_reduction_init (c, TREE_TYPE (new_var));
4153 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4154 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4156 /* reduction(-:var) sums up the partial results, so it
4157 acts identically to reduction(+:var). */
4158 if (code == MINUS_EXPR)
4159 code = PLUS_EXPR;
4161 tree new_vard = new_var;
4162 if (is_simd && is_reference (var))
4164 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4165 new_vard = TREE_OPERAND (new_var, 0);
4166 gcc_assert (DECL_P (new_vard));
4168 if (is_simd
4169 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4170 idx, lane, ivar, lvar))
4172 tree ref = build_outer_var_ref (var, ctx);
4174 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4176 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4177 ref = build_outer_var_ref (var, ctx);
4178 gimplify_assign (ref, x, &llist[1]);
4180 if (new_vard != new_var)
4182 SET_DECL_VALUE_EXPR (new_vard,
4183 build_fold_addr_expr (lvar));
4184 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4187 else
4189 if (is_reference (var) && is_simd)
4190 handle_simd_reference (clause_loc, new_vard, ilist);
4191 gimplify_assign (new_var, x, ilist);
4192 if (is_simd)
4194 tree ref = build_outer_var_ref (var, ctx);
4196 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4197 ref = build_outer_var_ref (var, ctx);
4198 gimplify_assign (ref, x, dlist);
4202 break;
4204 default:
4205 gcc_unreachable ();
4210 if (lane)
4212 tree uid = create_tmp_var (ptr_type_node, "simduid");
4213 /* Don't want uninit warnings on simduid, it is always uninitialized,
4214 but we use it not for the value, but for the DECL_UID only. */
4215 TREE_NO_WARNING (uid) = 1;
4216 gimple g
4217 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4218 gimple_call_set_lhs (g, lane);
4219 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4220 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4221 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4222 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4223 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4224 gimple_omp_for_set_clauses (ctx->stmt, c);
4225 g = gimple_build_assign (lane, INTEGER_CST,
4226 build_int_cst (unsigned_type_node, 0));
4227 gimple_seq_add_stmt (ilist, g);
4228 for (int i = 0; i < 2; i++)
4229 if (llist[i])
4231 tree vf = create_tmp_var (unsigned_type_node);
4232 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4233 gimple_call_set_lhs (g, vf);
4234 gimple_seq *seq = i == 0 ? ilist : dlist;
4235 gimple_seq_add_stmt (seq, g);
4236 tree t = build_int_cst (unsigned_type_node, 0);
4237 g = gimple_build_assign (idx, INTEGER_CST, t);
4238 gimple_seq_add_stmt (seq, g);
4239 tree body = create_artificial_label (UNKNOWN_LOCATION);
4240 tree header = create_artificial_label (UNKNOWN_LOCATION);
4241 tree end = create_artificial_label (UNKNOWN_LOCATION);
4242 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4243 gimple_seq_add_stmt (seq, gimple_build_label (body));
4244 gimple_seq_add_seq (seq, llist[i]);
4245 t = build_int_cst (unsigned_type_node, 1);
4246 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4247 gimple_seq_add_stmt (seq, g);
4248 gimple_seq_add_stmt (seq, gimple_build_label (header));
4249 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4250 gimple_seq_add_stmt (seq, g);
4251 gimple_seq_add_stmt (seq, gimple_build_label (end));
4255 /* The copyin sequence is not to be executed by the main thread, since
4256 that would result in self-copies. Perhaps not visible to scalars,
4257 but it certainly is to C++ operator=. */
4258 if (copyin_seq)
4260 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4262 x = build2 (NE_EXPR, boolean_type_node, x,
4263 build_int_cst (TREE_TYPE (x), 0));
4264 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4265 gimplify_and_add (x, ilist);
4268 /* If any copyin variable is passed by reference, we must ensure the
4269 master thread doesn't modify it before it is copied over in all
4270 threads. Similarly for variables in both firstprivate and
4271 lastprivate clauses we need to ensure the lastprivate copying
4272 happens after firstprivate copying in all threads. And similarly
4273 for UDRs if initializer expression refers to omp_orig. */
4274 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4276 /* Don't add any barrier for #pragma omp simd or
4277 #pragma omp distribute. */
4278 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4279 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4280 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4283 /* If max_vf is non-zero, then we can use only a vectorization factor
4284 up to the max_vf we chose. So stick it into the safelen clause. */
4285 if (max_vf)
4287 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4288 OMP_CLAUSE_SAFELEN);
4289 if (c == NULL_TREE
4290 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4291 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4292 max_vf) == 1))
4294 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4295 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4296 max_vf);
4297 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4298 gimple_omp_for_set_clauses (ctx->stmt, c);
4304 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4305 both parallel and workshare constructs. PREDICATE may be NULL if it's
4306 always true. */
4308 static void
4309 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4310 omp_context *ctx)
4312 tree x, c, label = NULL, orig_clauses = clauses;
4313 bool par_clauses = false;
4314 tree simduid = NULL, lastlane = NULL;
4316 /* Early exit if there are no lastprivate or linear clauses. */
4317 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4318 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4319 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4320 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4321 break;
4322 if (clauses == NULL)
4324 /* If this was a workshare clause, see if it had been combined
4325 with its parallel. In that case, look for the clauses on the
4326 parallel statement itself. */
4327 if (is_parallel_ctx (ctx))
4328 return;
4330 ctx = ctx->outer;
4331 if (ctx == NULL || !is_parallel_ctx (ctx))
4332 return;
4334 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4335 OMP_CLAUSE_LASTPRIVATE);
4336 if (clauses == NULL)
4337 return;
4338 par_clauses = true;
4341 if (predicate)
4343 gcond *stmt;
4344 tree label_true, arm1, arm2;
4346 label = create_artificial_label (UNKNOWN_LOCATION);
4347 label_true = create_artificial_label (UNKNOWN_LOCATION);
4348 arm1 = TREE_OPERAND (predicate, 0);
4349 arm2 = TREE_OPERAND (predicate, 1);
4350 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4351 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4352 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4353 label_true, label);
4354 gimple_seq_add_stmt (stmt_list, stmt);
4355 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4358 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4359 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4361 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4362 if (simduid)
4363 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4366 for (c = clauses; c ;)
4368 tree var, new_var;
4369 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4371 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4372 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4373 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4375 var = OMP_CLAUSE_DECL (c);
4376 new_var = lookup_decl (var, ctx);
4378 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4380 tree val = DECL_VALUE_EXPR (new_var);
4381 if (TREE_CODE (val) == ARRAY_REF
4382 && VAR_P (TREE_OPERAND (val, 0))
4383 && lookup_attribute ("omp simd array",
4384 DECL_ATTRIBUTES (TREE_OPERAND (val,
4385 0))))
4387 if (lastlane == NULL)
4389 lastlane = create_tmp_var (unsigned_type_node);
4390 gcall *g
4391 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4392 2, simduid,
4393 TREE_OPERAND (val, 1));
4394 gimple_call_set_lhs (g, lastlane);
4395 gimple_seq_add_stmt (stmt_list, g);
4397 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4398 TREE_OPERAND (val, 0), lastlane,
4399 NULL_TREE, NULL_TREE);
4403 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4404 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4406 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4407 gimple_seq_add_seq (stmt_list,
4408 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4409 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4411 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4412 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4414 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4415 gimple_seq_add_seq (stmt_list,
4416 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4417 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4420 x = build_outer_var_ref (var, ctx);
4421 if (is_reference (var))
4422 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4423 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4424 gimplify_and_add (x, stmt_list);
4426 c = OMP_CLAUSE_CHAIN (c);
4427 if (c == NULL && !par_clauses)
4429 /* If this was a workshare clause, see if it had been combined
4430 with its parallel. In that case, continue looking for the
4431 clauses also on the parallel statement itself. */
4432 if (is_parallel_ctx (ctx))
4433 break;
4435 ctx = ctx->outer;
4436 if (ctx == NULL || !is_parallel_ctx (ctx))
4437 break;
4439 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4440 OMP_CLAUSE_LASTPRIVATE);
4441 par_clauses = true;
4445 if (label)
4446 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4449 static void
4450 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4451 tree tid, tree var, tree new_var)
4453 /* The atomic add at the end of the sum creates unnecessary
4454 write contention on accelerators. To work around this,
4455 create an array to store the partial reductions. Later, in
4456 lower_omp_for (for openacc), the values of array will be
4457 combined. */
4459 tree t = NULL_TREE, array, x;
4460 tree type = get_base_type (var);
4461 gimple stmt;
4463 /* Now insert the partial reductions into the array. */
4465 /* Find the reduction array. */
4467 tree ptype = build_pointer_type (type);
4469 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4470 t = build_receiver_ref (t, false, ctx->outer);
4472 array = create_tmp_var (ptype);
4473 gimplify_assign (array, t, stmt_seqp);
4475 tree ptr = create_tmp_var (TREE_TYPE (array));
4477 /* Find the reduction array. */
4479 /* testing a unary conversion. */
4480 tree offset = create_tmp_var (sizetype);
4481 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4482 stmt_seqp);
4483 t = create_tmp_var (sizetype);
4484 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4485 stmt_seqp);
4486 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4487 gimple_seq_add_stmt (stmt_seqp, stmt);
4489 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4490 of adding sizeof(var) to the array? */
4491 ptr = create_tmp_var (ptype);
4492 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4493 offset);
4494 gimple_seq_add_stmt (stmt_seqp, stmt);
4496 /* Move the local sum to gfc$sum[i]. */
4497 x = unshare_expr (build_simple_mem_ref (ptr));
4498 stmt = gimplify_assign (x, new_var, stmt_seqp);
4501 /* Generate code to implement the REDUCTION clauses. */
4503 static void
4504 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4506 gimple_seq sub_seq = NULL;
4507 gimple stmt;
4508 tree x, c, tid = NULL_TREE;
4509 int count = 0;
4511 /* SIMD reductions are handled in lower_rec_input_clauses. */
4512 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4513 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4514 return;
4516 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4517 update in that case, otherwise use a lock. */
4518 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4519 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4521 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4523 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4524 count = -1;
4525 break;
4527 count++;
4530 if (count == 0)
4531 return;
4533 /* Initialize thread info for OpenACC. */
4534 if (is_gimple_omp_oacc (ctx->stmt))
4536 /* Get the current thread id. */
4537 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4538 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4539 gimple stmt = gimple_build_call (call, 0);
4540 gimple_call_set_lhs (stmt, tid);
4541 gimple_seq_add_stmt (stmt_seqp, stmt);
4544 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4546 tree var, ref, new_var;
4547 enum tree_code code;
4548 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4550 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4551 continue;
4553 var = OMP_CLAUSE_DECL (c);
4554 new_var = lookup_decl (var, ctx);
4555 if (is_reference (var))
4556 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4557 ref = build_outer_var_ref (var, ctx);
4558 code = OMP_CLAUSE_REDUCTION_CODE (c);
4560 /* reduction(-:var) sums up the partial results, so it acts
4561 identically to reduction(+:var). */
4562 if (code == MINUS_EXPR)
4563 code = PLUS_EXPR;
4565 if (is_gimple_omp_oacc (ctx->stmt))
4567 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4569 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4571 else if (count == 1)
4573 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4575 addr = save_expr (addr);
4576 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4577 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4578 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4579 gimplify_and_add (x, stmt_seqp);
4580 return;
4582 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4584 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4586 if (is_reference (var)
4587 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4588 TREE_TYPE (ref)))
4589 ref = build_fold_addr_expr_loc (clause_loc, ref);
4590 SET_DECL_VALUE_EXPR (placeholder, ref);
4591 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4592 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4593 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4594 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4595 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4597 else
4599 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4600 ref = build_outer_var_ref (var, ctx);
4601 gimplify_assign (ref, x, &sub_seq);
4605 if (is_gimple_omp_oacc (ctx->stmt))
4606 return;
4608 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4610 gimple_seq_add_stmt (stmt_seqp, stmt);
4612 gimple_seq_add_seq (stmt_seqp, sub_seq);
4614 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4616 gimple_seq_add_stmt (stmt_seqp, stmt);
4620 /* Generate code to implement the COPYPRIVATE clauses. */
4622 static void
4623 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4624 omp_context *ctx)
4626 tree c;
4628 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4630 tree var, new_var, ref, x;
4631 bool by_ref;
4632 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4634 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4635 continue;
4637 var = OMP_CLAUSE_DECL (c);
4638 by_ref = use_pointer_for_field (var, NULL);
4640 ref = build_sender_ref (var, ctx);
4641 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4642 if (by_ref)
4644 x = build_fold_addr_expr_loc (clause_loc, new_var);
4645 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4647 gimplify_assign (ref, x, slist);
4649 ref = build_receiver_ref (var, false, ctx);
4650 if (by_ref)
4652 ref = fold_convert_loc (clause_loc,
4653 build_pointer_type (TREE_TYPE (new_var)),
4654 ref);
4655 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4657 if (is_reference (var))
4659 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4660 ref = build_simple_mem_ref_loc (clause_loc, ref);
4661 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4663 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4664 gimplify_and_add (x, rlist);
4669 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4670 and REDUCTION from the sender (aka parent) side. */
4672 static void
4673 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4674 omp_context *ctx)
4676 tree c;
4678 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4680 tree val, ref, x, var;
4681 bool by_ref, do_in = false, do_out = false;
4682 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4684 switch (OMP_CLAUSE_CODE (c))
4686 case OMP_CLAUSE_PRIVATE:
4687 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4688 break;
4689 continue;
4690 case OMP_CLAUSE_FIRSTPRIVATE:
4691 case OMP_CLAUSE_COPYIN:
4692 case OMP_CLAUSE_LASTPRIVATE:
4693 case OMP_CLAUSE_REDUCTION:
4694 case OMP_CLAUSE__LOOPTEMP_:
4695 break;
4696 default:
4697 continue;
4700 val = OMP_CLAUSE_DECL (c);
4701 var = lookup_decl_in_outer_ctx (val, ctx);
4703 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4704 && is_global_var (var))
4705 continue;
4706 if (is_variable_sized (val))
4707 continue;
4708 by_ref = use_pointer_for_field (val, NULL);
4710 switch (OMP_CLAUSE_CODE (c))
4712 case OMP_CLAUSE_PRIVATE:
4713 case OMP_CLAUSE_FIRSTPRIVATE:
4714 case OMP_CLAUSE_COPYIN:
4715 case OMP_CLAUSE__LOOPTEMP_:
4716 do_in = true;
4717 break;
4719 case OMP_CLAUSE_LASTPRIVATE:
4720 if (by_ref || is_reference (val))
4722 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4723 continue;
4724 do_in = true;
4726 else
4728 do_out = true;
4729 if (lang_hooks.decls.omp_private_outer_ref (val))
4730 do_in = true;
4732 break;
4734 case OMP_CLAUSE_REDUCTION:
4735 do_in = true;
4736 do_out = !(by_ref || is_reference (val));
4737 break;
4739 default:
4740 gcc_unreachable ();
4743 if (do_in)
4745 ref = build_sender_ref (val, ctx);
4746 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4747 gimplify_assign (ref, x, ilist);
4748 if (is_task_ctx (ctx))
4749 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4752 if (do_out)
4754 ref = build_sender_ref (val, ctx);
4755 gimplify_assign (var, ref, olist);
4760 /* Generate code to implement SHARED from the sender (aka parent)
4761 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4762 list things that got automatically shared. */
4764 static void
4765 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4767 tree var, ovar, nvar, f, x, record_type;
4769 if (ctx->record_type == NULL)
4770 return;
4772 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4773 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4775 ovar = DECL_ABSTRACT_ORIGIN (f);
4776 nvar = maybe_lookup_decl (ovar, ctx);
4777 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4778 continue;
4780 /* If CTX is a nested parallel directive. Find the immediately
4781 enclosing parallel or workshare construct that contains a
4782 mapping for OVAR. */
4783 var = lookup_decl_in_outer_ctx (ovar, ctx);
4785 if (use_pointer_for_field (ovar, ctx))
4787 x = build_sender_ref (ovar, ctx);
4788 var = build_fold_addr_expr (var);
4789 gimplify_assign (x, var, ilist);
4791 else
4793 x = build_sender_ref (ovar, ctx);
4794 gimplify_assign (x, var, ilist);
4796 if (!TREE_READONLY (var)
4797 /* We don't need to receive a new reference to a result
4798 or parm decl. In fact we may not store to it as we will
4799 invalidate any pending RSO and generate wrong gimple
4800 during inlining. */
4801 && !((TREE_CODE (var) == RESULT_DECL
4802 || TREE_CODE (var) == PARM_DECL)
4803 && DECL_BY_REFERENCE (var)))
4805 x = build_sender_ref (ovar, ctx);
4806 gimplify_assign (var, x, olist);
4813 /* A convenience function to build an empty GIMPLE_COND with just the
4814 condition. */
4816 static gcond *
4817 gimple_build_cond_empty (tree cond)
4819 enum tree_code pred_code;
4820 tree lhs, rhs;
4822 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4823 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4827 /* Build the function calls to GOMP_parallel_start etc to actually
4828 generate the parallel operation. REGION is the parallel region
4829 being expanded. BB is the block where to insert the code. WS_ARGS
4830 will be set if this is a call to a combined parallel+workshare
4831 construct, it contains the list of additional arguments needed by
4832 the workshare construct. */
4834 static void
4835 expand_parallel_call (struct omp_region *region, basic_block bb,
4836 gomp_parallel *entry_stmt,
4837 vec<tree, va_gc> *ws_args)
4839 tree t, t1, t2, val, cond, c, clauses, flags;
4840 gimple_stmt_iterator gsi;
4841 gimple stmt;
4842 enum built_in_function start_ix;
4843 int start_ix2;
4844 location_t clause_loc;
4845 vec<tree, va_gc> *args;
4847 clauses = gimple_omp_parallel_clauses (entry_stmt);
4849 /* Determine what flavor of GOMP_parallel we will be
4850 emitting. */
4851 start_ix = BUILT_IN_GOMP_PARALLEL;
4852 if (is_combined_parallel (region))
4854 switch (region->inner->type)
4856 case GIMPLE_OMP_FOR:
4857 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4858 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4859 + (region->inner->sched_kind
4860 == OMP_CLAUSE_SCHEDULE_RUNTIME
4861 ? 3 : region->inner->sched_kind));
4862 start_ix = (enum built_in_function)start_ix2;
4863 break;
4864 case GIMPLE_OMP_SECTIONS:
4865 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4866 break;
4867 default:
4868 gcc_unreachable ();
4872 /* By default, the value of NUM_THREADS is zero (selected at run time)
4873 and there is no conditional. */
4874 cond = NULL_TREE;
4875 val = build_int_cst (unsigned_type_node, 0);
4876 flags = build_int_cst (unsigned_type_node, 0);
4878 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4879 if (c)
4880 cond = OMP_CLAUSE_IF_EXPR (c);
4882 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4883 if (c)
4885 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4886 clause_loc = OMP_CLAUSE_LOCATION (c);
4888 else
4889 clause_loc = gimple_location (entry_stmt);
4891 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4892 if (c)
4893 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4895 /* Ensure 'val' is of the correct type. */
4896 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4898 /* If we found the clause 'if (cond)', build either
4899 (cond != 0) or (cond ? val : 1u). */
4900 if (cond)
4902 cond = gimple_boolify (cond);
4904 if (integer_zerop (val))
4905 val = fold_build2_loc (clause_loc,
4906 EQ_EXPR, unsigned_type_node, cond,
4907 build_int_cst (TREE_TYPE (cond), 0));
4908 else
4910 basic_block cond_bb, then_bb, else_bb;
4911 edge e, e_then, e_else;
4912 tree tmp_then, tmp_else, tmp_join, tmp_var;
4914 tmp_var = create_tmp_var (TREE_TYPE (val));
4915 if (gimple_in_ssa_p (cfun))
4917 tmp_then = make_ssa_name (tmp_var);
4918 tmp_else = make_ssa_name (tmp_var);
4919 tmp_join = make_ssa_name (tmp_var);
4921 else
4923 tmp_then = tmp_var;
4924 tmp_else = tmp_var;
4925 tmp_join = tmp_var;
4928 e = split_block_after_labels (bb);
4929 cond_bb = e->src;
4930 bb = e->dest;
4931 remove_edge (e);
4933 then_bb = create_empty_bb (cond_bb);
4934 else_bb = create_empty_bb (then_bb);
4935 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4936 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4938 stmt = gimple_build_cond_empty (cond);
4939 gsi = gsi_start_bb (cond_bb);
4940 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4942 gsi = gsi_start_bb (then_bb);
4943 stmt = gimple_build_assign (tmp_then, val);
4944 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4946 gsi = gsi_start_bb (else_bb);
4947 stmt = gimple_build_assign
4948 (tmp_else, build_int_cst (unsigned_type_node, 1));
4949 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4951 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4952 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4953 add_bb_to_loop (then_bb, cond_bb->loop_father);
4954 add_bb_to_loop (else_bb, cond_bb->loop_father);
4955 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4956 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4958 if (gimple_in_ssa_p (cfun))
4960 gphi *phi = create_phi_node (tmp_join, bb);
4961 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4962 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4965 val = tmp_join;
4968 gsi = gsi_start_bb (bb);
4969 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4970 false, GSI_CONTINUE_LINKING);
4973 gsi = gsi_last_bb (bb);
4974 t = gimple_omp_parallel_data_arg (entry_stmt);
4975 if (t == NULL)
4976 t1 = null_pointer_node;
4977 else
4978 t1 = build_fold_addr_expr (t);
4979 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4981 vec_alloc (args, 4 + vec_safe_length (ws_args));
4982 args->quick_push (t2);
4983 args->quick_push (t1);
4984 args->quick_push (val);
4985 if (ws_args)
4986 args->splice (*ws_args);
4987 args->quick_push (flags);
4989 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4990 builtin_decl_explicit (start_ix), args);
4992 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4993 false, GSI_CONTINUE_LINKING);
4996 /* Insert a function call whose name is FUNC_NAME with the information from
4997 ENTRY_STMT into the basic_block BB. */
4999 static void
5000 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
5001 vec <tree, va_gc> *ws_args)
5003 tree t, t1, t2;
5004 gimple_stmt_iterator gsi;
5005 vec <tree, va_gc> *args;
5007 gcc_assert (vec_safe_length (ws_args) == 2);
5008 tree func_name = (*ws_args)[0];
5009 tree grain = (*ws_args)[1];
5011 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5012 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5013 gcc_assert (count != NULL_TREE);
5014 count = OMP_CLAUSE_OPERAND (count, 0);
5016 gsi = gsi_last_bb (bb);
5017 t = gimple_omp_parallel_data_arg (entry_stmt);
5018 if (t == NULL)
5019 t1 = null_pointer_node;
5020 else
5021 t1 = build_fold_addr_expr (t);
5022 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5024 vec_alloc (args, 4);
5025 args->quick_push (t2);
5026 args->quick_push (t1);
5027 args->quick_push (count);
5028 args->quick_push (grain);
5029 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5031 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5032 GSI_CONTINUE_LINKING);
5035 /* Build the function call to GOMP_task to actually
5036 generate the task operation. BB is the block where to insert the code. */
5038 static void
5039 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5041 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5042 gimple_stmt_iterator gsi;
5043 location_t loc = gimple_location (entry_stmt);
5045 clauses = gimple_omp_task_clauses (entry_stmt);
5047 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5048 if (c)
5049 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5050 else
5051 cond = boolean_true_node;
5053 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5054 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5055 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5056 flags = build_int_cst (unsigned_type_node,
5057 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5059 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5060 if (c)
5062 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5063 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5064 build_int_cst (unsigned_type_node, 2),
5065 build_int_cst (unsigned_type_node, 0));
5066 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5068 if (depend)
5069 depend = OMP_CLAUSE_DECL (depend);
5070 else
5071 depend = build_int_cst (ptr_type_node, 0);
5073 gsi = gsi_last_bb (bb);
5074 t = gimple_omp_task_data_arg (entry_stmt);
5075 if (t == NULL)
5076 t2 = null_pointer_node;
5077 else
5078 t2 = build_fold_addr_expr_loc (loc, t);
5079 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5080 t = gimple_omp_task_copy_fn (entry_stmt);
5081 if (t == NULL)
5082 t3 = null_pointer_node;
5083 else
5084 t3 = build_fold_addr_expr_loc (loc, t);
5086 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5087 8, t1, t2, t3,
5088 gimple_omp_task_arg_size (entry_stmt),
5089 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5090 depend);
5092 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5093 false, GSI_CONTINUE_LINKING);
5097 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5098 catch handler and return it. This prevents programs from violating the
5099 structured block semantics with throws. */
5101 static gimple_seq
5102 maybe_catch_exception (gimple_seq body)
5104 gimple g;
5105 tree decl;
5107 if (!flag_exceptions)
5108 return body;
5110 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5111 decl = lang_hooks.eh_protect_cleanup_actions ();
5112 else
5113 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5115 g = gimple_build_eh_must_not_throw (decl);
5116 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5117 GIMPLE_TRY_CATCH);
5119 return gimple_seq_alloc_with_stmt (g);
5122 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5124 static tree
5125 vec2chain (vec<tree, va_gc> *v)
5127 tree chain = NULL_TREE, t;
5128 unsigned ix;
5130 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5132 DECL_CHAIN (t) = chain;
5133 chain = t;
5136 return chain;
5140 /* Remove barriers in REGION->EXIT's block. Note that this is only
5141 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5142 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5143 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5144 removed. */
5146 static void
5147 remove_exit_barrier (struct omp_region *region)
5149 gimple_stmt_iterator gsi;
5150 basic_block exit_bb;
5151 edge_iterator ei;
5152 edge e;
5153 gimple stmt;
5154 int any_addressable_vars = -1;
5156 exit_bb = region->exit;
5158 /* If the parallel region doesn't return, we don't have REGION->EXIT
5159 block at all. */
5160 if (! exit_bb)
5161 return;
5163 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5164 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5165 statements that can appear in between are extremely limited -- no
5166 memory operations at all. Here, we allow nothing at all, so the
5167 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5168 gsi = gsi_last_bb (exit_bb);
5169 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5170 gsi_prev (&gsi);
5171 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5172 return;
5174 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5176 gsi = gsi_last_bb (e->src);
5177 if (gsi_end_p (gsi))
5178 continue;
5179 stmt = gsi_stmt (gsi);
5180 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5181 && !gimple_omp_return_nowait_p (stmt))
5183 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5184 in many cases. If there could be tasks queued, the barrier
5185 might be needed to let the tasks run before some local
5186 variable of the parallel that the task uses as shared
5187 runs out of scope. The task can be spawned either
5188 from within current function (this would be easy to check)
5189 or from some function it calls and gets passed an address
5190 of such a variable. */
5191 if (any_addressable_vars < 0)
5193 gomp_parallel *parallel_stmt
5194 = as_a <gomp_parallel *> (last_stmt (region->entry));
5195 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5196 tree local_decls, block, decl;
5197 unsigned ix;
5199 any_addressable_vars = 0;
5200 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5201 if (TREE_ADDRESSABLE (decl))
5203 any_addressable_vars = 1;
5204 break;
5206 for (block = gimple_block (stmt);
5207 !any_addressable_vars
5208 && block
5209 && TREE_CODE (block) == BLOCK;
5210 block = BLOCK_SUPERCONTEXT (block))
5212 for (local_decls = BLOCK_VARS (block);
5213 local_decls;
5214 local_decls = DECL_CHAIN (local_decls))
5215 if (TREE_ADDRESSABLE (local_decls))
5217 any_addressable_vars = 1;
5218 break;
5220 if (block == gimple_block (parallel_stmt))
5221 break;
5224 if (!any_addressable_vars)
5225 gimple_omp_return_set_nowait (stmt);
5230 static void
5231 remove_exit_barriers (struct omp_region *region)
5233 if (region->type == GIMPLE_OMP_PARALLEL)
5234 remove_exit_barrier (region);
5236 if (region->inner)
5238 region = region->inner;
5239 remove_exit_barriers (region);
5240 while (region->next)
5242 region = region->next;
5243 remove_exit_barriers (region);
5248 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5249 calls. These can't be declared as const functions, but
5250 within one parallel body they are constant, so they can be
5251 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5252 which are declared const. Similarly for task body, except
5253 that in untied task omp_get_thread_num () can change at any task
5254 scheduling point. */
5256 static void
5257 optimize_omp_library_calls (gimple entry_stmt)
5259 basic_block bb;
5260 gimple_stmt_iterator gsi;
5261 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5262 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5263 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5264 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5265 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5266 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5267 OMP_CLAUSE_UNTIED) != NULL);
5269 FOR_EACH_BB_FN (bb, cfun)
5270 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5272 gimple call = gsi_stmt (gsi);
5273 tree decl;
5275 if (is_gimple_call (call)
5276 && (decl = gimple_call_fndecl (call))
5277 && DECL_EXTERNAL (decl)
5278 && TREE_PUBLIC (decl)
5279 && DECL_INITIAL (decl) == NULL)
5281 tree built_in;
5283 if (DECL_NAME (decl) == thr_num_id)
5285 /* In #pragma omp task untied omp_get_thread_num () can change
5286 during the execution of the task region. */
5287 if (untied_task)
5288 continue;
5289 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5291 else if (DECL_NAME (decl) == num_thr_id)
5292 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5293 else
5294 continue;
5296 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5297 || gimple_call_num_args (call) != 0)
5298 continue;
5300 if (flag_exceptions && !TREE_NOTHROW (decl))
5301 continue;
5303 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5304 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5305 TREE_TYPE (TREE_TYPE (built_in))))
5306 continue;
5308 gimple_call_set_fndecl (call, built_in);
5313 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5314 regimplified. */
5316 static tree
5317 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5319 tree t = *tp;
5321 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5322 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5323 return t;
5325 if (TREE_CODE (t) == ADDR_EXPR)
5326 recompute_tree_invariant_for_addr_expr (t);
5328 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5329 return NULL_TREE;
5332 /* Prepend TO = FROM assignment before *GSI_P. */
5334 static void
5335 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5337 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5338 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5339 true, GSI_SAME_STMT);
5340 gimple stmt = gimple_build_assign (to, from);
5341 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5342 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5343 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5345 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5346 gimple_regimplify_operands (stmt, &gsi);
5350 /* Expand the OpenMP parallel or task directive starting at REGION. */
5352 static void
5353 expand_omp_taskreg (struct omp_region *region)
5355 basic_block entry_bb, exit_bb, new_bb;
5356 struct function *child_cfun;
5357 tree child_fn, block, t;
5358 gimple_stmt_iterator gsi;
5359 gimple entry_stmt, stmt;
5360 edge e;
5361 vec<tree, va_gc> *ws_args;
5363 entry_stmt = last_stmt (region->entry);
5364 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5365 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5367 entry_bb = region->entry;
5368 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
5369 exit_bb = region->cont;
5370 else
5371 exit_bb = region->exit;
5373 bool is_cilk_for
5374 = (flag_cilkplus
5375 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5376 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5377 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5379 if (is_cilk_for)
5380 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5381 and the inner statement contains the name of the built-in function
5382 and grain. */
5383 ws_args = region->inner->ws_args;
5384 else if (is_combined_parallel (region))
5385 ws_args = region->ws_args;
5386 else
5387 ws_args = NULL;
5389 if (child_cfun->cfg)
5391 /* Due to inlining, it may happen that we have already outlined
5392 the region, in which case all we need to do is make the
5393 sub-graph unreachable and emit the parallel call. */
5394 edge entry_succ_e, exit_succ_e;
5396 entry_succ_e = single_succ_edge (entry_bb);
5398 gsi = gsi_last_bb (entry_bb);
5399 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5400 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5401 gsi_remove (&gsi, true);
5403 new_bb = entry_bb;
5404 if (exit_bb)
5406 exit_succ_e = single_succ_edge (exit_bb);
5407 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5409 remove_edge_and_dominated_blocks (entry_succ_e);
5411 else
5413 unsigned srcidx, dstidx, num;
5415 /* If the parallel region needs data sent from the parent
5416 function, then the very first statement (except possible
5417 tree profile counter updates) of the parallel body
5418 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5419 &.OMP_DATA_O is passed as an argument to the child function,
5420 we need to replace it with the argument as seen by the child
5421 function.
5423 In most cases, this will end up being the identity assignment
5424 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5425 a function call that has been inlined, the original PARM_DECL
5426 .OMP_DATA_I may have been converted into a different local
5427 variable. In which case, we need to keep the assignment. */
5428 if (gimple_omp_taskreg_data_arg (entry_stmt))
5430 basic_block entry_succ_bb
5431 = single_succ_p (entry_bb) ? single_succ (entry_bb)
5432 : FALLTHRU_EDGE (entry_bb)->dest;
5433 tree arg, narg;
5434 gimple parcopy_stmt = NULL;
5436 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5438 gimple stmt;
5440 gcc_assert (!gsi_end_p (gsi));
5441 stmt = gsi_stmt (gsi);
5442 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5443 continue;
5445 if (gimple_num_ops (stmt) == 2)
5447 tree arg = gimple_assign_rhs1 (stmt);
5449 /* We're ignore the subcode because we're
5450 effectively doing a STRIP_NOPS. */
5452 if (TREE_CODE (arg) == ADDR_EXPR
5453 && TREE_OPERAND (arg, 0)
5454 == gimple_omp_taskreg_data_arg (entry_stmt))
5456 parcopy_stmt = stmt;
5457 break;
5462 gcc_assert (parcopy_stmt != NULL);
5463 arg = DECL_ARGUMENTS (child_fn);
5465 if (!gimple_in_ssa_p (cfun))
5467 if (gimple_assign_lhs (parcopy_stmt) == arg)
5468 gsi_remove (&gsi, true);
5469 else
5471 /* ?? Is setting the subcode really necessary ?? */
5472 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5473 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5476 else
5478 /* If we are in ssa form, we must load the value from the default
5479 definition of the argument. That should not be defined now,
5480 since the argument is not used uninitialized. */
5481 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5482 narg = make_ssa_name (arg, gimple_build_nop ());
5483 set_ssa_default_def (cfun, arg, narg);
5484 /* ?? Is setting the subcode really necessary ?? */
5485 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5486 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5487 update_stmt (parcopy_stmt);
5491 /* Declare local variables needed in CHILD_CFUN. */
5492 block = DECL_INITIAL (child_fn);
5493 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5494 /* The gimplifier could record temporaries in parallel/task block
5495 rather than in containing function's local_decls chain,
5496 which would mean cgraph missed finalizing them. Do it now. */
5497 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5498 if (TREE_CODE (t) == VAR_DECL
5499 && TREE_STATIC (t)
5500 && !DECL_EXTERNAL (t))
5501 varpool_node::finalize_decl (t);
5502 DECL_SAVED_TREE (child_fn) = NULL;
5503 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5504 gimple_set_body (child_fn, NULL);
5505 TREE_USED (block) = 1;
5507 /* Reset DECL_CONTEXT on function arguments. */
5508 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5509 DECL_CONTEXT (t) = child_fn;
5511 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5512 so that it can be moved to the child function. */
5513 gsi = gsi_last_bb (entry_bb);
5514 stmt = gsi_stmt (gsi);
5515 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5516 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5517 e = split_block (entry_bb, stmt);
5518 gsi_remove (&gsi, true);
5519 entry_bb = e->dest;
5520 edge e2 = NULL;
5521 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5522 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5523 else
5525 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
5526 gcc_assert (e2->dest == region->exit);
5527 remove_edge (BRANCH_EDGE (entry_bb));
5528 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
5529 gsi = gsi_last_bb (region->exit);
5530 gcc_assert (!gsi_end_p (gsi)
5531 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5532 gsi_remove (&gsi, true);
5535 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5536 if (exit_bb)
5538 gsi = gsi_last_bb (exit_bb);
5539 gcc_assert (!gsi_end_p (gsi)
5540 && (gimple_code (gsi_stmt (gsi))
5541 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
5542 stmt = gimple_build_return (NULL);
5543 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5544 gsi_remove (&gsi, true);
5547 /* Move the parallel region into CHILD_CFUN. */
5549 if (gimple_in_ssa_p (cfun))
5551 init_tree_ssa (child_cfun);
5552 init_ssa_operands (child_cfun);
5553 child_cfun->gimple_df->in_ssa_p = true;
5554 block = NULL_TREE;
5556 else
5557 block = gimple_block (entry_stmt);
5559 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5560 if (exit_bb)
5561 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5562 if (e2)
5564 basic_block dest_bb = e2->dest;
5565 if (!exit_bb)
5566 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
5567 remove_edge (e2);
5568 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
5570 /* When the OMP expansion process cannot guarantee an up-to-date
5571 loop tree arrange for the child function to fixup loops. */
5572 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5573 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5575 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5576 num = vec_safe_length (child_cfun->local_decls);
5577 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5579 t = (*child_cfun->local_decls)[srcidx];
5580 if (DECL_CONTEXT (t) == cfun->decl)
5581 continue;
5582 if (srcidx != dstidx)
5583 (*child_cfun->local_decls)[dstidx] = t;
5584 dstidx++;
5586 if (dstidx != num)
5587 vec_safe_truncate (child_cfun->local_decls, dstidx);
5589 /* Inform the callgraph about the new function. */
5590 child_cfun->curr_properties = cfun->curr_properties;
5591 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
5592 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
5593 cgraph_node *node = cgraph_node::get_create (child_fn);
5594 node->parallelized_function = 1;
5595 cgraph_node::add_new_function (child_fn, true);
5597 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5598 fixed in a following pass. */
5599 push_cfun (child_cfun);
5600 if (optimize)
5601 optimize_omp_library_calls (entry_stmt);
5602 cgraph_edge::rebuild_edges ();
5604 /* Some EH regions might become dead, see PR34608. If
5605 pass_cleanup_cfg isn't the first pass to happen with the
5606 new child, these dead EH edges might cause problems.
5607 Clean them up now. */
5608 if (flag_exceptions)
5610 basic_block bb;
5611 bool changed = false;
5613 FOR_EACH_BB_FN (bb, cfun)
5614 changed |= gimple_purge_dead_eh_edges (bb);
5615 if (changed)
5616 cleanup_tree_cfg ();
5618 if (gimple_in_ssa_p (cfun))
5619 update_ssa (TODO_update_ssa);
5620 pop_cfun ();
5623 /* Emit a library call to launch the children threads. */
5624 if (is_cilk_for)
5625 expand_cilk_for_call (new_bb,
5626 as_a <gomp_parallel *> (entry_stmt), ws_args);
5627 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5628 expand_parallel_call (region, new_bb,
5629 as_a <gomp_parallel *> (entry_stmt), ws_args);
5630 else
5631 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5632 if (gimple_in_ssa_p (cfun))
5633 update_ssa (TODO_update_ssa_only_virtuals);
5637 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5638 of the combined collapse > 1 loop constructs, generate code like:
5639 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5640 if (cond3 is <)
5641 adj = STEP3 - 1;
5642 else
5643 adj = STEP3 + 1;
5644 count3 = (adj + N32 - N31) / STEP3;
5645 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5646 if (cond2 is <)
5647 adj = STEP2 - 1;
5648 else
5649 adj = STEP2 + 1;
5650 count2 = (adj + N22 - N21) / STEP2;
5651 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5652 if (cond1 is <)
5653 adj = STEP1 - 1;
5654 else
5655 adj = STEP1 + 1;
5656 count1 = (adj + N12 - N11) / STEP1;
5657 count = count1 * count2 * count3;
5658 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5659 count = 0;
5660 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5661 of the combined loop constructs, just initialize COUNTS array
5662 from the _looptemp_ clauses. */
5664 /* NOTE: It *could* be better to moosh all of the BBs together,
5665 creating one larger BB with all the computation and the unexpected
5666 jump at the end. I.e.
5668 bool zero3, zero2, zero1, zero;
5670 zero3 = N32 c3 N31;
5671 count3 = (N32 - N31) /[cl] STEP3;
5672 zero2 = N22 c2 N21;
5673 count2 = (N22 - N21) /[cl] STEP2;
5674 zero1 = N12 c1 N11;
5675 count1 = (N12 - N11) /[cl] STEP1;
5676 zero = zero3 || zero2 || zero1;
5677 count = count1 * count2 * count3;
5678 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5680 After all, we expect the zero=false, and thus we expect to have to
5681 evaluate all of the comparison expressions, so short-circuiting
5682 oughtn't be a win. Since the condition isn't protecting a
5683 denominator, we're not concerned about divide-by-zero, so we can
5684 fully evaluate count even if a numerator turned out to be wrong.
5686 It seems like putting this all together would create much better
5687 scheduling opportunities, and less pressure on the chip's branch
5688 predictor. */
5690 static void
5691 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5692 basic_block &entry_bb, tree *counts,
5693 basic_block &zero_iter_bb, int &first_zero_iter,
5694 basic_block &l2_dom_bb)
5696 tree t, type = TREE_TYPE (fd->loop.v);
5697 edge e, ne;
5698 int i;
5700 /* Collapsed loops need work for expansion into SSA form. */
5701 gcc_assert (!gimple_in_ssa_p (cfun));
5703 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5704 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5706 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5707 isn't supposed to be handled, as the inner loop doesn't
5708 use it. */
5709 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5710 OMP_CLAUSE__LOOPTEMP_);
5711 gcc_assert (innerc);
5712 for (i = 0; i < fd->collapse; i++)
5714 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5715 OMP_CLAUSE__LOOPTEMP_);
5716 gcc_assert (innerc);
5717 if (i)
5718 counts[i] = OMP_CLAUSE_DECL (innerc);
5719 else
5720 counts[0] = NULL_TREE;
5722 return;
5725 for (i = 0; i < fd->collapse; i++)
5727 tree itype = TREE_TYPE (fd->loops[i].v);
5729 if (SSA_VAR_P (fd->loop.n2)
5730 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5731 fold_convert (itype, fd->loops[i].n1),
5732 fold_convert (itype, fd->loops[i].n2)))
5733 == NULL_TREE || !integer_onep (t)))
5735 gcond *cond_stmt;
5736 tree n1, n2;
5737 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5738 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5739 true, GSI_SAME_STMT);
5740 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5741 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5742 true, GSI_SAME_STMT);
5743 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5744 NULL_TREE, NULL_TREE);
5745 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5746 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5747 expand_omp_regimplify_p, NULL, NULL)
5748 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5749 expand_omp_regimplify_p, NULL, NULL))
5751 *gsi = gsi_for_stmt (cond_stmt);
5752 gimple_regimplify_operands (cond_stmt, gsi);
5754 e = split_block (entry_bb, cond_stmt);
5755 if (zero_iter_bb == NULL)
5757 gassign *assign_stmt;
5758 first_zero_iter = i;
5759 zero_iter_bb = create_empty_bb (entry_bb);
5760 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5761 *gsi = gsi_after_labels (zero_iter_bb);
5762 assign_stmt = gimple_build_assign (fd->loop.n2,
5763 build_zero_cst (type));
5764 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5765 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5766 entry_bb);
5768 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5769 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5770 e->flags = EDGE_TRUE_VALUE;
5771 e->probability = REG_BR_PROB_BASE - ne->probability;
5772 if (l2_dom_bb == NULL)
5773 l2_dom_bb = entry_bb;
5774 entry_bb = e->dest;
5775 *gsi = gsi_last_bb (entry_bb);
5778 if (POINTER_TYPE_P (itype))
5779 itype = signed_type_for (itype);
5780 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5781 ? -1 : 1));
5782 t = fold_build2 (PLUS_EXPR, itype,
5783 fold_convert (itype, fd->loops[i].step), t);
5784 t = fold_build2 (PLUS_EXPR, itype, t,
5785 fold_convert (itype, fd->loops[i].n2));
5786 t = fold_build2 (MINUS_EXPR, itype, t,
5787 fold_convert (itype, fd->loops[i].n1));
5788 /* ?? We could probably use CEIL_DIV_EXPR instead of
5789 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5790 generate the same code in the end because generically we
5791 don't know that the values involved must be negative for
5792 GT?? */
5793 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5794 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5795 fold_build1 (NEGATE_EXPR, itype, t),
5796 fold_build1 (NEGATE_EXPR, itype,
5797 fold_convert (itype,
5798 fd->loops[i].step)));
5799 else
5800 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5801 fold_convert (itype, fd->loops[i].step));
5802 t = fold_convert (type, t);
5803 if (TREE_CODE (t) == INTEGER_CST)
5804 counts[i] = t;
5805 else
5807 counts[i] = create_tmp_reg (type, ".count");
5808 expand_omp_build_assign (gsi, counts[i], t);
5810 if (SSA_VAR_P (fd->loop.n2))
5812 if (i == 0)
5813 t = counts[0];
5814 else
5815 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5816 expand_omp_build_assign (gsi, fd->loop.n2, t);
5822 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5823 T = V;
5824 V3 = N31 + (T % count3) * STEP3;
5825 T = T / count3;
5826 V2 = N21 + (T % count2) * STEP2;
5827 T = T / count2;
5828 V1 = N11 + T * STEP1;
5829 if this loop doesn't have an inner loop construct combined with it.
5830 If it does have an inner loop construct combined with it and the
5831 iteration count isn't known constant, store values from counts array
5832 into its _looptemp_ temporaries instead. */
5834 static void
5835 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5836 tree *counts, gimple inner_stmt, tree startvar)
5838 int i;
5839 if (gimple_omp_for_combined_p (fd->for_stmt))
5841 /* If fd->loop.n2 is constant, then no propagation of the counts
5842 is needed, they are constant. */
5843 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5844 return;
5846 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5847 ? gimple_omp_parallel_clauses (inner_stmt)
5848 : gimple_omp_for_clauses (inner_stmt);
5849 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5850 isn't supposed to be handled, as the inner loop doesn't
5851 use it. */
5852 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5853 gcc_assert (innerc);
5854 for (i = 0; i < fd->collapse; i++)
5856 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5857 OMP_CLAUSE__LOOPTEMP_);
5858 gcc_assert (innerc);
5859 if (i)
5861 tree tem = OMP_CLAUSE_DECL (innerc);
5862 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5863 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5864 false, GSI_CONTINUE_LINKING);
5865 gassign *stmt = gimple_build_assign (tem, t);
5866 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5869 return;
5872 tree type = TREE_TYPE (fd->loop.v);
5873 tree tem = create_tmp_reg (type, ".tem");
5874 gassign *stmt = gimple_build_assign (tem, startvar);
5875 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5877 for (i = fd->collapse - 1; i >= 0; i--)
5879 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5880 itype = vtype;
5881 if (POINTER_TYPE_P (vtype))
5882 itype = signed_type_for (vtype);
5883 if (i != 0)
5884 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5885 else
5886 t = tem;
5887 t = fold_convert (itype, t);
5888 t = fold_build2 (MULT_EXPR, itype, t,
5889 fold_convert (itype, fd->loops[i].step));
5890 if (POINTER_TYPE_P (vtype))
5891 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5892 else
5893 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5894 t = force_gimple_operand_gsi (gsi, t,
5895 DECL_P (fd->loops[i].v)
5896 && TREE_ADDRESSABLE (fd->loops[i].v),
5897 NULL_TREE, false,
5898 GSI_CONTINUE_LINKING);
5899 stmt = gimple_build_assign (fd->loops[i].v, t);
5900 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5901 if (i != 0)
5903 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5904 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5905 false, GSI_CONTINUE_LINKING);
5906 stmt = gimple_build_assign (tem, t);
5907 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5913 /* Helper function for expand_omp_for_*. Generate code like:
5914 L10:
5915 V3 += STEP3;
5916 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5917 L11:
5918 V3 = N31;
5919 V2 += STEP2;
5920 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5921 L12:
5922 V2 = N21;
5923 V1 += STEP1;
5924 goto BODY_BB; */
5926 static basic_block
5927 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5928 basic_block body_bb)
5930 basic_block last_bb, bb, collapse_bb = NULL;
5931 int i;
5932 gimple_stmt_iterator gsi;
5933 edge e;
5934 tree t;
5935 gimple stmt;
5937 last_bb = cont_bb;
5938 for (i = fd->collapse - 1; i >= 0; i--)
5940 tree vtype = TREE_TYPE (fd->loops[i].v);
5942 bb = create_empty_bb (last_bb);
5943 add_bb_to_loop (bb, last_bb->loop_father);
5944 gsi = gsi_start_bb (bb);
5946 if (i < fd->collapse - 1)
5948 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5949 e->probability = REG_BR_PROB_BASE / 8;
5951 t = fd->loops[i + 1].n1;
5952 t = force_gimple_operand_gsi (&gsi, t,
5953 DECL_P (fd->loops[i + 1].v)
5954 && TREE_ADDRESSABLE (fd->loops[i
5955 + 1].v),
5956 NULL_TREE, false,
5957 GSI_CONTINUE_LINKING);
5958 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5959 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5961 else
5962 collapse_bb = bb;
5964 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5966 if (POINTER_TYPE_P (vtype))
5967 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5968 else
5969 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5970 t = force_gimple_operand_gsi (&gsi, t,
5971 DECL_P (fd->loops[i].v)
5972 && TREE_ADDRESSABLE (fd->loops[i].v),
5973 NULL_TREE, false, GSI_CONTINUE_LINKING);
5974 stmt = gimple_build_assign (fd->loops[i].v, t);
5975 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5977 if (i > 0)
5979 t = fd->loops[i].n2;
5980 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5981 false, GSI_CONTINUE_LINKING);
5982 tree v = fd->loops[i].v;
5983 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5984 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5985 false, GSI_CONTINUE_LINKING);
5986 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5987 stmt = gimple_build_cond_empty (t);
5988 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5989 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5990 e->probability = REG_BR_PROB_BASE * 7 / 8;
5992 else
5993 make_edge (bb, body_bb, EDGE_FALLTHRU);
5994 last_bb = bb;
5997 return collapse_bb;
6001 /* A subroutine of expand_omp_for. Generate code for a parallel
6002 loop with any schedule. Given parameters:
6004 for (V = N1; V cond N2; V += STEP) BODY;
6006 where COND is "<" or ">", we generate pseudocode
6008 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
6009 if (more) goto L0; else goto L3;
6011 V = istart0;
6012 iend = iend0;
6014 BODY;
6015 V += STEP;
6016 if (V cond iend) goto L1; else goto L2;
6018 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6021 If this is a combined omp parallel loop, instead of the call to
6022 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6023 If this is gimple_omp_for_combined_p loop, then instead of assigning
6024 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6025 inner GIMPLE_OMP_FOR and V += STEP; and
6026 if (V cond iend) goto L1; else goto L2; are removed.
6028 For collapsed loops, given parameters:
6029 collapse(3)
6030 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6031 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6032 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6033 BODY;
6035 we generate pseudocode
6037 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6038 if (cond3 is <)
6039 adj = STEP3 - 1;
6040 else
6041 adj = STEP3 + 1;
6042 count3 = (adj + N32 - N31) / STEP3;
6043 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6044 if (cond2 is <)
6045 adj = STEP2 - 1;
6046 else
6047 adj = STEP2 + 1;
6048 count2 = (adj + N22 - N21) / STEP2;
6049 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6050 if (cond1 is <)
6051 adj = STEP1 - 1;
6052 else
6053 adj = STEP1 + 1;
6054 count1 = (adj + N12 - N11) / STEP1;
6055 count = count1 * count2 * count3;
6056 goto Z1;
6058 count = 0;
6060 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6061 if (more) goto L0; else goto L3;
6063 V = istart0;
6064 T = V;
6065 V3 = N31 + (T % count3) * STEP3;
6066 T = T / count3;
6067 V2 = N21 + (T % count2) * STEP2;
6068 T = T / count2;
6069 V1 = N11 + T * STEP1;
6070 iend = iend0;
6072 BODY;
6073 V += 1;
6074 if (V < iend) goto L10; else goto L2;
6075 L10:
6076 V3 += STEP3;
6077 if (V3 cond3 N32) goto L1; else goto L11;
6078 L11:
6079 V3 = N31;
6080 V2 += STEP2;
6081 if (V2 cond2 N22) goto L1; else goto L12;
6082 L12:
6083 V2 = N21;
6084 V1 += STEP1;
6085 goto L1;
6087 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6092 static void
6093 expand_omp_for_generic (struct omp_region *region,
6094 struct omp_for_data *fd,
6095 enum built_in_function start_fn,
6096 enum built_in_function next_fn,
6097 gimple inner_stmt)
6099 tree type, istart0, iend0, iend;
6100 tree t, vmain, vback, bias = NULL_TREE;
6101 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6102 basic_block l2_bb = NULL, l3_bb = NULL;
6103 gimple_stmt_iterator gsi;
6104 gassign *assign_stmt;
6105 bool in_combined_parallel = is_combined_parallel (region);
6106 bool broken_loop = region->cont == NULL;
6107 edge e, ne;
6108 tree *counts = NULL;
6109 int i;
6111 gcc_assert (!broken_loop || !in_combined_parallel);
6112 gcc_assert (fd->iter_type == long_integer_type_node
6113 || !in_combined_parallel);
6115 type = TREE_TYPE (fd->loop.v);
6116 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6117 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6118 TREE_ADDRESSABLE (istart0) = 1;
6119 TREE_ADDRESSABLE (iend0) = 1;
6121 /* See if we need to bias by LLONG_MIN. */
6122 if (fd->iter_type == long_long_unsigned_type_node
6123 && TREE_CODE (type) == INTEGER_TYPE
6124 && !TYPE_UNSIGNED (type))
6126 tree n1, n2;
6128 if (fd->loop.cond_code == LT_EXPR)
6130 n1 = fd->loop.n1;
6131 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6133 else
6135 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6136 n2 = fd->loop.n1;
6138 if (TREE_CODE (n1) != INTEGER_CST
6139 || TREE_CODE (n2) != INTEGER_CST
6140 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6141 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6144 entry_bb = region->entry;
6145 cont_bb = region->cont;
6146 collapse_bb = NULL;
6147 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6148 gcc_assert (broken_loop
6149 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6150 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6151 l1_bb = single_succ (l0_bb);
6152 if (!broken_loop)
6154 l2_bb = create_empty_bb (cont_bb);
6155 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6156 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6158 else
6159 l2_bb = NULL;
6160 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6161 exit_bb = region->exit;
6163 gsi = gsi_last_bb (entry_bb);
6165 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6166 if (fd->collapse > 1)
6168 int first_zero_iter = -1;
6169 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6171 counts = XALLOCAVEC (tree, fd->collapse);
6172 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6173 zero_iter_bb, first_zero_iter,
6174 l2_dom_bb);
6176 if (zero_iter_bb)
6178 /* Some counts[i] vars might be uninitialized if
6179 some loop has zero iterations. But the body shouldn't
6180 be executed in that case, so just avoid uninit warnings. */
6181 for (i = first_zero_iter; i < fd->collapse; i++)
6182 if (SSA_VAR_P (counts[i]))
6183 TREE_NO_WARNING (counts[i]) = 1;
6184 gsi_prev (&gsi);
6185 e = split_block (entry_bb, gsi_stmt (gsi));
6186 entry_bb = e->dest;
6187 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6188 gsi = gsi_last_bb (entry_bb);
6189 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6190 get_immediate_dominator (CDI_DOMINATORS,
6191 zero_iter_bb));
6194 if (in_combined_parallel)
6196 /* In a combined parallel loop, emit a call to
6197 GOMP_loop_foo_next. */
6198 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6199 build_fold_addr_expr (istart0),
6200 build_fold_addr_expr (iend0));
6202 else
6204 tree t0, t1, t2, t3, t4;
6205 /* If this is not a combined parallel loop, emit a call to
6206 GOMP_loop_foo_start in ENTRY_BB. */
6207 t4 = build_fold_addr_expr (iend0);
6208 t3 = build_fold_addr_expr (istart0);
6209 t2 = fold_convert (fd->iter_type, fd->loop.step);
6210 t1 = fd->loop.n2;
6211 t0 = fd->loop.n1;
6212 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6214 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6215 OMP_CLAUSE__LOOPTEMP_);
6216 gcc_assert (innerc);
6217 t0 = OMP_CLAUSE_DECL (innerc);
6218 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6219 OMP_CLAUSE__LOOPTEMP_);
6220 gcc_assert (innerc);
6221 t1 = OMP_CLAUSE_DECL (innerc);
6223 if (POINTER_TYPE_P (TREE_TYPE (t0))
6224 && TYPE_PRECISION (TREE_TYPE (t0))
6225 != TYPE_PRECISION (fd->iter_type))
6227 /* Avoid casting pointers to integer of a different size. */
6228 tree itype = signed_type_for (type);
6229 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6230 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6232 else
6234 t1 = fold_convert (fd->iter_type, t1);
6235 t0 = fold_convert (fd->iter_type, t0);
6237 if (bias)
6239 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6240 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6242 if (fd->iter_type == long_integer_type_node)
6244 if (fd->chunk_size)
6246 t = fold_convert (fd->iter_type, fd->chunk_size);
6247 t = build_call_expr (builtin_decl_explicit (start_fn),
6248 6, t0, t1, t2, t, t3, t4);
6250 else
6251 t = build_call_expr (builtin_decl_explicit (start_fn),
6252 5, t0, t1, t2, t3, t4);
6254 else
6256 tree t5;
6257 tree c_bool_type;
6258 tree bfn_decl;
6260 /* The GOMP_loop_ull_*start functions have additional boolean
6261 argument, true for < loops and false for > loops.
6262 In Fortran, the C bool type can be different from
6263 boolean_type_node. */
6264 bfn_decl = builtin_decl_explicit (start_fn);
6265 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6266 t5 = build_int_cst (c_bool_type,
6267 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6268 if (fd->chunk_size)
6270 tree bfn_decl = builtin_decl_explicit (start_fn);
6271 t = fold_convert (fd->iter_type, fd->chunk_size);
6272 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6274 else
6275 t = build_call_expr (builtin_decl_explicit (start_fn),
6276 6, t5, t0, t1, t2, t3, t4);
6279 if (TREE_TYPE (t) != boolean_type_node)
6280 t = fold_build2 (NE_EXPR, boolean_type_node,
6281 t, build_int_cst (TREE_TYPE (t), 0));
6282 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6283 true, GSI_SAME_STMT);
6284 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6286 /* Remove the GIMPLE_OMP_FOR statement. */
6287 gsi_remove (&gsi, true);
6289 /* Iteration setup for sequential loop goes in L0_BB. */
6290 tree startvar = fd->loop.v;
6291 tree endvar = NULL_TREE;
6293 if (gimple_omp_for_combined_p (fd->for_stmt))
6295 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6296 && gimple_omp_for_kind (inner_stmt)
6297 == GF_OMP_FOR_KIND_SIMD);
6298 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6299 OMP_CLAUSE__LOOPTEMP_);
6300 gcc_assert (innerc);
6301 startvar = OMP_CLAUSE_DECL (innerc);
6302 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6303 OMP_CLAUSE__LOOPTEMP_);
6304 gcc_assert (innerc);
6305 endvar = OMP_CLAUSE_DECL (innerc);
6308 gsi = gsi_start_bb (l0_bb);
6309 t = istart0;
6310 if (bias)
6311 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6312 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6313 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6314 t = fold_convert (TREE_TYPE (startvar), t);
6315 t = force_gimple_operand_gsi (&gsi, t,
6316 DECL_P (startvar)
6317 && TREE_ADDRESSABLE (startvar),
6318 NULL_TREE, false, GSI_CONTINUE_LINKING);
6319 assign_stmt = gimple_build_assign (startvar, t);
6320 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6322 t = iend0;
6323 if (bias)
6324 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6325 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6326 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6327 t = fold_convert (TREE_TYPE (startvar), t);
6328 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6329 false, GSI_CONTINUE_LINKING);
6330 if (endvar)
6332 assign_stmt = gimple_build_assign (endvar, iend);
6333 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6334 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6335 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6336 else
6337 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6338 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6340 if (fd->collapse > 1)
6341 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6343 if (!broken_loop)
6345 /* Code to control the increment and predicate for the sequential
6346 loop goes in the CONT_BB. */
6347 gsi = gsi_last_bb (cont_bb);
6348 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6349 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6350 vmain = gimple_omp_continue_control_use (cont_stmt);
6351 vback = gimple_omp_continue_control_def (cont_stmt);
6353 if (!gimple_omp_for_combined_p (fd->for_stmt))
6355 if (POINTER_TYPE_P (type))
6356 t = fold_build_pointer_plus (vmain, fd->loop.step);
6357 else
6358 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6359 t = force_gimple_operand_gsi (&gsi, t,
6360 DECL_P (vback)
6361 && TREE_ADDRESSABLE (vback),
6362 NULL_TREE, true, GSI_SAME_STMT);
6363 assign_stmt = gimple_build_assign (vback, t);
6364 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6366 t = build2 (fd->loop.cond_code, boolean_type_node,
6367 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6368 iend);
6369 gcond *cond_stmt = gimple_build_cond_empty (t);
6370 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6373 /* Remove GIMPLE_OMP_CONTINUE. */
6374 gsi_remove (&gsi, true);
6376 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6377 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6379 /* Emit code to get the next parallel iteration in L2_BB. */
6380 gsi = gsi_start_bb (l2_bb);
6382 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6383 build_fold_addr_expr (istart0),
6384 build_fold_addr_expr (iend0));
6385 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6386 false, GSI_CONTINUE_LINKING);
6387 if (TREE_TYPE (t) != boolean_type_node)
6388 t = fold_build2 (NE_EXPR, boolean_type_node,
6389 t, build_int_cst (TREE_TYPE (t), 0));
6390 gcond *cond_stmt = gimple_build_cond_empty (t);
6391 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6394 /* Add the loop cleanup function. */
6395 gsi = gsi_last_bb (exit_bb);
6396 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6397 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6398 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6399 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6400 else
6401 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6402 gcall *call_stmt = gimple_build_call (t, 0);
6403 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6404 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6405 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6406 gsi_remove (&gsi, true);
6408 /* Connect the new blocks. */
6409 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6410 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6412 if (!broken_loop)
6414 gimple_seq phis;
6416 e = find_edge (cont_bb, l3_bb);
6417 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6419 phis = phi_nodes (l3_bb);
6420 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6422 gimple phi = gsi_stmt (gsi);
6423 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6424 PHI_ARG_DEF_FROM_EDGE (phi, e));
6426 remove_edge (e);
6428 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6429 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6430 e = find_edge (cont_bb, l1_bb);
6431 if (gimple_omp_for_combined_p (fd->for_stmt))
6433 remove_edge (e);
6434 e = NULL;
6436 else if (fd->collapse > 1)
6438 remove_edge (e);
6439 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6441 else
6442 e->flags = EDGE_TRUE_VALUE;
6443 if (e)
6445 e->probability = REG_BR_PROB_BASE * 7 / 8;
6446 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6448 else
6450 e = find_edge (cont_bb, l2_bb);
6451 e->flags = EDGE_FALLTHRU;
6453 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6455 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6456 recompute_dominator (CDI_DOMINATORS, l2_bb));
6457 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6458 recompute_dominator (CDI_DOMINATORS, l3_bb));
6459 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6460 recompute_dominator (CDI_DOMINATORS, l0_bb));
6461 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6462 recompute_dominator (CDI_DOMINATORS, l1_bb));
6464 struct loop *outer_loop = alloc_loop ();
6465 outer_loop->header = l0_bb;
6466 outer_loop->latch = l2_bb;
6467 add_loop (outer_loop, l0_bb->loop_father);
6469 if (!gimple_omp_for_combined_p (fd->for_stmt))
6471 struct loop *loop = alloc_loop ();
6472 loop->header = l1_bb;
6473 /* The loop may have multiple latches. */
6474 add_loop (loop, outer_loop);
6480 /* A subroutine of expand_omp_for. Generate code for a parallel
6481 loop with static schedule and no specified chunk size. Given
6482 parameters:
6484 for (V = N1; V cond N2; V += STEP) BODY;
6486 where COND is "<" or ">", we generate pseudocode
6488 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6489 if (cond is <)
6490 adj = STEP - 1;
6491 else
6492 adj = STEP + 1;
6493 if ((__typeof (V)) -1 > 0 && cond is >)
6494 n = -(adj + N2 - N1) / -STEP;
6495 else
6496 n = (adj + N2 - N1) / STEP;
6497 q = n / nthreads;
6498 tt = n % nthreads;
6499 if (threadid < tt) goto L3; else goto L4;
6501 tt = 0;
6502 q = q + 1;
6504 s0 = q * threadid + tt;
6505 e0 = s0 + q;
6506 V = s0 * STEP + N1;
6507 if (s0 >= e0) goto L2; else goto L0;
6509 e = e0 * STEP + N1;
6511 BODY;
6512 V += STEP;
6513 if (V cond e) goto L1;
6517 static void
6518 expand_omp_for_static_nochunk (struct omp_region *region,
6519 struct omp_for_data *fd,
6520 gimple inner_stmt)
6522 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6523 tree type, itype, vmain, vback;
6524 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6525 basic_block body_bb, cont_bb, collapse_bb = NULL;
6526 basic_block fin_bb;
6527 gimple_stmt_iterator gsi;
6528 edge ep;
6529 bool broken_loop = region->cont == NULL;
6530 tree *counts = NULL;
6531 tree n1, n2, step;
6533 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6534 != GF_OMP_FOR_KIND_OACC_LOOP)
6535 || !inner_stmt);
6537 itype = type = TREE_TYPE (fd->loop.v);
6538 if (POINTER_TYPE_P (type))
6539 itype = signed_type_for (type);
6541 entry_bb = region->entry;
6542 cont_bb = region->cont;
6543 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6544 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6545 gcc_assert (broken_loop
6546 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6547 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6548 body_bb = single_succ (seq_start_bb);
6549 if (!broken_loop)
6551 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6552 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6554 exit_bb = region->exit;
6556 /* Iteration space partitioning goes in ENTRY_BB. */
6557 gsi = gsi_last_bb (entry_bb);
6558 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6560 if (fd->collapse > 1)
6562 int first_zero_iter = -1;
6563 basic_block l2_dom_bb = NULL;
6565 counts = XALLOCAVEC (tree, fd->collapse);
6566 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6567 fin_bb, first_zero_iter,
6568 l2_dom_bb);
6569 t = NULL_TREE;
6571 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6572 t = integer_one_node;
6573 else
6574 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6575 fold_convert (type, fd->loop.n1),
6576 fold_convert (type, fd->loop.n2));
6577 if (fd->collapse == 1
6578 && TYPE_UNSIGNED (type)
6579 && (t == NULL_TREE || !integer_onep (t)))
6581 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6582 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6583 true, GSI_SAME_STMT);
6584 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6585 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6586 true, GSI_SAME_STMT);
6587 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6588 NULL_TREE, NULL_TREE);
6589 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6590 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6591 expand_omp_regimplify_p, NULL, NULL)
6592 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6593 expand_omp_regimplify_p, NULL, NULL))
6595 gsi = gsi_for_stmt (cond_stmt);
6596 gimple_regimplify_operands (cond_stmt, &gsi);
6598 ep = split_block (entry_bb, cond_stmt);
6599 ep->flags = EDGE_TRUE_VALUE;
6600 entry_bb = ep->dest;
6601 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6602 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6603 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6604 if (gimple_in_ssa_p (cfun))
6606 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6607 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6608 !gsi_end_p (gpi); gsi_next (&gpi))
6610 gphi *phi = gpi.phi ();
6611 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6612 ep, UNKNOWN_LOCATION);
6615 gsi = gsi_last_bb (entry_bb);
6618 switch (gimple_omp_for_kind (fd->for_stmt))
6620 case GF_OMP_FOR_KIND_FOR:
6621 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6622 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6623 break;
6624 case GF_OMP_FOR_KIND_DISTRIBUTE:
6625 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6626 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6627 break;
6628 case GF_OMP_FOR_KIND_OACC_LOOP:
6629 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6630 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6631 break;
6632 default:
6633 gcc_unreachable ();
6635 nthreads = build_call_expr (nthreads, 0);
6636 nthreads = fold_convert (itype, nthreads);
6637 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6638 true, GSI_SAME_STMT);
6639 threadid = build_call_expr (threadid, 0);
6640 threadid = fold_convert (itype, threadid);
6641 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6642 true, GSI_SAME_STMT);
6644 n1 = fd->loop.n1;
6645 n2 = fd->loop.n2;
6646 step = fd->loop.step;
6647 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6649 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6650 OMP_CLAUSE__LOOPTEMP_);
6651 gcc_assert (innerc);
6652 n1 = OMP_CLAUSE_DECL (innerc);
6653 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6654 OMP_CLAUSE__LOOPTEMP_);
6655 gcc_assert (innerc);
6656 n2 = OMP_CLAUSE_DECL (innerc);
6658 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6659 true, NULL_TREE, true, GSI_SAME_STMT);
6660 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6661 true, NULL_TREE, true, GSI_SAME_STMT);
6662 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6663 true, NULL_TREE, true, GSI_SAME_STMT);
6665 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6666 t = fold_build2 (PLUS_EXPR, itype, step, t);
6667 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6668 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6669 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6670 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6671 fold_build1 (NEGATE_EXPR, itype, t),
6672 fold_build1 (NEGATE_EXPR, itype, step));
6673 else
6674 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6675 t = fold_convert (itype, t);
6676 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6678 q = create_tmp_reg (itype, "q");
6679 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6680 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6681 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6683 tt = create_tmp_reg (itype, "tt");
6684 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6685 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6686 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6688 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6689 gcond *cond_stmt = gimple_build_cond_empty (t);
6690 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6692 second_bb = split_block (entry_bb, cond_stmt)->dest;
6693 gsi = gsi_last_bb (second_bb);
6694 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6696 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6697 GSI_SAME_STMT);
6698 gassign *assign_stmt
6699 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6700 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6702 third_bb = split_block (second_bb, assign_stmt)->dest;
6703 gsi = gsi_last_bb (third_bb);
6704 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6706 t = build2 (MULT_EXPR, itype, q, threadid);
6707 t = build2 (PLUS_EXPR, itype, t, tt);
6708 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6710 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6711 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6713 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6714 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6716 /* Remove the GIMPLE_OMP_FOR statement. */
6717 gsi_remove (&gsi, true);
6719 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6720 gsi = gsi_start_bb (seq_start_bb);
6722 tree startvar = fd->loop.v;
6723 tree endvar = NULL_TREE;
6725 if (gimple_omp_for_combined_p (fd->for_stmt))
6727 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6728 ? gimple_omp_parallel_clauses (inner_stmt)
6729 : gimple_omp_for_clauses (inner_stmt);
6730 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6731 gcc_assert (innerc);
6732 startvar = OMP_CLAUSE_DECL (innerc);
6733 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6734 OMP_CLAUSE__LOOPTEMP_);
6735 gcc_assert (innerc);
6736 endvar = OMP_CLAUSE_DECL (innerc);
6738 t = fold_convert (itype, s0);
6739 t = fold_build2 (MULT_EXPR, itype, t, step);
6740 if (POINTER_TYPE_P (type))
6741 t = fold_build_pointer_plus (n1, t);
6742 else
6743 t = fold_build2 (PLUS_EXPR, type, t, n1);
6744 t = fold_convert (TREE_TYPE (startvar), t);
6745 t = force_gimple_operand_gsi (&gsi, t,
6746 DECL_P (startvar)
6747 && TREE_ADDRESSABLE (startvar),
6748 NULL_TREE, false, GSI_CONTINUE_LINKING);
6749 assign_stmt = gimple_build_assign (startvar, t);
6750 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6752 t = fold_convert (itype, e0);
6753 t = fold_build2 (MULT_EXPR, itype, t, step);
6754 if (POINTER_TYPE_P (type))
6755 t = fold_build_pointer_plus (n1, t);
6756 else
6757 t = fold_build2 (PLUS_EXPR, type, t, n1);
6758 t = fold_convert (TREE_TYPE (startvar), t);
6759 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6760 false, GSI_CONTINUE_LINKING);
6761 if (endvar)
6763 assign_stmt = gimple_build_assign (endvar, e);
6764 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6765 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6766 assign_stmt = gimple_build_assign (fd->loop.v, e);
6767 else
6768 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6769 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6771 if (fd->collapse > 1)
6772 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6774 if (!broken_loop)
6776 /* The code controlling the sequential loop replaces the
6777 GIMPLE_OMP_CONTINUE. */
6778 gsi = gsi_last_bb (cont_bb);
6779 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6780 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6781 vmain = gimple_omp_continue_control_use (cont_stmt);
6782 vback = gimple_omp_continue_control_def (cont_stmt);
6784 if (!gimple_omp_for_combined_p (fd->for_stmt))
6786 if (POINTER_TYPE_P (type))
6787 t = fold_build_pointer_plus (vmain, step);
6788 else
6789 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6790 t = force_gimple_operand_gsi (&gsi, t,
6791 DECL_P (vback)
6792 && TREE_ADDRESSABLE (vback),
6793 NULL_TREE, true, GSI_SAME_STMT);
6794 assign_stmt = gimple_build_assign (vback, t);
6795 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6797 t = build2 (fd->loop.cond_code, boolean_type_node,
6798 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6799 ? t : vback, e);
6800 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6803 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6804 gsi_remove (&gsi, true);
6806 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6807 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6810 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6811 gsi = gsi_last_bb (exit_bb);
6812 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6814 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6815 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6816 gcc_checking_assert (t == NULL_TREE);
6817 else
6818 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6820 gsi_remove (&gsi, true);
6822 /* Connect all the blocks. */
6823 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6824 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6825 ep = find_edge (entry_bb, second_bb);
6826 ep->flags = EDGE_TRUE_VALUE;
6827 ep->probability = REG_BR_PROB_BASE / 4;
6828 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6829 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6831 if (!broken_loop)
6833 ep = find_edge (cont_bb, body_bb);
6834 if (gimple_omp_for_combined_p (fd->for_stmt))
6836 remove_edge (ep);
6837 ep = NULL;
6839 else if (fd->collapse > 1)
6841 remove_edge (ep);
6842 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6844 else
6845 ep->flags = EDGE_TRUE_VALUE;
6846 find_edge (cont_bb, fin_bb)->flags
6847 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6850 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6851 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6852 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6854 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6855 recompute_dominator (CDI_DOMINATORS, body_bb));
6856 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6857 recompute_dominator (CDI_DOMINATORS, fin_bb));
6859 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6861 struct loop *loop = alloc_loop ();
6862 loop->header = body_bb;
6863 if (collapse_bb == NULL)
6864 loop->latch = cont_bb;
6865 add_loop (loop, body_bb->loop_father);
6870 /* A subroutine of expand_omp_for. Generate code for a parallel
6871 loop with static schedule and a specified chunk size. Given
6872 parameters:
6874 for (V = N1; V cond N2; V += STEP) BODY;
6876 where COND is "<" or ">", we generate pseudocode
6878 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6879 if (cond is <)
6880 adj = STEP - 1;
6881 else
6882 adj = STEP + 1;
6883 if ((__typeof (V)) -1 > 0 && cond is >)
6884 n = -(adj + N2 - N1) / -STEP;
6885 else
6886 n = (adj + N2 - N1) / STEP;
6887 trip = 0;
6888 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6889 here so that V is defined
6890 if the loop is not entered
6892 s0 = (trip * nthreads + threadid) * CHUNK;
6893 e0 = min(s0 + CHUNK, n);
6894 if (s0 < n) goto L1; else goto L4;
6896 V = s0 * STEP + N1;
6897 e = e0 * STEP + N1;
6899 BODY;
6900 V += STEP;
6901 if (V cond e) goto L2; else goto L3;
6903 trip += 1;
6904 goto L0;
6908 static void
6909 expand_omp_for_static_chunk (struct omp_region *region,
6910 struct omp_for_data *fd, gimple inner_stmt)
6912 tree n, s0, e0, e, t;
6913 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6914 tree type, itype, vmain, vback, vextra;
6915 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6916 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6917 gimple_stmt_iterator gsi;
6918 edge se;
6919 bool broken_loop = region->cont == NULL;
6920 tree *counts = NULL;
6921 tree n1, n2, step;
6923 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6924 != GF_OMP_FOR_KIND_OACC_LOOP)
6925 || !inner_stmt);
6927 itype = type = TREE_TYPE (fd->loop.v);
6928 if (POINTER_TYPE_P (type))
6929 itype = signed_type_for (type);
6931 entry_bb = region->entry;
6932 se = split_block (entry_bb, last_stmt (entry_bb));
6933 entry_bb = se->src;
6934 iter_part_bb = se->dest;
6935 cont_bb = region->cont;
6936 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6937 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6938 gcc_assert (broken_loop
6939 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6940 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6941 body_bb = single_succ (seq_start_bb);
6942 if (!broken_loop)
6944 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6945 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6946 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6948 exit_bb = region->exit;
6950 /* Trip and adjustment setup goes in ENTRY_BB. */
6951 gsi = gsi_last_bb (entry_bb);
6952 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6954 if (fd->collapse > 1)
6956 int first_zero_iter = -1;
6957 basic_block l2_dom_bb = NULL;
6959 counts = XALLOCAVEC (tree, fd->collapse);
6960 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6961 fin_bb, first_zero_iter,
6962 l2_dom_bb);
6963 t = NULL_TREE;
6965 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6966 t = integer_one_node;
6967 else
6968 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6969 fold_convert (type, fd->loop.n1),
6970 fold_convert (type, fd->loop.n2));
6971 if (fd->collapse == 1
6972 && TYPE_UNSIGNED (type)
6973 && (t == NULL_TREE || !integer_onep (t)))
6975 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6976 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6977 true, GSI_SAME_STMT);
6978 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6979 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6980 true, GSI_SAME_STMT);
6981 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6982 NULL_TREE, NULL_TREE);
6983 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6984 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6985 expand_omp_regimplify_p, NULL, NULL)
6986 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6987 expand_omp_regimplify_p, NULL, NULL))
6989 gsi = gsi_for_stmt (cond_stmt);
6990 gimple_regimplify_operands (cond_stmt, &gsi);
6992 se = split_block (entry_bb, cond_stmt);
6993 se->flags = EDGE_TRUE_VALUE;
6994 entry_bb = se->dest;
6995 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6996 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6997 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6998 if (gimple_in_ssa_p (cfun))
7000 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
7001 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
7002 !gsi_end_p (gpi); gsi_next (&gpi))
7004 gphi *phi = gpi.phi ();
7005 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
7006 se, UNKNOWN_LOCATION);
7009 gsi = gsi_last_bb (entry_bb);
7012 switch (gimple_omp_for_kind (fd->for_stmt))
7014 case GF_OMP_FOR_KIND_FOR:
7015 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7016 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7017 break;
7018 case GF_OMP_FOR_KIND_DISTRIBUTE:
7019 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7020 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7021 break;
7022 case GF_OMP_FOR_KIND_OACC_LOOP:
7023 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7024 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7025 break;
7026 default:
7027 gcc_unreachable ();
7029 nthreads = build_call_expr (nthreads, 0);
7030 nthreads = fold_convert (itype, nthreads);
7031 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7032 true, GSI_SAME_STMT);
7033 threadid = build_call_expr (threadid, 0);
7034 threadid = fold_convert (itype, threadid);
7035 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7036 true, GSI_SAME_STMT);
7038 n1 = fd->loop.n1;
7039 n2 = fd->loop.n2;
7040 step = fd->loop.step;
7041 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7043 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7044 OMP_CLAUSE__LOOPTEMP_);
7045 gcc_assert (innerc);
7046 n1 = OMP_CLAUSE_DECL (innerc);
7047 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7048 OMP_CLAUSE__LOOPTEMP_);
7049 gcc_assert (innerc);
7050 n2 = OMP_CLAUSE_DECL (innerc);
7052 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7053 true, NULL_TREE, true, GSI_SAME_STMT);
7054 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7055 true, NULL_TREE, true, GSI_SAME_STMT);
7056 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7057 true, NULL_TREE, true, GSI_SAME_STMT);
7058 fd->chunk_size
7059 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7060 true, NULL_TREE, true, GSI_SAME_STMT);
7062 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7063 t = fold_build2 (PLUS_EXPR, itype, step, t);
7064 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7065 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7066 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7067 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7068 fold_build1 (NEGATE_EXPR, itype, t),
7069 fold_build1 (NEGATE_EXPR, itype, step));
7070 else
7071 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7072 t = fold_convert (itype, t);
7073 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7074 true, GSI_SAME_STMT);
7076 trip_var = create_tmp_reg (itype, ".trip");
7077 if (gimple_in_ssa_p (cfun))
7079 trip_init = make_ssa_name (trip_var);
7080 trip_main = make_ssa_name (trip_var);
7081 trip_back = make_ssa_name (trip_var);
7083 else
7085 trip_init = trip_var;
7086 trip_main = trip_var;
7087 trip_back = trip_var;
7090 gassign *assign_stmt
7091 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7092 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7094 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7095 t = fold_build2 (MULT_EXPR, itype, t, step);
7096 if (POINTER_TYPE_P (type))
7097 t = fold_build_pointer_plus (n1, t);
7098 else
7099 t = fold_build2 (PLUS_EXPR, type, t, n1);
7100 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7101 true, GSI_SAME_STMT);
7103 /* Remove the GIMPLE_OMP_FOR. */
7104 gsi_remove (&gsi, true);
7106 /* Iteration space partitioning goes in ITER_PART_BB. */
7107 gsi = gsi_last_bb (iter_part_bb);
7109 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7110 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7111 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7112 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7113 false, GSI_CONTINUE_LINKING);
7115 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7116 t = fold_build2 (MIN_EXPR, itype, t, n);
7117 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7118 false, GSI_CONTINUE_LINKING);
7120 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7121 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7123 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7124 gsi = gsi_start_bb (seq_start_bb);
7126 tree startvar = fd->loop.v;
7127 tree endvar = NULL_TREE;
7129 if (gimple_omp_for_combined_p (fd->for_stmt))
7131 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7132 ? gimple_omp_parallel_clauses (inner_stmt)
7133 : gimple_omp_for_clauses (inner_stmt);
7134 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7135 gcc_assert (innerc);
7136 startvar = OMP_CLAUSE_DECL (innerc);
7137 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7138 OMP_CLAUSE__LOOPTEMP_);
7139 gcc_assert (innerc);
7140 endvar = OMP_CLAUSE_DECL (innerc);
7143 t = fold_convert (itype, s0);
7144 t = fold_build2 (MULT_EXPR, itype, t, step);
7145 if (POINTER_TYPE_P (type))
7146 t = fold_build_pointer_plus (n1, t);
7147 else
7148 t = fold_build2 (PLUS_EXPR, type, t, n1);
7149 t = fold_convert (TREE_TYPE (startvar), t);
7150 t = force_gimple_operand_gsi (&gsi, t,
7151 DECL_P (startvar)
7152 && TREE_ADDRESSABLE (startvar),
7153 NULL_TREE, false, GSI_CONTINUE_LINKING);
7154 assign_stmt = gimple_build_assign (startvar, t);
7155 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7157 t = fold_convert (itype, e0);
7158 t = fold_build2 (MULT_EXPR, itype, t, step);
7159 if (POINTER_TYPE_P (type))
7160 t = fold_build_pointer_plus (n1, t);
7161 else
7162 t = fold_build2 (PLUS_EXPR, type, t, n1);
7163 t = fold_convert (TREE_TYPE (startvar), t);
7164 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7165 false, GSI_CONTINUE_LINKING);
7166 if (endvar)
7168 assign_stmt = gimple_build_assign (endvar, e);
7169 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7170 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7171 assign_stmt = gimple_build_assign (fd->loop.v, e);
7172 else
7173 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7174 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7176 if (fd->collapse > 1)
7177 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7179 if (!broken_loop)
7181 /* The code controlling the sequential loop goes in CONT_BB,
7182 replacing the GIMPLE_OMP_CONTINUE. */
7183 gsi = gsi_last_bb (cont_bb);
7184 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7185 vmain = gimple_omp_continue_control_use (cont_stmt);
7186 vback = gimple_omp_continue_control_def (cont_stmt);
7188 if (!gimple_omp_for_combined_p (fd->for_stmt))
7190 if (POINTER_TYPE_P (type))
7191 t = fold_build_pointer_plus (vmain, step);
7192 else
7193 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7194 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7195 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7196 true, GSI_SAME_STMT);
7197 assign_stmt = gimple_build_assign (vback, t);
7198 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7200 t = build2 (fd->loop.cond_code, boolean_type_node,
7201 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7202 ? t : vback, e);
7203 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7206 /* Remove GIMPLE_OMP_CONTINUE. */
7207 gsi_remove (&gsi, true);
7209 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7210 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7212 /* Trip update code goes into TRIP_UPDATE_BB. */
7213 gsi = gsi_start_bb (trip_update_bb);
7215 t = build_int_cst (itype, 1);
7216 t = build2 (PLUS_EXPR, itype, trip_main, t);
7217 assign_stmt = gimple_build_assign (trip_back, t);
7218 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7221 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7222 gsi = gsi_last_bb (exit_bb);
7223 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7225 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7226 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7227 gcc_checking_assert (t == NULL_TREE);
7228 else
7229 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7231 gsi_remove (&gsi, true);
7233 /* Connect the new blocks. */
7234 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7235 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7237 if (!broken_loop)
7239 se = find_edge (cont_bb, body_bb);
7240 if (gimple_omp_for_combined_p (fd->for_stmt))
7242 remove_edge (se);
7243 se = NULL;
7245 else if (fd->collapse > 1)
7247 remove_edge (se);
7248 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7250 else
7251 se->flags = EDGE_TRUE_VALUE;
7252 find_edge (cont_bb, trip_update_bb)->flags
7253 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7255 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7258 if (gimple_in_ssa_p (cfun))
7260 gphi_iterator psi;
7261 gphi *phi;
7262 edge re, ene;
7263 edge_var_map *vm;
7264 size_t i;
7266 gcc_assert (fd->collapse == 1 && !broken_loop);
7268 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7269 remove arguments of the phi nodes in fin_bb. We need to create
7270 appropriate phi nodes in iter_part_bb instead. */
7271 se = single_pred_edge (fin_bb);
7272 re = single_succ_edge (trip_update_bb);
7273 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7274 ene = single_succ_edge (entry_bb);
7276 psi = gsi_start_phis (fin_bb);
7277 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7278 gsi_next (&psi), ++i)
7280 gphi *nphi;
7281 source_location locus;
7283 phi = psi.phi ();
7284 t = gimple_phi_result (phi);
7285 gcc_assert (t == redirect_edge_var_map_result (vm));
7286 nphi = create_phi_node (t, iter_part_bb);
7288 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7289 locus = gimple_phi_arg_location_from_edge (phi, se);
7291 /* A special case -- fd->loop.v is not yet computed in
7292 iter_part_bb, we need to use vextra instead. */
7293 if (t == fd->loop.v)
7294 t = vextra;
7295 add_phi_arg (nphi, t, ene, locus);
7296 locus = redirect_edge_var_map_location (vm);
7297 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7299 gcc_assert (gsi_end_p (psi) && i == head->length ());
7300 redirect_edge_var_map_clear (re);
7301 while (1)
7303 psi = gsi_start_phis (fin_bb);
7304 if (gsi_end_p (psi))
7305 break;
7306 remove_phi_node (&psi, false);
7309 /* Make phi node for trip. */
7310 phi = create_phi_node (trip_main, iter_part_bb);
7311 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7312 UNKNOWN_LOCATION);
7313 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7314 UNKNOWN_LOCATION);
7317 if (!broken_loop)
7318 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7319 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7320 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7321 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7322 recompute_dominator (CDI_DOMINATORS, fin_bb));
7323 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7324 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7325 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7326 recompute_dominator (CDI_DOMINATORS, body_bb));
7328 if (!broken_loop)
7330 struct loop *trip_loop = alloc_loop ();
7331 trip_loop->header = iter_part_bb;
7332 trip_loop->latch = trip_update_bb;
7333 add_loop (trip_loop, iter_part_bb->loop_father);
7335 if (!gimple_omp_for_combined_p (fd->for_stmt))
7337 struct loop *loop = alloc_loop ();
7338 loop->header = body_bb;
7339 if (collapse_bb == NULL)
7340 loop->latch = cont_bb;
7341 add_loop (loop, trip_loop);
7346 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7347 Given parameters:
7348 for (V = N1; V cond N2; V += STEP) BODY;
7350 where COND is "<" or ">" or "!=", we generate pseudocode
7352 for (ind_var = low; ind_var < high; ind_var++)
7354 V = n1 + (ind_var * STEP)
7356 <BODY>
7359 In the above pseudocode, low and high are function parameters of the
7360 child function. In the function below, we are inserting a temp.
7361 variable that will be making a call to two OMP functions that will not be
7362 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7363 with _Cilk_for). These functions are replaced with low and high
7364 by the function that handles taskreg. */
7367 static void
7368 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7370 bool broken_loop = region->cont == NULL;
7371 basic_block entry_bb = region->entry;
7372 basic_block cont_bb = region->cont;
7374 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7375 gcc_assert (broken_loop
7376 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7377 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7378 basic_block l1_bb, l2_bb;
7380 if (!broken_loop)
7382 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7383 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7384 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7385 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7387 else
7389 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7390 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7391 l2_bb = single_succ (l1_bb);
7393 basic_block exit_bb = region->exit;
7394 basic_block l2_dom_bb = NULL;
7396 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7398 /* Below statements until the "tree high_val = ..." are pseudo statements
7399 used to pass information to be used by expand_omp_taskreg.
7400 low_val and high_val will be replaced by the __low and __high
7401 parameter from the child function.
7403 The call_exprs part is a place-holder, it is mainly used
7404 to distinctly identify to the top-level part that this is
7405 where we should put low and high (reasoning given in header
7406 comment). */
7408 tree child_fndecl
7409 = gimple_omp_parallel_child_fn (
7410 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7411 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7412 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7414 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7415 high_val = t;
7416 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7417 low_val = t;
7419 gcc_assert (low_val && high_val);
7421 tree type = TREE_TYPE (low_val);
7422 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7423 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7425 /* Not needed in SSA form right now. */
7426 gcc_assert (!gimple_in_ssa_p (cfun));
7427 if (l2_dom_bb == NULL)
7428 l2_dom_bb = l1_bb;
7430 tree n1 = low_val;
7431 tree n2 = high_val;
7433 gimple stmt = gimple_build_assign (ind_var, n1);
7435 /* Replace the GIMPLE_OMP_FOR statement. */
7436 gsi_replace (&gsi, stmt, true);
7438 if (!broken_loop)
7440 /* Code to control the increment goes in the CONT_BB. */
7441 gsi = gsi_last_bb (cont_bb);
7442 stmt = gsi_stmt (gsi);
7443 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7444 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7445 build_one_cst (type));
7447 /* Replace GIMPLE_OMP_CONTINUE. */
7448 gsi_replace (&gsi, stmt, true);
7451 /* Emit the condition in L1_BB. */
7452 gsi = gsi_after_labels (l1_bb);
7453 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7454 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7455 fd->loop.step);
7456 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7457 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7458 fd->loop.n1, fold_convert (sizetype, t));
7459 else
7460 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7461 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7462 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7463 expand_omp_build_assign (&gsi, fd->loop.v, t);
7465 /* The condition is always '<' since the runtime will fill in the low
7466 and high values. */
7467 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7468 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7470 /* Remove GIMPLE_OMP_RETURN. */
7471 gsi = gsi_last_bb (exit_bb);
7472 gsi_remove (&gsi, true);
7474 /* Connect the new blocks. */
7475 remove_edge (FALLTHRU_EDGE (entry_bb));
7477 edge e, ne;
7478 if (!broken_loop)
7480 remove_edge (BRANCH_EDGE (entry_bb));
7481 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7483 e = BRANCH_EDGE (l1_bb);
7484 ne = FALLTHRU_EDGE (l1_bb);
7485 e->flags = EDGE_TRUE_VALUE;
7487 else
7489 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7491 ne = single_succ_edge (l1_bb);
7492 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7495 ne->flags = EDGE_FALSE_VALUE;
7496 e->probability = REG_BR_PROB_BASE * 7 / 8;
7497 ne->probability = REG_BR_PROB_BASE / 8;
7499 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7500 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7501 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7503 if (!broken_loop)
7505 struct loop *loop = alloc_loop ();
7506 loop->header = l1_bb;
7507 loop->latch = cont_bb;
7508 add_loop (loop, l1_bb->loop_father);
7509 loop->safelen = INT_MAX;
7512 /* Pick the correct library function based on the precision of the
7513 induction variable type. */
7514 tree lib_fun = NULL_TREE;
7515 if (TYPE_PRECISION (type) == 32)
7516 lib_fun = cilk_for_32_fndecl;
7517 else if (TYPE_PRECISION (type) == 64)
7518 lib_fun = cilk_for_64_fndecl;
7519 else
7520 gcc_unreachable ();
7522 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7524 /* WS_ARGS contains the library function flavor to call:
7525 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7526 user-defined grain value. If the user does not define one, then zero
7527 is passed in by the parser. */
7528 vec_alloc (region->ws_args, 2);
7529 region->ws_args->quick_push (lib_fun);
7530 region->ws_args->quick_push (fd->chunk_size);
7533 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7534 loop. Given parameters:
7536 for (V = N1; V cond N2; V += STEP) BODY;
7538 where COND is "<" or ">", we generate pseudocode
7540 V = N1;
7541 goto L1;
7543 BODY;
7544 V += STEP;
7546 if (V cond N2) goto L0; else goto L2;
7549 For collapsed loops, given parameters:
7550 collapse(3)
7551 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7552 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7553 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7554 BODY;
7556 we generate pseudocode
7558 if (cond3 is <)
7559 adj = STEP3 - 1;
7560 else
7561 adj = STEP3 + 1;
7562 count3 = (adj + N32 - N31) / STEP3;
7563 if (cond2 is <)
7564 adj = STEP2 - 1;
7565 else
7566 adj = STEP2 + 1;
7567 count2 = (adj + N22 - N21) / STEP2;
7568 if (cond1 is <)
7569 adj = STEP1 - 1;
7570 else
7571 adj = STEP1 + 1;
7572 count1 = (adj + N12 - N11) / STEP1;
7573 count = count1 * count2 * count3;
7574 V = 0;
7575 V1 = N11;
7576 V2 = N21;
7577 V3 = N31;
7578 goto L1;
7580 BODY;
7581 V += 1;
7582 V3 += STEP3;
7583 V2 += (V3 cond3 N32) ? 0 : STEP2;
7584 V3 = (V3 cond3 N32) ? V3 : N31;
7585 V1 += (V2 cond2 N22) ? 0 : STEP1;
7586 V2 = (V2 cond2 N22) ? V2 : N21;
7588 if (V < count) goto L0; else goto L2;
7593 static void
7594 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7596 tree type, t;
7597 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7598 gimple_stmt_iterator gsi;
7599 gimple stmt;
7600 gcond *cond_stmt;
7601 bool broken_loop = region->cont == NULL;
7602 edge e, ne;
7603 tree *counts = NULL;
7604 int i;
7605 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7606 OMP_CLAUSE_SAFELEN);
7607 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7608 OMP_CLAUSE__SIMDUID_);
7609 tree n1, n2;
7611 type = TREE_TYPE (fd->loop.v);
7612 entry_bb = region->entry;
7613 cont_bb = region->cont;
7614 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7615 gcc_assert (broken_loop
7616 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7617 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7618 if (!broken_loop)
7620 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7621 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7622 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7623 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7625 else
7627 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7628 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7629 l2_bb = single_succ (l1_bb);
7631 exit_bb = region->exit;
7632 l2_dom_bb = NULL;
7634 gsi = gsi_last_bb (entry_bb);
7636 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7637 /* Not needed in SSA form right now. */
7638 gcc_assert (!gimple_in_ssa_p (cfun));
7639 if (fd->collapse > 1)
7641 int first_zero_iter = -1;
7642 basic_block zero_iter_bb = l2_bb;
7644 counts = XALLOCAVEC (tree, fd->collapse);
7645 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7646 zero_iter_bb, first_zero_iter,
7647 l2_dom_bb);
7649 if (l2_dom_bb == NULL)
7650 l2_dom_bb = l1_bb;
7652 n1 = fd->loop.n1;
7653 n2 = fd->loop.n2;
7654 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7656 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7657 OMP_CLAUSE__LOOPTEMP_);
7658 gcc_assert (innerc);
7659 n1 = OMP_CLAUSE_DECL (innerc);
7660 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7661 OMP_CLAUSE__LOOPTEMP_);
7662 gcc_assert (innerc);
7663 n2 = OMP_CLAUSE_DECL (innerc);
7664 expand_omp_build_assign (&gsi, fd->loop.v,
7665 fold_convert (type, n1));
7666 if (fd->collapse > 1)
7668 gsi_prev (&gsi);
7669 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7670 gsi_next (&gsi);
7673 else
7675 expand_omp_build_assign (&gsi, fd->loop.v,
7676 fold_convert (type, fd->loop.n1));
7677 if (fd->collapse > 1)
7678 for (i = 0; i < fd->collapse; i++)
7680 tree itype = TREE_TYPE (fd->loops[i].v);
7681 if (POINTER_TYPE_P (itype))
7682 itype = signed_type_for (itype);
7683 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7684 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7688 /* Remove the GIMPLE_OMP_FOR statement. */
7689 gsi_remove (&gsi, true);
7691 if (!broken_loop)
7693 /* Code to control the increment goes in the CONT_BB. */
7694 gsi = gsi_last_bb (cont_bb);
7695 stmt = gsi_stmt (gsi);
7696 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7698 if (POINTER_TYPE_P (type))
7699 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7700 else
7701 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7702 expand_omp_build_assign (&gsi, fd->loop.v, t);
7704 if (fd->collapse > 1)
7706 i = fd->collapse - 1;
7707 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7709 t = fold_convert (sizetype, fd->loops[i].step);
7710 t = fold_build_pointer_plus (fd->loops[i].v, t);
7712 else
7714 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7715 fd->loops[i].step);
7716 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7717 fd->loops[i].v, t);
7719 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7721 for (i = fd->collapse - 1; i > 0; i--)
7723 tree itype = TREE_TYPE (fd->loops[i].v);
7724 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7725 if (POINTER_TYPE_P (itype2))
7726 itype2 = signed_type_for (itype2);
7727 t = build3 (COND_EXPR, itype2,
7728 build2 (fd->loops[i].cond_code, boolean_type_node,
7729 fd->loops[i].v,
7730 fold_convert (itype, fd->loops[i].n2)),
7731 build_int_cst (itype2, 0),
7732 fold_convert (itype2, fd->loops[i - 1].step));
7733 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7734 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7735 else
7736 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7737 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7739 t = build3 (COND_EXPR, itype,
7740 build2 (fd->loops[i].cond_code, boolean_type_node,
7741 fd->loops[i].v,
7742 fold_convert (itype, fd->loops[i].n2)),
7743 fd->loops[i].v,
7744 fold_convert (itype, fd->loops[i].n1));
7745 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7749 /* Remove GIMPLE_OMP_CONTINUE. */
7750 gsi_remove (&gsi, true);
7753 /* Emit the condition in L1_BB. */
7754 gsi = gsi_start_bb (l1_bb);
7756 t = fold_convert (type, n2);
7757 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7758 false, GSI_CONTINUE_LINKING);
7759 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7760 cond_stmt = gimple_build_cond_empty (t);
7761 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7762 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7763 NULL, NULL)
7764 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7765 NULL, NULL))
7767 gsi = gsi_for_stmt (cond_stmt);
7768 gimple_regimplify_operands (cond_stmt, &gsi);
7771 /* Remove GIMPLE_OMP_RETURN. */
7772 gsi = gsi_last_bb (exit_bb);
7773 gsi_remove (&gsi, true);
7775 /* Connect the new blocks. */
7776 remove_edge (FALLTHRU_EDGE (entry_bb));
7778 if (!broken_loop)
7780 remove_edge (BRANCH_EDGE (entry_bb));
7781 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7783 e = BRANCH_EDGE (l1_bb);
7784 ne = FALLTHRU_EDGE (l1_bb);
7785 e->flags = EDGE_TRUE_VALUE;
7787 else
7789 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7791 ne = single_succ_edge (l1_bb);
7792 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7795 ne->flags = EDGE_FALSE_VALUE;
7796 e->probability = REG_BR_PROB_BASE * 7 / 8;
7797 ne->probability = REG_BR_PROB_BASE / 8;
7799 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7800 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7801 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7803 if (!broken_loop)
7805 struct loop *loop = alloc_loop ();
7806 loop->header = l1_bb;
7807 loop->latch = cont_bb;
7808 add_loop (loop, l1_bb->loop_father);
7809 if (safelen == NULL_TREE)
7810 loop->safelen = INT_MAX;
7811 else
7813 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7814 if (TREE_CODE (safelen) != INTEGER_CST)
7815 loop->safelen = 0;
7816 else if (!tree_fits_uhwi_p (safelen)
7817 || tree_to_uhwi (safelen) > INT_MAX)
7818 loop->safelen = INT_MAX;
7819 else
7820 loop->safelen = tree_to_uhwi (safelen);
7821 if (loop->safelen == 1)
7822 loop->safelen = 0;
7824 if (simduid)
7826 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7827 cfun->has_simduid_loops = true;
7829 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7830 the loop. */
7831 if ((flag_tree_loop_vectorize
7832 || (!global_options_set.x_flag_tree_loop_vectorize
7833 && !global_options_set.x_flag_tree_vectorize))
7834 && flag_tree_loop_optimize
7835 && loop->safelen > 1)
7837 loop->force_vectorize = true;
7838 cfun->has_force_vectorize_loops = true;
7841 else if (simduid)
7842 cfun->has_simduid_loops = true;
7846 /* Expand the OMP loop defined by REGION. */
7848 static void
7849 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7851 struct omp_for_data fd;
7852 struct omp_for_data_loop *loops;
7854 loops
7855 = (struct omp_for_data_loop *)
7856 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7857 * sizeof (struct omp_for_data_loop));
7858 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7859 &fd, loops);
7860 region->sched_kind = fd.sched_kind;
7862 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7863 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7864 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7865 if (region->cont)
7867 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7868 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7869 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7871 else
7872 /* If there isn't a continue then this is a degerate case where
7873 the introduction of abnormal edges during lowering will prevent
7874 original loops from being detected. Fix that up. */
7875 loops_state_set (LOOPS_NEED_FIXUP);
7877 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7878 expand_omp_simd (region, &fd);
7879 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7880 expand_cilk_for (region, &fd);
7881 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7882 && !fd.have_ordered)
7884 if (fd.chunk_size == NULL)
7885 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7886 else
7887 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7889 else
7891 int fn_index, start_ix, next_ix;
7893 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7894 == GF_OMP_FOR_KIND_FOR);
7895 if (fd.chunk_size == NULL
7896 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7897 fd.chunk_size = integer_zero_node;
7898 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7899 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7900 ? 3 : fd.sched_kind;
7901 fn_index += fd.have_ordered * 4;
7902 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7903 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7904 if (fd.iter_type == long_long_unsigned_type_node)
7906 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7907 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7908 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7909 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7911 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7912 (enum built_in_function) next_ix, inner_stmt);
7915 if (gimple_in_ssa_p (cfun))
7916 update_ssa (TODO_update_ssa_only_virtuals);
7920 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7922 v = GOMP_sections_start (n);
7924 switch (v)
7926 case 0:
7927 goto L2;
7928 case 1:
7929 section 1;
7930 goto L1;
7931 case 2:
7933 case n:
7935 default:
7936 abort ();
7939 v = GOMP_sections_next ();
7940 goto L0;
7942 reduction;
7944 If this is a combined parallel sections, replace the call to
7945 GOMP_sections_start with call to GOMP_sections_next. */
7947 static void
7948 expand_omp_sections (struct omp_region *region)
7950 tree t, u, vin = NULL, vmain, vnext, l2;
7951 unsigned len;
7952 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7953 gimple_stmt_iterator si, switch_si;
7954 gomp_sections *sections_stmt;
7955 gimple stmt;
7956 gomp_continue *cont;
7957 edge_iterator ei;
7958 edge e;
7959 struct omp_region *inner;
7960 unsigned i, casei;
7961 bool exit_reachable = region->cont != NULL;
7963 gcc_assert (region->exit != NULL);
7964 entry_bb = region->entry;
7965 l0_bb = single_succ (entry_bb);
7966 l1_bb = region->cont;
7967 l2_bb = region->exit;
7968 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7969 l2 = gimple_block_label (l2_bb);
7970 else
7972 /* This can happen if there are reductions. */
7973 len = EDGE_COUNT (l0_bb->succs);
7974 gcc_assert (len > 0);
7975 e = EDGE_SUCC (l0_bb, len - 1);
7976 si = gsi_last_bb (e->dest);
7977 l2 = NULL_TREE;
7978 if (gsi_end_p (si)
7979 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7980 l2 = gimple_block_label (e->dest);
7981 else
7982 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7984 si = gsi_last_bb (e->dest);
7985 if (gsi_end_p (si)
7986 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7988 l2 = gimple_block_label (e->dest);
7989 break;
7993 if (exit_reachable)
7994 default_bb = create_empty_bb (l1_bb->prev_bb);
7995 else
7996 default_bb = create_empty_bb (l0_bb);
7998 /* We will build a switch() with enough cases for all the
7999 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
8000 and a default case to abort if something goes wrong. */
8001 len = EDGE_COUNT (l0_bb->succs);
8003 /* Use vec::quick_push on label_vec throughout, since we know the size
8004 in advance. */
8005 auto_vec<tree> label_vec (len);
8007 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
8008 GIMPLE_OMP_SECTIONS statement. */
8009 si = gsi_last_bb (entry_bb);
8010 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
8011 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8012 vin = gimple_omp_sections_control (sections_stmt);
8013 if (!is_combined_parallel (region))
8015 /* If we are not inside a combined parallel+sections region,
8016 call GOMP_sections_start. */
8017 t = build_int_cst (unsigned_type_node, len - 1);
8018 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
8019 stmt = gimple_build_call (u, 1, t);
8021 else
8023 /* Otherwise, call GOMP_sections_next. */
8024 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8025 stmt = gimple_build_call (u, 0);
8027 gimple_call_set_lhs (stmt, vin);
8028 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8029 gsi_remove (&si, true);
8031 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8032 L0_BB. */
8033 switch_si = gsi_last_bb (l0_bb);
8034 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8035 if (exit_reachable)
8037 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8038 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8039 vmain = gimple_omp_continue_control_use (cont);
8040 vnext = gimple_omp_continue_control_def (cont);
8042 else
8044 vmain = vin;
8045 vnext = NULL_TREE;
8048 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8049 label_vec.quick_push (t);
8050 i = 1;
8052 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8053 for (inner = region->inner, casei = 1;
8054 inner;
8055 inner = inner->next, i++, casei++)
8057 basic_block s_entry_bb, s_exit_bb;
8059 /* Skip optional reduction region. */
8060 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8062 --i;
8063 --casei;
8064 continue;
8067 s_entry_bb = inner->entry;
8068 s_exit_bb = inner->exit;
8070 t = gimple_block_label (s_entry_bb);
8071 u = build_int_cst (unsigned_type_node, casei);
8072 u = build_case_label (u, NULL, t);
8073 label_vec.quick_push (u);
8075 si = gsi_last_bb (s_entry_bb);
8076 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8077 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8078 gsi_remove (&si, true);
8079 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8081 if (s_exit_bb == NULL)
8082 continue;
8084 si = gsi_last_bb (s_exit_bb);
8085 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8086 gsi_remove (&si, true);
8088 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8091 /* Error handling code goes in DEFAULT_BB. */
8092 t = gimple_block_label (default_bb);
8093 u = build_case_label (NULL, NULL, t);
8094 make_edge (l0_bb, default_bb, 0);
8095 add_bb_to_loop (default_bb, current_loops->tree_root);
8097 stmt = gimple_build_switch (vmain, u, label_vec);
8098 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8099 gsi_remove (&switch_si, true);
8101 si = gsi_start_bb (default_bb);
8102 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8103 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8105 if (exit_reachable)
8107 tree bfn_decl;
8109 /* Code to get the next section goes in L1_BB. */
8110 si = gsi_last_bb (l1_bb);
8111 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8113 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8114 stmt = gimple_build_call (bfn_decl, 0);
8115 gimple_call_set_lhs (stmt, vnext);
8116 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8117 gsi_remove (&si, true);
8119 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8122 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8123 si = gsi_last_bb (l2_bb);
8124 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8125 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8126 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8127 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8128 else
8129 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8130 stmt = gimple_build_call (t, 0);
8131 if (gimple_omp_return_lhs (gsi_stmt (si)))
8132 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8133 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8134 gsi_remove (&si, true);
8136 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8140 /* Expand code for an OpenMP single directive. We've already expanded
8141 much of the code, here we simply place the GOMP_barrier call. */
8143 static void
8144 expand_omp_single (struct omp_region *region)
8146 basic_block entry_bb, exit_bb;
8147 gimple_stmt_iterator si;
8149 entry_bb = region->entry;
8150 exit_bb = region->exit;
8152 si = gsi_last_bb (entry_bb);
8153 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8154 gsi_remove (&si, true);
8155 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8157 si = gsi_last_bb (exit_bb);
8158 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8160 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8161 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8163 gsi_remove (&si, true);
8164 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8168 /* Generic expansion for OpenMP synchronization directives: master,
8169 ordered and critical. All we need to do here is remove the entry
8170 and exit markers for REGION. */
8172 static void
8173 expand_omp_synch (struct omp_region *region)
8175 basic_block entry_bb, exit_bb;
8176 gimple_stmt_iterator si;
8178 entry_bb = region->entry;
8179 exit_bb = region->exit;
8181 si = gsi_last_bb (entry_bb);
8182 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8183 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8184 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8185 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8186 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8187 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8188 gsi_remove (&si, true);
8189 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8191 if (exit_bb)
8193 si = gsi_last_bb (exit_bb);
8194 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8195 gsi_remove (&si, true);
8196 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8200 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8201 operation as a normal volatile load. */
8203 static bool
8204 expand_omp_atomic_load (basic_block load_bb, tree addr,
8205 tree loaded_val, int index)
8207 enum built_in_function tmpbase;
8208 gimple_stmt_iterator gsi;
8209 basic_block store_bb;
8210 location_t loc;
8211 gimple stmt;
8212 tree decl, call, type, itype;
8214 gsi = gsi_last_bb (load_bb);
8215 stmt = gsi_stmt (gsi);
8216 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8217 loc = gimple_location (stmt);
8219 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8220 is smaller than word size, then expand_atomic_load assumes that the load
8221 is atomic. We could avoid the builtin entirely in this case. */
8223 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8224 decl = builtin_decl_explicit (tmpbase);
8225 if (decl == NULL_TREE)
8226 return false;
8228 type = TREE_TYPE (loaded_val);
8229 itype = TREE_TYPE (TREE_TYPE (decl));
8231 call = build_call_expr_loc (loc, decl, 2, addr,
8232 build_int_cst (NULL,
8233 gimple_omp_atomic_seq_cst_p (stmt)
8234 ? MEMMODEL_SEQ_CST
8235 : MEMMODEL_RELAXED));
8236 if (!useless_type_conversion_p (type, itype))
8237 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8238 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8240 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8241 gsi_remove (&gsi, true);
8243 store_bb = single_succ (load_bb);
8244 gsi = gsi_last_bb (store_bb);
8245 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8246 gsi_remove (&gsi, true);
8248 if (gimple_in_ssa_p (cfun))
8249 update_ssa (TODO_update_ssa_no_phi);
8251 return true;
8254 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8255 operation as a normal volatile store. */
8257 static bool
8258 expand_omp_atomic_store (basic_block load_bb, tree addr,
8259 tree loaded_val, tree stored_val, int index)
8261 enum built_in_function tmpbase;
8262 gimple_stmt_iterator gsi;
8263 basic_block store_bb = single_succ (load_bb);
8264 location_t loc;
8265 gimple stmt;
8266 tree decl, call, type, itype;
8267 machine_mode imode;
8268 bool exchange;
8270 gsi = gsi_last_bb (load_bb);
8271 stmt = gsi_stmt (gsi);
8272 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8274 /* If the load value is needed, then this isn't a store but an exchange. */
8275 exchange = gimple_omp_atomic_need_value_p (stmt);
8277 gsi = gsi_last_bb (store_bb);
8278 stmt = gsi_stmt (gsi);
8279 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8280 loc = gimple_location (stmt);
8282 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8283 is smaller than word size, then expand_atomic_store assumes that the store
8284 is atomic. We could avoid the builtin entirely in this case. */
8286 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8287 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8288 decl = builtin_decl_explicit (tmpbase);
8289 if (decl == NULL_TREE)
8290 return false;
8292 type = TREE_TYPE (stored_val);
8294 /* Dig out the type of the function's second argument. */
8295 itype = TREE_TYPE (decl);
8296 itype = TYPE_ARG_TYPES (itype);
8297 itype = TREE_CHAIN (itype);
8298 itype = TREE_VALUE (itype);
8299 imode = TYPE_MODE (itype);
8301 if (exchange && !can_atomic_exchange_p (imode, true))
8302 return false;
8304 if (!useless_type_conversion_p (itype, type))
8305 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8306 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8307 build_int_cst (NULL,
8308 gimple_omp_atomic_seq_cst_p (stmt)
8309 ? MEMMODEL_SEQ_CST
8310 : MEMMODEL_RELAXED));
8311 if (exchange)
8313 if (!useless_type_conversion_p (type, itype))
8314 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8315 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8318 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8319 gsi_remove (&gsi, true);
8321 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8322 gsi = gsi_last_bb (load_bb);
8323 gsi_remove (&gsi, true);
8325 if (gimple_in_ssa_p (cfun))
8326 update_ssa (TODO_update_ssa_no_phi);
8328 return true;
8331 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8332 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8333 size of the data type, and thus usable to find the index of the builtin
8334 decl. Returns false if the expression is not of the proper form. */
8336 static bool
8337 expand_omp_atomic_fetch_op (basic_block load_bb,
8338 tree addr, tree loaded_val,
8339 tree stored_val, int index)
8341 enum built_in_function oldbase, newbase, tmpbase;
8342 tree decl, itype, call;
8343 tree lhs, rhs;
8344 basic_block store_bb = single_succ (load_bb);
8345 gimple_stmt_iterator gsi;
8346 gimple stmt;
8347 location_t loc;
8348 enum tree_code code;
8349 bool need_old, need_new;
8350 machine_mode imode;
8351 bool seq_cst;
8353 /* We expect to find the following sequences:
8355 load_bb:
8356 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8358 store_bb:
8359 val = tmp OP something; (or: something OP tmp)
8360 GIMPLE_OMP_STORE (val)
8362 ???FIXME: Allow a more flexible sequence.
8363 Perhaps use data flow to pick the statements.
8367 gsi = gsi_after_labels (store_bb);
8368 stmt = gsi_stmt (gsi);
8369 loc = gimple_location (stmt);
8370 if (!is_gimple_assign (stmt))
8371 return false;
8372 gsi_next (&gsi);
8373 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8374 return false;
8375 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8376 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8377 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8378 gcc_checking_assert (!need_old || !need_new);
8380 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8381 return false;
8383 /* Check for one of the supported fetch-op operations. */
8384 code = gimple_assign_rhs_code (stmt);
8385 switch (code)
8387 case PLUS_EXPR:
8388 case POINTER_PLUS_EXPR:
8389 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8390 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8391 break;
8392 case MINUS_EXPR:
8393 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8394 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8395 break;
8396 case BIT_AND_EXPR:
8397 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8398 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8399 break;
8400 case BIT_IOR_EXPR:
8401 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8402 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8403 break;
8404 case BIT_XOR_EXPR:
8405 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8406 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8407 break;
8408 default:
8409 return false;
8412 /* Make sure the expression is of the proper form. */
8413 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8414 rhs = gimple_assign_rhs2 (stmt);
8415 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8416 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8417 rhs = gimple_assign_rhs1 (stmt);
8418 else
8419 return false;
8421 tmpbase = ((enum built_in_function)
8422 ((need_new ? newbase : oldbase) + index + 1));
8423 decl = builtin_decl_explicit (tmpbase);
8424 if (decl == NULL_TREE)
8425 return false;
8426 itype = TREE_TYPE (TREE_TYPE (decl));
8427 imode = TYPE_MODE (itype);
8429 /* We could test all of the various optabs involved, but the fact of the
8430 matter is that (with the exception of i486 vs i586 and xadd) all targets
8431 that support any atomic operaton optab also implements compare-and-swap.
8432 Let optabs.c take care of expanding any compare-and-swap loop. */
8433 if (!can_compare_and_swap_p (imode, true))
8434 return false;
8436 gsi = gsi_last_bb (load_bb);
8437 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8439 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8440 It only requires that the operation happen atomically. Thus we can
8441 use the RELAXED memory model. */
8442 call = build_call_expr_loc (loc, decl, 3, addr,
8443 fold_convert_loc (loc, itype, rhs),
8444 build_int_cst (NULL,
8445 seq_cst ? MEMMODEL_SEQ_CST
8446 : MEMMODEL_RELAXED));
8448 if (need_old || need_new)
8450 lhs = need_old ? loaded_val : stored_val;
8451 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8452 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8454 else
8455 call = fold_convert_loc (loc, void_type_node, call);
8456 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8457 gsi_remove (&gsi, true);
8459 gsi = gsi_last_bb (store_bb);
8460 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8461 gsi_remove (&gsi, true);
8462 gsi = gsi_last_bb (store_bb);
8463 gsi_remove (&gsi, true);
8465 if (gimple_in_ssa_p (cfun))
8466 update_ssa (TODO_update_ssa_no_phi);
8468 return true;
8471 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8473 oldval = *addr;
8474 repeat:
8475 newval = rhs; // with oldval replacing *addr in rhs
8476 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8477 if (oldval != newval)
8478 goto repeat;
8480 INDEX is log2 of the size of the data type, and thus usable to find the
8481 index of the builtin decl. */
8483 static bool
8484 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8485 tree addr, tree loaded_val, tree stored_val,
8486 int index)
8488 tree loadedi, storedi, initial, new_storedi, old_vali;
8489 tree type, itype, cmpxchg, iaddr;
8490 gimple_stmt_iterator si;
8491 basic_block loop_header = single_succ (load_bb);
8492 gimple phi, stmt;
8493 edge e;
8494 enum built_in_function fncode;
8496 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8497 order to use the RELAXED memory model effectively. */
8498 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8499 + index + 1);
8500 cmpxchg = builtin_decl_explicit (fncode);
8501 if (cmpxchg == NULL_TREE)
8502 return false;
8503 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8504 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8506 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8507 return false;
8509 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8510 si = gsi_last_bb (load_bb);
8511 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8513 /* For floating-point values, we'll need to view-convert them to integers
8514 so that we can perform the atomic compare and swap. Simplify the
8515 following code by always setting up the "i"ntegral variables. */
8516 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8518 tree iaddr_val;
8520 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8521 true));
8522 iaddr_val
8523 = force_gimple_operand_gsi (&si,
8524 fold_convert (TREE_TYPE (iaddr), addr),
8525 false, NULL_TREE, true, GSI_SAME_STMT);
8526 stmt = gimple_build_assign (iaddr, iaddr_val);
8527 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8528 loadedi = create_tmp_var (itype);
8529 if (gimple_in_ssa_p (cfun))
8530 loadedi = make_ssa_name (loadedi);
8532 else
8534 iaddr = addr;
8535 loadedi = loaded_val;
8538 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8539 tree loaddecl = builtin_decl_explicit (fncode);
8540 if (loaddecl)
8541 initial
8542 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8543 build_call_expr (loaddecl, 2, iaddr,
8544 build_int_cst (NULL_TREE,
8545 MEMMODEL_RELAXED)));
8546 else
8547 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8548 build_int_cst (TREE_TYPE (iaddr), 0));
8550 initial
8551 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8552 GSI_SAME_STMT);
8554 /* Move the value to the LOADEDI temporary. */
8555 if (gimple_in_ssa_p (cfun))
8557 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8558 phi = create_phi_node (loadedi, loop_header);
8559 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8560 initial);
8562 else
8563 gsi_insert_before (&si,
8564 gimple_build_assign (loadedi, initial),
8565 GSI_SAME_STMT);
8566 if (loadedi != loaded_val)
8568 gimple_stmt_iterator gsi2;
8569 tree x;
8571 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8572 gsi2 = gsi_start_bb (loop_header);
8573 if (gimple_in_ssa_p (cfun))
8575 gassign *stmt;
8576 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8577 true, GSI_SAME_STMT);
8578 stmt = gimple_build_assign (loaded_val, x);
8579 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8581 else
8583 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8584 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8585 true, GSI_SAME_STMT);
8588 gsi_remove (&si, true);
8590 si = gsi_last_bb (store_bb);
8591 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8593 if (iaddr == addr)
8594 storedi = stored_val;
8595 else
8596 storedi =
8597 force_gimple_operand_gsi (&si,
8598 build1 (VIEW_CONVERT_EXPR, itype,
8599 stored_val), true, NULL_TREE, true,
8600 GSI_SAME_STMT);
8602 /* Build the compare&swap statement. */
8603 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8604 new_storedi = force_gimple_operand_gsi (&si,
8605 fold_convert (TREE_TYPE (loadedi),
8606 new_storedi),
8607 true, NULL_TREE,
8608 true, GSI_SAME_STMT);
8610 if (gimple_in_ssa_p (cfun))
8611 old_vali = loadedi;
8612 else
8614 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8615 stmt = gimple_build_assign (old_vali, loadedi);
8616 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8618 stmt = gimple_build_assign (loadedi, new_storedi);
8619 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8622 /* Note that we always perform the comparison as an integer, even for
8623 floating point. This allows the atomic operation to properly
8624 succeed even with NaNs and -0.0. */
8625 stmt = gimple_build_cond_empty
8626 (build2 (NE_EXPR, boolean_type_node,
8627 new_storedi, old_vali));
8628 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8630 /* Update cfg. */
8631 e = single_succ_edge (store_bb);
8632 e->flags &= ~EDGE_FALLTHRU;
8633 e->flags |= EDGE_FALSE_VALUE;
8635 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8637 /* Copy the new value to loadedi (we already did that before the condition
8638 if we are not in SSA). */
8639 if (gimple_in_ssa_p (cfun))
8641 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8642 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8645 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8646 gsi_remove (&si, true);
8648 struct loop *loop = alloc_loop ();
8649 loop->header = loop_header;
8650 loop->latch = store_bb;
8651 add_loop (loop, loop_header->loop_father);
8653 if (gimple_in_ssa_p (cfun))
8654 update_ssa (TODO_update_ssa_no_phi);
8656 return true;
8659 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8661 GOMP_atomic_start ();
8662 *addr = rhs;
8663 GOMP_atomic_end ();
8665 The result is not globally atomic, but works so long as all parallel
8666 references are within #pragma omp atomic directives. According to
8667 responses received from omp@openmp.org, appears to be within spec.
8668 Which makes sense, since that's how several other compilers handle
8669 this situation as well.
8670 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8671 expanding. STORED_VAL is the operand of the matching
8672 GIMPLE_OMP_ATOMIC_STORE.
8674 We replace
8675 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8676 loaded_val = *addr;
8678 and replace
8679 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8680 *addr = stored_val;
8683 static bool
8684 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8685 tree addr, tree loaded_val, tree stored_val)
8687 gimple_stmt_iterator si;
8688 gassign *stmt;
8689 tree t;
8691 si = gsi_last_bb (load_bb);
8692 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8694 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8695 t = build_call_expr (t, 0);
8696 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8698 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8699 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8700 gsi_remove (&si, true);
8702 si = gsi_last_bb (store_bb);
8703 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8705 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8706 stored_val);
8707 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8709 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8710 t = build_call_expr (t, 0);
8711 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8712 gsi_remove (&si, true);
8714 if (gimple_in_ssa_p (cfun))
8715 update_ssa (TODO_update_ssa_no_phi);
8716 return true;
8719 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8720 using expand_omp_atomic_fetch_op. If it failed, we try to
8721 call expand_omp_atomic_pipeline, and if it fails too, the
8722 ultimate fallback is wrapping the operation in a mutex
8723 (expand_omp_atomic_mutex). REGION is the atomic region built
8724 by build_omp_regions_1(). */
8726 static void
8727 expand_omp_atomic (struct omp_region *region)
8729 basic_block load_bb = region->entry, store_bb = region->exit;
8730 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8731 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8732 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8733 tree addr = gimple_omp_atomic_load_rhs (load);
8734 tree stored_val = gimple_omp_atomic_store_val (store);
8735 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8736 HOST_WIDE_INT index;
8738 /* Make sure the type is one of the supported sizes. */
8739 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8740 index = exact_log2 (index);
8741 if (index >= 0 && index <= 4)
8743 unsigned int align = TYPE_ALIGN_UNIT (type);
8745 /* __sync builtins require strict data alignment. */
8746 if (exact_log2 (align) >= index)
8748 /* Atomic load. */
8749 if (loaded_val == stored_val
8750 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8751 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8752 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8753 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8754 return;
8756 /* Atomic store. */
8757 if ((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 && store_bb == single_succ (load_bb)
8761 && first_stmt (store_bb) == store
8762 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8763 stored_val, index))
8764 return;
8766 /* When possible, use specialized atomic update functions. */
8767 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8768 && store_bb == single_succ (load_bb)
8769 && expand_omp_atomic_fetch_op (load_bb, addr,
8770 loaded_val, stored_val, index))
8771 return;
8773 /* If we don't have specialized __sync builtins, try and implement
8774 as a compare and swap loop. */
8775 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8776 loaded_val, stored_val, index))
8777 return;
8781 /* The ultimate fallback is wrapping the operation in a mutex. */
8782 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8786 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8788 static void
8789 expand_omp_target (struct omp_region *region)
8791 basic_block entry_bb, exit_bb, new_bb;
8792 struct function *child_cfun;
8793 tree child_fn, block, t;
8794 gimple_stmt_iterator gsi;
8795 gomp_target *entry_stmt;
8796 gimple stmt;
8797 edge e;
8798 bool offloaded, data_region;
8800 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8801 new_bb = region->entry;
8803 offloaded = is_gimple_omp_offloaded (entry_stmt);
8804 switch (gimple_omp_target_kind (entry_stmt))
8806 case GF_OMP_TARGET_KIND_REGION:
8807 case GF_OMP_TARGET_KIND_UPDATE:
8808 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8809 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8810 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8811 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8812 data_region = false;
8813 break;
8814 case GF_OMP_TARGET_KIND_DATA:
8815 case GF_OMP_TARGET_KIND_OACC_DATA:
8816 data_region = true;
8817 break;
8818 default:
8819 gcc_unreachable ();
8822 child_fn = NULL_TREE;
8823 child_cfun = NULL;
8824 if (offloaded)
8826 child_fn = gimple_omp_target_child_fn (entry_stmt);
8827 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8830 /* Supported by expand_omp_taskreg, but not here. */
8831 if (child_cfun != NULL)
8832 gcc_checking_assert (!child_cfun->cfg);
8833 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8835 entry_bb = region->entry;
8836 exit_bb = region->exit;
8838 if (offloaded)
8840 unsigned srcidx, dstidx, num;
8842 /* If the offloading region needs data sent from the parent
8843 function, then the very first statement (except possible
8844 tree profile counter updates) of the offloading body
8845 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8846 &.OMP_DATA_O is passed as an argument to the child function,
8847 we need to replace it with the argument as seen by the child
8848 function.
8850 In most cases, this will end up being the identity assignment
8851 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8852 a function call that has been inlined, the original PARM_DECL
8853 .OMP_DATA_I may have been converted into a different local
8854 variable. In which case, we need to keep the assignment. */
8855 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8856 if (data_arg)
8858 basic_block entry_succ_bb = single_succ (entry_bb);
8859 gimple_stmt_iterator gsi;
8860 tree arg;
8861 gimple tgtcopy_stmt = NULL;
8862 tree sender = TREE_VEC_ELT (data_arg, 0);
8864 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8866 gcc_assert (!gsi_end_p (gsi));
8867 stmt = gsi_stmt (gsi);
8868 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8869 continue;
8871 if (gimple_num_ops (stmt) == 2)
8873 tree arg = gimple_assign_rhs1 (stmt);
8875 /* We're ignoring the subcode because we're
8876 effectively doing a STRIP_NOPS. */
8878 if (TREE_CODE (arg) == ADDR_EXPR
8879 && TREE_OPERAND (arg, 0) == sender)
8881 tgtcopy_stmt = stmt;
8882 break;
8887 gcc_assert (tgtcopy_stmt != NULL);
8888 arg = DECL_ARGUMENTS (child_fn);
8890 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8891 gsi_remove (&gsi, true);
8894 /* Declare local variables needed in CHILD_CFUN. */
8895 block = DECL_INITIAL (child_fn);
8896 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8897 /* The gimplifier could record temporaries in the offloading block
8898 rather than in containing function's local_decls chain,
8899 which would mean cgraph missed finalizing them. Do it now. */
8900 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8901 if (TREE_CODE (t) == VAR_DECL
8902 && TREE_STATIC (t)
8903 && !DECL_EXTERNAL (t))
8904 varpool_node::finalize_decl (t);
8905 DECL_SAVED_TREE (child_fn) = NULL;
8906 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8907 gimple_set_body (child_fn, NULL);
8908 TREE_USED (block) = 1;
8910 /* Reset DECL_CONTEXT on function arguments. */
8911 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8912 DECL_CONTEXT (t) = child_fn;
8914 /* Split ENTRY_BB at GIMPLE_*,
8915 so that it can be moved to the child function. */
8916 gsi = gsi_last_bb (entry_bb);
8917 stmt = gsi_stmt (gsi);
8918 gcc_assert (stmt
8919 && gimple_code (stmt) == gimple_code (entry_stmt));
8920 e = split_block (entry_bb, stmt);
8921 gsi_remove (&gsi, true);
8922 entry_bb = e->dest;
8923 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8925 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8926 if (exit_bb)
8928 gsi = gsi_last_bb (exit_bb);
8929 gcc_assert (!gsi_end_p (gsi)
8930 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8931 stmt = gimple_build_return (NULL);
8932 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8933 gsi_remove (&gsi, true);
8936 /* Move the offloading region into CHILD_CFUN. */
8938 block = gimple_block (entry_stmt);
8940 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8941 if (exit_bb)
8942 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8943 /* When the OMP expansion process cannot guarantee an up-to-date
8944 loop tree arrange for the child function to fixup loops. */
8945 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8946 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8948 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8949 num = vec_safe_length (child_cfun->local_decls);
8950 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8952 t = (*child_cfun->local_decls)[srcidx];
8953 if (DECL_CONTEXT (t) == cfun->decl)
8954 continue;
8955 if (srcidx != dstidx)
8956 (*child_cfun->local_decls)[dstidx] = t;
8957 dstidx++;
8959 if (dstidx != num)
8960 vec_safe_truncate (child_cfun->local_decls, dstidx);
8962 /* Inform the callgraph about the new function. */
8963 child_cfun->curr_properties = cfun->curr_properties;
8964 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
8965 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
8966 cgraph_node *node = cgraph_node::get_create (child_fn);
8967 node->parallelized_function = 1;
8968 cgraph_node::add_new_function (child_fn, true);
8970 #ifdef ENABLE_OFFLOADING
8971 /* Add the new function to the offload table. */
8972 vec_safe_push (offload_funcs, child_fn);
8973 #endif
8975 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8976 fixed in a following pass. */
8977 push_cfun (child_cfun);
8978 cgraph_edge::rebuild_edges ();
8980 #ifdef ENABLE_OFFLOADING
8981 /* Prevent IPA from removing child_fn as unreachable, since there are no
8982 refs from the parent function to child_fn in offload LTO mode. */
8983 cgraph_node::get (child_fn)->mark_force_output ();
8984 #endif
8986 /* Some EH regions might become dead, see PR34608. If
8987 pass_cleanup_cfg isn't the first pass to happen with the
8988 new child, these dead EH edges might cause problems.
8989 Clean them up now. */
8990 if (flag_exceptions)
8992 basic_block bb;
8993 bool changed = false;
8995 FOR_EACH_BB_FN (bb, cfun)
8996 changed |= gimple_purge_dead_eh_edges (bb);
8997 if (changed)
8998 cleanup_tree_cfg ();
9000 pop_cfun ();
9003 /* Emit a library call to launch the offloading region, or do data
9004 transfers. */
9005 tree t1, t2, t3, t4, device, cond, c, clauses;
9006 enum built_in_function start_ix;
9007 location_t clause_loc;
9009 switch (gimple_omp_target_kind (entry_stmt))
9011 case GF_OMP_TARGET_KIND_REGION:
9012 start_ix = BUILT_IN_GOMP_TARGET;
9013 break;
9014 case GF_OMP_TARGET_KIND_DATA:
9015 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9016 break;
9017 case GF_OMP_TARGET_KIND_UPDATE:
9018 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9019 break;
9020 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9021 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9022 start_ix = BUILT_IN_GOACC_PARALLEL;
9023 break;
9024 case GF_OMP_TARGET_KIND_OACC_DATA:
9025 start_ix = BUILT_IN_GOACC_DATA_START;
9026 break;
9027 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9028 start_ix = BUILT_IN_GOACC_UPDATE;
9029 break;
9030 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9031 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9032 break;
9033 default:
9034 gcc_unreachable ();
9037 clauses = gimple_omp_target_clauses (entry_stmt);
9039 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9040 library choose) and there is no conditional. */
9041 cond = NULL_TREE;
9042 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
9044 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9045 if (c)
9046 cond = OMP_CLAUSE_IF_EXPR (c);
9048 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9049 if (c)
9051 /* Even if we pass it to all library function calls, it is currently only
9052 defined/used for the OpenMP target ones. */
9053 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9054 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9055 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9057 device = OMP_CLAUSE_DEVICE_ID (c);
9058 clause_loc = OMP_CLAUSE_LOCATION (c);
9060 else
9061 clause_loc = gimple_location (entry_stmt);
9063 /* Ensure 'device' is of the correct type. */
9064 device = fold_convert_loc (clause_loc, integer_type_node, device);
9066 /* If we found the clause 'if (cond)', build
9067 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9068 if (cond)
9070 cond = gimple_boolify (cond);
9072 basic_block cond_bb, then_bb, else_bb;
9073 edge e;
9074 tree tmp_var;
9076 tmp_var = create_tmp_var (TREE_TYPE (device));
9077 if (offloaded)
9078 e = split_block_after_labels (new_bb);
9079 else
9081 gsi = gsi_last_bb (new_bb);
9082 gsi_prev (&gsi);
9083 e = split_block (new_bb, gsi_stmt (gsi));
9085 cond_bb = e->src;
9086 new_bb = e->dest;
9087 remove_edge (e);
9089 then_bb = create_empty_bb (cond_bb);
9090 else_bb = create_empty_bb (then_bb);
9091 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9092 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9094 stmt = gimple_build_cond_empty (cond);
9095 gsi = gsi_last_bb (cond_bb);
9096 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9098 gsi = gsi_start_bb (then_bb);
9099 stmt = gimple_build_assign (tmp_var, device);
9100 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9102 gsi = gsi_start_bb (else_bb);
9103 stmt = gimple_build_assign (tmp_var,
9104 build_int_cst (integer_type_node,
9105 GOMP_DEVICE_HOST_FALLBACK));
9106 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9108 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9109 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9110 add_bb_to_loop (then_bb, cond_bb->loop_father);
9111 add_bb_to_loop (else_bb, cond_bb->loop_father);
9112 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9113 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9115 device = tmp_var;
9118 gsi = gsi_last_bb (new_bb);
9119 t = gimple_omp_target_data_arg (entry_stmt);
9120 if (t == NULL)
9122 t1 = size_zero_node;
9123 t2 = build_zero_cst (ptr_type_node);
9124 t3 = t2;
9125 t4 = t2;
9127 else
9129 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9130 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9131 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9132 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9133 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9136 gimple g;
9137 /* The maximum number used by any start_ix, without varargs. */
9138 auto_vec<tree, 11> args;
9139 args.quick_push (device);
9140 if (offloaded)
9141 args.quick_push (build_fold_addr_expr (child_fn));
9142 switch (start_ix)
9144 case BUILT_IN_GOMP_TARGET:
9145 case BUILT_IN_GOMP_TARGET_DATA:
9146 case BUILT_IN_GOMP_TARGET_UPDATE:
9147 /* This const void * is part of the current ABI, but we're not actually
9148 using it. */
9149 args.quick_push (build_zero_cst (ptr_type_node));
9150 break;
9151 case BUILT_IN_GOACC_DATA_START:
9152 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9153 case BUILT_IN_GOACC_PARALLEL:
9154 case BUILT_IN_GOACC_UPDATE:
9155 break;
9156 default:
9157 gcc_unreachable ();
9159 args.quick_push (t1);
9160 args.quick_push (t2);
9161 args.quick_push (t3);
9162 args.quick_push (t4);
9163 switch (start_ix)
9165 case BUILT_IN_GOACC_DATA_START:
9166 case BUILT_IN_GOMP_TARGET:
9167 case BUILT_IN_GOMP_TARGET_DATA:
9168 case BUILT_IN_GOMP_TARGET_UPDATE:
9169 break;
9170 case BUILT_IN_GOACC_PARALLEL:
9172 tree t_num_gangs, t_num_workers, t_vector_length;
9174 /* Default values for num_gangs, num_workers, and vector_length. */
9175 t_num_gangs = t_num_workers = t_vector_length
9176 = fold_convert_loc (gimple_location (entry_stmt),
9177 integer_type_node, integer_one_node);
9178 /* ..., but if present, use the value specified by the respective
9179 clause, making sure that are of the correct type. */
9180 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9181 if (c)
9182 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9183 integer_type_node,
9184 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9185 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9186 if (c)
9187 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9188 integer_type_node,
9189 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9190 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9191 if (c)
9192 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9193 integer_type_node,
9194 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9195 args.quick_push (t_num_gangs);
9196 args.quick_push (t_num_workers);
9197 args.quick_push (t_vector_length);
9199 /* FALLTHRU */
9200 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9201 case BUILT_IN_GOACC_UPDATE:
9203 tree t_async;
9204 int t_wait_idx;
9206 /* Default values for t_async. */
9207 t_async = fold_convert_loc (gimple_location (entry_stmt),
9208 integer_type_node,
9209 build_int_cst (integer_type_node,
9210 GOMP_ASYNC_SYNC));
9211 /* ..., but if present, use the value specified by the respective
9212 clause, making sure that is of the correct type. */
9213 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9214 if (c)
9215 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9216 integer_type_node,
9217 OMP_CLAUSE_ASYNC_EXPR (c));
9219 args.quick_push (t_async);
9220 /* Save the index, and... */
9221 t_wait_idx = args.length ();
9222 /* ... push a default value. */
9223 args.quick_push (fold_convert_loc (gimple_location (entry_stmt),
9224 integer_type_node,
9225 integer_zero_node));
9226 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9227 if (c)
9229 int n = 0;
9231 for (; c; c = OMP_CLAUSE_CHAIN (c))
9233 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9235 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9236 integer_type_node,
9237 OMP_CLAUSE_WAIT_EXPR (c)));
9238 n++;
9242 /* Now that we know the number, replace the default value. */
9243 args.ordered_remove (t_wait_idx);
9244 args.quick_insert (t_wait_idx,
9245 fold_convert_loc (gimple_location (entry_stmt),
9246 integer_type_node,
9247 build_int_cst (integer_type_node, n)));
9250 break;
9251 default:
9252 gcc_unreachable ();
9255 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
9256 gimple_set_location (g, gimple_location (entry_stmt));
9257 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9258 if (!offloaded)
9260 g = gsi_stmt (gsi);
9261 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9262 gsi_remove (&gsi, true);
9264 if (data_region
9265 && region->exit)
9267 gsi = gsi_last_bb (region->exit);
9268 g = gsi_stmt (gsi);
9269 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9270 gsi_remove (&gsi, true);
9275 /* Expand the parallel region tree rooted at REGION. Expansion
9276 proceeds in depth-first order. Innermost regions are expanded
9277 first. This way, parallel regions that require a new function to
9278 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9279 internal dependencies in their body. */
9281 static void
9282 expand_omp (struct omp_region *region)
9284 while (region)
9286 location_t saved_location;
9287 gimple inner_stmt = NULL;
9289 /* First, determine whether this is a combined parallel+workshare
9290 region. */
9291 if (region->type == GIMPLE_OMP_PARALLEL)
9292 determine_parallel_type (region);
9294 if (region->type == GIMPLE_OMP_FOR
9295 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9296 inner_stmt = last_stmt (region->inner->entry);
9298 if (region->inner)
9299 expand_omp (region->inner);
9301 saved_location = input_location;
9302 if (gimple_has_location (last_stmt (region->entry)))
9303 input_location = gimple_location (last_stmt (region->entry));
9305 switch (region->type)
9307 case GIMPLE_OMP_PARALLEL:
9308 case GIMPLE_OMP_TASK:
9309 expand_omp_taskreg (region);
9310 break;
9312 case GIMPLE_OMP_FOR:
9313 expand_omp_for (region, inner_stmt);
9314 break;
9316 case GIMPLE_OMP_SECTIONS:
9317 expand_omp_sections (region);
9318 break;
9320 case GIMPLE_OMP_SECTION:
9321 /* Individual omp sections are handled together with their
9322 parent GIMPLE_OMP_SECTIONS region. */
9323 break;
9325 case GIMPLE_OMP_SINGLE:
9326 expand_omp_single (region);
9327 break;
9329 case GIMPLE_OMP_MASTER:
9330 case GIMPLE_OMP_TASKGROUP:
9331 case GIMPLE_OMP_ORDERED:
9332 case GIMPLE_OMP_CRITICAL:
9333 case GIMPLE_OMP_TEAMS:
9334 expand_omp_synch (region);
9335 break;
9337 case GIMPLE_OMP_ATOMIC_LOAD:
9338 expand_omp_atomic (region);
9339 break;
9341 case GIMPLE_OMP_TARGET:
9342 expand_omp_target (region);
9343 break;
9345 default:
9346 gcc_unreachable ();
9349 input_location = saved_location;
9350 region = region->next;
9355 /* Helper for build_omp_regions. Scan the dominator tree starting at
9356 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9357 true, the function ends once a single tree is built (otherwise, whole
9358 forest of OMP constructs may be built). */
9360 static void
9361 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9362 bool single_tree)
9364 gimple_stmt_iterator gsi;
9365 gimple stmt;
9366 basic_block son;
9368 gsi = gsi_last_bb (bb);
9369 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9371 struct omp_region *region;
9372 enum gimple_code code;
9374 stmt = gsi_stmt (gsi);
9375 code = gimple_code (stmt);
9376 if (code == GIMPLE_OMP_RETURN)
9378 /* STMT is the return point out of region PARENT. Mark it
9379 as the exit point and make PARENT the immediately
9380 enclosing region. */
9381 gcc_assert (parent);
9382 region = parent;
9383 region->exit = bb;
9384 parent = parent->outer;
9386 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9388 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9389 GIMPLE_OMP_RETURN, but matches with
9390 GIMPLE_OMP_ATOMIC_LOAD. */
9391 gcc_assert (parent);
9392 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9393 region = parent;
9394 region->exit = bb;
9395 parent = parent->outer;
9397 else if (code == GIMPLE_OMP_CONTINUE)
9399 gcc_assert (parent);
9400 parent->cont = bb;
9402 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9404 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9405 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9407 else
9409 region = new_omp_region (bb, code, parent);
9410 /* Otherwise... */
9411 if (code == GIMPLE_OMP_TARGET)
9413 switch (gimple_omp_target_kind (stmt))
9415 case GF_OMP_TARGET_KIND_REGION:
9416 case GF_OMP_TARGET_KIND_DATA:
9417 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9418 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9419 case GF_OMP_TARGET_KIND_OACC_DATA:
9420 break;
9421 case GF_OMP_TARGET_KIND_UPDATE:
9422 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9423 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9424 /* ..., other than for those stand-alone directives... */
9425 region = NULL;
9426 break;
9427 default:
9428 gcc_unreachable ();
9431 /* ..., this directive becomes the parent for a new region. */
9432 if (region)
9433 parent = region;
9437 if (single_tree && !parent)
9438 return;
9440 for (son = first_dom_son (CDI_DOMINATORS, bb);
9441 son;
9442 son = next_dom_son (CDI_DOMINATORS, son))
9443 build_omp_regions_1 (son, parent, single_tree);
9446 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9447 root_omp_region. */
9449 static void
9450 build_omp_regions_root (basic_block root)
9452 gcc_assert (root_omp_region == NULL);
9453 build_omp_regions_1 (root, NULL, true);
9454 gcc_assert (root_omp_region != NULL);
9457 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9459 void
9460 omp_expand_local (basic_block head)
9462 build_omp_regions_root (head);
9463 if (dump_file && (dump_flags & TDF_DETAILS))
9465 fprintf (dump_file, "\nOMP region tree\n\n");
9466 dump_omp_region (dump_file, root_omp_region, 0);
9467 fprintf (dump_file, "\n");
9470 remove_exit_barriers (root_omp_region);
9471 expand_omp (root_omp_region);
9473 free_omp_regions ();
9476 /* Scan the CFG and build a tree of OMP regions. Return the root of
9477 the OMP region tree. */
9479 static void
9480 build_omp_regions (void)
9482 gcc_assert (root_omp_region == NULL);
9483 calculate_dominance_info (CDI_DOMINATORS);
9484 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9487 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9489 static unsigned int
9490 execute_expand_omp (void)
9492 build_omp_regions ();
9494 if (!root_omp_region)
9495 return 0;
9497 if (dump_file)
9499 fprintf (dump_file, "\nOMP region tree\n\n");
9500 dump_omp_region (dump_file, root_omp_region, 0);
9501 fprintf (dump_file, "\n");
9504 remove_exit_barriers (root_omp_region);
9506 expand_omp (root_omp_region);
9508 cleanup_tree_cfg ();
9510 free_omp_regions ();
9512 return 0;
9515 /* OMP expansion -- the default pass, run before creation of SSA form. */
9517 namespace {
9519 const pass_data pass_data_expand_omp =
9521 GIMPLE_PASS, /* type */
9522 "ompexp", /* name */
9523 OPTGROUP_NONE, /* optinfo_flags */
9524 TV_NONE, /* tv_id */
9525 PROP_gimple_any, /* properties_required */
9526 PROP_gimple_eomp, /* properties_provided */
9527 0, /* properties_destroyed */
9528 0, /* todo_flags_start */
9529 0, /* todo_flags_finish */
9532 class pass_expand_omp : public gimple_opt_pass
9534 public:
9535 pass_expand_omp (gcc::context *ctxt)
9536 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9539 /* opt_pass methods: */
9540 virtual unsigned int execute (function *)
9542 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9543 || flag_openmp_simd != 0)
9544 && !seen_error ());
9546 /* This pass always runs, to provide PROP_gimple_eomp.
9547 But often, there is nothing to do. */
9548 if (!gate)
9549 return 0;
9551 return execute_expand_omp ();
9554 }; // class pass_expand_omp
9556 } // anon namespace
9558 gimple_opt_pass *
9559 make_pass_expand_omp (gcc::context *ctxt)
9561 return new pass_expand_omp (ctxt);
9564 namespace {
9566 const pass_data pass_data_expand_omp_ssa =
9568 GIMPLE_PASS, /* type */
9569 "ompexpssa", /* name */
9570 OPTGROUP_NONE, /* optinfo_flags */
9571 TV_NONE, /* tv_id */
9572 PROP_cfg | PROP_ssa, /* properties_required */
9573 PROP_gimple_eomp, /* properties_provided */
9574 0, /* properties_destroyed */
9575 0, /* todo_flags_start */
9576 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9579 class pass_expand_omp_ssa : public gimple_opt_pass
9581 public:
9582 pass_expand_omp_ssa (gcc::context *ctxt)
9583 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9586 /* opt_pass methods: */
9587 virtual bool gate (function *fun)
9589 return !(fun->curr_properties & PROP_gimple_eomp);
9591 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9593 }; // class pass_expand_omp_ssa
9595 } // anon namespace
9597 gimple_opt_pass *
9598 make_pass_expand_omp_ssa (gcc::context *ctxt)
9600 return new pass_expand_omp_ssa (ctxt);
9603 /* Routines to lower OMP directives into OMP-GIMPLE. */
9605 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9606 convert it to gimple. */
9607 static void
9608 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9610 gimple stmt;
9612 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9614 stmt = gimple_build_assign (dest, op, dest, src);
9615 gimple_seq_add_stmt (seq, stmt);
9616 return;
9619 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9620 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9621 gimplify_assign (t, rdest, seq);
9622 rdest = t;
9624 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9625 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9626 gimplify_assign (t, idest, seq);
9627 idest = t;
9629 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9630 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9631 gimplify_assign (t, rsrc, seq);
9632 rsrc = t;
9634 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9635 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9636 gimplify_assign (t, isrc, seq);
9637 isrc = t;
9639 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9640 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9641 tree result;
9643 if (op == PLUS_EXPR)
9645 stmt = gimple_build_assign (r, op, rdest, rsrc);
9646 gimple_seq_add_stmt (seq, stmt);
9648 stmt = gimple_build_assign (i, op, idest, isrc);
9649 gimple_seq_add_stmt (seq, stmt);
9651 else if (op == MULT_EXPR)
9653 /* Let x = a + ib = dest, y = c + id = src.
9654 x * y = (ac - bd) + i(ad + bc) */
9655 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9656 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9657 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9658 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9660 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9661 gimple_seq_add_stmt (seq, stmt);
9663 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9664 gimple_seq_add_stmt (seq, stmt);
9666 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9667 gimple_seq_add_stmt (seq, stmt);
9669 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9670 gimple_seq_add_stmt (seq, stmt);
9672 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9673 gimple_seq_add_stmt (seq, stmt);
9675 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9676 gimple_seq_add_stmt (seq, stmt);
9678 else
9679 gcc_unreachable ();
9681 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9682 gimplify_assign (dest, result, seq);
9685 /* Helper function to initialize local data for the reduction arrays.
9686 The reduction arrays need to be placed inside the calling function
9687 for accelerators, or else the host won't be able to preform the final
9688 reduction. */
9690 static void
9691 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9692 gimple_seq *stmt_seqp, omp_context *ctx)
9694 tree c, t, oc;
9695 gimple stmt;
9696 omp_context *octx;
9698 /* Find the innermost OpenACC parallel context. */
9699 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9700 && (gimple_omp_target_kind (ctx->stmt)
9701 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9702 octx = ctx;
9703 else
9704 octx = ctx->outer;
9705 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9706 && (gimple_omp_target_kind (octx->stmt)
9707 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9709 /* Extract the clauses. */
9710 oc = gimple_omp_target_clauses (octx->stmt);
9712 /* Find the last outer clause. */
9713 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9716 /* Allocate arrays for each reduction variable. */
9717 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9719 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9720 continue;
9722 tree var = OMP_CLAUSE_DECL (c);
9723 tree type = get_base_type (var);
9724 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9725 ctx);
9726 tree size, call;
9728 /* Calculate size of the reduction array. */
9729 t = create_tmp_var (TREE_TYPE (nthreads));
9730 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9731 fold_convert (TREE_TYPE (nthreads),
9732 TYPE_SIZE_UNIT (type)));
9733 gimple_seq_add_stmt (stmt_seqp, stmt);
9735 size = create_tmp_var (sizetype);
9736 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9738 /* Now allocate memory for it. */
9739 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9740 stmt = gimple_build_call (call, 1, size);
9741 gimple_call_set_lhs (stmt, array);
9742 gimple_seq_add_stmt (stmt_seqp, stmt);
9744 /* Map this array into the accelerator. */
9746 /* Add the reduction array to the list of clauses. */
9747 tree x = array;
9748 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9749 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9750 OMP_CLAUSE_DECL (t) = x;
9751 OMP_CLAUSE_CHAIN (t) = NULL;
9752 if (oc)
9753 OMP_CLAUSE_CHAIN (oc) = t;
9754 else
9755 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9756 OMP_CLAUSE_SIZE (t) = size;
9757 oc = t;
9761 /* Helper function to process the array of partial reductions. Nthreads
9762 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9763 cannot be used here, because nthreads on the host may be different than
9764 on the accelerator. */
9766 static void
9767 oacc_finalize_reduction_data (tree clauses, tree nthreads,
9768 gimple_seq *stmt_seqp, omp_context *ctx)
9770 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9771 gimple stmt;
9773 /* Create for loop.
9775 let var = the original reduction variable
9776 let array = reduction variable array
9778 for (i = 0; i < nthreads; i++)
9779 var op= array[i]
9782 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9783 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9784 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9786 /* Create and initialize an index variable. */
9787 tree ix = create_tmp_var (sizetype);
9788 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9789 stmt_seqp);
9791 /* Insert the loop header label here. */
9792 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9794 /* Exit loop if ix >= nthreads. */
9795 x = create_tmp_var (sizetype);
9796 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9797 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9798 gimple_seq_add_stmt (stmt_seqp, stmt);
9800 /* Insert the loop body label here. */
9801 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9803 /* Collapse each reduction array, one element at a time. */
9804 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9806 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9807 continue;
9809 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9811 /* reduction(-:var) sums up the partial results, so it acts
9812 identically to reduction(+:var). */
9813 if (reduction_code == MINUS_EXPR)
9814 reduction_code = PLUS_EXPR;
9816 /* Set up reduction variable var. */
9817 var = OMP_CLAUSE_DECL (c);
9818 type = get_base_type (var);
9819 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9820 (OMP_CLAUSE_DECL (c)), ctx);
9822 /* Calculate the array offset. */
9823 tree offset = create_tmp_var (sizetype);
9824 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9825 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9826 gimple_seq_add_stmt (stmt_seqp, stmt);
9828 tree ptr = create_tmp_var (TREE_TYPE (array));
9829 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9830 gimple_seq_add_stmt (stmt_seqp, stmt);
9832 /* Extract array[ix] into mem. */
9833 tree mem = create_tmp_var (type);
9834 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9836 /* Find the original reduction variable. */
9837 if (is_reference (var))
9838 var = build_simple_mem_ref (var);
9840 tree t = create_tmp_var (type);
9842 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9843 gimplify_and_add (unshare_expr(x), stmt_seqp);
9845 /* var = var op mem */
9846 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9848 case TRUTH_ANDIF_EXPR:
9849 case TRUTH_ORIF_EXPR:
9850 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9851 t, mem);
9852 gimplify_and_add (t, stmt_seqp);
9853 break;
9854 default:
9855 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9856 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9857 stmt_seqp);
9860 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9861 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9862 gimplify_and_add (unshare_expr(x), stmt_seqp);
9865 /* Increment the induction variable. */
9866 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9867 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9868 gimple_seq_add_stmt (stmt_seqp, stmt);
9870 /* Go back to the top of the loop. */
9871 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9873 /* Place the loop exit label here. */
9874 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9877 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9878 scan that for reductions. */
9880 static void
9881 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9882 gimple_seq *out_stmt_seqp, omp_context *ctx)
9884 gimple_stmt_iterator gsi;
9885 gimple_seq inner = NULL;
9887 /* A collapse clause may have inserted a new bind block. */
9888 gsi = gsi_start (*body);
9889 while (!gsi_end_p (gsi))
9891 gimple stmt = gsi_stmt (gsi);
9892 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9894 inner = gimple_bind_body (bind_stmt);
9895 body = &inner;
9896 gsi = gsi_start (*body);
9898 else if (dyn_cast <gomp_for *> (stmt))
9899 break;
9900 else
9901 gsi_next (&gsi);
9904 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9906 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9907 enter, exit;
9908 bool reduction_found = false;
9910 gimple stmt = gsi_stmt (gsi);
9912 switch (gimple_code (stmt))
9914 case GIMPLE_OMP_FOR:
9915 clauses = gimple_omp_for_clauses (stmt);
9917 /* Search for a reduction clause. */
9918 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9919 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9921 reduction_found = true;
9922 break;
9925 if (!reduction_found)
9926 break;
9928 ctx = maybe_lookup_ctx (stmt);
9929 t = NULL_TREE;
9931 /* Extract the number of threads. */
9932 nthreads = create_tmp_var (sizetype);
9933 t = oacc_max_threads (ctx);
9934 gimplify_assign (nthreads, t, in_stmt_seqp);
9936 /* Determine if this is kernel will be executed on the host. */
9937 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9938 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9939 stmt = gimple_build_call (call, 0);
9940 gimple_call_set_lhs (stmt, acc_device);
9941 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9943 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9944 acc_device_host = create_tmp_var (integer_type_node,
9945 ".acc_device_host");
9946 gimplify_assign (acc_device_host,
9947 build_int_cst (integer_type_node,
9948 GOMP_DEVICE_HOST),
9949 in_stmt_seqp);
9951 enter = create_artificial_label (UNKNOWN_LOCATION);
9952 exit = create_artificial_label (UNKNOWN_LOCATION);
9954 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9955 enter, exit);
9956 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9957 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9958 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9959 integer_one_node),
9960 in_stmt_seqp);
9961 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9963 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9964 gimplify_assign (acc_device_host,
9965 build_int_cst (integer_type_node,
9966 GOMP_DEVICE_HOST_NONSHM),
9967 in_stmt_seqp);
9969 enter = create_artificial_label (UNKNOWN_LOCATION);
9970 exit = create_artificial_label (UNKNOWN_LOCATION);
9972 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9973 enter, exit);
9974 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9975 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9976 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9977 integer_one_node),
9978 in_stmt_seqp);
9979 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9981 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9982 ctx);
9983 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9984 break;
9985 default:
9986 // Scan for other directives which support reduction here.
9987 break;
9992 /* If ctx is a worksharing context inside of a cancellable parallel
9993 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9994 and conditional branch to parallel's cancel_label to handle
9995 cancellation in the implicit barrier. */
9997 static void
9998 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
10000 gimple omp_return = gimple_seq_last_stmt (*body);
10001 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
10002 if (gimple_omp_return_nowait_p (omp_return))
10003 return;
10004 if (ctx->outer
10005 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
10006 && ctx->outer->cancellable)
10008 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
10009 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
10010 tree lhs = create_tmp_var (c_bool_type);
10011 gimple_omp_return_set_lhs (omp_return, lhs);
10012 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10013 gimple g = gimple_build_cond (NE_EXPR, lhs,
10014 fold_convert (c_bool_type,
10015 boolean_false_node),
10016 ctx->outer->cancel_label, fallthru_label);
10017 gimple_seq_add_stmt (body, g);
10018 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10022 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10023 CTX is the enclosing OMP context for the current statement. */
10025 static void
10026 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10028 tree block, control;
10029 gimple_stmt_iterator tgsi;
10030 gomp_sections *stmt;
10031 gimple t;
10032 gbind *new_stmt, *bind;
10033 gimple_seq ilist, dlist, olist, new_body;
10035 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
10037 push_gimplify_context ();
10039 dlist = NULL;
10040 ilist = NULL;
10041 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10042 &ilist, &dlist, ctx, NULL);
10044 new_body = gimple_omp_body (stmt);
10045 gimple_omp_set_body (stmt, NULL);
10046 tgsi = gsi_start (new_body);
10047 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10049 omp_context *sctx;
10050 gimple sec_start;
10052 sec_start = gsi_stmt (tgsi);
10053 sctx = maybe_lookup_ctx (sec_start);
10054 gcc_assert (sctx);
10056 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10057 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10058 GSI_CONTINUE_LINKING);
10059 gimple_omp_set_body (sec_start, NULL);
10061 if (gsi_one_before_end_p (tgsi))
10063 gimple_seq l = NULL;
10064 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10065 &l, ctx);
10066 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10067 gimple_omp_section_set_last (sec_start);
10070 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10071 GSI_CONTINUE_LINKING);
10074 block = make_node (BLOCK);
10075 bind = gimple_build_bind (NULL, new_body, block);
10077 olist = NULL;
10078 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10080 block = make_node (BLOCK);
10081 new_stmt = gimple_build_bind (NULL, NULL, block);
10082 gsi_replace (gsi_p, new_stmt, true);
10084 pop_gimplify_context (new_stmt);
10085 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10086 BLOCK_VARS (block) = gimple_bind_vars (bind);
10087 if (BLOCK_VARS (block))
10088 TREE_USED (block) = 1;
10090 new_body = NULL;
10091 gimple_seq_add_seq (&new_body, ilist);
10092 gimple_seq_add_stmt (&new_body, stmt);
10093 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10094 gimple_seq_add_stmt (&new_body, bind);
10096 control = create_tmp_var (unsigned_type_node, ".section");
10097 t = gimple_build_omp_continue (control, control);
10098 gimple_omp_sections_set_control (stmt, control);
10099 gimple_seq_add_stmt (&new_body, t);
10101 gimple_seq_add_seq (&new_body, olist);
10102 if (ctx->cancellable)
10103 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10104 gimple_seq_add_seq (&new_body, dlist);
10106 new_body = maybe_catch_exception (new_body);
10108 t = gimple_build_omp_return
10109 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10110 OMP_CLAUSE_NOWAIT));
10111 gimple_seq_add_stmt (&new_body, t);
10112 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10114 gimple_bind_set_body (new_stmt, new_body);
10118 /* A subroutine of lower_omp_single. Expand the simple form of
10119 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10121 if (GOMP_single_start ())
10122 BODY;
10123 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10125 FIXME. It may be better to delay expanding the logic of this until
10126 pass_expand_omp. The expanded logic may make the job more difficult
10127 to a synchronization analysis pass. */
10129 static void
10130 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10132 location_t loc = gimple_location (single_stmt);
10133 tree tlabel = create_artificial_label (loc);
10134 tree flabel = create_artificial_label (loc);
10135 gimple call, cond;
10136 tree lhs, decl;
10138 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10139 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10140 call = gimple_build_call (decl, 0);
10141 gimple_call_set_lhs (call, lhs);
10142 gimple_seq_add_stmt (pre_p, call);
10144 cond = gimple_build_cond (EQ_EXPR, lhs,
10145 fold_convert_loc (loc, TREE_TYPE (lhs),
10146 boolean_true_node),
10147 tlabel, flabel);
10148 gimple_seq_add_stmt (pre_p, cond);
10149 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10150 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10151 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10155 /* A subroutine of lower_omp_single. Expand the simple form of
10156 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10158 #pragma omp single copyprivate (a, b, c)
10160 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10163 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10165 BODY;
10166 copyout.a = a;
10167 copyout.b = b;
10168 copyout.c = c;
10169 GOMP_single_copy_end (&copyout);
10171 else
10173 a = copyout_p->a;
10174 b = copyout_p->b;
10175 c = copyout_p->c;
10177 GOMP_barrier ();
10180 FIXME. It may be better to delay expanding the logic of this until
10181 pass_expand_omp. The expanded logic may make the job more difficult
10182 to a synchronization analysis pass. */
10184 static void
10185 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10186 omp_context *ctx)
10188 tree ptr_type, t, l0, l1, l2, bfn_decl;
10189 gimple_seq copyin_seq;
10190 location_t loc = gimple_location (single_stmt);
10192 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10194 ptr_type = build_pointer_type (ctx->record_type);
10195 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10197 l0 = create_artificial_label (loc);
10198 l1 = create_artificial_label (loc);
10199 l2 = create_artificial_label (loc);
10201 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10202 t = build_call_expr_loc (loc, bfn_decl, 0);
10203 t = fold_convert_loc (loc, ptr_type, t);
10204 gimplify_assign (ctx->receiver_decl, t, pre_p);
10206 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10207 build_int_cst (ptr_type, 0));
10208 t = build3 (COND_EXPR, void_type_node, t,
10209 build_and_jump (&l0), build_and_jump (&l1));
10210 gimplify_and_add (t, pre_p);
10212 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10214 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10216 copyin_seq = NULL;
10217 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10218 &copyin_seq, ctx);
10220 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10221 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10222 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10223 gimplify_and_add (t, pre_p);
10225 t = build_and_jump (&l2);
10226 gimplify_and_add (t, pre_p);
10228 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10230 gimple_seq_add_seq (pre_p, copyin_seq);
10232 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10236 /* Expand code for an OpenMP single directive. */
10238 static void
10239 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10241 tree block;
10242 gimple t;
10243 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10244 gbind *bind;
10245 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10247 push_gimplify_context ();
10249 block = make_node (BLOCK);
10250 bind = gimple_build_bind (NULL, NULL, block);
10251 gsi_replace (gsi_p, bind, true);
10252 bind_body = NULL;
10253 dlist = NULL;
10254 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10255 &bind_body, &dlist, ctx, NULL);
10256 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10258 gimple_seq_add_stmt (&bind_body, single_stmt);
10260 if (ctx->record_type)
10261 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10262 else
10263 lower_omp_single_simple (single_stmt, &bind_body);
10265 gimple_omp_set_body (single_stmt, NULL);
10267 gimple_seq_add_seq (&bind_body, dlist);
10269 bind_body = maybe_catch_exception (bind_body);
10271 t = gimple_build_omp_return
10272 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10273 OMP_CLAUSE_NOWAIT));
10274 gimple_seq_add_stmt (&bind_body_tail, t);
10275 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10276 if (ctx->record_type)
10278 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10279 tree clobber = build_constructor (ctx->record_type, NULL);
10280 TREE_THIS_VOLATILE (clobber) = 1;
10281 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10282 clobber), GSI_SAME_STMT);
10284 gimple_seq_add_seq (&bind_body, bind_body_tail);
10285 gimple_bind_set_body (bind, bind_body);
10287 pop_gimplify_context (bind);
10289 gimple_bind_append_vars (bind, ctx->block_vars);
10290 BLOCK_VARS (block) = ctx->block_vars;
10291 if (BLOCK_VARS (block))
10292 TREE_USED (block) = 1;
10296 /* Expand code for an OpenMP master directive. */
10298 static void
10299 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10301 tree block, lab = NULL, x, bfn_decl;
10302 gimple stmt = gsi_stmt (*gsi_p);
10303 gbind *bind;
10304 location_t loc = gimple_location (stmt);
10305 gimple_seq tseq;
10307 push_gimplify_context ();
10309 block = make_node (BLOCK);
10310 bind = gimple_build_bind (NULL, NULL, block);
10311 gsi_replace (gsi_p, bind, true);
10312 gimple_bind_add_stmt (bind, stmt);
10314 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10315 x = build_call_expr_loc (loc, bfn_decl, 0);
10316 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10317 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10318 tseq = NULL;
10319 gimplify_and_add (x, &tseq);
10320 gimple_bind_add_seq (bind, tseq);
10322 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10323 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10324 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10325 gimple_omp_set_body (stmt, NULL);
10327 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10329 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10331 pop_gimplify_context (bind);
10333 gimple_bind_append_vars (bind, ctx->block_vars);
10334 BLOCK_VARS (block) = ctx->block_vars;
10338 /* Expand code for an OpenMP taskgroup directive. */
10340 static void
10341 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10343 gimple stmt = gsi_stmt (*gsi_p);
10344 gcall *x;
10345 gbind *bind;
10346 tree block = make_node (BLOCK);
10348 bind = gimple_build_bind (NULL, NULL, block);
10349 gsi_replace (gsi_p, bind, true);
10350 gimple_bind_add_stmt (bind, stmt);
10352 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10354 gimple_bind_add_stmt (bind, x);
10356 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10357 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10358 gimple_omp_set_body (stmt, NULL);
10360 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10362 gimple_bind_append_vars (bind, ctx->block_vars);
10363 BLOCK_VARS (block) = ctx->block_vars;
10367 /* Expand code for an OpenMP ordered directive. */
10369 static void
10370 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10372 tree block;
10373 gimple stmt = gsi_stmt (*gsi_p);
10374 gcall *x;
10375 gbind *bind;
10377 push_gimplify_context ();
10379 block = make_node (BLOCK);
10380 bind = gimple_build_bind (NULL, NULL, block);
10381 gsi_replace (gsi_p, bind, true);
10382 gimple_bind_add_stmt (bind, stmt);
10384 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10386 gimple_bind_add_stmt (bind, x);
10388 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10389 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10390 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10391 gimple_omp_set_body (stmt, NULL);
10393 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10394 gimple_bind_add_stmt (bind, x);
10396 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10398 pop_gimplify_context (bind);
10400 gimple_bind_append_vars (bind, ctx->block_vars);
10401 BLOCK_VARS (block) = gimple_bind_vars (bind);
10405 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10406 substitution of a couple of function calls. But in the NAMED case,
10407 requires that languages coordinate a symbol name. It is therefore
10408 best put here in common code. */
10410 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10412 static void
10413 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10415 tree block;
10416 tree name, lock, unlock;
10417 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10418 gbind *bind;
10419 location_t loc = gimple_location (stmt);
10420 gimple_seq tbody;
10422 name = gimple_omp_critical_name (stmt);
10423 if (name)
10425 tree decl;
10427 if (!critical_name_mutexes)
10428 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10430 tree *n = critical_name_mutexes->get (name);
10431 if (n == NULL)
10433 char *new_str;
10435 decl = create_tmp_var_raw (ptr_type_node);
10437 new_str = ACONCAT ((".gomp_critical_user_",
10438 IDENTIFIER_POINTER (name), NULL));
10439 DECL_NAME (decl) = get_identifier (new_str);
10440 TREE_PUBLIC (decl) = 1;
10441 TREE_STATIC (decl) = 1;
10442 DECL_COMMON (decl) = 1;
10443 DECL_ARTIFICIAL (decl) = 1;
10444 DECL_IGNORED_P (decl) = 1;
10446 varpool_node::finalize_decl (decl);
10448 critical_name_mutexes->put (name, decl);
10450 else
10451 decl = *n;
10453 /* If '#pragma omp critical' is inside offloaded region or
10454 inside function marked as offloadable, the symbol must be
10455 marked as offloadable too. */
10456 omp_context *octx;
10457 if (cgraph_node::get (current_function_decl)->offloadable)
10458 varpool_node::get_create (decl)->offloadable = 1;
10459 else
10460 for (octx = ctx->outer; octx; octx = octx->outer)
10461 if (is_gimple_omp_offloaded (octx->stmt))
10463 varpool_node::get_create (decl)->offloadable = 1;
10464 break;
10467 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10468 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10470 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10471 unlock = build_call_expr_loc (loc, unlock, 1,
10472 build_fold_addr_expr_loc (loc, decl));
10474 else
10476 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10477 lock = build_call_expr_loc (loc, lock, 0);
10479 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10480 unlock = build_call_expr_loc (loc, unlock, 0);
10483 push_gimplify_context ();
10485 block = make_node (BLOCK);
10486 bind = gimple_build_bind (NULL, NULL, block);
10487 gsi_replace (gsi_p, bind, true);
10488 gimple_bind_add_stmt (bind, stmt);
10490 tbody = gimple_bind_body (bind);
10491 gimplify_and_add (lock, &tbody);
10492 gimple_bind_set_body (bind, tbody);
10494 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10495 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10496 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10497 gimple_omp_set_body (stmt, NULL);
10499 tbody = gimple_bind_body (bind);
10500 gimplify_and_add (unlock, &tbody);
10501 gimple_bind_set_body (bind, tbody);
10503 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10505 pop_gimplify_context (bind);
10506 gimple_bind_append_vars (bind, ctx->block_vars);
10507 BLOCK_VARS (block) = gimple_bind_vars (bind);
10511 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10512 for a lastprivate clause. Given a loop control predicate of (V
10513 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10514 is appended to *DLIST, iterator initialization is appended to
10515 *BODY_P. */
10517 static void
10518 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10519 gimple_seq *dlist, struct omp_context *ctx)
10521 tree clauses, cond, vinit;
10522 enum tree_code cond_code;
10523 gimple_seq stmts;
10525 cond_code = fd->loop.cond_code;
10526 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10528 /* When possible, use a strict equality expression. This can let VRP
10529 type optimizations deduce the value and remove a copy. */
10530 if (tree_fits_shwi_p (fd->loop.step))
10532 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10533 if (step == 1 || step == -1)
10534 cond_code = EQ_EXPR;
10537 tree n2 = fd->loop.n2;
10538 if (fd->collapse > 1
10539 && TREE_CODE (n2) != INTEGER_CST
10540 && gimple_omp_for_combined_into_p (fd->for_stmt)
10541 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10543 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10544 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
10546 struct omp_for_data outer_fd;
10547 extract_omp_for_data (gfor, &outer_fd, NULL);
10548 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10551 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
10553 clauses = gimple_omp_for_clauses (fd->for_stmt);
10554 stmts = NULL;
10555 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10556 if (!gimple_seq_empty_p (stmts))
10558 gimple_seq_add_seq (&stmts, *dlist);
10559 *dlist = stmts;
10561 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10562 vinit = fd->loop.n1;
10563 if (cond_code == EQ_EXPR
10564 && tree_fits_shwi_p (fd->loop.n2)
10565 && ! integer_zerop (fd->loop.n2))
10566 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10567 else
10568 vinit = unshare_expr (vinit);
10570 /* Initialize the iterator variable, so that threads that don't execute
10571 any iterations don't execute the lastprivate clauses by accident. */
10572 gimplify_assign (fd->loop.v, vinit, body_p);
10577 /* Lower code for an OMP loop directive. */
10579 static void
10580 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10582 tree *rhs_p, block;
10583 struct omp_for_data fd, *fdp = NULL;
10584 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10585 gbind *new_stmt;
10586 gimple_seq omp_for_body, body, dlist;
10587 size_t i;
10589 push_gimplify_context ();
10591 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10593 block = make_node (BLOCK);
10594 new_stmt = gimple_build_bind (NULL, NULL, block);
10595 /* Replace at gsi right away, so that 'stmt' is no member
10596 of a sequence anymore as we're going to add to to a different
10597 one below. */
10598 gsi_replace (gsi_p, new_stmt, true);
10600 /* Move declaration of temporaries in the loop body before we make
10601 it go away. */
10602 omp_for_body = gimple_omp_body (stmt);
10603 if (!gimple_seq_empty_p (omp_for_body)
10604 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10606 gbind *inner_bind
10607 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10608 tree vars = gimple_bind_vars (inner_bind);
10609 gimple_bind_append_vars (new_stmt, vars);
10610 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10611 keep them on the inner_bind and it's block. */
10612 gimple_bind_set_vars (inner_bind, NULL_TREE);
10613 if (gimple_bind_block (inner_bind))
10614 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10617 if (gimple_omp_for_combined_into_p (stmt))
10619 extract_omp_for_data (stmt, &fd, NULL);
10620 fdp = &fd;
10622 /* We need two temporaries with fd.loop.v type (istart/iend)
10623 and then (fd.collapse - 1) temporaries with the same
10624 type for count2 ... countN-1 vars if not constant. */
10625 size_t count = 2;
10626 tree type = fd.iter_type;
10627 if (fd.collapse > 1
10628 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10629 count += fd.collapse - 1;
10630 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10631 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10632 tree clauses = *pc;
10633 if (parallel_for)
10634 outerc
10635 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10636 OMP_CLAUSE__LOOPTEMP_);
10637 for (i = 0; i < count; i++)
10639 tree temp;
10640 if (parallel_for)
10642 gcc_assert (outerc);
10643 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10644 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10645 OMP_CLAUSE__LOOPTEMP_);
10647 else
10649 temp = create_tmp_var (type);
10650 insert_decl_map (&ctx->outer->cb, temp, temp);
10652 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10653 OMP_CLAUSE_DECL (*pc) = temp;
10654 pc = &OMP_CLAUSE_CHAIN (*pc);
10656 *pc = clauses;
10659 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10660 dlist = NULL;
10661 body = NULL;
10662 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10663 fdp);
10664 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10666 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10668 /* Lower the header expressions. At this point, we can assume that
10669 the header is of the form:
10671 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10673 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10674 using the .omp_data_s mapping, if needed. */
10675 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10677 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10678 if (!is_gimple_min_invariant (*rhs_p))
10679 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10681 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10682 if (!is_gimple_min_invariant (*rhs_p))
10683 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10685 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10686 if (!is_gimple_min_invariant (*rhs_p))
10687 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10690 /* Once lowered, extract the bounds and clauses. */
10691 extract_omp_for_data (stmt, &fd, NULL);
10693 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10695 gimple_seq_add_stmt (&body, stmt);
10696 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10698 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10699 fd.loop.v));
10701 /* After the loop, add exit clauses. */
10702 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10704 if (ctx->cancellable)
10705 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10707 gimple_seq_add_seq (&body, dlist);
10709 body = maybe_catch_exception (body);
10711 /* Region exit marker goes at the end of the loop body. */
10712 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10713 maybe_add_implicit_barrier_cancel (ctx, &body);
10714 pop_gimplify_context (new_stmt);
10716 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10717 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10718 if (BLOCK_VARS (block))
10719 TREE_USED (block) = 1;
10721 gimple_bind_set_body (new_stmt, body);
10722 gimple_omp_set_body (stmt, NULL);
10723 gimple_omp_for_set_pre_body (stmt, NULL);
10726 /* Callback for walk_stmts. Check if the current statement only contains
10727 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10729 static tree
10730 check_combined_parallel (gimple_stmt_iterator *gsi_p,
10731 bool *handled_ops_p,
10732 struct walk_stmt_info *wi)
10734 int *info = (int *) wi->info;
10735 gimple stmt = gsi_stmt (*gsi_p);
10737 *handled_ops_p = true;
10738 switch (gimple_code (stmt))
10740 WALK_SUBSTMTS;
10742 case GIMPLE_OMP_FOR:
10743 case GIMPLE_OMP_SECTIONS:
10744 *info = *info == 0 ? 1 : -1;
10745 break;
10746 default:
10747 *info = -1;
10748 break;
10750 return NULL;
10753 struct omp_taskcopy_context
10755 /* This field must be at the beginning, as we do "inheritance": Some
10756 callback functions for tree-inline.c (e.g., omp_copy_decl)
10757 receive a copy_body_data pointer that is up-casted to an
10758 omp_context pointer. */
10759 copy_body_data cb;
10760 omp_context *ctx;
10763 static tree
10764 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10766 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10768 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10769 return create_tmp_var (TREE_TYPE (var));
10771 return var;
10774 static tree
10775 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10777 tree name, new_fields = NULL, type, f;
10779 type = lang_hooks.types.make_type (RECORD_TYPE);
10780 name = DECL_NAME (TYPE_NAME (orig_type));
10781 name = build_decl (gimple_location (tcctx->ctx->stmt),
10782 TYPE_DECL, name, type);
10783 TYPE_NAME (type) = name;
10785 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10787 tree new_f = copy_node (f);
10788 DECL_CONTEXT (new_f) = type;
10789 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10790 TREE_CHAIN (new_f) = new_fields;
10791 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10792 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10793 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10794 &tcctx->cb, NULL);
10795 new_fields = new_f;
10796 tcctx->cb.decl_map->put (f, new_f);
10798 TYPE_FIELDS (type) = nreverse (new_fields);
10799 layout_type (type);
10800 return type;
10803 /* Create task copyfn. */
10805 static void
10806 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
10808 struct function *child_cfun;
10809 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10810 tree record_type, srecord_type, bind, list;
10811 bool record_needs_remap = false, srecord_needs_remap = false;
10812 splay_tree_node n;
10813 struct omp_taskcopy_context tcctx;
10814 location_t loc = gimple_location (task_stmt);
10816 child_fn = gimple_omp_task_copy_fn (task_stmt);
10817 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10818 gcc_assert (child_cfun->cfg == NULL);
10819 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10821 /* Reset DECL_CONTEXT on function arguments. */
10822 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10823 DECL_CONTEXT (t) = child_fn;
10825 /* Populate the function. */
10826 push_gimplify_context ();
10827 push_cfun (child_cfun);
10829 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10830 TREE_SIDE_EFFECTS (bind) = 1;
10831 list = NULL;
10832 DECL_SAVED_TREE (child_fn) = bind;
10833 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10835 /* Remap src and dst argument types if needed. */
10836 record_type = ctx->record_type;
10837 srecord_type = ctx->srecord_type;
10838 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10839 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10841 record_needs_remap = true;
10842 break;
10844 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10845 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10847 srecord_needs_remap = true;
10848 break;
10851 if (record_needs_remap || srecord_needs_remap)
10853 memset (&tcctx, '\0', sizeof (tcctx));
10854 tcctx.cb.src_fn = ctx->cb.src_fn;
10855 tcctx.cb.dst_fn = child_fn;
10856 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
10857 gcc_checking_assert (tcctx.cb.src_node);
10858 tcctx.cb.dst_node = tcctx.cb.src_node;
10859 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10860 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10861 tcctx.cb.eh_lp_nr = 0;
10862 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10863 tcctx.cb.decl_map = new hash_map<tree, tree>;
10864 tcctx.ctx = ctx;
10866 if (record_needs_remap)
10867 record_type = task_copyfn_remap_type (&tcctx, record_type);
10868 if (srecord_needs_remap)
10869 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10871 else
10872 tcctx.cb.decl_map = NULL;
10874 arg = DECL_ARGUMENTS (child_fn);
10875 TREE_TYPE (arg) = build_pointer_type (record_type);
10876 sarg = DECL_CHAIN (arg);
10877 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10879 /* First pass: initialize temporaries used in record_type and srecord_type
10880 sizes and field offsets. */
10881 if (tcctx.cb.decl_map)
10882 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10883 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10885 tree *p;
10887 decl = OMP_CLAUSE_DECL (c);
10888 p = tcctx.cb.decl_map->get (decl);
10889 if (p == NULL)
10890 continue;
10891 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10892 sf = (tree) n->value;
10893 sf = *tcctx.cb.decl_map->get (sf);
10894 src = build_simple_mem_ref_loc (loc, sarg);
10895 src = omp_build_component_ref (src, sf);
10896 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10897 append_to_statement_list (t, &list);
10900 /* Second pass: copy shared var pointers and copy construct non-VLA
10901 firstprivate vars. */
10902 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10903 switch (OMP_CLAUSE_CODE (c))
10905 case OMP_CLAUSE_SHARED:
10906 decl = OMP_CLAUSE_DECL (c);
10907 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10908 if (n == NULL)
10909 break;
10910 f = (tree) n->value;
10911 if (tcctx.cb.decl_map)
10912 f = *tcctx.cb.decl_map->get (f);
10913 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10914 sf = (tree) n->value;
10915 if (tcctx.cb.decl_map)
10916 sf = *tcctx.cb.decl_map->get (sf);
10917 src = build_simple_mem_ref_loc (loc, sarg);
10918 src = omp_build_component_ref (src, sf);
10919 dst = build_simple_mem_ref_loc (loc, arg);
10920 dst = omp_build_component_ref (dst, f);
10921 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10922 append_to_statement_list (t, &list);
10923 break;
10924 case OMP_CLAUSE_FIRSTPRIVATE:
10925 decl = OMP_CLAUSE_DECL (c);
10926 if (is_variable_sized (decl))
10927 break;
10928 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10929 if (n == NULL)
10930 break;
10931 f = (tree) n->value;
10932 if (tcctx.cb.decl_map)
10933 f = *tcctx.cb.decl_map->get (f);
10934 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10935 if (n != NULL)
10937 sf = (tree) n->value;
10938 if (tcctx.cb.decl_map)
10939 sf = *tcctx.cb.decl_map->get (sf);
10940 src = build_simple_mem_ref_loc (loc, sarg);
10941 src = omp_build_component_ref (src, sf);
10942 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
10943 src = build_simple_mem_ref_loc (loc, src);
10945 else
10946 src = decl;
10947 dst = build_simple_mem_ref_loc (loc, arg);
10948 dst = omp_build_component_ref (dst, f);
10949 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10950 append_to_statement_list (t, &list);
10951 break;
10952 case OMP_CLAUSE_PRIVATE:
10953 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10954 break;
10955 decl = OMP_CLAUSE_DECL (c);
10956 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10957 f = (tree) n->value;
10958 if (tcctx.cb.decl_map)
10959 f = *tcctx.cb.decl_map->get (f);
10960 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10961 if (n != NULL)
10963 sf = (tree) n->value;
10964 if (tcctx.cb.decl_map)
10965 sf = *tcctx.cb.decl_map->get (sf);
10966 src = build_simple_mem_ref_loc (loc, sarg);
10967 src = omp_build_component_ref (src, sf);
10968 if (use_pointer_for_field (decl, NULL))
10969 src = build_simple_mem_ref_loc (loc, src);
10971 else
10972 src = decl;
10973 dst = build_simple_mem_ref_loc (loc, arg);
10974 dst = omp_build_component_ref (dst, f);
10975 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10976 append_to_statement_list (t, &list);
10977 break;
10978 default:
10979 break;
10982 /* Last pass: handle VLA firstprivates. */
10983 if (tcctx.cb.decl_map)
10984 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10985 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10987 tree ind, ptr, df;
10989 decl = OMP_CLAUSE_DECL (c);
10990 if (!is_variable_sized (decl))
10991 continue;
10992 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10993 if (n == NULL)
10994 continue;
10995 f = (tree) n->value;
10996 f = *tcctx.cb.decl_map->get (f);
10997 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10998 ind = DECL_VALUE_EXPR (decl);
10999 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
11000 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
11001 n = splay_tree_lookup (ctx->sfield_map,
11002 (splay_tree_key) TREE_OPERAND (ind, 0));
11003 sf = (tree) n->value;
11004 sf = *tcctx.cb.decl_map->get (sf);
11005 src = build_simple_mem_ref_loc (loc, sarg);
11006 src = omp_build_component_ref (src, sf);
11007 src = build_simple_mem_ref_loc (loc, src);
11008 dst = build_simple_mem_ref_loc (loc, arg);
11009 dst = omp_build_component_ref (dst, f);
11010 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11011 append_to_statement_list (t, &list);
11012 n = splay_tree_lookup (ctx->field_map,
11013 (splay_tree_key) TREE_OPERAND (ind, 0));
11014 df = (tree) n->value;
11015 df = *tcctx.cb.decl_map->get (df);
11016 ptr = build_simple_mem_ref_loc (loc, arg);
11017 ptr = omp_build_component_ref (ptr, df);
11018 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
11019 build_fold_addr_expr_loc (loc, dst));
11020 append_to_statement_list (t, &list);
11023 t = build1 (RETURN_EXPR, void_type_node, NULL);
11024 append_to_statement_list (t, &list);
11026 if (tcctx.cb.decl_map)
11027 delete tcctx.cb.decl_map;
11028 pop_gimplify_context (NULL);
11029 BIND_EXPR_BODY (bind) = list;
11030 pop_cfun ();
11033 static void
11034 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
11036 tree c, clauses;
11037 gimple g;
11038 size_t n_in = 0, n_out = 0, idx = 2, i;
11040 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11041 OMP_CLAUSE_DEPEND);
11042 gcc_assert (clauses);
11043 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11044 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11045 switch (OMP_CLAUSE_DEPEND_KIND (c))
11047 case OMP_CLAUSE_DEPEND_IN:
11048 n_in++;
11049 break;
11050 case OMP_CLAUSE_DEPEND_OUT:
11051 case OMP_CLAUSE_DEPEND_INOUT:
11052 n_out++;
11053 break;
11054 default:
11055 gcc_unreachable ();
11057 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11058 tree array = create_tmp_var (type);
11059 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11060 NULL_TREE);
11061 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11062 gimple_seq_add_stmt (iseq, g);
11063 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11064 NULL_TREE);
11065 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11066 gimple_seq_add_stmt (iseq, g);
11067 for (i = 0; i < 2; i++)
11069 if ((i ? n_in : n_out) == 0)
11070 continue;
11071 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11072 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11073 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11075 tree t = OMP_CLAUSE_DECL (c);
11076 t = fold_convert (ptr_type_node, t);
11077 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11078 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11079 NULL_TREE, NULL_TREE);
11080 g = gimple_build_assign (r, t);
11081 gimple_seq_add_stmt (iseq, g);
11084 tree *p = gimple_omp_task_clauses_ptr (stmt);
11085 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11086 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11087 OMP_CLAUSE_CHAIN (c) = *p;
11088 *p = c;
11089 tree clobber = build_constructor (type, NULL);
11090 TREE_THIS_VOLATILE (clobber) = 1;
11091 g = gimple_build_assign (array, clobber);
11092 gimple_seq_add_stmt (oseq, g);
11095 /* Lower the OpenMP parallel or task directive in the current statement
11096 in GSI_P. CTX holds context information for the directive. */
11098 static void
11099 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11101 tree clauses;
11102 tree child_fn, t;
11103 gimple stmt = gsi_stmt (*gsi_p);
11104 gbind *par_bind, *bind, *dep_bind = NULL;
11105 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11106 location_t loc = gimple_location (stmt);
11108 clauses = gimple_omp_taskreg_clauses (stmt);
11109 par_bind
11110 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11111 par_body = gimple_bind_body (par_bind);
11112 child_fn = ctx->cb.dst_fn;
11113 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11114 && !gimple_omp_parallel_combined_p (stmt))
11116 struct walk_stmt_info wi;
11117 int ws_num = 0;
11119 memset (&wi, 0, sizeof (wi));
11120 wi.info = &ws_num;
11121 wi.val_only = true;
11122 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11123 if (ws_num == 1)
11124 gimple_omp_parallel_set_combined_p (stmt, true);
11126 gimple_seq dep_ilist = NULL;
11127 gimple_seq dep_olist = NULL;
11128 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11129 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11131 push_gimplify_context ();
11132 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11133 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11136 if (ctx->srecord_type)
11137 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11139 push_gimplify_context ();
11141 par_olist = NULL;
11142 par_ilist = NULL;
11143 par_rlist = NULL;
11144 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11145 lower_omp (&par_body, ctx);
11146 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11147 lower_reduction_clauses (clauses, &par_rlist, ctx);
11149 /* Declare all the variables created by mapping and the variables
11150 declared in the scope of the parallel body. */
11151 record_vars_into (ctx->block_vars, child_fn);
11152 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11154 if (ctx->record_type)
11156 ctx->sender_decl
11157 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11158 : ctx->record_type, ".omp_data_o");
11159 DECL_NAMELESS (ctx->sender_decl) = 1;
11160 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11161 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11164 olist = NULL;
11165 ilist = NULL;
11166 lower_send_clauses (clauses, &ilist, &olist, ctx);
11167 lower_send_shared_vars (&ilist, &olist, ctx);
11169 if (ctx->record_type)
11171 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11172 TREE_THIS_VOLATILE (clobber) = 1;
11173 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11174 clobber));
11177 /* Once all the expansions are done, sequence all the different
11178 fragments inside gimple_omp_body. */
11180 new_body = NULL;
11182 if (ctx->record_type)
11184 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11185 /* fixup_child_record_type might have changed receiver_decl's type. */
11186 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11187 gimple_seq_add_stmt (&new_body,
11188 gimple_build_assign (ctx->receiver_decl, t));
11191 gimple_seq_add_seq (&new_body, par_ilist);
11192 gimple_seq_add_seq (&new_body, par_body);
11193 gimple_seq_add_seq (&new_body, par_rlist);
11194 if (ctx->cancellable)
11195 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11196 gimple_seq_add_seq (&new_body, par_olist);
11197 new_body = maybe_catch_exception (new_body);
11198 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
11199 gimple_seq_add_stmt (&new_body,
11200 gimple_build_omp_continue (integer_zero_node,
11201 integer_zero_node));
11202 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11203 gimple_omp_set_body (stmt, new_body);
11205 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11206 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11207 gimple_bind_add_seq (bind, ilist);
11208 gimple_bind_add_stmt (bind, stmt);
11209 gimple_bind_add_seq (bind, olist);
11211 pop_gimplify_context (NULL);
11213 if (dep_bind)
11215 gimple_bind_add_seq (dep_bind, dep_ilist);
11216 gimple_bind_add_stmt (dep_bind, bind);
11217 gimple_bind_add_seq (dep_bind, dep_olist);
11218 pop_gimplify_context (dep_bind);
11222 /* Lower the GIMPLE_OMP_TARGET in the current statement
11223 in GSI_P. CTX holds context information for the directive. */
11225 static void
11226 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11228 tree clauses;
11229 tree child_fn, t, c;
11230 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11231 gbind *tgt_bind, *bind;
11232 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11233 location_t loc = gimple_location (stmt);
11234 bool offloaded, data_region;
11235 unsigned int map_cnt = 0;
11237 offloaded = is_gimple_omp_offloaded (stmt);
11238 switch (gimple_omp_target_kind (stmt))
11240 case GF_OMP_TARGET_KIND_REGION:
11241 case GF_OMP_TARGET_KIND_UPDATE:
11242 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11243 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11244 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11245 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11246 data_region = false;
11247 break;
11248 case GF_OMP_TARGET_KIND_DATA:
11249 case GF_OMP_TARGET_KIND_OACC_DATA:
11250 data_region = true;
11251 break;
11252 default:
11253 gcc_unreachable ();
11256 clauses = gimple_omp_target_clauses (stmt);
11258 tgt_bind = NULL;
11259 tgt_body = NULL;
11260 if (offloaded)
11262 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11263 tgt_body = gimple_bind_body (tgt_bind);
11265 else if (data_region)
11266 tgt_body = gimple_omp_body (stmt);
11267 child_fn = ctx->cb.dst_fn;
11269 push_gimplify_context ();
11271 irlist = NULL;
11272 orlist = NULL;
11273 if (offloaded
11274 && is_gimple_omp_oacc (stmt))
11275 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11277 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11278 switch (OMP_CLAUSE_CODE (c))
11280 tree var, x;
11282 default:
11283 break;
11284 case OMP_CLAUSE_MAP:
11285 #ifdef ENABLE_CHECKING
11286 /* First check what we're prepared to handle in the following. */
11287 switch (OMP_CLAUSE_MAP_KIND (c))
11289 case GOMP_MAP_ALLOC:
11290 case GOMP_MAP_TO:
11291 case GOMP_MAP_FROM:
11292 case GOMP_MAP_TOFROM:
11293 case GOMP_MAP_POINTER:
11294 case GOMP_MAP_TO_PSET:
11295 break;
11296 case GOMP_MAP_FORCE_ALLOC:
11297 case GOMP_MAP_FORCE_TO:
11298 case GOMP_MAP_FORCE_FROM:
11299 case GOMP_MAP_FORCE_TOFROM:
11300 case GOMP_MAP_FORCE_PRESENT:
11301 case GOMP_MAP_FORCE_DEALLOC:
11302 case GOMP_MAP_FORCE_DEVICEPTR:
11303 gcc_assert (is_gimple_omp_oacc (stmt));
11304 break;
11305 default:
11306 gcc_unreachable ();
11308 #endif
11309 /* FALLTHRU */
11310 case OMP_CLAUSE_TO:
11311 case OMP_CLAUSE_FROM:
11312 var = OMP_CLAUSE_DECL (c);
11313 if (!DECL_P (var))
11315 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11316 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11317 map_cnt++;
11318 continue;
11321 if (DECL_SIZE (var)
11322 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11324 tree var2 = DECL_VALUE_EXPR (var);
11325 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11326 var2 = TREE_OPERAND (var2, 0);
11327 gcc_assert (DECL_P (var2));
11328 var = var2;
11331 if (!maybe_lookup_field (var, ctx))
11332 continue;
11334 if (offloaded)
11336 x = build_receiver_ref (var, true, ctx);
11337 tree new_var = lookup_decl (var, ctx);
11338 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11339 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11340 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11341 x = build_simple_mem_ref (x);
11342 SET_DECL_VALUE_EXPR (new_var, x);
11343 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11345 map_cnt++;
11348 if (offloaded)
11350 target_nesting_level++;
11351 lower_omp (&tgt_body, ctx);
11352 target_nesting_level--;
11354 else if (data_region)
11355 lower_omp (&tgt_body, ctx);
11357 if (offloaded)
11359 /* Declare all the variables created by mapping and the variables
11360 declared in the scope of the target body. */
11361 record_vars_into (ctx->block_vars, child_fn);
11362 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11365 olist = NULL;
11366 ilist = NULL;
11367 if (ctx->record_type)
11369 ctx->sender_decl
11370 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11371 DECL_NAMELESS (ctx->sender_decl) = 1;
11372 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11373 t = make_tree_vec (3);
11374 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11375 TREE_VEC_ELT (t, 1)
11376 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11377 ".omp_data_sizes");
11378 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11379 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11380 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11381 tree tkind_type;
11382 int talign_shift;
11383 if (is_gimple_omp_oacc (stmt))
11385 tkind_type = short_unsigned_type_node;
11386 talign_shift = 8;
11388 else
11390 tkind_type = unsigned_char_type_node;
11391 talign_shift = 3;
11393 TREE_VEC_ELT (t, 2)
11394 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11395 ".omp_data_kinds");
11396 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11397 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11398 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11399 gimple_omp_target_set_data_arg (stmt, t);
11401 vec<constructor_elt, va_gc> *vsize;
11402 vec<constructor_elt, va_gc> *vkind;
11403 vec_alloc (vsize, map_cnt);
11404 vec_alloc (vkind, map_cnt);
11405 unsigned int map_idx = 0;
11407 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11408 switch (OMP_CLAUSE_CODE (c))
11410 tree ovar, nc;
11412 default:
11413 break;
11414 case OMP_CLAUSE_MAP:
11415 case OMP_CLAUSE_TO:
11416 case OMP_CLAUSE_FROM:
11417 nc = c;
11418 ovar = OMP_CLAUSE_DECL (c);
11419 if (!DECL_P (ovar))
11421 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11422 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11424 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11425 == get_base_address (ovar));
11426 nc = OMP_CLAUSE_CHAIN (c);
11427 ovar = OMP_CLAUSE_DECL (nc);
11429 else
11431 tree x = build_sender_ref (ovar, ctx);
11432 tree v
11433 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11434 gimplify_assign (x, v, &ilist);
11435 nc = NULL_TREE;
11438 else
11440 if (DECL_SIZE (ovar)
11441 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11443 tree ovar2 = DECL_VALUE_EXPR (ovar);
11444 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11445 ovar2 = TREE_OPERAND (ovar2, 0);
11446 gcc_assert (DECL_P (ovar2));
11447 ovar = ovar2;
11449 if (!maybe_lookup_field (ovar, ctx))
11450 continue;
11453 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11454 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11455 talign = DECL_ALIGN_UNIT (ovar);
11456 if (nc)
11458 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11459 tree x = build_sender_ref (ovar, ctx);
11460 if (maybe_lookup_oacc_reduction (var, ctx))
11462 gcc_checking_assert (offloaded
11463 && is_gimple_omp_oacc (stmt));
11464 gimplify_assign (x, var, &ilist);
11466 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11467 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11468 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11469 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11471 gcc_assert (offloaded);
11472 tree avar
11473 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11474 mark_addressable (avar);
11475 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11476 talign = DECL_ALIGN_UNIT (avar);
11477 avar = build_fold_addr_expr (avar);
11478 gimplify_assign (x, avar, &ilist);
11480 else if (is_gimple_reg (var))
11482 gcc_assert (offloaded);
11483 tree avar = create_tmp_var (TREE_TYPE (var));
11484 mark_addressable (avar);
11485 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11486 if (GOMP_MAP_COPY_TO_P (map_kind)
11487 || map_kind == GOMP_MAP_POINTER
11488 || map_kind == GOMP_MAP_TO_PSET
11489 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11490 gimplify_assign (avar, var, &ilist);
11491 avar = build_fold_addr_expr (avar);
11492 gimplify_assign (x, avar, &ilist);
11493 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11494 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11495 && !TYPE_READONLY (TREE_TYPE (var)))
11497 x = build_sender_ref (ovar, ctx);
11498 x = build_simple_mem_ref (x);
11499 gimplify_assign (var, x, &olist);
11502 else
11504 var = build_fold_addr_expr (var);
11505 gimplify_assign (x, var, &ilist);
11508 tree s = OMP_CLAUSE_SIZE (c);
11509 if (s == NULL_TREE)
11510 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11511 s = fold_convert (size_type_node, s);
11512 tree purpose = size_int (map_idx++);
11513 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11514 if (TREE_CODE (s) != INTEGER_CST)
11515 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11517 unsigned HOST_WIDE_INT tkind;
11518 switch (OMP_CLAUSE_CODE (c))
11520 case OMP_CLAUSE_MAP:
11521 tkind = OMP_CLAUSE_MAP_KIND (c);
11522 break;
11523 case OMP_CLAUSE_TO:
11524 tkind = GOMP_MAP_TO;
11525 break;
11526 case OMP_CLAUSE_FROM:
11527 tkind = GOMP_MAP_FROM;
11528 break;
11529 default:
11530 gcc_unreachable ();
11532 gcc_checking_assert (tkind
11533 < (HOST_WIDE_INT_C (1U) << talign_shift));
11534 talign = ceil_log2 (talign);
11535 tkind |= talign << talign_shift;
11536 gcc_checking_assert (tkind
11537 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11538 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11539 build_int_cstu (tkind_type, tkind));
11540 if (nc && nc != c)
11541 c = nc;
11544 gcc_assert (map_idx == map_cnt);
11546 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11547 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11548 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11549 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11550 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11552 gimple_seq initlist = NULL;
11553 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11554 TREE_VEC_ELT (t, 1)),
11555 &initlist, true, NULL_TREE);
11556 gimple_seq_add_seq (&ilist, initlist);
11558 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11559 NULL);
11560 TREE_THIS_VOLATILE (clobber) = 1;
11561 gimple_seq_add_stmt (&olist,
11562 gimple_build_assign (TREE_VEC_ELT (t, 1),
11563 clobber));
11566 tree clobber = build_constructor (ctx->record_type, NULL);
11567 TREE_THIS_VOLATILE (clobber) = 1;
11568 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11569 clobber));
11572 /* Once all the expansions are done, sequence all the different
11573 fragments inside gimple_omp_body. */
11575 new_body = NULL;
11577 if (offloaded
11578 && ctx->record_type)
11580 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11581 /* fixup_child_record_type might have changed receiver_decl's type. */
11582 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11583 gimple_seq_add_stmt (&new_body,
11584 gimple_build_assign (ctx->receiver_decl, t));
11587 if (offloaded)
11589 gimple_seq_add_seq (&new_body, tgt_body);
11590 new_body = maybe_catch_exception (new_body);
11592 else if (data_region)
11593 new_body = tgt_body;
11594 if (offloaded || data_region)
11596 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11597 gimple_omp_set_body (stmt, new_body);
11600 bind = gimple_build_bind (NULL, NULL,
11601 tgt_bind ? gimple_bind_block (tgt_bind)
11602 : NULL_TREE);
11603 gsi_replace (gsi_p, bind, true);
11604 gimple_bind_add_seq (bind, irlist);
11605 gimple_bind_add_seq (bind, ilist);
11606 gimple_bind_add_stmt (bind, stmt);
11607 gimple_bind_add_seq (bind, olist);
11608 gimple_bind_add_seq (bind, orlist);
11610 pop_gimplify_context (NULL);
11613 /* Expand code for an OpenMP teams directive. */
11615 static void
11616 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11618 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11619 push_gimplify_context ();
11621 tree block = make_node (BLOCK);
11622 gbind *bind = gimple_build_bind (NULL, NULL, block);
11623 gsi_replace (gsi_p, bind, true);
11624 gimple_seq bind_body = NULL;
11625 gimple_seq dlist = NULL;
11626 gimple_seq olist = NULL;
11628 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11629 OMP_CLAUSE_NUM_TEAMS);
11630 if (num_teams == NULL_TREE)
11631 num_teams = build_int_cst (unsigned_type_node, 0);
11632 else
11634 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11635 num_teams = fold_convert (unsigned_type_node, num_teams);
11636 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11638 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11639 OMP_CLAUSE_THREAD_LIMIT);
11640 if (thread_limit == NULL_TREE)
11641 thread_limit = build_int_cst (unsigned_type_node, 0);
11642 else
11644 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11645 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11646 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11647 fb_rvalue);
11650 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11651 &bind_body, &dlist, ctx, NULL);
11652 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11653 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11654 gimple_seq_add_stmt (&bind_body, teams_stmt);
11656 location_t loc = gimple_location (teams_stmt);
11657 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11658 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11659 gimple_set_location (call, loc);
11660 gimple_seq_add_stmt (&bind_body, call);
11662 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11663 gimple_omp_set_body (teams_stmt, NULL);
11664 gimple_seq_add_seq (&bind_body, olist);
11665 gimple_seq_add_seq (&bind_body, dlist);
11666 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11667 gimple_bind_set_body (bind, bind_body);
11669 pop_gimplify_context (bind);
11671 gimple_bind_append_vars (bind, ctx->block_vars);
11672 BLOCK_VARS (block) = ctx->block_vars;
11673 if (BLOCK_VARS (block))
11674 TREE_USED (block) = 1;
11678 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11679 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11680 of OMP context, but with task_shared_vars set. */
11682 static tree
11683 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11684 void *data)
11686 tree t = *tp;
11688 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11689 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11690 return t;
11692 if (task_shared_vars
11693 && DECL_P (t)
11694 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11695 return t;
11697 /* If a global variable has been privatized, TREE_CONSTANT on
11698 ADDR_EXPR might be wrong. */
11699 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11700 recompute_tree_invariant_for_addr_expr (t);
11702 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11703 return NULL_TREE;
11706 static void
11707 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11709 gimple stmt = gsi_stmt (*gsi_p);
11710 struct walk_stmt_info wi;
11711 gcall *call_stmt;
11713 if (gimple_has_location (stmt))
11714 input_location = gimple_location (stmt);
11716 if (task_shared_vars)
11717 memset (&wi, '\0', sizeof (wi));
11719 /* If we have issued syntax errors, avoid doing any heavy lifting.
11720 Just replace the OMP directives with a NOP to avoid
11721 confusing RTL expansion. */
11722 if (seen_error () && is_gimple_omp (stmt))
11724 gsi_replace (gsi_p, gimple_build_nop (), true);
11725 return;
11728 switch (gimple_code (stmt))
11730 case GIMPLE_COND:
11732 gcond *cond_stmt = as_a <gcond *> (stmt);
11733 if ((ctx || task_shared_vars)
11734 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11735 lower_omp_regimplify_p,
11736 ctx ? NULL : &wi, NULL)
11737 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11738 lower_omp_regimplify_p,
11739 ctx ? NULL : &wi, NULL)))
11740 gimple_regimplify_operands (cond_stmt, gsi_p);
11742 break;
11743 case GIMPLE_CATCH:
11744 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
11745 break;
11746 case GIMPLE_EH_FILTER:
11747 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
11748 break;
11749 case GIMPLE_TRY:
11750 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11751 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
11752 break;
11753 case GIMPLE_TRANSACTION:
11754 lower_omp (gimple_transaction_body_ptr (
11755 as_a <gtransaction *> (stmt)),
11756 ctx);
11757 break;
11758 case GIMPLE_BIND:
11759 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
11760 break;
11761 case GIMPLE_OMP_PARALLEL:
11762 case GIMPLE_OMP_TASK:
11763 ctx = maybe_lookup_ctx (stmt);
11764 gcc_assert (ctx);
11765 if (ctx->cancellable)
11766 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11767 lower_omp_taskreg (gsi_p, ctx);
11768 break;
11769 case GIMPLE_OMP_FOR:
11770 ctx = maybe_lookup_ctx (stmt);
11771 gcc_assert (ctx);
11772 if (ctx->cancellable)
11773 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11774 lower_omp_for (gsi_p, ctx);
11775 break;
11776 case GIMPLE_OMP_SECTIONS:
11777 ctx = maybe_lookup_ctx (stmt);
11778 gcc_assert (ctx);
11779 if (ctx->cancellable)
11780 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11781 lower_omp_sections (gsi_p, ctx);
11782 break;
11783 case GIMPLE_OMP_SINGLE:
11784 ctx = maybe_lookup_ctx (stmt);
11785 gcc_assert (ctx);
11786 lower_omp_single (gsi_p, ctx);
11787 break;
11788 case GIMPLE_OMP_MASTER:
11789 ctx = maybe_lookup_ctx (stmt);
11790 gcc_assert (ctx);
11791 lower_omp_master (gsi_p, ctx);
11792 break;
11793 case GIMPLE_OMP_TASKGROUP:
11794 ctx = maybe_lookup_ctx (stmt);
11795 gcc_assert (ctx);
11796 lower_omp_taskgroup (gsi_p, ctx);
11797 break;
11798 case GIMPLE_OMP_ORDERED:
11799 ctx = maybe_lookup_ctx (stmt);
11800 gcc_assert (ctx);
11801 lower_omp_ordered (gsi_p, ctx);
11802 break;
11803 case GIMPLE_OMP_CRITICAL:
11804 ctx = maybe_lookup_ctx (stmt);
11805 gcc_assert (ctx);
11806 lower_omp_critical (gsi_p, ctx);
11807 break;
11808 case GIMPLE_OMP_ATOMIC_LOAD:
11809 if ((ctx || task_shared_vars)
11810 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11811 as_a <gomp_atomic_load *> (stmt)),
11812 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11813 gimple_regimplify_operands (stmt, gsi_p);
11814 break;
11815 case GIMPLE_OMP_TARGET:
11816 ctx = maybe_lookup_ctx (stmt);
11817 gcc_assert (ctx);
11818 lower_omp_target (gsi_p, ctx);
11819 break;
11820 case GIMPLE_OMP_TEAMS:
11821 ctx = maybe_lookup_ctx (stmt);
11822 gcc_assert (ctx);
11823 lower_omp_teams (gsi_p, ctx);
11824 break;
11825 case GIMPLE_CALL:
11826 tree fndecl;
11827 call_stmt = as_a <gcall *> (stmt);
11828 fndecl = gimple_call_fndecl (call_stmt);
11829 if (fndecl
11830 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11831 switch (DECL_FUNCTION_CODE (fndecl))
11833 case BUILT_IN_GOMP_BARRIER:
11834 if (ctx == NULL)
11835 break;
11836 /* FALLTHRU */
11837 case BUILT_IN_GOMP_CANCEL:
11838 case BUILT_IN_GOMP_CANCELLATION_POINT:
11839 omp_context *cctx;
11840 cctx = ctx;
11841 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11842 cctx = cctx->outer;
11843 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
11844 if (!cctx->cancellable)
11846 if (DECL_FUNCTION_CODE (fndecl)
11847 == BUILT_IN_GOMP_CANCELLATION_POINT)
11849 stmt = gimple_build_nop ();
11850 gsi_replace (gsi_p, stmt, false);
11852 break;
11854 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11856 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
11857 gimple_call_set_fndecl (call_stmt, fndecl);
11858 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
11860 tree lhs;
11861 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
11862 gimple_call_set_lhs (call_stmt, lhs);
11863 tree fallthru_label;
11864 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11865 gimple g;
11866 g = gimple_build_label (fallthru_label);
11867 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11868 g = gimple_build_cond (NE_EXPR, lhs,
11869 fold_convert (TREE_TYPE (lhs),
11870 boolean_false_node),
11871 cctx->cancel_label, fallthru_label);
11872 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11873 break;
11874 default:
11875 break;
11877 /* FALLTHRU */
11878 default:
11879 if ((ctx || task_shared_vars)
11880 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11881 ctx ? NULL : &wi))
11883 /* Just remove clobbers, this should happen only if we have
11884 "privatized" local addressable variables in SIMD regions,
11885 the clobber isn't needed in that case and gimplifying address
11886 of the ARRAY_REF into a pointer and creating MEM_REF based
11887 clobber would create worse code than we get with the clobber
11888 dropped. */
11889 if (gimple_clobber_p (stmt))
11891 gsi_replace (gsi_p, gimple_build_nop (), true);
11892 break;
11894 gimple_regimplify_operands (stmt, gsi_p);
11896 break;
11900 static void
11901 lower_omp (gimple_seq *body, omp_context *ctx)
11903 location_t saved_location = input_location;
11904 gimple_stmt_iterator gsi;
11905 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11906 lower_omp_1 (&gsi, ctx);
11907 /* During gimplification, we haven't folded statments inside offloading
11908 regions (gimplify.c:maybe_fold_stmt); do that now. */
11909 if (target_nesting_level)
11910 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11911 fold_stmt (&gsi);
11912 input_location = saved_location;
11915 /* Main entry point. */
11917 static unsigned int
11918 execute_lower_omp (void)
11920 gimple_seq body;
11921 int i;
11922 omp_context *ctx;
11924 /* This pass always runs, to provide PROP_gimple_lomp.
11925 But often, there is nothing to do. */
11926 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11927 && flag_openmp_simd == 0)
11928 return 0;
11930 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11931 delete_omp_context);
11933 body = gimple_body (current_function_decl);
11934 scan_omp (&body, NULL);
11935 gcc_assert (taskreg_nesting_level == 0);
11936 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11937 finish_taskreg_scan (ctx);
11938 taskreg_contexts.release ();
11940 if (all_contexts->root)
11942 if (task_shared_vars)
11943 push_gimplify_context ();
11944 lower_omp (&body, NULL);
11945 if (task_shared_vars)
11946 pop_gimplify_context (NULL);
11949 if (all_contexts)
11951 splay_tree_delete (all_contexts);
11952 all_contexts = NULL;
11954 BITMAP_FREE (task_shared_vars);
11955 return 0;
11958 namespace {
11960 const pass_data pass_data_lower_omp =
11962 GIMPLE_PASS, /* type */
11963 "omplower", /* name */
11964 OPTGROUP_NONE, /* optinfo_flags */
11965 TV_NONE, /* tv_id */
11966 PROP_gimple_any, /* properties_required */
11967 PROP_gimple_lomp, /* properties_provided */
11968 0, /* properties_destroyed */
11969 0, /* todo_flags_start */
11970 0, /* todo_flags_finish */
11973 class pass_lower_omp : public gimple_opt_pass
11975 public:
11976 pass_lower_omp (gcc::context *ctxt)
11977 : gimple_opt_pass (pass_data_lower_omp, ctxt)
11980 /* opt_pass methods: */
11981 virtual unsigned int execute (function *) { return execute_lower_omp (); }
11983 }; // class pass_lower_omp
11985 } // anon namespace
11987 gimple_opt_pass *
11988 make_pass_lower_omp (gcc::context *ctxt)
11990 return new pass_lower_omp (ctxt);
11993 /* The following is a utility to diagnose structured block violations.
11994 It is not part of the "omplower" pass, as that's invoked too late. It
11995 should be invoked by the respective front ends after gimplification. */
11997 static splay_tree all_labels;
11999 /* Check for mismatched contexts and generate an error if needed. Return
12000 true if an error is detected. */
12002 static bool
12003 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
12004 gimple branch_ctx, gimple label_ctx)
12006 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
12007 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
12009 if (label_ctx == branch_ctx)
12010 return false;
12012 const char* kind = NULL;
12014 if (flag_cilkplus)
12016 if ((branch_ctx
12017 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12018 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12019 || (label_ctx
12020 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12021 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12022 kind = "Cilk Plus";
12024 if (flag_openacc)
12026 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
12027 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
12029 gcc_checking_assert (kind == NULL);
12030 kind = "OpenACC";
12033 if (kind == NULL)
12035 gcc_checking_assert (flag_openmp);
12036 kind = "OpenMP";
12040 Previously we kept track of the label's entire context in diagnose_sb_[12]
12041 so we could traverse it and issue a correct "exit" or "enter" error
12042 message upon a structured block violation.
12044 We built the context by building a list with tree_cons'ing, but there is
12045 no easy counterpart in gimple tuples. It seems like far too much work
12046 for issuing exit/enter error messages. If someone really misses the
12047 distinct error message... patches welcome.
12050 #if 0
12051 /* Try to avoid confusing the user by producing and error message
12052 with correct "exit" or "enter" verbiage. We prefer "exit"
12053 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12054 if (branch_ctx == NULL)
12055 exit_p = false;
12056 else
12058 while (label_ctx)
12060 if (TREE_VALUE (label_ctx) == branch_ctx)
12062 exit_p = false;
12063 break;
12065 label_ctx = TREE_CHAIN (label_ctx);
12069 if (exit_p)
12070 error ("invalid exit from %s structured block", kind);
12071 else
12072 error ("invalid entry to %s structured block", kind);
12073 #endif
12075 /* If it's obvious we have an invalid entry, be specific about the error. */
12076 if (branch_ctx == NULL)
12077 error ("invalid entry to %s structured block", kind);
12078 else
12080 /* Otherwise, be vague and lazy, but efficient. */
12081 error ("invalid branch to/from %s structured block", kind);
12084 gsi_replace (gsi_p, gimple_build_nop (), false);
12085 return true;
12088 /* Pass 1: Create a minimal tree of structured blocks, and record
12089 where each label is found. */
12091 static tree
12092 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12093 struct walk_stmt_info *wi)
12095 gimple context = (gimple) wi->info;
12096 gimple inner_context;
12097 gimple stmt = gsi_stmt (*gsi_p);
12099 *handled_ops_p = true;
12101 switch (gimple_code (stmt))
12103 WALK_SUBSTMTS;
12105 case GIMPLE_OMP_PARALLEL:
12106 case GIMPLE_OMP_TASK:
12107 case GIMPLE_OMP_SECTIONS:
12108 case GIMPLE_OMP_SINGLE:
12109 case GIMPLE_OMP_SECTION:
12110 case GIMPLE_OMP_MASTER:
12111 case GIMPLE_OMP_ORDERED:
12112 case GIMPLE_OMP_CRITICAL:
12113 case GIMPLE_OMP_TARGET:
12114 case GIMPLE_OMP_TEAMS:
12115 case GIMPLE_OMP_TASKGROUP:
12116 /* The minimal context here is just the current OMP construct. */
12117 inner_context = stmt;
12118 wi->info = inner_context;
12119 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12120 wi->info = context;
12121 break;
12123 case GIMPLE_OMP_FOR:
12124 inner_context = stmt;
12125 wi->info = inner_context;
12126 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12127 walk them. */
12128 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12129 diagnose_sb_1, NULL, wi);
12130 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12131 wi->info = context;
12132 break;
12134 case GIMPLE_LABEL:
12135 splay_tree_insert (all_labels,
12136 (splay_tree_key) gimple_label_label (
12137 as_a <glabel *> (stmt)),
12138 (splay_tree_value) context);
12139 break;
12141 default:
12142 break;
12145 return NULL_TREE;
12148 /* Pass 2: Check each branch and see if its context differs from that of
12149 the destination label's context. */
12151 static tree
12152 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12153 struct walk_stmt_info *wi)
12155 gimple context = (gimple) wi->info;
12156 splay_tree_node n;
12157 gimple stmt = gsi_stmt (*gsi_p);
12159 *handled_ops_p = true;
12161 switch (gimple_code (stmt))
12163 WALK_SUBSTMTS;
12165 case GIMPLE_OMP_PARALLEL:
12166 case GIMPLE_OMP_TASK:
12167 case GIMPLE_OMP_SECTIONS:
12168 case GIMPLE_OMP_SINGLE:
12169 case GIMPLE_OMP_SECTION:
12170 case GIMPLE_OMP_MASTER:
12171 case GIMPLE_OMP_ORDERED:
12172 case GIMPLE_OMP_CRITICAL:
12173 case GIMPLE_OMP_TARGET:
12174 case GIMPLE_OMP_TEAMS:
12175 case GIMPLE_OMP_TASKGROUP:
12176 wi->info = stmt;
12177 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12178 wi->info = context;
12179 break;
12181 case GIMPLE_OMP_FOR:
12182 wi->info = stmt;
12183 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12184 walk them. */
12185 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12186 diagnose_sb_2, NULL, wi);
12187 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12188 wi->info = context;
12189 break;
12191 case GIMPLE_COND:
12193 gcond *cond_stmt = as_a <gcond *> (stmt);
12194 tree lab = gimple_cond_true_label (cond_stmt);
12195 if (lab)
12197 n = splay_tree_lookup (all_labels,
12198 (splay_tree_key) lab);
12199 diagnose_sb_0 (gsi_p, context,
12200 n ? (gimple) n->value : NULL);
12202 lab = gimple_cond_false_label (cond_stmt);
12203 if (lab)
12205 n = splay_tree_lookup (all_labels,
12206 (splay_tree_key) lab);
12207 diagnose_sb_0 (gsi_p, context,
12208 n ? (gimple) n->value : NULL);
12211 break;
12213 case GIMPLE_GOTO:
12215 tree lab = gimple_goto_dest (stmt);
12216 if (TREE_CODE (lab) != LABEL_DECL)
12217 break;
12219 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12220 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
12222 break;
12224 case GIMPLE_SWITCH:
12226 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12227 unsigned int i;
12228 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12230 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12231 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12232 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
12233 break;
12236 break;
12238 case GIMPLE_RETURN:
12239 diagnose_sb_0 (gsi_p, context, NULL);
12240 break;
12242 default:
12243 break;
12246 return NULL_TREE;
12249 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12250 GIMPLE_* codes. */
12251 bool
12252 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12253 int *region_idx)
12255 gimple last = last_stmt (bb);
12256 enum gimple_code code = gimple_code (last);
12257 struct omp_region *cur_region = *region;
12258 bool fallthru = false;
12260 switch (code)
12262 case GIMPLE_OMP_PARALLEL:
12263 case GIMPLE_OMP_TASK:
12264 case GIMPLE_OMP_FOR:
12265 case GIMPLE_OMP_SINGLE:
12266 case GIMPLE_OMP_TEAMS:
12267 case GIMPLE_OMP_MASTER:
12268 case GIMPLE_OMP_TASKGROUP:
12269 case GIMPLE_OMP_ORDERED:
12270 case GIMPLE_OMP_CRITICAL:
12271 case GIMPLE_OMP_SECTION:
12272 cur_region = new_omp_region (bb, code, cur_region);
12273 fallthru = true;
12274 break;
12276 case GIMPLE_OMP_TARGET:
12277 cur_region = new_omp_region (bb, code, cur_region);
12278 fallthru = true;
12279 switch (gimple_omp_target_kind (last))
12281 case GF_OMP_TARGET_KIND_REGION:
12282 case GF_OMP_TARGET_KIND_DATA:
12283 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12284 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12285 case GF_OMP_TARGET_KIND_OACC_DATA:
12286 break;
12287 case GF_OMP_TARGET_KIND_UPDATE:
12288 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12289 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12290 cur_region = cur_region->outer;
12291 break;
12292 default:
12293 gcc_unreachable ();
12295 break;
12297 case GIMPLE_OMP_SECTIONS:
12298 cur_region = new_omp_region (bb, code, cur_region);
12299 fallthru = true;
12300 break;
12302 case GIMPLE_OMP_SECTIONS_SWITCH:
12303 fallthru = false;
12304 break;
12306 case GIMPLE_OMP_ATOMIC_LOAD:
12307 case GIMPLE_OMP_ATOMIC_STORE:
12308 fallthru = true;
12309 break;
12311 case GIMPLE_OMP_RETURN:
12312 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12313 somewhere other than the next block. This will be
12314 created later. */
12315 cur_region->exit = bb;
12316 if (cur_region->type == GIMPLE_OMP_TASK)
12317 /* Add an edge corresponding to not scheduling the task
12318 immediately. */
12319 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
12320 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12321 cur_region = cur_region->outer;
12322 break;
12324 case GIMPLE_OMP_CONTINUE:
12325 cur_region->cont = bb;
12326 switch (cur_region->type)
12328 case GIMPLE_OMP_FOR:
12329 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12330 succs edges as abnormal to prevent splitting
12331 them. */
12332 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12333 /* Make the loopback edge. */
12334 make_edge (bb, single_succ (cur_region->entry),
12335 EDGE_ABNORMAL);
12337 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12338 corresponds to the case that the body of the loop
12339 is not executed at all. */
12340 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12341 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12342 fallthru = false;
12343 break;
12345 case GIMPLE_OMP_SECTIONS:
12346 /* Wire up the edges into and out of the nested sections. */
12348 basic_block switch_bb = single_succ (cur_region->entry);
12350 struct omp_region *i;
12351 for (i = cur_region->inner; i ; i = i->next)
12353 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12354 make_edge (switch_bb, i->entry, 0);
12355 make_edge (i->exit, bb, EDGE_FALLTHRU);
12358 /* Make the loopback edge to the block with
12359 GIMPLE_OMP_SECTIONS_SWITCH. */
12360 make_edge (bb, switch_bb, 0);
12362 /* Make the edge from the switch to exit. */
12363 make_edge (switch_bb, bb->next_bb, 0);
12364 fallthru = false;
12366 break;
12368 case GIMPLE_OMP_TASK:
12369 fallthru = true;
12370 break;
12372 default:
12373 gcc_unreachable ();
12375 break;
12377 default:
12378 gcc_unreachable ();
12381 if (*region != cur_region)
12383 *region = cur_region;
12384 if (cur_region)
12385 *region_idx = cur_region->entry->index;
12386 else
12387 *region_idx = 0;
12390 return fallthru;
12393 static unsigned int
12394 diagnose_omp_structured_block_errors (void)
12396 struct walk_stmt_info wi;
12397 gimple_seq body = gimple_body (current_function_decl);
12399 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12401 memset (&wi, 0, sizeof (wi));
12402 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12404 memset (&wi, 0, sizeof (wi));
12405 wi.want_locations = true;
12406 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12408 gimple_set_body (current_function_decl, body);
12410 splay_tree_delete (all_labels);
12411 all_labels = NULL;
12413 return 0;
12416 namespace {
12418 const pass_data pass_data_diagnose_omp_blocks =
12420 GIMPLE_PASS, /* type */
12421 "*diagnose_omp_blocks", /* name */
12422 OPTGROUP_NONE, /* optinfo_flags */
12423 TV_NONE, /* tv_id */
12424 PROP_gimple_any, /* properties_required */
12425 0, /* properties_provided */
12426 0, /* properties_destroyed */
12427 0, /* todo_flags_start */
12428 0, /* todo_flags_finish */
12431 class pass_diagnose_omp_blocks : public gimple_opt_pass
12433 public:
12434 pass_diagnose_omp_blocks (gcc::context *ctxt)
12435 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12438 /* opt_pass methods: */
12439 virtual bool gate (function *)
12441 return flag_cilkplus || flag_openacc || flag_openmp;
12443 virtual unsigned int execute (function *)
12445 return diagnose_omp_structured_block_errors ();
12448 }; // class pass_diagnose_omp_blocks
12450 } // anon namespace
12452 gimple_opt_pass *
12453 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12455 return new pass_diagnose_omp_blocks (ctxt);
12458 /* SIMD clone supporting code. */
12460 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12461 of arguments to reserve space for. */
12463 static struct cgraph_simd_clone *
12464 simd_clone_struct_alloc (int nargs)
12466 struct cgraph_simd_clone *clone_info;
12467 size_t len = (sizeof (struct cgraph_simd_clone)
12468 + nargs * sizeof (struct cgraph_simd_clone_arg));
12469 clone_info = (struct cgraph_simd_clone *)
12470 ggc_internal_cleared_alloc (len);
12471 return clone_info;
12474 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12476 static inline void
12477 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12478 struct cgraph_simd_clone *from)
12480 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12481 + ((from->nargs - from->inbranch)
12482 * sizeof (struct cgraph_simd_clone_arg))));
12485 /* Return vector of parameter types of function FNDECL. This uses
12486 TYPE_ARG_TYPES if available, otherwise falls back to types of
12487 DECL_ARGUMENTS types. */
12489 vec<tree>
12490 simd_clone_vector_of_formal_parm_types (tree fndecl)
12492 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12493 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12494 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12495 unsigned int i;
12496 tree arg;
12497 FOR_EACH_VEC_ELT (args, i, arg)
12498 args[i] = TREE_TYPE (args[i]);
12499 return args;
12502 /* Given a simd function in NODE, extract the simd specific
12503 information from the OMP clauses passed in CLAUSES, and return
12504 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12505 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12506 otherwise set to FALSE. */
12508 static struct cgraph_simd_clone *
12509 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12510 bool *inbranch_specified)
12512 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12513 tree t;
12514 int n;
12515 *inbranch_specified = false;
12517 n = args.length ();
12518 if (n > 0 && args.last () == void_type_node)
12519 n--;
12521 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12522 be cloned have a distinctive artificial label in addition to "omp
12523 declare simd". */
12524 bool cilk_clone
12525 = (flag_cilkplus
12526 && lookup_attribute ("cilk simd function",
12527 DECL_ATTRIBUTES (node->decl)));
12529 /* Allocate one more than needed just in case this is an in-branch
12530 clone which will require a mask argument. */
12531 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12532 clone_info->nargs = n;
12533 clone_info->cilk_elemental = cilk_clone;
12535 if (!clauses)
12537 args.release ();
12538 return clone_info;
12540 clauses = TREE_VALUE (clauses);
12541 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12542 return clone_info;
12544 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12546 switch (OMP_CLAUSE_CODE (t))
12548 case OMP_CLAUSE_INBRANCH:
12549 clone_info->inbranch = 1;
12550 *inbranch_specified = true;
12551 break;
12552 case OMP_CLAUSE_NOTINBRANCH:
12553 clone_info->inbranch = 0;
12554 *inbranch_specified = true;
12555 break;
12556 case OMP_CLAUSE_SIMDLEN:
12557 clone_info->simdlen
12558 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12559 break;
12560 case OMP_CLAUSE_LINEAR:
12562 tree decl = OMP_CLAUSE_DECL (t);
12563 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12564 int argno = TREE_INT_CST_LOW (decl);
12565 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12567 clone_info->args[argno].arg_type
12568 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12569 clone_info->args[argno].linear_step = tree_to_shwi (step);
12570 gcc_assert (clone_info->args[argno].linear_step >= 0
12571 && clone_info->args[argno].linear_step < n);
12573 else
12575 if (POINTER_TYPE_P (args[argno]))
12576 step = fold_convert (ssizetype, step);
12577 if (!tree_fits_shwi_p (step))
12579 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12580 "ignoring large linear step");
12581 args.release ();
12582 return NULL;
12584 else if (integer_zerop (step))
12586 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12587 "ignoring zero linear step");
12588 args.release ();
12589 return NULL;
12591 else
12593 clone_info->args[argno].arg_type
12594 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12595 clone_info->args[argno].linear_step = tree_to_shwi (step);
12598 break;
12600 case OMP_CLAUSE_UNIFORM:
12602 tree decl = OMP_CLAUSE_DECL (t);
12603 int argno = tree_to_uhwi (decl);
12604 clone_info->args[argno].arg_type
12605 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12606 break;
12608 case OMP_CLAUSE_ALIGNED:
12610 tree decl = OMP_CLAUSE_DECL (t);
12611 int argno = tree_to_uhwi (decl);
12612 clone_info->args[argno].alignment
12613 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12614 break;
12616 default:
12617 break;
12620 args.release ();
12621 return clone_info;
12624 /* Given a SIMD clone in NODE, calculate the characteristic data
12625 type and return the coresponding type. The characteristic data
12626 type is computed as described in the Intel Vector ABI. */
12628 static tree
12629 simd_clone_compute_base_data_type (struct cgraph_node *node,
12630 struct cgraph_simd_clone *clone_info)
12632 tree type = integer_type_node;
12633 tree fndecl = node->decl;
12635 /* a) For non-void function, the characteristic data type is the
12636 return type. */
12637 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12638 type = TREE_TYPE (TREE_TYPE (fndecl));
12640 /* b) If the function has any non-uniform, non-linear parameters,
12641 then the characteristic data type is the type of the first
12642 such parameter. */
12643 else
12645 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12646 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12647 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12649 type = map[i];
12650 break;
12652 map.release ();
12655 /* c) If the characteristic data type determined by a) or b) above
12656 is struct, union, or class type which is pass-by-value (except
12657 for the type that maps to the built-in complex data type), the
12658 characteristic data type is int. */
12659 if (RECORD_OR_UNION_TYPE_P (type)
12660 && !aggregate_value_p (type, NULL)
12661 && TREE_CODE (type) != COMPLEX_TYPE)
12662 return integer_type_node;
12664 /* d) If none of the above three classes is applicable, the
12665 characteristic data type is int. */
12667 return type;
12669 /* e) For Intel Xeon Phi native and offload compilation, if the
12670 resulting characteristic data type is 8-bit or 16-bit integer
12671 data type, the characteristic data type is int. */
12672 /* Well, we don't handle Xeon Phi yet. */
12675 static tree
12676 simd_clone_mangle (struct cgraph_node *node,
12677 struct cgraph_simd_clone *clone_info)
12679 char vecsize_mangle = clone_info->vecsize_mangle;
12680 char mask = clone_info->inbranch ? 'M' : 'N';
12681 unsigned int simdlen = clone_info->simdlen;
12682 unsigned int n;
12683 pretty_printer pp;
12685 gcc_assert (vecsize_mangle && simdlen);
12687 pp_string (&pp, "_ZGV");
12688 pp_character (&pp, vecsize_mangle);
12689 pp_character (&pp, mask);
12690 pp_decimal_int (&pp, simdlen);
12692 for (n = 0; n < clone_info->nargs; ++n)
12694 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12696 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12697 pp_character (&pp, 'u');
12698 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12700 gcc_assert (arg.linear_step != 0);
12701 pp_character (&pp, 'l');
12702 if (arg.linear_step > 1)
12703 pp_unsigned_wide_integer (&pp, arg.linear_step);
12704 else if (arg.linear_step < 0)
12706 pp_character (&pp, 'n');
12707 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12708 arg.linear_step));
12711 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12713 pp_character (&pp, 's');
12714 pp_unsigned_wide_integer (&pp, arg.linear_step);
12716 else
12717 pp_character (&pp, 'v');
12718 if (arg.alignment)
12720 pp_character (&pp, 'a');
12721 pp_decimal_int (&pp, arg.alignment);
12725 pp_underscore (&pp);
12726 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12727 if (*str == '*')
12728 ++str;
12729 pp_string (&pp, str);
12730 str = pp_formatted_text (&pp);
12732 /* If there already is a SIMD clone with the same mangled name, don't
12733 add another one. This can happen e.g. for
12734 #pragma omp declare simd
12735 #pragma omp declare simd simdlen(8)
12736 int foo (int, int);
12737 if the simdlen is assumed to be 8 for the first one, etc. */
12738 for (struct cgraph_node *clone = node->simd_clones; clone;
12739 clone = clone->simdclone->next_clone)
12740 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12741 str) == 0)
12742 return NULL_TREE;
12744 return get_identifier (str);
12747 /* Create a simd clone of OLD_NODE and return it. */
12749 static struct cgraph_node *
12750 simd_clone_create (struct cgraph_node *old_node)
12752 struct cgraph_node *new_node;
12753 if (old_node->definition)
12755 if (!old_node->has_gimple_body_p ())
12756 return NULL;
12757 old_node->get_body ();
12758 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12759 false, NULL, NULL,
12760 "simdclone");
12762 else
12764 tree old_decl = old_node->decl;
12765 tree new_decl = copy_node (old_node->decl);
12766 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12767 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12768 SET_DECL_RTL (new_decl, NULL);
12769 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12770 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
12771 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
12772 symtab->call_cgraph_insertion_hooks (new_node);
12774 if (new_node == NULL)
12775 return new_node;
12777 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12779 /* The function cgraph_function_versioning () will force the new
12780 symbol local. Undo this, and inherit external visability from
12781 the old node. */
12782 new_node->local.local = old_node->local.local;
12783 new_node->externally_visible = old_node->externally_visible;
12785 return new_node;
12788 /* Adjust the return type of the given function to its appropriate
12789 vector counterpart. Returns a simd array to be used throughout the
12790 function as a return value. */
12792 static tree
12793 simd_clone_adjust_return_type (struct cgraph_node *node)
12795 tree fndecl = node->decl;
12796 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12797 unsigned int veclen;
12798 tree t;
12800 /* Adjust the function return type. */
12801 if (orig_rettype == void_type_node)
12802 return NULL_TREE;
12803 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
12804 t = TREE_TYPE (TREE_TYPE (fndecl));
12805 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
12806 veclen = node->simdclone->vecsize_int;
12807 else
12808 veclen = node->simdclone->vecsize_float;
12809 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
12810 if (veclen > node->simdclone->simdlen)
12811 veclen = node->simdclone->simdlen;
12812 if (POINTER_TYPE_P (t))
12813 t = pointer_sized_int_node;
12814 if (veclen == node->simdclone->simdlen)
12815 t = build_vector_type (t, node->simdclone->simdlen);
12816 else
12818 t = build_vector_type (t, veclen);
12819 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
12821 TREE_TYPE (TREE_TYPE (fndecl)) = t;
12822 if (!node->definition)
12823 return NULL_TREE;
12825 t = DECL_RESULT (fndecl);
12826 /* Adjust the DECL_RESULT. */
12827 gcc_assert (TREE_TYPE (t) != void_type_node);
12828 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12829 relayout_decl (t);
12831 tree atype = build_array_type_nelts (orig_rettype,
12832 node->simdclone->simdlen);
12833 if (veclen != node->simdclone->simdlen)
12834 return build1 (VIEW_CONVERT_EXPR, atype, t);
12836 /* Set up a SIMD array to use as the return value. */
12837 tree retval = create_tmp_var_raw (atype, "retval");
12838 gimple_add_tmp_var (retval);
12839 return retval;
12842 /* Each vector argument has a corresponding array to be used locally
12843 as part of the eventual loop. Create such temporary array and
12844 return it.
12846 PREFIX is the prefix to be used for the temporary.
12848 TYPE is the inner element type.
12850 SIMDLEN is the number of elements. */
12852 static tree
12853 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12855 tree atype = build_array_type_nelts (type, simdlen);
12856 tree avar = create_tmp_var_raw (atype, prefix);
12857 gimple_add_tmp_var (avar);
12858 return avar;
12861 /* Modify the function argument types to their corresponding vector
12862 counterparts if appropriate. Also, create one array for each simd
12863 argument to be used locally when using the function arguments as
12864 part of the loop.
12866 NODE is the function whose arguments are to be adjusted.
12868 Returns an adjustment vector that will be filled describing how the
12869 argument types will be adjusted. */
12871 static ipa_parm_adjustment_vec
12872 simd_clone_adjust_argument_types (struct cgraph_node *node)
12874 vec<tree> args;
12875 ipa_parm_adjustment_vec adjustments;
12877 if (node->definition)
12878 args = ipa_get_vector_of_formal_parms (node->decl);
12879 else
12880 args = simd_clone_vector_of_formal_parm_types (node->decl);
12881 adjustments.create (args.length ());
12882 unsigned i, j, veclen;
12883 struct ipa_parm_adjustment adj;
12884 for (i = 0; i < node->simdclone->nargs; ++i)
12886 memset (&adj, 0, sizeof (adj));
12887 tree parm = args[i];
12888 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12889 adj.base_index = i;
12890 adj.base = parm;
12892 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12893 node->simdclone->args[i].orig_type = parm_type;
12895 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12897 /* No adjustment necessary for scalar arguments. */
12898 adj.op = IPA_PARM_OP_COPY;
12900 else
12902 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12903 veclen = node->simdclone->vecsize_int;
12904 else
12905 veclen = node->simdclone->vecsize_float;
12906 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12907 if (veclen > node->simdclone->simdlen)
12908 veclen = node->simdclone->simdlen;
12909 adj.arg_prefix = "simd";
12910 if (POINTER_TYPE_P (parm_type))
12911 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12912 else
12913 adj.type = build_vector_type (parm_type, veclen);
12914 node->simdclone->args[i].vector_type = adj.type;
12915 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12917 adjustments.safe_push (adj);
12918 if (j == veclen)
12920 memset (&adj, 0, sizeof (adj));
12921 adj.op = IPA_PARM_OP_NEW;
12922 adj.arg_prefix = "simd";
12923 adj.base_index = i;
12924 adj.type = node->simdclone->args[i].vector_type;
12928 if (node->definition)
12929 node->simdclone->args[i].simd_array
12930 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12931 parm_type, node->simdclone->simdlen);
12933 adjustments.safe_push (adj);
12936 if (node->simdclone->inbranch)
12938 tree base_type
12939 = simd_clone_compute_base_data_type (node->simdclone->origin,
12940 node->simdclone);
12942 memset (&adj, 0, sizeof (adj));
12943 adj.op = IPA_PARM_OP_NEW;
12944 adj.arg_prefix = "mask";
12946 adj.base_index = i;
12947 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12948 veclen = node->simdclone->vecsize_int;
12949 else
12950 veclen = node->simdclone->vecsize_float;
12951 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12952 if (veclen > node->simdclone->simdlen)
12953 veclen = node->simdclone->simdlen;
12954 if (POINTER_TYPE_P (base_type))
12955 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12956 else
12957 adj.type = build_vector_type (base_type, veclen);
12958 adjustments.safe_push (adj);
12960 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12961 adjustments.safe_push (adj);
12963 /* We have previously allocated one extra entry for the mask. Use
12964 it and fill it. */
12965 struct cgraph_simd_clone *sc = node->simdclone;
12966 sc->nargs++;
12967 if (node->definition)
12969 sc->args[i].orig_arg
12970 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12971 sc->args[i].simd_array
12972 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12974 sc->args[i].orig_type = base_type;
12975 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12978 if (node->definition)
12979 ipa_modify_formal_parameters (node->decl, adjustments);
12980 else
12982 tree new_arg_types = NULL_TREE, new_reversed;
12983 bool last_parm_void = false;
12984 if (args.length () > 0 && args.last () == void_type_node)
12985 last_parm_void = true;
12987 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12988 j = adjustments.length ();
12989 for (i = 0; i < j; i++)
12991 struct ipa_parm_adjustment *adj = &adjustments[i];
12992 tree ptype;
12993 if (adj->op == IPA_PARM_OP_COPY)
12994 ptype = args[adj->base_index];
12995 else
12996 ptype = adj->type;
12997 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12999 new_reversed = nreverse (new_arg_types);
13000 if (last_parm_void)
13002 if (new_reversed)
13003 TREE_CHAIN (new_arg_types) = void_list_node;
13004 else
13005 new_reversed = void_list_node;
13008 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
13009 TYPE_ARG_TYPES (new_type) = new_reversed;
13010 TREE_TYPE (node->decl) = new_type;
13012 adjustments.release ();
13014 args.release ();
13015 return adjustments;
13018 /* Initialize and copy the function arguments in NODE to their
13019 corresponding local simd arrays. Returns a fresh gimple_seq with
13020 the instruction sequence generated. */
13022 static gimple_seq
13023 simd_clone_init_simd_arrays (struct cgraph_node *node,
13024 ipa_parm_adjustment_vec adjustments)
13026 gimple_seq seq = NULL;
13027 unsigned i = 0, j = 0, k;
13029 for (tree arg = DECL_ARGUMENTS (node->decl);
13030 arg;
13031 arg = DECL_CHAIN (arg), i++, j++)
13033 if (adjustments[j].op == IPA_PARM_OP_COPY)
13034 continue;
13036 node->simdclone->args[i].vector_arg = arg;
13038 tree array = node->simdclone->args[i].simd_array;
13039 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13041 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13042 tree ptr = build_fold_addr_expr (array);
13043 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13044 build_int_cst (ptype, 0));
13045 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13046 gimplify_and_add (t, &seq);
13048 else
13050 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13051 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13052 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13054 tree ptr = build_fold_addr_expr (array);
13055 int elemsize;
13056 if (k)
13058 arg = DECL_CHAIN (arg);
13059 j++;
13061 elemsize
13062 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13063 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13064 build_int_cst (ptype, k * elemsize));
13065 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13066 gimplify_and_add (t, &seq);
13070 return seq;
13073 /* Callback info for ipa_simd_modify_stmt_ops below. */
13075 struct modify_stmt_info {
13076 ipa_parm_adjustment_vec adjustments;
13077 gimple stmt;
13078 /* True if the parent statement was modified by
13079 ipa_simd_modify_stmt_ops. */
13080 bool modified;
13083 /* Callback for walk_gimple_op.
13085 Adjust operands from a given statement as specified in the
13086 adjustments vector in the callback data. */
13088 static tree
13089 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13091 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13092 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13093 tree *orig_tp = tp;
13094 if (TREE_CODE (*tp) == ADDR_EXPR)
13095 tp = &TREE_OPERAND (*tp, 0);
13096 struct ipa_parm_adjustment *cand = NULL;
13097 if (TREE_CODE (*tp) == PARM_DECL)
13098 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13099 else
13101 if (TYPE_P (*tp))
13102 *walk_subtrees = 0;
13105 tree repl = NULL_TREE;
13106 if (cand)
13107 repl = unshare_expr (cand->new_decl);
13108 else
13110 if (tp != orig_tp)
13112 *walk_subtrees = 0;
13113 bool modified = info->modified;
13114 info->modified = false;
13115 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13116 if (!info->modified)
13118 info->modified = modified;
13119 return NULL_TREE;
13121 info->modified = modified;
13122 repl = *tp;
13124 else
13125 return NULL_TREE;
13128 if (tp != orig_tp)
13130 repl = build_fold_addr_expr (repl);
13131 gimple stmt;
13132 if (is_gimple_debug (info->stmt))
13134 tree vexpr = make_node (DEBUG_EXPR_DECL);
13135 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13136 DECL_ARTIFICIAL (vexpr) = 1;
13137 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13138 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13139 repl = vexpr;
13141 else
13143 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13144 repl = gimple_assign_lhs (stmt);
13146 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13147 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13148 *orig_tp = repl;
13150 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13152 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13153 *tp = vce;
13155 else
13156 *tp = repl;
13158 info->modified = true;
13159 return NULL_TREE;
13162 /* Traverse the function body and perform all modifications as
13163 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13164 modified such that the replacement/reduction value will now be an
13165 offset into the corresponding simd_array.
13167 This function will replace all function argument uses with their
13168 corresponding simd array elements, and ajust the return values
13169 accordingly. */
13171 static void
13172 ipa_simd_modify_function_body (struct cgraph_node *node,
13173 ipa_parm_adjustment_vec adjustments,
13174 tree retval_array, tree iter)
13176 basic_block bb;
13177 unsigned int i, j, l;
13179 /* Re-use the adjustments array, but this time use it to replace
13180 every function argument use to an offset into the corresponding
13181 simd_array. */
13182 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13184 if (!node->simdclone->args[i].vector_arg)
13185 continue;
13187 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13188 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13189 adjustments[j].new_decl
13190 = build4 (ARRAY_REF,
13191 basetype,
13192 node->simdclone->args[i].simd_array,
13193 iter,
13194 NULL_TREE, NULL_TREE);
13195 if (adjustments[j].op == IPA_PARM_OP_NONE
13196 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13197 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13200 l = adjustments.length ();
13201 for (i = 1; i < num_ssa_names; i++)
13203 tree name = ssa_name (i);
13204 if (name
13205 && SSA_NAME_VAR (name)
13206 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13208 for (j = 0; j < l; j++)
13209 if (SSA_NAME_VAR (name) == adjustments[j].base
13210 && adjustments[j].new_decl)
13212 tree base_var;
13213 if (adjustments[j].new_ssa_base == NULL_TREE)
13215 base_var
13216 = copy_var_decl (adjustments[j].base,
13217 DECL_NAME (adjustments[j].base),
13218 TREE_TYPE (adjustments[j].base));
13219 adjustments[j].new_ssa_base = base_var;
13221 else
13222 base_var = adjustments[j].new_ssa_base;
13223 if (SSA_NAME_IS_DEFAULT_DEF (name))
13225 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13226 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13227 tree new_decl = unshare_expr (adjustments[j].new_decl);
13228 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13229 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13230 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13231 gimple stmt = gimple_build_assign (name, new_decl);
13232 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13234 else
13235 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13240 struct modify_stmt_info info;
13241 info.adjustments = adjustments;
13243 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13245 gimple_stmt_iterator gsi;
13247 gsi = gsi_start_bb (bb);
13248 while (!gsi_end_p (gsi))
13250 gimple stmt = gsi_stmt (gsi);
13251 info.stmt = stmt;
13252 struct walk_stmt_info wi;
13254 memset (&wi, 0, sizeof (wi));
13255 info.modified = false;
13256 wi.info = &info;
13257 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13259 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13261 tree retval = gimple_return_retval (return_stmt);
13262 if (!retval)
13264 gsi_remove (&gsi, true);
13265 continue;
13268 /* Replace `return foo' with `retval_array[iter] = foo'. */
13269 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13270 retval_array, iter, NULL, NULL);
13271 stmt = gimple_build_assign (ref, retval);
13272 gsi_replace (&gsi, stmt, true);
13273 info.modified = true;
13276 if (info.modified)
13278 update_stmt (stmt);
13279 if (maybe_clean_eh_stmt (stmt))
13280 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13282 gsi_next (&gsi);
13287 /* Adjust the argument types in NODE to their appropriate vector
13288 counterparts. */
13290 static void
13291 simd_clone_adjust (struct cgraph_node *node)
13293 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13295 targetm.simd_clone.adjust (node);
13297 tree retval = simd_clone_adjust_return_type (node);
13298 ipa_parm_adjustment_vec adjustments
13299 = simd_clone_adjust_argument_types (node);
13301 push_gimplify_context ();
13303 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13305 /* Adjust all uses of vector arguments accordingly. Adjust all
13306 return values accordingly. */
13307 tree iter = create_tmp_var (unsigned_type_node, "iter");
13308 tree iter1 = make_ssa_name (iter);
13309 tree iter2 = make_ssa_name (iter);
13310 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13312 /* Initialize the iteration variable. */
13313 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13314 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13315 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13316 /* Insert the SIMD array and iv initialization at function
13317 entry. */
13318 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13320 pop_gimplify_context (NULL);
13322 /* Create a new BB right before the original exit BB, to hold the
13323 iteration increment and the condition/branch. */
13324 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13325 basic_block incr_bb = create_empty_bb (orig_exit);
13326 add_bb_to_loop (incr_bb, body_bb->loop_father);
13327 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13328 flag. Set it now to be a FALLTHRU_EDGE. */
13329 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13330 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13331 for (unsigned i = 0;
13332 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13334 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13335 redirect_edge_succ (e, incr_bb);
13337 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13338 e->probability = REG_BR_PROB_BASE;
13339 gsi = gsi_last_bb (incr_bb);
13340 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13341 build_int_cst (unsigned_type_node, 1));
13342 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13344 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13345 struct loop *loop = alloc_loop ();
13346 cfun->has_force_vectorize_loops = true;
13347 loop->safelen = node->simdclone->simdlen;
13348 loop->force_vectorize = true;
13349 loop->header = body_bb;
13351 /* Branch around the body if the mask applies. */
13352 if (node->simdclone->inbranch)
13354 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13355 tree mask_array
13356 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13357 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13358 tree aref = build4 (ARRAY_REF,
13359 TREE_TYPE (TREE_TYPE (mask_array)),
13360 mask_array, iter1,
13361 NULL, NULL);
13362 g = gimple_build_assign (mask, aref);
13363 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13364 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13365 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13367 aref = build1 (VIEW_CONVERT_EXPR,
13368 build_nonstandard_integer_type (bitsize, 0), mask);
13369 mask = make_ssa_name (TREE_TYPE (aref));
13370 g = gimple_build_assign (mask, aref);
13371 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13374 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13375 NULL, NULL);
13376 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13377 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13378 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13381 /* Generate the condition. */
13382 g = gimple_build_cond (LT_EXPR,
13383 iter2,
13384 build_int_cst (unsigned_type_node,
13385 node->simdclone->simdlen),
13386 NULL, NULL);
13387 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13388 e = split_block (incr_bb, gsi_stmt (gsi));
13389 basic_block latch_bb = e->dest;
13390 basic_block new_exit_bb;
13391 new_exit_bb = split_block_after_labels (latch_bb)->dest;
13392 loop->latch = latch_bb;
13394 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13396 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13397 /* The successor of incr_bb is already pointing to latch_bb; just
13398 change the flags.
13399 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13400 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13402 gphi *phi = create_phi_node (iter1, body_bb);
13403 edge preheader_edge = find_edge (entry_bb, body_bb);
13404 edge latch_edge = single_succ_edge (latch_bb);
13405 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13406 UNKNOWN_LOCATION);
13407 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13409 /* Generate the new return. */
13410 gsi = gsi_last_bb (new_exit_bb);
13411 if (retval
13412 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13413 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13414 retval = TREE_OPERAND (retval, 0);
13415 else if (retval)
13417 retval = build1 (VIEW_CONVERT_EXPR,
13418 TREE_TYPE (TREE_TYPE (node->decl)),
13419 retval);
13420 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13421 false, GSI_CONTINUE_LINKING);
13423 g = gimple_build_return (retval);
13424 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13426 /* Handle aligned clauses by replacing default defs of the aligned
13427 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13428 lhs. Handle linear by adding PHIs. */
13429 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13430 if (node->simdclone->args[i].alignment
13431 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13432 && (node->simdclone->args[i].alignment
13433 & (node->simdclone->args[i].alignment - 1)) == 0
13434 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13435 == POINTER_TYPE)
13437 unsigned int alignment = node->simdclone->args[i].alignment;
13438 tree orig_arg = node->simdclone->args[i].orig_arg;
13439 tree def = ssa_default_def (cfun, orig_arg);
13440 if (def && !has_zero_uses (def))
13442 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13443 gimple_seq seq = NULL;
13444 bool need_cvt = false;
13445 gcall *call
13446 = gimple_build_call (fn, 2, def, size_int (alignment));
13447 g = call;
13448 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13449 ptr_type_node))
13450 need_cvt = true;
13451 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13452 gimple_call_set_lhs (g, t);
13453 gimple_seq_add_stmt_without_update (&seq, g);
13454 if (need_cvt)
13456 t = make_ssa_name (orig_arg);
13457 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13458 gimple_seq_add_stmt_without_update (&seq, g);
13460 gsi_insert_seq_on_edge_immediate
13461 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13463 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13464 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13465 entry_bb);
13466 node->create_edge (cgraph_node::get_create (fn),
13467 call, entry_bb->count, freq);
13469 imm_use_iterator iter;
13470 use_operand_p use_p;
13471 gimple use_stmt;
13472 tree repl = gimple_get_lhs (g);
13473 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13474 if (is_gimple_debug (use_stmt) || use_stmt == call)
13475 continue;
13476 else
13477 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13478 SET_USE (use_p, repl);
13481 else if (node->simdclone->args[i].arg_type
13482 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13484 tree orig_arg = node->simdclone->args[i].orig_arg;
13485 tree def = ssa_default_def (cfun, orig_arg);
13486 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13487 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13488 if (def && !has_zero_uses (def))
13490 iter1 = make_ssa_name (orig_arg);
13491 iter2 = make_ssa_name (orig_arg);
13492 phi = create_phi_node (iter1, body_bb);
13493 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13494 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13495 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13496 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13497 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13498 ? TREE_TYPE (orig_arg) : sizetype;
13499 tree addcst
13500 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13501 g = gimple_build_assign (iter2, code, iter1, addcst);
13502 gsi = gsi_last_bb (incr_bb);
13503 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13505 imm_use_iterator iter;
13506 use_operand_p use_p;
13507 gimple use_stmt;
13508 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13509 if (use_stmt == phi)
13510 continue;
13511 else
13512 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13513 SET_USE (use_p, iter1);
13517 calculate_dominance_info (CDI_DOMINATORS);
13518 add_loop (loop, loop->header->loop_father);
13519 update_ssa (TODO_update_ssa);
13521 pop_cfun ();
13524 /* If the function in NODE is tagged as an elemental SIMD function,
13525 create the appropriate SIMD clones. */
13527 static void
13528 expand_simd_clones (struct cgraph_node *node)
13530 tree attr = lookup_attribute ("omp declare simd",
13531 DECL_ATTRIBUTES (node->decl));
13532 if (attr == NULL_TREE
13533 || node->global.inlined_to
13534 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13535 return;
13537 /* Ignore
13538 #pragma omp declare simd
13539 extern int foo ();
13540 in C, there we don't know the argument types at all. */
13541 if (!node->definition
13542 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13543 return;
13547 /* Start with parsing the "omp declare simd" attribute(s). */
13548 bool inbranch_clause_specified;
13549 struct cgraph_simd_clone *clone_info
13550 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13551 &inbranch_clause_specified);
13552 if (clone_info == NULL)
13553 continue;
13555 int orig_simdlen = clone_info->simdlen;
13556 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13557 /* The target can return 0 (no simd clones should be created),
13558 1 (just one ISA of simd clones should be created) or higher
13559 count of ISA variants. In that case, clone_info is initialized
13560 for the first ISA variant. */
13561 int count
13562 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13563 base_type, 0);
13564 if (count == 0)
13565 continue;
13567 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13568 also create one inbranch and one !inbranch clone of it. */
13569 for (int i = 0; i < count * 2; i++)
13571 struct cgraph_simd_clone *clone = clone_info;
13572 if (inbranch_clause_specified && (i & 1) != 0)
13573 continue;
13575 if (i != 0)
13577 clone = simd_clone_struct_alloc (clone_info->nargs
13578 + ((i & 1) != 0));
13579 simd_clone_struct_copy (clone, clone_info);
13580 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13581 and simd_clone_adjust_argument_types did to the first
13582 clone's info. */
13583 clone->nargs -= clone_info->inbranch;
13584 clone->simdlen = orig_simdlen;
13585 /* And call the target hook again to get the right ISA. */
13586 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13587 base_type,
13588 i / 2);
13589 if ((i & 1) != 0)
13590 clone->inbranch = 1;
13593 /* simd_clone_mangle might fail if such a clone has been created
13594 already. */
13595 tree id = simd_clone_mangle (node, clone);
13596 if (id == NULL_TREE)
13597 continue;
13599 /* Only when we are sure we want to create the clone actually
13600 clone the function (or definitions) or create another
13601 extern FUNCTION_DECL (for prototypes without definitions). */
13602 struct cgraph_node *n = simd_clone_create (node);
13603 if (n == NULL)
13604 continue;
13606 n->simdclone = clone;
13607 clone->origin = node;
13608 clone->next_clone = NULL;
13609 if (node->simd_clones == NULL)
13611 clone->prev_clone = n;
13612 node->simd_clones = n;
13614 else
13616 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13617 clone->prev_clone->simdclone->next_clone = n;
13618 node->simd_clones->simdclone->prev_clone = n;
13620 symtab->change_decl_assembler_name (n->decl, id);
13621 /* And finally adjust the return type, parameters and for
13622 definitions also function body. */
13623 if (node->definition)
13624 simd_clone_adjust (n);
13625 else
13627 simd_clone_adjust_return_type (n);
13628 simd_clone_adjust_argument_types (n);
13632 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13635 /* Entry point for IPA simd clone creation pass. */
13637 static unsigned int
13638 ipa_omp_simd_clone (void)
13640 struct cgraph_node *node;
13641 FOR_EACH_FUNCTION (node)
13642 expand_simd_clones (node);
13643 return 0;
13646 namespace {
13648 const pass_data pass_data_omp_simd_clone =
13650 SIMPLE_IPA_PASS, /* type */
13651 "simdclone", /* name */
13652 OPTGROUP_NONE, /* optinfo_flags */
13653 TV_NONE, /* tv_id */
13654 ( PROP_ssa | PROP_cfg ), /* properties_required */
13655 0, /* properties_provided */
13656 0, /* properties_destroyed */
13657 0, /* todo_flags_start */
13658 0, /* todo_flags_finish */
13661 class pass_omp_simd_clone : public simple_ipa_opt_pass
13663 public:
13664 pass_omp_simd_clone(gcc::context *ctxt)
13665 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13668 /* opt_pass methods: */
13669 virtual bool gate (function *);
13670 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
13673 bool
13674 pass_omp_simd_clone::gate (function *)
13676 return ((flag_openmp || flag_openmp_simd
13677 || flag_cilkplus
13678 || (in_lto_p && !flag_wpa))
13679 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13682 } // anon namespace
13684 simple_ipa_opt_pass *
13685 make_pass_omp_simd_clone (gcc::context *ctxt)
13687 return new pass_omp_simd_clone (ctxt);
13690 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13691 adds their addresses and sizes to constructor-vector V_CTOR. */
13692 static void
13693 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13694 vec<constructor_elt, va_gc> *v_ctor)
13696 unsigned len = vec_safe_length (v_decls);
13697 for (unsigned i = 0; i < len; i++)
13699 tree it = (*v_decls)[i];
13700 bool is_function = TREE_CODE (it) != VAR_DECL;
13702 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13703 if (!is_function)
13704 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13705 fold_convert (const_ptr_type_node,
13706 DECL_SIZE_UNIT (it)));
13710 /* Create new symbols containing (address, size) pairs for global variables,
13711 marked with "omp declare target" attribute, as well as addresses for the
13712 functions, which are outlined offloading regions. */
13713 void
13714 omp_finish_file (void)
13716 unsigned num_funcs = vec_safe_length (offload_funcs);
13717 unsigned num_vars = vec_safe_length (offload_vars);
13719 if (num_funcs == 0 && num_vars == 0)
13720 return;
13722 if (targetm_common.have_named_sections)
13724 vec<constructor_elt, va_gc> *v_f, *v_v;
13725 vec_alloc (v_f, num_funcs);
13726 vec_alloc (v_v, num_vars * 2);
13728 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13729 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13731 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13732 num_vars * 2);
13733 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13734 num_funcs);
13735 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13736 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13737 tree ctor_v = build_constructor (vars_decl_type, v_v);
13738 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13739 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13740 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13741 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13742 get_identifier (".offload_func_table"),
13743 funcs_decl_type);
13744 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13745 get_identifier (".offload_var_table"),
13746 vars_decl_type);
13747 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13748 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13749 otherwise a joint table in a binary will contain padding between
13750 tables from multiple object files. */
13751 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13752 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13753 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13754 DECL_INITIAL (funcs_decl) = ctor_f;
13755 DECL_INITIAL (vars_decl) = ctor_v;
13756 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13757 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13759 varpool_node::finalize_decl (vars_decl);
13760 varpool_node::finalize_decl (funcs_decl);
13762 else
13764 for (unsigned i = 0; i < num_funcs; i++)
13766 tree it = (*offload_funcs)[i];
13767 targetm.record_offload_symbol (it);
13769 for (unsigned i = 0; i < num_vars; i++)
13771 tree it = (*offload_vars)[i];
13772 targetm.record_offload_symbol (it);
13777 #include "gt-omp-low.h"