Add C++11 header <cuchar>.
[official-gcc.git] / gcc / omp-low.c
blob88a5149250b49cb908817063ced7b8c0e59b8ab9
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 "backend.h"
29 #include "cfghooks.h"
30 #include "tree.h"
31 #include "gimple.h"
32 #include "rtl.h"
33 #include "ssa.h"
34 #include "alias.h"
35 #include "fold-const.h"
36 #include "stor-layout.h"
37 #include "cfganal.h"
38 #include "internal-fn.h"
39 #include "gimple-fold.h"
40 #include "gimplify.h"
41 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
43 #include "gimple-walk.h"
44 #include "tree-iterator.h"
45 #include "tree-inline.h"
46 #include "langhooks.h"
47 #include "diagnostic-core.h"
48 #include "cgraph.h"
49 #include "tree-cfg.h"
50 #include "tree-into-ssa.h"
51 #include "flags.h"
52 #include "insn-config.h"
53 #include "expmed.h"
54 #include "dojump.h"
55 #include "explow.h"
56 #include "calls.h"
57 #include "emit-rtl.h"
58 #include "varasm.h"
59 #include "stmt.h"
60 #include "expr.h"
61 #include "tree-dfa.h"
62 #include "tree-ssa.h"
63 #include "tree-pass.h"
64 #include "except.h"
65 #include "splay-tree.h"
66 #include "insn-codes.h"
67 #include "optabs.h"
68 #include "cfgloop.h"
69 #include "target.h"
70 #include "common/common-target.h"
71 #include "omp-low.h"
72 #include "gimple-low.h"
73 #include "tree-cfgcleanup.h"
74 #include "pretty-print.h"
75 #include "alloc-pool.h"
76 #include "symbol-summary.h"
77 #include "ipa-prop.h"
78 #include "tree-nested.h"
79 #include "tree-eh.h"
80 #include "cilk.h"
81 #include "context.h"
82 #include "lto-section-names.h"
83 #include "gomp-constants.h"
86 /* Lowering of OMP parallel and workshare constructs proceeds in two
87 phases. The first phase scans the function looking for OMP statements
88 and then for variables that must be replaced to satisfy data sharing
89 clauses. The second phase expands code for the constructs, as well as
90 re-gimplifying things when variables have been replaced with complex
91 expressions.
93 Final code generation is done by pass_expand_omp. The flowgraph is
94 scanned for regions which are then moved to a new
95 function, to be invoked by the thread library, or offloaded. */
97 /* OMP region information. Every parallel and workshare
98 directive is enclosed between two markers, the OMP_* directive
99 and a corresponding OMP_RETURN statement. */
101 struct omp_region
103 /* The enclosing region. */
104 struct omp_region *outer;
106 /* First child region. */
107 struct omp_region *inner;
109 /* Next peer region. */
110 struct omp_region *next;
112 /* Block containing the omp directive as its last stmt. */
113 basic_block entry;
115 /* Block containing the OMP_RETURN as its last stmt. */
116 basic_block exit;
118 /* Block containing the OMP_CONTINUE as its last stmt. */
119 basic_block cont;
121 /* If this is a combined parallel+workshare region, this is a list
122 of additional arguments needed by the combined parallel+workshare
123 library call. */
124 vec<tree, va_gc> *ws_args;
126 /* The code for the omp directive of this region. */
127 enum gimple_code type;
129 /* Schedule kind, only used for OMP_FOR type regions. */
130 enum omp_clause_schedule_kind sched_kind;
132 /* True if this is a combined parallel+workshare region. */
133 bool is_combined_parallel;
136 /* Levels of parallelism as defined by OpenACC. Increasing numbers
137 correspond to deeper loop nesting levels. */
138 #define MASK_GANG 1
139 #define MASK_WORKER 2
140 #define MASK_VECTOR 4
142 /* Context structure. Used to store information about each parallel
143 directive in the code. */
145 struct omp_context
147 /* This field must be at the beginning, as we do "inheritance": Some
148 callback functions for tree-inline.c (e.g., omp_copy_decl)
149 receive a copy_body_data pointer that is up-casted to an
150 omp_context pointer. */
151 copy_body_data cb;
153 /* The tree of contexts corresponding to the encountered constructs. */
154 struct omp_context *outer;
155 gimple stmt;
157 /* Map variables to fields in a structure that allows communication
158 between sending and receiving threads. */
159 splay_tree field_map;
160 tree record_type;
161 tree sender_decl;
162 tree receiver_decl;
164 /* These are used just by task contexts, if task firstprivate fn is
165 needed. srecord_type is used to communicate from the thread
166 that encountered the task construct to task firstprivate fn,
167 record_type is allocated by GOMP_task, initialized by task firstprivate
168 fn and passed to the task body fn. */
169 splay_tree sfield_map;
170 tree srecord_type;
172 /* A chain of variables to add to the top-level block surrounding the
173 construct. In the case of a parallel, this is in the child function. */
174 tree block_vars;
176 /* A map of reduction pointer variables. For accelerators, each
177 reduction variable is replaced with an array. Each thread, in turn,
178 is assigned to a slot on that array. */
179 splay_tree reduction_map;
181 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
182 barriers should jump to during omplower pass. */
183 tree cancel_label;
185 /* What to do with variables with implicitly determined sharing
186 attributes. */
187 enum omp_clause_default_kind default_kind;
189 /* Nesting depth of this context. Used to beautify error messages re
190 invalid gotos. The outermost ctx is depth 1, with depth 0 being
191 reserved for the main body of the function. */
192 int depth;
194 /* True if this parallel directive is nested within another. */
195 bool is_nested;
197 /* True if this construct can be cancelled. */
198 bool cancellable;
200 /* For OpenACC loops, a mask of gang, worker and vector used at
201 levels below this one. */
202 int gwv_below;
203 /* For OpenACC loops, a mask of gang, worker and vector used at
204 this level and above. For parallel and kernels clauses, a mask
205 indicating which of num_gangs/num_workers/num_vectors was used. */
206 int gwv_this;
209 /* A structure holding the elements of:
210 for (V = N1; V cond N2; V += STEP) [...] */
212 struct omp_for_data_loop
214 tree v, n1, n2, step;
215 enum tree_code cond_code;
218 /* A structure describing the main elements of a parallel loop. */
220 struct omp_for_data
222 struct omp_for_data_loop loop;
223 tree chunk_size;
224 gomp_for *for_stmt;
225 tree pre, iter_type;
226 int collapse;
227 bool have_nowait, have_ordered;
228 enum omp_clause_schedule_kind sched_kind;
229 struct omp_for_data_loop *loops;
233 static splay_tree all_contexts;
234 static int taskreg_nesting_level;
235 static int target_nesting_level;
236 static struct omp_region *root_omp_region;
237 static bitmap task_shared_vars;
238 static vec<omp_context *> taskreg_contexts;
240 static void scan_omp (gimple_seq *, omp_context *);
241 static tree scan_omp_1_op (tree *, int *, void *);
243 #define WALK_SUBSTMTS \
244 case GIMPLE_BIND: \
245 case GIMPLE_TRY: \
246 case GIMPLE_CATCH: \
247 case GIMPLE_EH_FILTER: \
248 case GIMPLE_TRANSACTION: \
249 /* The sub-statements for these should be walked. */ \
250 *handled_ops_p = false; \
251 break;
253 /* Helper function to get the name of the array containing the partial
254 reductions for OpenACC reductions. */
255 static const char *
256 oacc_get_reduction_array_id (tree node)
258 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
259 int len = strlen ("OACC") + strlen (id);
260 char *temp_name = XALLOCAVEC (char, len + 1);
261 snprintf (temp_name, len + 1, "OACC%s", id);
262 return IDENTIFIER_POINTER (get_identifier (temp_name));
265 /* Determine the number of threads OpenACC threads used to determine the
266 size of the array of partial reductions. Currently, this is num_gangs
267 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
268 because it is independed of the device used. */
270 static tree
271 oacc_max_threads (omp_context *ctx)
273 tree nthreads, vector_length, gangs, clauses;
275 gangs = fold_convert (sizetype, integer_one_node);
276 vector_length = gangs;
278 /* The reduction clause may be nested inside a loop directive.
279 Scan for the innermost vector_length clause. */
280 for (omp_context *oc = ctx; oc; oc = oc->outer)
282 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
283 || (gimple_omp_target_kind (oc->stmt)
284 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
285 continue;
287 clauses = gimple_omp_target_clauses (oc->stmt);
289 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
290 if (vector_length)
291 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
292 sizetype,
293 OMP_CLAUSE_VECTOR_LENGTH_EXPR
294 (vector_length));
295 else
296 vector_length = fold_convert (sizetype, integer_one_node);
298 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
299 if (gangs)
300 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
301 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
302 else
303 gangs = fold_convert (sizetype, integer_one_node);
305 break;
308 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
310 return nthreads;
313 /* Holds offload tables with decls. */
314 vec<tree, va_gc> *offload_funcs, *offload_vars;
316 /* Convenience function for calling scan_omp_1_op on tree operands. */
318 static inline tree
319 scan_omp_op (tree *tp, omp_context *ctx)
321 struct walk_stmt_info wi;
323 memset (&wi, 0, sizeof (wi));
324 wi.info = ctx;
325 wi.want_locations = true;
327 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
330 static void lower_omp (gimple_seq *, omp_context *);
331 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
332 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
334 /* Find an OMP clause of type KIND within CLAUSES. */
336 tree
337 find_omp_clause (tree clauses, enum omp_clause_code kind)
339 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
340 if (OMP_CLAUSE_CODE (clauses) == kind)
341 return clauses;
343 return NULL_TREE;
346 /* Return true if CTX is for an omp parallel. */
348 static inline bool
349 is_parallel_ctx (omp_context *ctx)
351 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
355 /* Return true if CTX is for an omp task. */
357 static inline bool
358 is_task_ctx (omp_context *ctx)
360 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
364 /* Return true if CTX is for an omp parallel or omp task. */
366 static inline bool
367 is_taskreg_ctx (omp_context *ctx)
369 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
370 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
374 /* Return true if REGION is a combined parallel+workshare region. */
376 static inline bool
377 is_combined_parallel (struct omp_region *region)
379 return region->is_combined_parallel;
383 /* Extract the header elements of parallel loop FOR_STMT and store
384 them into *FD. */
386 static void
387 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
388 struct omp_for_data_loop *loops)
390 tree t, var, *collapse_iter, *collapse_count;
391 tree count = NULL_TREE, iter_type = long_integer_type_node;
392 struct omp_for_data_loop *loop;
393 int i;
394 struct omp_for_data_loop dummy_loop;
395 location_t loc = gimple_location (for_stmt);
396 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
397 bool distribute = gimple_omp_for_kind (for_stmt)
398 == GF_OMP_FOR_KIND_DISTRIBUTE;
400 fd->for_stmt = for_stmt;
401 fd->pre = NULL;
402 fd->collapse = gimple_omp_for_collapse (for_stmt);
403 if (fd->collapse > 1)
404 fd->loops = loops;
405 else
406 fd->loops = &fd->loop;
408 fd->have_nowait = distribute || simd;
409 fd->have_ordered = false;
410 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
411 fd->chunk_size = NULL_TREE;
412 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
413 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
414 collapse_iter = NULL;
415 collapse_count = NULL;
417 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
418 switch (OMP_CLAUSE_CODE (t))
420 case OMP_CLAUSE_NOWAIT:
421 fd->have_nowait = true;
422 break;
423 case OMP_CLAUSE_ORDERED:
424 fd->have_ordered = true;
425 break;
426 case OMP_CLAUSE_SCHEDULE:
427 gcc_assert (!distribute);
428 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
429 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
430 break;
431 case OMP_CLAUSE_DIST_SCHEDULE:
432 gcc_assert (distribute);
433 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
434 break;
435 case OMP_CLAUSE_COLLAPSE:
436 if (fd->collapse > 1)
438 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
439 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
441 break;
442 default:
443 break;
446 /* FIXME: for now map schedule(auto) to schedule(static).
447 There should be analysis to determine whether all iterations
448 are approximately the same amount of work (then schedule(static)
449 is best) or if it varies (then schedule(dynamic,N) is better). */
450 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
452 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
453 gcc_assert (fd->chunk_size == NULL);
455 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
456 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
457 gcc_assert (fd->chunk_size == NULL);
458 else if (fd->chunk_size == NULL)
460 /* We only need to compute a default chunk size for ordered
461 static loops and dynamic loops. */
462 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
463 || fd->have_ordered)
464 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
465 ? integer_zero_node : integer_one_node;
468 for (i = 0; i < fd->collapse; i++)
470 if (fd->collapse == 1)
471 loop = &fd->loop;
472 else if (loops != NULL)
473 loop = loops + i;
474 else
475 loop = &dummy_loop;
477 loop->v = gimple_omp_for_index (for_stmt, i);
478 gcc_assert (SSA_VAR_P (loop->v));
479 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
480 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
481 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
482 loop->n1 = gimple_omp_for_initial (for_stmt, i);
484 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
485 loop->n2 = gimple_omp_for_final (for_stmt, i);
486 switch (loop->cond_code)
488 case LT_EXPR:
489 case GT_EXPR:
490 break;
491 case NE_EXPR:
492 gcc_assert (gimple_omp_for_kind (for_stmt)
493 == GF_OMP_FOR_KIND_CILKSIMD
494 || (gimple_omp_for_kind (for_stmt)
495 == GF_OMP_FOR_KIND_CILKFOR));
496 break;
497 case LE_EXPR:
498 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
499 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
500 else
501 loop->n2 = fold_build2_loc (loc,
502 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
503 build_int_cst (TREE_TYPE (loop->n2), 1));
504 loop->cond_code = LT_EXPR;
505 break;
506 case GE_EXPR:
507 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
508 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
509 else
510 loop->n2 = fold_build2_loc (loc,
511 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
512 build_int_cst (TREE_TYPE (loop->n2), 1));
513 loop->cond_code = GT_EXPR;
514 break;
515 default:
516 gcc_unreachable ();
519 t = gimple_omp_for_incr (for_stmt, i);
520 gcc_assert (TREE_OPERAND (t, 0) == var);
521 switch (TREE_CODE (t))
523 case PLUS_EXPR:
524 loop->step = TREE_OPERAND (t, 1);
525 break;
526 case POINTER_PLUS_EXPR:
527 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
528 break;
529 case MINUS_EXPR:
530 loop->step = TREE_OPERAND (t, 1);
531 loop->step = fold_build1_loc (loc,
532 NEGATE_EXPR, TREE_TYPE (loop->step),
533 loop->step);
534 break;
535 default:
536 gcc_unreachable ();
539 if (simd
540 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
541 && !fd->have_ordered))
543 if (fd->collapse == 1)
544 iter_type = TREE_TYPE (loop->v);
545 else if (i == 0
546 || TYPE_PRECISION (iter_type)
547 < TYPE_PRECISION (TREE_TYPE (loop->v)))
548 iter_type
549 = build_nonstandard_integer_type
550 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
552 else if (iter_type != long_long_unsigned_type_node)
554 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
555 iter_type = long_long_unsigned_type_node;
556 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
557 && TYPE_PRECISION (TREE_TYPE (loop->v))
558 >= TYPE_PRECISION (iter_type))
560 tree n;
562 if (loop->cond_code == LT_EXPR)
563 n = fold_build2_loc (loc,
564 PLUS_EXPR, TREE_TYPE (loop->v),
565 loop->n2, loop->step);
566 else
567 n = loop->n1;
568 if (TREE_CODE (n) != INTEGER_CST
569 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
570 iter_type = long_long_unsigned_type_node;
572 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
573 > TYPE_PRECISION (iter_type))
575 tree n1, n2;
577 if (loop->cond_code == LT_EXPR)
579 n1 = loop->n1;
580 n2 = fold_build2_loc (loc,
581 PLUS_EXPR, TREE_TYPE (loop->v),
582 loop->n2, loop->step);
584 else
586 n1 = fold_build2_loc (loc,
587 MINUS_EXPR, TREE_TYPE (loop->v),
588 loop->n2, loop->step);
589 n2 = loop->n1;
591 if (TREE_CODE (n1) != INTEGER_CST
592 || TREE_CODE (n2) != INTEGER_CST
593 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
594 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
595 iter_type = long_long_unsigned_type_node;
599 if (collapse_count && *collapse_count == NULL)
601 t = fold_binary (loop->cond_code, boolean_type_node,
602 fold_convert (TREE_TYPE (loop->v), loop->n1),
603 fold_convert (TREE_TYPE (loop->v), loop->n2));
604 if (t && integer_zerop (t))
605 count = build_zero_cst (long_long_unsigned_type_node);
606 else if ((i == 0 || count != NULL_TREE)
607 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
608 && TREE_CONSTANT (loop->n1)
609 && TREE_CONSTANT (loop->n2)
610 && TREE_CODE (loop->step) == INTEGER_CST)
612 tree itype = TREE_TYPE (loop->v);
614 if (POINTER_TYPE_P (itype))
615 itype = signed_type_for (itype);
616 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
617 t = fold_build2_loc (loc,
618 PLUS_EXPR, itype,
619 fold_convert_loc (loc, itype, loop->step), t);
620 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
621 fold_convert_loc (loc, itype, loop->n2));
622 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
623 fold_convert_loc (loc, itype, loop->n1));
624 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
625 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
626 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
627 fold_build1_loc (loc, NEGATE_EXPR, itype,
628 fold_convert_loc (loc, itype,
629 loop->step)));
630 else
631 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
632 fold_convert_loc (loc, itype, loop->step));
633 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
634 if (count != NULL_TREE)
635 count = fold_build2_loc (loc,
636 MULT_EXPR, long_long_unsigned_type_node,
637 count, t);
638 else
639 count = t;
640 if (TREE_CODE (count) != INTEGER_CST)
641 count = NULL_TREE;
643 else if (count && !integer_zerop (count))
644 count = NULL_TREE;
648 if (count
649 && !simd
650 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
651 || fd->have_ordered))
653 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
654 iter_type = long_long_unsigned_type_node;
655 else
656 iter_type = long_integer_type_node;
658 else if (collapse_iter && *collapse_iter != NULL)
659 iter_type = TREE_TYPE (*collapse_iter);
660 fd->iter_type = iter_type;
661 if (collapse_iter && *collapse_iter == NULL)
662 *collapse_iter = create_tmp_var (iter_type, ".iter");
663 if (collapse_count && *collapse_count == NULL)
665 if (count)
666 *collapse_count = fold_convert_loc (loc, iter_type, count);
667 else
668 *collapse_count = create_tmp_var (iter_type, ".count");
671 if (fd->collapse > 1)
673 fd->loop.v = *collapse_iter;
674 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
675 fd->loop.n2 = *collapse_count;
676 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
677 fd->loop.cond_code = LT_EXPR;
680 /* For OpenACC loops, force a chunk size of one, as this avoids the default
681 scheduling where several subsequent iterations are being executed by the
682 same thread. */
683 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
685 gcc_assert (fd->chunk_size == NULL_TREE);
686 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
691 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
692 is the immediate dominator of PAR_ENTRY_BB, return true if there
693 are no data dependencies that would prevent expanding the parallel
694 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
696 When expanding a combined parallel+workshare region, the call to
697 the child function may need additional arguments in the case of
698 GIMPLE_OMP_FOR regions. In some cases, these arguments are
699 computed out of variables passed in from the parent to the child
700 via 'struct .omp_data_s'. For instance:
702 #pragma omp parallel for schedule (guided, i * 4)
703 for (j ...)
705 Is lowered into:
707 # BLOCK 2 (PAR_ENTRY_BB)
708 .omp_data_o.i = i;
709 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
711 # BLOCK 3 (WS_ENTRY_BB)
712 .omp_data_i = &.omp_data_o;
713 D.1667 = .omp_data_i->i;
714 D.1598 = D.1667 * 4;
715 #pragma omp for schedule (guided, D.1598)
717 When we outline the parallel region, the call to the child function
718 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
719 that value is computed *after* the call site. So, in principle we
720 cannot do the transformation.
722 To see whether the code in WS_ENTRY_BB blocks the combined
723 parallel+workshare call, we collect all the variables used in the
724 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
725 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
726 call.
728 FIXME. If we had the SSA form built at this point, we could merely
729 hoist the code in block 3 into block 2 and be done with it. But at
730 this point we don't have dataflow information and though we could
731 hack something up here, it is really not worth the aggravation. */
733 static bool
734 workshare_safe_to_combine_p (basic_block ws_entry_bb)
736 struct omp_for_data fd;
737 gimple ws_stmt = last_stmt (ws_entry_bb);
739 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
740 return true;
742 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
744 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
746 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
747 return false;
748 if (fd.iter_type != long_integer_type_node)
749 return false;
751 /* FIXME. We give up too easily here. If any of these arguments
752 are not constants, they will likely involve variables that have
753 been mapped into fields of .omp_data_s for sharing with the child
754 function. With appropriate data flow, it would be possible to
755 see through this. */
756 if (!is_gimple_min_invariant (fd.loop.n1)
757 || !is_gimple_min_invariant (fd.loop.n2)
758 || !is_gimple_min_invariant (fd.loop.step)
759 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
760 return false;
762 return true;
766 /* Collect additional arguments needed to emit a combined
767 parallel+workshare call. WS_STMT is the workshare directive being
768 expanded. */
770 static vec<tree, va_gc> *
771 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
773 tree t;
774 location_t loc = gimple_location (ws_stmt);
775 vec<tree, va_gc> *ws_args;
777 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
779 struct omp_for_data fd;
780 tree n1, n2;
782 extract_omp_for_data (for_stmt, &fd, NULL);
783 n1 = fd.loop.n1;
784 n2 = fd.loop.n2;
786 if (gimple_omp_for_combined_into_p (for_stmt))
788 tree innerc
789 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
790 OMP_CLAUSE__LOOPTEMP_);
791 gcc_assert (innerc);
792 n1 = OMP_CLAUSE_DECL (innerc);
793 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
794 OMP_CLAUSE__LOOPTEMP_);
795 gcc_assert (innerc);
796 n2 = OMP_CLAUSE_DECL (innerc);
799 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
801 t = fold_convert_loc (loc, long_integer_type_node, n1);
802 ws_args->quick_push (t);
804 t = fold_convert_loc (loc, long_integer_type_node, n2);
805 ws_args->quick_push (t);
807 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
808 ws_args->quick_push (t);
810 if (fd.chunk_size)
812 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
813 ws_args->quick_push (t);
816 return ws_args;
818 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
820 /* Number of sections is equal to the number of edges from the
821 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
822 the exit of the sections region. */
823 basic_block bb = single_succ (gimple_bb (ws_stmt));
824 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
825 vec_alloc (ws_args, 1);
826 ws_args->quick_push (t);
827 return ws_args;
830 gcc_unreachable ();
834 /* Discover whether REGION is a combined parallel+workshare region. */
836 static void
837 determine_parallel_type (struct omp_region *region)
839 basic_block par_entry_bb, par_exit_bb;
840 basic_block ws_entry_bb, ws_exit_bb;
842 if (region == NULL || region->inner == NULL
843 || region->exit == NULL || region->inner->exit == NULL
844 || region->inner->cont == NULL)
845 return;
847 /* We only support parallel+for and parallel+sections. */
848 if (region->type != GIMPLE_OMP_PARALLEL
849 || (region->inner->type != GIMPLE_OMP_FOR
850 && region->inner->type != GIMPLE_OMP_SECTIONS))
851 return;
853 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
854 WS_EXIT_BB -> PAR_EXIT_BB. */
855 par_entry_bb = region->entry;
856 par_exit_bb = region->exit;
857 ws_entry_bb = region->inner->entry;
858 ws_exit_bb = region->inner->exit;
860 if (single_succ (par_entry_bb) == ws_entry_bb
861 && single_succ (ws_exit_bb) == par_exit_bb
862 && workshare_safe_to_combine_p (ws_entry_bb)
863 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
864 || (last_and_only_stmt (ws_entry_bb)
865 && last_and_only_stmt (par_exit_bb))))
867 gimple par_stmt = last_stmt (par_entry_bb);
868 gimple ws_stmt = last_stmt (ws_entry_bb);
870 if (region->inner->type == GIMPLE_OMP_FOR)
872 /* If this is a combined parallel loop, we need to determine
873 whether or not to use the combined library calls. There
874 are two cases where we do not apply the transformation:
875 static loops and any kind of ordered loop. In the first
876 case, we already open code the loop so there is no need
877 to do anything else. In the latter case, the combined
878 parallel loop call would still need extra synchronization
879 to implement ordered semantics, so there would not be any
880 gain in using the combined call. */
881 tree clauses = gimple_omp_for_clauses (ws_stmt);
882 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
883 if (c == NULL
884 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
885 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
887 region->is_combined_parallel = false;
888 region->inner->is_combined_parallel = false;
889 return;
893 region->is_combined_parallel = true;
894 region->inner->is_combined_parallel = true;
895 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
900 /* Return true if EXPR is variable sized. */
902 static inline bool
903 is_variable_sized (const_tree expr)
905 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
908 /* Return true if DECL is a reference type. */
910 static inline bool
911 is_reference (tree decl)
913 return lang_hooks.decls.omp_privatize_by_reference (decl);
916 /* Return the type of a decl. If the decl is reference type,
917 return its base type. */
918 static inline tree
919 get_base_type (tree decl)
921 tree type = TREE_TYPE (decl);
922 if (is_reference (decl))
923 type = TREE_TYPE (type);
924 return type;
927 /* Lookup variables. The "maybe" form
928 allows for the variable form to not have been entered, otherwise we
929 assert that the variable must have been entered. */
931 static inline tree
932 lookup_decl (tree var, omp_context *ctx)
934 tree *n = ctx->cb.decl_map->get (var);
935 return *n;
938 static inline tree
939 maybe_lookup_decl (const_tree var, omp_context *ctx)
941 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
942 return n ? *n : NULL_TREE;
945 static inline tree
946 lookup_field (tree var, omp_context *ctx)
948 splay_tree_node n;
949 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
950 return (tree) n->value;
953 static inline tree
954 lookup_sfield (tree var, omp_context *ctx)
956 splay_tree_node n;
957 n = splay_tree_lookup (ctx->sfield_map
958 ? ctx->sfield_map : ctx->field_map,
959 (splay_tree_key) var);
960 return (tree) n->value;
963 static inline tree
964 maybe_lookup_field (tree var, omp_context *ctx)
966 splay_tree_node n;
967 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
968 return n ? (tree) n->value : NULL_TREE;
971 static inline tree
972 lookup_oacc_reduction (const char *id, omp_context *ctx)
974 splay_tree_node n;
975 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
976 return (tree) n->value;
979 static inline tree
980 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
982 splay_tree_node n = NULL;
983 if (ctx->reduction_map)
984 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
985 return n ? (tree) n->value : NULL_TREE;
988 /* Return true if DECL should be copied by pointer. SHARED_CTX is
989 the parallel context if DECL is to be shared. */
991 static bool
992 use_pointer_for_field (tree decl, omp_context *shared_ctx)
994 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
995 return true;
997 /* We can only use copy-in/copy-out semantics for shared variables
998 when we know the value is not accessible from an outer scope. */
999 if (shared_ctx)
1001 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1003 /* ??? Trivially accessible from anywhere. But why would we even
1004 be passing an address in this case? Should we simply assert
1005 this to be false, or should we have a cleanup pass that removes
1006 these from the list of mappings? */
1007 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1008 return true;
1010 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1011 without analyzing the expression whether or not its location
1012 is accessible to anyone else. In the case of nested parallel
1013 regions it certainly may be. */
1014 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1015 return true;
1017 /* Do not use copy-in/copy-out for variables that have their
1018 address taken. */
1019 if (TREE_ADDRESSABLE (decl))
1020 return true;
1022 /* lower_send_shared_vars only uses copy-in, but not copy-out
1023 for these. */
1024 if (TREE_READONLY (decl)
1025 || ((TREE_CODE (decl) == RESULT_DECL
1026 || TREE_CODE (decl) == PARM_DECL)
1027 && DECL_BY_REFERENCE (decl)))
1028 return false;
1030 /* Disallow copy-in/out in nested parallel if
1031 decl is shared in outer parallel, otherwise
1032 each thread could store the shared variable
1033 in its own copy-in location, making the
1034 variable no longer really shared. */
1035 if (shared_ctx->is_nested)
1037 omp_context *up;
1039 for (up = shared_ctx->outer; up; up = up->outer)
1040 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1041 break;
1043 if (up)
1045 tree c;
1047 for (c = gimple_omp_taskreg_clauses (up->stmt);
1048 c; c = OMP_CLAUSE_CHAIN (c))
1049 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1050 && OMP_CLAUSE_DECL (c) == decl)
1051 break;
1053 if (c)
1054 goto maybe_mark_addressable_and_ret;
1058 /* For tasks avoid using copy-in/out. As tasks can be
1059 deferred or executed in different thread, when GOMP_task
1060 returns, the task hasn't necessarily terminated. */
1061 if (is_task_ctx (shared_ctx))
1063 tree outer;
1064 maybe_mark_addressable_and_ret:
1065 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1066 if (is_gimple_reg (outer))
1068 /* Taking address of OUTER in lower_send_shared_vars
1069 might need regimplification of everything that uses the
1070 variable. */
1071 if (!task_shared_vars)
1072 task_shared_vars = BITMAP_ALLOC (NULL);
1073 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1074 TREE_ADDRESSABLE (outer) = 1;
1076 return true;
1080 return false;
1083 /* Construct a new automatic decl similar to VAR. */
1085 static tree
1086 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1088 tree copy = copy_var_decl (var, name, type);
1090 DECL_CONTEXT (copy) = current_function_decl;
1091 DECL_CHAIN (copy) = ctx->block_vars;
1092 ctx->block_vars = copy;
1094 return copy;
1097 static tree
1098 omp_copy_decl_1 (tree var, omp_context *ctx)
1100 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1103 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1104 as appropriate. */
1105 static tree
1106 omp_build_component_ref (tree obj, tree field)
1108 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1109 if (TREE_THIS_VOLATILE (field))
1110 TREE_THIS_VOLATILE (ret) |= 1;
1111 if (TREE_READONLY (field))
1112 TREE_READONLY (ret) |= 1;
1113 return ret;
1116 /* Build tree nodes to access the field for VAR on the receiver side. */
1118 static tree
1119 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1121 tree x, field = lookup_field (var, ctx);
1123 /* If the receiver record type was remapped in the child function,
1124 remap the field into the new record type. */
1125 x = maybe_lookup_field (field, ctx);
1126 if (x != NULL)
1127 field = x;
1129 x = build_simple_mem_ref (ctx->receiver_decl);
1130 TREE_THIS_NOTRAP (x) = 1;
1131 x = omp_build_component_ref (x, field);
1132 if (by_ref)
1133 x = build_simple_mem_ref (x);
1135 return x;
1138 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1139 of a parallel, this is a component reference; for workshare constructs
1140 this is some variable. */
1142 static tree
1143 build_outer_var_ref (tree var, omp_context *ctx)
1145 tree x;
1147 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1148 x = var;
1149 else if (is_variable_sized (var))
1151 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1152 x = build_outer_var_ref (x, ctx);
1153 x = build_simple_mem_ref (x);
1155 else if (is_taskreg_ctx (ctx))
1157 bool by_ref = use_pointer_for_field (var, NULL);
1158 x = build_receiver_ref (var, by_ref, ctx);
1160 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1161 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1163 /* #pragma omp simd isn't a worksharing construct, and can reference even
1164 private vars in its linear etc. clauses. */
1165 x = NULL_TREE;
1166 if (ctx->outer && is_taskreg_ctx (ctx))
1167 x = lookup_decl (var, ctx->outer);
1168 else if (ctx->outer)
1169 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1170 if (x == NULL_TREE)
1171 x = var;
1173 else if (ctx->outer)
1174 x = lookup_decl (var, ctx->outer);
1175 else if (is_reference (var))
1176 /* This can happen with orphaned constructs. If var is reference, it is
1177 possible it is shared and as such valid. */
1178 x = var;
1179 else
1180 gcc_unreachable ();
1182 if (is_reference (var))
1183 x = build_simple_mem_ref (x);
1185 return x;
1188 /* Build tree nodes to access the field for VAR on the sender side. */
1190 static tree
1191 build_sender_ref (tree var, omp_context *ctx)
1193 tree field = lookup_sfield (var, ctx);
1194 return omp_build_component_ref (ctx->sender_decl, field);
1197 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1199 static void
1200 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1202 tree field, type, sfield = NULL_TREE;
1204 gcc_assert ((mask & 1) == 0
1205 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1206 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1207 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1208 gcc_assert ((mask & 3) == 3
1209 || !is_gimple_omp_oacc (ctx->stmt));
1211 type = TREE_TYPE (var);
1212 if (mask & 4)
1214 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1215 type = build_pointer_type (build_pointer_type (type));
1217 else if (by_ref)
1218 type = build_pointer_type (type);
1219 else if ((mask & 3) == 1 && is_reference (var))
1220 type = TREE_TYPE (type);
1222 field = build_decl (DECL_SOURCE_LOCATION (var),
1223 FIELD_DECL, DECL_NAME (var), type);
1225 /* Remember what variable this field was created for. This does have a
1226 side effect of making dwarf2out ignore this member, so for helpful
1227 debugging we clear it later in delete_omp_context. */
1228 DECL_ABSTRACT_ORIGIN (field) = var;
1229 if (type == TREE_TYPE (var))
1231 DECL_ALIGN (field) = DECL_ALIGN (var);
1232 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1233 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1235 else
1236 DECL_ALIGN (field) = TYPE_ALIGN (type);
1238 if ((mask & 3) == 3)
1240 insert_field_into_struct (ctx->record_type, field);
1241 if (ctx->srecord_type)
1243 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1244 FIELD_DECL, DECL_NAME (var), type);
1245 DECL_ABSTRACT_ORIGIN (sfield) = var;
1246 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1247 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1248 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1249 insert_field_into_struct (ctx->srecord_type, sfield);
1252 else
1254 if (ctx->srecord_type == NULL_TREE)
1256 tree t;
1258 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1259 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1260 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1262 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1263 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1264 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1265 insert_field_into_struct (ctx->srecord_type, sfield);
1266 splay_tree_insert (ctx->sfield_map,
1267 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1268 (splay_tree_value) sfield);
1271 sfield = field;
1272 insert_field_into_struct ((mask & 1) ? ctx->record_type
1273 : ctx->srecord_type, field);
1276 if (mask & 1)
1277 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1278 (splay_tree_value) field);
1279 if ((mask & 2) && ctx->sfield_map)
1280 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1281 (splay_tree_value) sfield);
1284 static tree
1285 install_var_local (tree var, omp_context *ctx)
1287 tree new_var = omp_copy_decl_1 (var, ctx);
1288 insert_decl_map (&ctx->cb, var, new_var);
1289 return new_var;
1292 /* Adjust the replacement for DECL in CTX for the new context. This means
1293 copying the DECL_VALUE_EXPR, and fixing up the type. */
1295 static void
1296 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1298 tree new_decl, size;
1300 new_decl = lookup_decl (decl, ctx);
1302 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1304 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1305 && DECL_HAS_VALUE_EXPR_P (decl))
1307 tree ve = DECL_VALUE_EXPR (decl);
1308 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1309 SET_DECL_VALUE_EXPR (new_decl, ve);
1310 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1313 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1315 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1316 if (size == error_mark_node)
1317 size = TYPE_SIZE (TREE_TYPE (new_decl));
1318 DECL_SIZE (new_decl) = size;
1320 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1321 if (size == error_mark_node)
1322 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1323 DECL_SIZE_UNIT (new_decl) = size;
1327 /* The callback for remap_decl. Search all containing contexts for a
1328 mapping of the variable; this avoids having to duplicate the splay
1329 tree ahead of time. We know a mapping doesn't already exist in the
1330 given context. Create new mappings to implement default semantics. */
1332 static tree
1333 omp_copy_decl (tree var, copy_body_data *cb)
1335 omp_context *ctx = (omp_context *) cb;
1336 tree new_var;
1338 if (TREE_CODE (var) == LABEL_DECL)
1340 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1341 DECL_CONTEXT (new_var) = current_function_decl;
1342 insert_decl_map (&ctx->cb, var, new_var);
1343 return new_var;
1346 while (!is_taskreg_ctx (ctx))
1348 ctx = ctx->outer;
1349 if (ctx == NULL)
1350 return var;
1351 new_var = maybe_lookup_decl (var, ctx);
1352 if (new_var)
1353 return new_var;
1356 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1357 return var;
1359 return error_mark_node;
1363 /* Debugging dumps for parallel regions. */
1364 void dump_omp_region (FILE *, struct omp_region *, int);
1365 void debug_omp_region (struct omp_region *);
1366 void debug_all_omp_regions (void);
1368 /* Dump the parallel region tree rooted at REGION. */
1370 void
1371 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1373 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1374 gimple_code_name[region->type]);
1376 if (region->inner)
1377 dump_omp_region (file, region->inner, indent + 4);
1379 if (region->cont)
1381 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1382 region->cont->index);
1385 if (region->exit)
1386 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1387 region->exit->index);
1388 else
1389 fprintf (file, "%*s[no exit marker]\n", indent, "");
1391 if (region->next)
1392 dump_omp_region (file, region->next, indent);
1395 DEBUG_FUNCTION void
1396 debug_omp_region (struct omp_region *region)
1398 dump_omp_region (stderr, region, 0);
1401 DEBUG_FUNCTION void
1402 debug_all_omp_regions (void)
1404 dump_omp_region (stderr, root_omp_region, 0);
1408 /* Create a new parallel region starting at STMT inside region PARENT. */
1410 static struct omp_region *
1411 new_omp_region (basic_block bb, enum gimple_code type,
1412 struct omp_region *parent)
1414 struct omp_region *region = XCNEW (struct omp_region);
1416 region->outer = parent;
1417 region->entry = bb;
1418 region->type = type;
1420 if (parent)
1422 /* This is a nested region. Add it to the list of inner
1423 regions in PARENT. */
1424 region->next = parent->inner;
1425 parent->inner = region;
1427 else
1429 /* This is a toplevel region. Add it to the list of toplevel
1430 regions in ROOT_OMP_REGION. */
1431 region->next = root_omp_region;
1432 root_omp_region = region;
1435 return region;
1438 /* Release the memory associated with the region tree rooted at REGION. */
1440 static void
1441 free_omp_region_1 (struct omp_region *region)
1443 struct omp_region *i, *n;
1445 for (i = region->inner; i ; i = n)
1447 n = i->next;
1448 free_omp_region_1 (i);
1451 free (region);
1454 /* Release the memory for the entire omp region tree. */
1456 void
1457 free_omp_regions (void)
1459 struct omp_region *r, *n;
1460 for (r = root_omp_region; r ; r = n)
1462 n = r->next;
1463 free_omp_region_1 (r);
1465 root_omp_region = NULL;
1469 /* Create a new context, with OUTER_CTX being the surrounding context. */
1471 static omp_context *
1472 new_omp_context (gimple stmt, omp_context *outer_ctx)
1474 omp_context *ctx = XCNEW (omp_context);
1476 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1477 (splay_tree_value) ctx);
1478 ctx->stmt = stmt;
1480 if (outer_ctx)
1482 ctx->outer = outer_ctx;
1483 ctx->cb = outer_ctx->cb;
1484 ctx->cb.block = NULL;
1485 ctx->depth = outer_ctx->depth + 1;
1486 ctx->reduction_map = outer_ctx->reduction_map;
1488 else
1490 ctx->cb.src_fn = current_function_decl;
1491 ctx->cb.dst_fn = current_function_decl;
1492 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1493 gcc_checking_assert (ctx->cb.src_node);
1494 ctx->cb.dst_node = ctx->cb.src_node;
1495 ctx->cb.src_cfun = cfun;
1496 ctx->cb.copy_decl = omp_copy_decl;
1497 ctx->cb.eh_lp_nr = 0;
1498 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1499 ctx->depth = 1;
1502 ctx->cb.decl_map = new hash_map<tree, tree>;
1504 return ctx;
1507 static gimple_seq maybe_catch_exception (gimple_seq);
1509 /* Finalize task copyfn. */
1511 static void
1512 finalize_task_copyfn (gomp_task *task_stmt)
1514 struct function *child_cfun;
1515 tree child_fn;
1516 gimple_seq seq = NULL, new_seq;
1517 gbind *bind;
1519 child_fn = gimple_omp_task_copy_fn (task_stmt);
1520 if (child_fn == NULL_TREE)
1521 return;
1523 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1524 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1526 push_cfun (child_cfun);
1527 bind = gimplify_body (child_fn, false);
1528 gimple_seq_add_stmt (&seq, bind);
1529 new_seq = maybe_catch_exception (seq);
1530 if (new_seq != seq)
1532 bind = gimple_build_bind (NULL, new_seq, NULL);
1533 seq = NULL;
1534 gimple_seq_add_stmt (&seq, bind);
1536 gimple_set_body (child_fn, seq);
1537 pop_cfun ();
1539 /* Inform the callgraph about the new function. */
1540 cgraph_node *node = cgraph_node::get_create (child_fn);
1541 node->parallelized_function = 1;
1542 cgraph_node::add_new_function (child_fn, false);
1545 /* Destroy a omp_context data structures. Called through the splay tree
1546 value delete callback. */
1548 static void
1549 delete_omp_context (splay_tree_value value)
1551 omp_context *ctx = (omp_context *) value;
1553 delete ctx->cb.decl_map;
1555 if (ctx->field_map)
1556 splay_tree_delete (ctx->field_map);
1557 if (ctx->sfield_map)
1558 splay_tree_delete (ctx->sfield_map);
1559 /* Reduction map is copied to nested contexts, so only delete it in the
1560 owner. */
1561 if (ctx->reduction_map
1562 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1563 && is_gimple_omp_offloaded (ctx->stmt)
1564 && is_gimple_omp_oacc (ctx->stmt))
1565 splay_tree_delete (ctx->reduction_map);
1567 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1568 it produces corrupt debug information. */
1569 if (ctx->record_type)
1571 tree t;
1572 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1573 DECL_ABSTRACT_ORIGIN (t) = NULL;
1575 if (ctx->srecord_type)
1577 tree t;
1578 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1579 DECL_ABSTRACT_ORIGIN (t) = NULL;
1582 if (is_task_ctx (ctx))
1583 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1585 XDELETE (ctx);
1588 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1589 context. */
1591 static void
1592 fixup_child_record_type (omp_context *ctx)
1594 tree f, type = ctx->record_type;
1596 /* ??? It isn't sufficient to just call remap_type here, because
1597 variably_modified_type_p doesn't work the way we expect for
1598 record types. Testing each field for whether it needs remapping
1599 and creating a new record by hand works, however. */
1600 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1601 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1602 break;
1603 if (f)
1605 tree name, new_fields = NULL;
1607 type = lang_hooks.types.make_type (RECORD_TYPE);
1608 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1609 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1610 TYPE_DECL, name, type);
1611 TYPE_NAME (type) = name;
1613 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1615 tree new_f = copy_node (f);
1616 DECL_CONTEXT (new_f) = type;
1617 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1618 DECL_CHAIN (new_f) = new_fields;
1619 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1620 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1621 &ctx->cb, NULL);
1622 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1623 &ctx->cb, NULL);
1624 new_fields = new_f;
1626 /* Arrange to be able to look up the receiver field
1627 given the sender field. */
1628 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1629 (splay_tree_value) new_f);
1631 TYPE_FIELDS (type) = nreverse (new_fields);
1632 layout_type (type);
1635 TREE_TYPE (ctx->receiver_decl)
1636 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1639 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1640 specified by CLAUSES. */
1642 static void
1643 scan_sharing_clauses (tree clauses, omp_context *ctx)
1645 tree c, decl;
1646 bool scan_array_reductions = false;
1648 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1650 bool by_ref;
1652 switch (OMP_CLAUSE_CODE (c))
1654 case OMP_CLAUSE_PRIVATE:
1655 decl = OMP_CLAUSE_DECL (c);
1656 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1657 goto do_private;
1658 else if (!is_variable_sized (decl))
1659 install_var_local (decl, ctx);
1660 break;
1662 case OMP_CLAUSE_SHARED:
1663 decl = OMP_CLAUSE_DECL (c);
1664 /* Ignore shared directives in teams construct. */
1665 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1667 /* Global variables don't need to be copied,
1668 the receiver side will use them directly. */
1669 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1670 if (is_global_var (odecl))
1671 break;
1672 insert_decl_map (&ctx->cb, decl, odecl);
1673 break;
1675 gcc_assert (is_taskreg_ctx (ctx));
1676 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1677 || !is_variable_sized (decl));
1678 /* Global variables don't need to be copied,
1679 the receiver side will use them directly. */
1680 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1681 break;
1682 by_ref = use_pointer_for_field (decl, ctx);
1683 if (! TREE_READONLY (decl)
1684 || TREE_ADDRESSABLE (decl)
1685 || by_ref
1686 || is_reference (decl))
1688 install_var_field (decl, by_ref, 3, ctx);
1689 install_var_local (decl, ctx);
1690 break;
1692 /* We don't need to copy const scalar vars back. */
1693 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1694 goto do_private;
1696 case OMP_CLAUSE_LASTPRIVATE:
1697 /* Let the corresponding firstprivate clause create
1698 the variable. */
1699 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1700 break;
1701 /* FALLTHRU */
1703 case OMP_CLAUSE_FIRSTPRIVATE:
1704 if (is_gimple_omp_oacc (ctx->stmt))
1706 sorry ("clause not supported yet");
1707 break;
1709 /* FALLTHRU */
1710 case OMP_CLAUSE_REDUCTION:
1711 case OMP_CLAUSE_LINEAR:
1712 decl = OMP_CLAUSE_DECL (c);
1713 do_private:
1714 if (is_variable_sized (decl))
1716 if (is_task_ctx (ctx))
1717 install_var_field (decl, false, 1, ctx);
1718 break;
1720 else if (is_taskreg_ctx (ctx))
1722 bool global
1723 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1724 by_ref = use_pointer_for_field (decl, NULL);
1726 if (is_task_ctx (ctx)
1727 && (global || by_ref || is_reference (decl)))
1729 install_var_field (decl, false, 1, ctx);
1730 if (!global)
1731 install_var_field (decl, by_ref, 2, ctx);
1733 else if (!global)
1734 install_var_field (decl, by_ref, 3, ctx);
1736 install_var_local (decl, ctx);
1737 if (is_gimple_omp_oacc (ctx->stmt)
1738 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1740 /* Create a decl for the reduction array. */
1741 tree var = OMP_CLAUSE_DECL (c);
1742 tree type = get_base_type (var);
1743 tree ptype = build_pointer_type (type);
1744 tree array = create_tmp_var (ptype,
1745 oacc_get_reduction_array_id (var));
1746 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1747 install_var_field (array, true, 3, c);
1748 install_var_local (array, c);
1750 /* Insert it into the current context. */
1751 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1752 oacc_get_reduction_array_id (var),
1753 (splay_tree_value) array);
1754 splay_tree_insert (ctx->reduction_map,
1755 (splay_tree_key) array,
1756 (splay_tree_value) array);
1758 break;
1760 case OMP_CLAUSE__LOOPTEMP_:
1761 gcc_assert (is_parallel_ctx (ctx));
1762 decl = OMP_CLAUSE_DECL (c);
1763 install_var_field (decl, false, 3, ctx);
1764 install_var_local (decl, ctx);
1765 break;
1767 case OMP_CLAUSE_COPYPRIVATE:
1768 case OMP_CLAUSE_COPYIN:
1769 decl = OMP_CLAUSE_DECL (c);
1770 by_ref = use_pointer_for_field (decl, NULL);
1771 install_var_field (decl, by_ref, 3, ctx);
1772 break;
1774 case OMP_CLAUSE_DEFAULT:
1775 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1776 break;
1778 case OMP_CLAUSE_FINAL:
1779 case OMP_CLAUSE_IF:
1780 case OMP_CLAUSE_NUM_THREADS:
1781 case OMP_CLAUSE_NUM_TEAMS:
1782 case OMP_CLAUSE_THREAD_LIMIT:
1783 case OMP_CLAUSE_DEVICE:
1784 case OMP_CLAUSE_SCHEDULE:
1785 case OMP_CLAUSE_DIST_SCHEDULE:
1786 case OMP_CLAUSE_DEPEND:
1787 case OMP_CLAUSE__CILK_FOR_COUNT_:
1788 case OMP_CLAUSE_NUM_GANGS:
1789 case OMP_CLAUSE_NUM_WORKERS:
1790 case OMP_CLAUSE_VECTOR_LENGTH:
1791 if (ctx->outer)
1792 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1793 break;
1795 case OMP_CLAUSE_TO:
1796 case OMP_CLAUSE_FROM:
1797 case OMP_CLAUSE_MAP:
1798 if (ctx->outer)
1799 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1800 decl = OMP_CLAUSE_DECL (c);
1801 /* Global variables with "omp declare target" attribute
1802 don't need to be copied, the receiver side will use them
1803 directly. */
1804 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1805 && DECL_P (decl)
1806 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1807 && varpool_node::get_create (decl)->offloadable)
1808 break;
1809 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1810 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
1812 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1813 not offloaded; there is nothing to map for those. */
1814 if (!is_gimple_omp_offloaded (ctx->stmt)
1815 && !POINTER_TYPE_P (TREE_TYPE (decl))
1816 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
1817 break;
1819 if (DECL_P (decl))
1821 if (DECL_SIZE (decl)
1822 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1824 tree decl2 = DECL_VALUE_EXPR (decl);
1825 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1826 decl2 = TREE_OPERAND (decl2, 0);
1827 gcc_assert (DECL_P (decl2));
1828 install_var_field (decl2, true, 3, ctx);
1829 install_var_local (decl2, ctx);
1830 install_var_local (decl, ctx);
1832 else
1834 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1835 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1836 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1837 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1838 install_var_field (decl, true, 7, ctx);
1839 else
1840 install_var_field (decl, true, 3, ctx);
1841 if (is_gimple_omp_offloaded (ctx->stmt))
1842 install_var_local (decl, ctx);
1845 else
1847 tree base = get_base_address (decl);
1848 tree nc = OMP_CLAUSE_CHAIN (c);
1849 if (DECL_P (base)
1850 && nc != NULL_TREE
1851 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1852 && OMP_CLAUSE_DECL (nc) == base
1853 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1854 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1856 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1857 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1859 else
1861 if (ctx->outer)
1863 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1864 decl = OMP_CLAUSE_DECL (c);
1866 gcc_assert (!splay_tree_lookup (ctx->field_map,
1867 (splay_tree_key) decl));
1868 tree field
1869 = build_decl (OMP_CLAUSE_LOCATION (c),
1870 FIELD_DECL, NULL_TREE, ptr_type_node);
1871 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1872 insert_field_into_struct (ctx->record_type, field);
1873 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1874 (splay_tree_value) field);
1877 break;
1879 case OMP_CLAUSE_NOWAIT:
1880 case OMP_CLAUSE_ORDERED:
1881 case OMP_CLAUSE_COLLAPSE:
1882 case OMP_CLAUSE_UNTIED:
1883 case OMP_CLAUSE_MERGEABLE:
1884 case OMP_CLAUSE_PROC_BIND:
1885 case OMP_CLAUSE_SAFELEN:
1886 case OMP_CLAUSE_ASYNC:
1887 case OMP_CLAUSE_WAIT:
1888 case OMP_CLAUSE_GANG:
1889 case OMP_CLAUSE_WORKER:
1890 case OMP_CLAUSE_VECTOR:
1891 break;
1893 case OMP_CLAUSE_ALIGNED:
1894 decl = OMP_CLAUSE_DECL (c);
1895 if (is_global_var (decl)
1896 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1897 install_var_local (decl, ctx);
1898 break;
1900 case OMP_CLAUSE_DEVICE_RESIDENT:
1901 case OMP_CLAUSE_USE_DEVICE:
1902 case OMP_CLAUSE__CACHE_:
1903 case OMP_CLAUSE_INDEPENDENT:
1904 case OMP_CLAUSE_AUTO:
1905 case OMP_CLAUSE_SEQ:
1906 sorry ("Clause not supported yet");
1907 break;
1909 default:
1910 gcc_unreachable ();
1914 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1916 switch (OMP_CLAUSE_CODE (c))
1918 case OMP_CLAUSE_LASTPRIVATE:
1919 /* Let the corresponding firstprivate clause create
1920 the variable. */
1921 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1922 scan_array_reductions = true;
1923 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1924 break;
1925 /* FALLTHRU */
1927 case OMP_CLAUSE_FIRSTPRIVATE:
1928 if (is_gimple_omp_oacc (ctx->stmt))
1930 sorry ("clause not supported yet");
1931 break;
1933 /* FALLTHRU */
1934 case OMP_CLAUSE_PRIVATE:
1935 case OMP_CLAUSE_REDUCTION:
1936 case OMP_CLAUSE_LINEAR:
1937 decl = OMP_CLAUSE_DECL (c);
1938 if (is_variable_sized (decl))
1939 install_var_local (decl, ctx);
1940 fixup_remapped_decl (decl, ctx,
1941 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1942 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1943 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1944 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1945 scan_array_reductions = true;
1946 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1947 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1948 scan_array_reductions = true;
1949 break;
1951 case OMP_CLAUSE_SHARED:
1952 /* Ignore shared directives in teams construct. */
1953 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1954 break;
1955 decl = OMP_CLAUSE_DECL (c);
1956 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1957 fixup_remapped_decl (decl, ctx, false);
1958 break;
1960 case OMP_CLAUSE_MAP:
1961 if (!is_gimple_omp_offloaded (ctx->stmt))
1962 break;
1963 decl = OMP_CLAUSE_DECL (c);
1964 if (DECL_P (decl)
1965 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1966 && varpool_node::get_create (decl)->offloadable)
1967 break;
1968 if (DECL_P (decl))
1970 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1971 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1972 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1974 tree new_decl = lookup_decl (decl, ctx);
1975 TREE_TYPE (new_decl)
1976 = remap_type (TREE_TYPE (decl), &ctx->cb);
1978 else if (DECL_SIZE (decl)
1979 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1981 tree decl2 = DECL_VALUE_EXPR (decl);
1982 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1983 decl2 = TREE_OPERAND (decl2, 0);
1984 gcc_assert (DECL_P (decl2));
1985 fixup_remapped_decl (decl2, ctx, false);
1986 fixup_remapped_decl (decl, ctx, true);
1988 else
1989 fixup_remapped_decl (decl, ctx, false);
1991 break;
1993 case OMP_CLAUSE_COPYPRIVATE:
1994 case OMP_CLAUSE_COPYIN:
1995 case OMP_CLAUSE_DEFAULT:
1996 case OMP_CLAUSE_IF:
1997 case OMP_CLAUSE_NUM_THREADS:
1998 case OMP_CLAUSE_NUM_TEAMS:
1999 case OMP_CLAUSE_THREAD_LIMIT:
2000 case OMP_CLAUSE_DEVICE:
2001 case OMP_CLAUSE_SCHEDULE:
2002 case OMP_CLAUSE_DIST_SCHEDULE:
2003 case OMP_CLAUSE_NOWAIT:
2004 case OMP_CLAUSE_ORDERED:
2005 case OMP_CLAUSE_COLLAPSE:
2006 case OMP_CLAUSE_UNTIED:
2007 case OMP_CLAUSE_FINAL:
2008 case OMP_CLAUSE_MERGEABLE:
2009 case OMP_CLAUSE_PROC_BIND:
2010 case OMP_CLAUSE_SAFELEN:
2011 case OMP_CLAUSE_ALIGNED:
2012 case OMP_CLAUSE_DEPEND:
2013 case OMP_CLAUSE__LOOPTEMP_:
2014 case OMP_CLAUSE_TO:
2015 case OMP_CLAUSE_FROM:
2016 case OMP_CLAUSE__CILK_FOR_COUNT_:
2017 case OMP_CLAUSE_ASYNC:
2018 case OMP_CLAUSE_WAIT:
2019 case OMP_CLAUSE_NUM_GANGS:
2020 case OMP_CLAUSE_NUM_WORKERS:
2021 case OMP_CLAUSE_VECTOR_LENGTH:
2022 case OMP_CLAUSE_GANG:
2023 case OMP_CLAUSE_WORKER:
2024 case OMP_CLAUSE_VECTOR:
2025 break;
2027 case OMP_CLAUSE_DEVICE_RESIDENT:
2028 case OMP_CLAUSE_USE_DEVICE:
2029 case OMP_CLAUSE__CACHE_:
2030 case OMP_CLAUSE_INDEPENDENT:
2031 case OMP_CLAUSE_AUTO:
2032 case OMP_CLAUSE_SEQ:
2033 sorry ("Clause not supported yet");
2034 break;
2036 default:
2037 gcc_unreachable ();
2041 gcc_checking_assert (!scan_array_reductions
2042 || !is_gimple_omp_oacc (ctx->stmt));
2043 if (scan_array_reductions)
2044 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2045 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2046 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2048 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2049 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2051 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2052 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2053 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2054 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2055 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2056 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2059 /* Create a new name for omp child function. Returns an identifier. If
2060 IS_CILK_FOR is true then the suffix for the child function is
2061 "_cilk_for_fn." */
2063 static tree
2064 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2066 if (is_cilk_for)
2067 return clone_function_name (current_function_decl, "_cilk_for_fn");
2068 return clone_function_name (current_function_decl,
2069 task_copy ? "_omp_cpyfn" : "_omp_fn");
2072 /* Returns the type of the induction variable for the child function for
2073 _Cilk_for and the types for _high and _low variables based on TYPE. */
2075 static tree
2076 cilk_for_check_loop_diff_type (tree type)
2078 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2080 if (TYPE_UNSIGNED (type))
2081 return uint32_type_node;
2082 else
2083 return integer_type_node;
2085 else
2087 if (TYPE_UNSIGNED (type))
2088 return uint64_type_node;
2089 else
2090 return long_long_integer_type_node;
2094 /* Build a decl for the omp child function. It'll not contain a body
2095 yet, just the bare decl. */
2097 static void
2098 create_omp_child_function (omp_context *ctx, bool task_copy)
2100 tree decl, type, name, t;
2102 tree cilk_for_count
2103 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2104 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2105 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2106 tree cilk_var_type = NULL_TREE;
2108 name = create_omp_child_function_name (task_copy,
2109 cilk_for_count != NULL_TREE);
2110 if (task_copy)
2111 type = build_function_type_list (void_type_node, ptr_type_node,
2112 ptr_type_node, NULL_TREE);
2113 else if (cilk_for_count)
2115 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2116 cilk_var_type = cilk_for_check_loop_diff_type (type);
2117 type = build_function_type_list (void_type_node, ptr_type_node,
2118 cilk_var_type, cilk_var_type, NULL_TREE);
2120 else
2121 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2123 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2125 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2126 || !task_copy);
2127 if (!task_copy)
2128 ctx->cb.dst_fn = decl;
2129 else
2130 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2132 TREE_STATIC (decl) = 1;
2133 TREE_USED (decl) = 1;
2134 DECL_ARTIFICIAL (decl) = 1;
2135 DECL_IGNORED_P (decl) = 0;
2136 TREE_PUBLIC (decl) = 0;
2137 DECL_UNINLINABLE (decl) = 1;
2138 DECL_EXTERNAL (decl) = 0;
2139 DECL_CONTEXT (decl) = NULL_TREE;
2140 DECL_INITIAL (decl) = make_node (BLOCK);
2141 if (cgraph_node::get (current_function_decl)->offloadable)
2142 cgraph_node::get_create (decl)->offloadable = 1;
2143 else
2145 omp_context *octx;
2146 for (octx = ctx; octx; octx = octx->outer)
2147 if (is_gimple_omp_offloaded (octx->stmt))
2149 cgraph_node::get_create (decl)->offloadable = 1;
2150 #ifdef ENABLE_OFFLOADING
2151 g->have_offload = true;
2152 #endif
2153 break;
2157 if (cgraph_node::get_create (decl)->offloadable
2158 && !lookup_attribute ("omp declare target",
2159 DECL_ATTRIBUTES (current_function_decl)))
2160 DECL_ATTRIBUTES (decl)
2161 = tree_cons (get_identifier ("omp target entrypoint"),
2162 NULL_TREE, DECL_ATTRIBUTES (decl));
2164 t = build_decl (DECL_SOURCE_LOCATION (decl),
2165 RESULT_DECL, NULL_TREE, void_type_node);
2166 DECL_ARTIFICIAL (t) = 1;
2167 DECL_IGNORED_P (t) = 1;
2168 DECL_CONTEXT (t) = decl;
2169 DECL_RESULT (decl) = t;
2171 /* _Cilk_for's child function requires two extra parameters called
2172 __low and __high that are set the by Cilk runtime when it calls this
2173 function. */
2174 if (cilk_for_count)
2176 t = build_decl (DECL_SOURCE_LOCATION (decl),
2177 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2178 DECL_ARTIFICIAL (t) = 1;
2179 DECL_NAMELESS (t) = 1;
2180 DECL_ARG_TYPE (t) = ptr_type_node;
2181 DECL_CONTEXT (t) = current_function_decl;
2182 TREE_USED (t) = 1;
2183 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2184 DECL_ARGUMENTS (decl) = t;
2186 t = build_decl (DECL_SOURCE_LOCATION (decl),
2187 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2188 DECL_ARTIFICIAL (t) = 1;
2189 DECL_NAMELESS (t) = 1;
2190 DECL_ARG_TYPE (t) = ptr_type_node;
2191 DECL_CONTEXT (t) = current_function_decl;
2192 TREE_USED (t) = 1;
2193 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2194 DECL_ARGUMENTS (decl) = t;
2197 tree data_name = get_identifier (".omp_data_i");
2198 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2199 ptr_type_node);
2200 DECL_ARTIFICIAL (t) = 1;
2201 DECL_NAMELESS (t) = 1;
2202 DECL_ARG_TYPE (t) = ptr_type_node;
2203 DECL_CONTEXT (t) = current_function_decl;
2204 TREE_USED (t) = 1;
2205 if (cilk_for_count)
2206 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2207 DECL_ARGUMENTS (decl) = t;
2208 if (!task_copy)
2209 ctx->receiver_decl = t;
2210 else
2212 t = build_decl (DECL_SOURCE_LOCATION (decl),
2213 PARM_DECL, get_identifier (".omp_data_o"),
2214 ptr_type_node);
2215 DECL_ARTIFICIAL (t) = 1;
2216 DECL_NAMELESS (t) = 1;
2217 DECL_ARG_TYPE (t) = ptr_type_node;
2218 DECL_CONTEXT (t) = current_function_decl;
2219 TREE_USED (t) = 1;
2220 TREE_ADDRESSABLE (t) = 1;
2221 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2222 DECL_ARGUMENTS (decl) = t;
2225 /* Allocate memory for the function structure. The call to
2226 allocate_struct_function clobbers CFUN, so we need to restore
2227 it afterward. */
2228 push_struct_function (decl);
2229 cfun->function_end_locus = gimple_location (ctx->stmt);
2230 pop_cfun ();
2233 /* Callback for walk_gimple_seq. Check if combined parallel
2234 contains gimple_omp_for_combined_into_p OMP_FOR. */
2236 static tree
2237 find_combined_for (gimple_stmt_iterator *gsi_p,
2238 bool *handled_ops_p,
2239 struct walk_stmt_info *wi)
2241 gimple stmt = gsi_stmt (*gsi_p);
2243 *handled_ops_p = true;
2244 switch (gimple_code (stmt))
2246 WALK_SUBSTMTS;
2248 case GIMPLE_OMP_FOR:
2249 if (gimple_omp_for_combined_into_p (stmt)
2250 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2252 wi->info = stmt;
2253 return integer_zero_node;
2255 break;
2256 default:
2257 break;
2259 return NULL;
2262 /* Scan an OpenMP parallel directive. */
2264 static void
2265 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2267 omp_context *ctx;
2268 tree name;
2269 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2271 /* Ignore parallel directives with empty bodies, unless there
2272 are copyin clauses. */
2273 if (optimize > 0
2274 && empty_body_p (gimple_omp_body (stmt))
2275 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2276 OMP_CLAUSE_COPYIN) == NULL)
2278 gsi_replace (gsi, gimple_build_nop (), false);
2279 return;
2282 if (gimple_omp_parallel_combined_p (stmt))
2284 struct walk_stmt_info wi;
2286 memset (&wi, 0, sizeof (wi));
2287 wi.val_only = true;
2288 walk_gimple_seq (gimple_omp_body (stmt),
2289 find_combined_for, NULL, &wi);
2290 if (wi.info)
2292 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2293 struct omp_for_data fd;
2294 extract_omp_for_data (for_stmt, &fd, NULL);
2295 /* We need two temporaries with fd.loop.v type (istart/iend)
2296 and then (fd.collapse - 1) temporaries with the same
2297 type for count2 ... countN-1 vars if not constant. */
2298 size_t count = 2, i;
2299 tree type = fd.iter_type;
2300 if (fd.collapse > 1
2301 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2302 count += fd.collapse - 1;
2303 for (i = 0; i < count; i++)
2305 tree temp = create_tmp_var (type);
2306 tree c = build_omp_clause (UNKNOWN_LOCATION,
2307 OMP_CLAUSE__LOOPTEMP_);
2308 insert_decl_map (&outer_ctx->cb, temp, temp);
2309 OMP_CLAUSE_DECL (c) = temp;
2310 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2311 gimple_omp_parallel_set_clauses (stmt, c);
2316 ctx = new_omp_context (stmt, outer_ctx);
2317 taskreg_contexts.safe_push (ctx);
2318 if (taskreg_nesting_level > 1)
2319 ctx->is_nested = true;
2320 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2321 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2322 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2323 name = create_tmp_var_name (".omp_data_s");
2324 name = build_decl (gimple_location (stmt),
2325 TYPE_DECL, name, ctx->record_type);
2326 DECL_ARTIFICIAL (name) = 1;
2327 DECL_NAMELESS (name) = 1;
2328 TYPE_NAME (ctx->record_type) = name;
2329 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2330 create_omp_child_function (ctx, false);
2331 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2333 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2334 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2336 if (TYPE_FIELDS (ctx->record_type) == NULL)
2337 ctx->record_type = ctx->receiver_decl = NULL;
2340 /* Scan an OpenMP task directive. */
2342 static void
2343 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2345 omp_context *ctx;
2346 tree name, t;
2347 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2349 /* Ignore task directives with empty bodies. */
2350 if (optimize > 0
2351 && empty_body_p (gimple_omp_body (stmt)))
2353 gsi_replace (gsi, gimple_build_nop (), false);
2354 return;
2357 ctx = new_omp_context (stmt, outer_ctx);
2358 taskreg_contexts.safe_push (ctx);
2359 if (taskreg_nesting_level > 1)
2360 ctx->is_nested = true;
2361 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2362 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2363 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2364 name = create_tmp_var_name (".omp_data_s");
2365 name = build_decl (gimple_location (stmt),
2366 TYPE_DECL, name, ctx->record_type);
2367 DECL_ARTIFICIAL (name) = 1;
2368 DECL_NAMELESS (name) = 1;
2369 TYPE_NAME (ctx->record_type) = name;
2370 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2371 create_omp_child_function (ctx, false);
2372 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2374 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2376 if (ctx->srecord_type)
2378 name = create_tmp_var_name (".omp_data_a");
2379 name = build_decl (gimple_location (stmt),
2380 TYPE_DECL, name, ctx->srecord_type);
2381 DECL_ARTIFICIAL (name) = 1;
2382 DECL_NAMELESS (name) = 1;
2383 TYPE_NAME (ctx->srecord_type) = name;
2384 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2385 create_omp_child_function (ctx, true);
2388 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2390 if (TYPE_FIELDS (ctx->record_type) == NULL)
2392 ctx->record_type = ctx->receiver_decl = NULL;
2393 t = build_int_cst (long_integer_type_node, 0);
2394 gimple_omp_task_set_arg_size (stmt, t);
2395 t = build_int_cst (long_integer_type_node, 1);
2396 gimple_omp_task_set_arg_align (stmt, t);
2401 /* If any decls have been made addressable during scan_omp,
2402 adjust their fields if needed, and layout record types
2403 of parallel/task constructs. */
2405 static void
2406 finish_taskreg_scan (omp_context *ctx)
2408 if (ctx->record_type == NULL_TREE)
2409 return;
2411 /* If any task_shared_vars were needed, verify all
2412 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2413 statements if use_pointer_for_field hasn't changed
2414 because of that. If it did, update field types now. */
2415 if (task_shared_vars)
2417 tree c;
2419 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2420 c; c = OMP_CLAUSE_CHAIN (c))
2421 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2423 tree decl = OMP_CLAUSE_DECL (c);
2425 /* Global variables don't need to be copied,
2426 the receiver side will use them directly. */
2427 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2428 continue;
2429 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2430 || !use_pointer_for_field (decl, ctx))
2431 continue;
2432 tree field = lookup_field (decl, ctx);
2433 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2434 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2435 continue;
2436 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2437 TREE_THIS_VOLATILE (field) = 0;
2438 DECL_USER_ALIGN (field) = 0;
2439 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2440 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2441 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2442 if (ctx->srecord_type)
2444 tree sfield = lookup_sfield (decl, ctx);
2445 TREE_TYPE (sfield) = TREE_TYPE (field);
2446 TREE_THIS_VOLATILE (sfield) = 0;
2447 DECL_USER_ALIGN (sfield) = 0;
2448 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2449 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2450 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2455 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2457 layout_type (ctx->record_type);
2458 fixup_child_record_type (ctx);
2460 else
2462 location_t loc = gimple_location (ctx->stmt);
2463 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2464 /* Move VLA fields to the end. */
2465 p = &TYPE_FIELDS (ctx->record_type);
2466 while (*p)
2467 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2468 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2470 *q = *p;
2471 *p = TREE_CHAIN (*p);
2472 TREE_CHAIN (*q) = NULL_TREE;
2473 q = &TREE_CHAIN (*q);
2475 else
2476 p = &DECL_CHAIN (*p);
2477 *p = vla_fields;
2478 layout_type (ctx->record_type);
2479 fixup_child_record_type (ctx);
2480 if (ctx->srecord_type)
2481 layout_type (ctx->srecord_type);
2482 tree t = fold_convert_loc (loc, long_integer_type_node,
2483 TYPE_SIZE_UNIT (ctx->record_type));
2484 gimple_omp_task_set_arg_size (ctx->stmt, t);
2485 t = build_int_cst (long_integer_type_node,
2486 TYPE_ALIGN_UNIT (ctx->record_type));
2487 gimple_omp_task_set_arg_align (ctx->stmt, t);
2492 static omp_context *
2493 enclosing_target_ctx (omp_context *ctx)
2495 while (ctx != NULL
2496 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2497 ctx = ctx->outer;
2498 gcc_assert (ctx != NULL);
2499 return ctx;
2502 static bool
2503 oacc_loop_or_target_p (gimple stmt)
2505 enum gimple_code outer_type = gimple_code (stmt);
2506 return ((outer_type == GIMPLE_OMP_TARGET
2507 && ((gimple_omp_target_kind (stmt)
2508 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2509 || (gimple_omp_target_kind (stmt)
2510 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2511 || (outer_type == GIMPLE_OMP_FOR
2512 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2515 /* Scan a GIMPLE_OMP_FOR. */
2517 static void
2518 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2520 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
2521 omp_context *ctx;
2522 size_t i;
2523 tree clauses = gimple_omp_for_clauses (stmt);
2525 if (outer_ctx)
2526 outer_type = gimple_code (outer_ctx->stmt);
2528 ctx = new_omp_context (stmt, outer_ctx);
2530 if (is_gimple_omp_oacc (stmt))
2532 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2533 ctx->gwv_this = outer_ctx->gwv_this;
2534 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2536 int val;
2537 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2538 val = MASK_GANG;
2539 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2540 val = MASK_WORKER;
2541 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2542 val = MASK_VECTOR;
2543 else
2544 continue;
2545 ctx->gwv_this |= val;
2546 if (!outer_ctx)
2548 /* Skip; not nested inside a region. */
2549 continue;
2551 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2553 /* Skip; not nested inside an OpenACC region. */
2554 continue;
2556 if (outer_type == GIMPLE_OMP_FOR)
2557 outer_ctx->gwv_below |= val;
2558 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2560 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2561 if (gimple_omp_target_kind (enclosing->stmt)
2562 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2563 error_at (gimple_location (stmt),
2564 "no arguments allowed to gang, worker and vector clauses inside parallel");
2569 scan_sharing_clauses (clauses, ctx);
2571 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2572 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2574 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2575 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2576 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2577 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2579 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2581 if (is_gimple_omp_oacc (stmt))
2583 if (ctx->gwv_this & ctx->gwv_below)
2584 error_at (gimple_location (stmt),
2585 "gang, worker and vector may occur only once in a loop nest");
2586 else if (ctx->gwv_below != 0
2587 && ctx->gwv_this > ctx->gwv_below)
2588 error_at (gimple_location (stmt),
2589 "gang, worker and vector must occur in this order in a loop nest");
2590 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2591 outer_ctx->gwv_below |= ctx->gwv_below;
2595 /* Scan an OpenMP sections directive. */
2597 static void
2598 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2600 omp_context *ctx;
2602 ctx = new_omp_context (stmt, outer_ctx);
2603 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2604 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2607 /* Scan an OpenMP single directive. */
2609 static void
2610 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2612 omp_context *ctx;
2613 tree name;
2615 ctx = new_omp_context (stmt, outer_ctx);
2616 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2617 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2618 name = create_tmp_var_name (".omp_copy_s");
2619 name = build_decl (gimple_location (stmt),
2620 TYPE_DECL, name, ctx->record_type);
2621 TYPE_NAME (ctx->record_type) = name;
2623 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2624 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2626 if (TYPE_FIELDS (ctx->record_type) == NULL)
2627 ctx->record_type = NULL;
2628 else
2629 layout_type (ctx->record_type);
2632 /* Scan a GIMPLE_OMP_TARGET. */
2634 static void
2635 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2637 omp_context *ctx;
2638 tree name;
2639 bool offloaded = is_gimple_omp_offloaded (stmt);
2640 tree clauses = gimple_omp_target_clauses (stmt);
2642 ctx = new_omp_context (stmt, outer_ctx);
2643 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2644 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2645 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2646 name = create_tmp_var_name (".omp_data_t");
2647 name = build_decl (gimple_location (stmt),
2648 TYPE_DECL, name, ctx->record_type);
2649 DECL_ARTIFICIAL (name) = 1;
2650 DECL_NAMELESS (name) = 1;
2651 TYPE_NAME (ctx->record_type) = name;
2652 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2653 if (offloaded)
2655 if (is_gimple_omp_oacc (stmt))
2656 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2657 0, 0);
2659 create_omp_child_function (ctx, false);
2660 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2663 if (is_gimple_omp_oacc (stmt))
2665 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2667 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2668 ctx->gwv_this |= MASK_GANG;
2669 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2670 ctx->gwv_this |= MASK_WORKER;
2671 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2672 ctx->gwv_this |= MASK_VECTOR;
2676 scan_sharing_clauses (clauses, ctx);
2677 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2679 if (TYPE_FIELDS (ctx->record_type) == NULL)
2680 ctx->record_type = ctx->receiver_decl = NULL;
2681 else
2683 TYPE_FIELDS (ctx->record_type)
2684 = nreverse (TYPE_FIELDS (ctx->record_type));
2685 #ifdef ENABLE_CHECKING
2686 tree field;
2687 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2688 for (field = TYPE_FIELDS (ctx->record_type);
2689 field;
2690 field = DECL_CHAIN (field))
2691 gcc_assert (DECL_ALIGN (field) == align);
2692 #endif
2693 layout_type (ctx->record_type);
2694 if (offloaded)
2695 fixup_child_record_type (ctx);
2699 /* Scan an OpenMP teams directive. */
2701 static void
2702 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2704 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2705 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2706 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2709 /* Check nesting restrictions. */
2710 static bool
2711 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2713 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2714 inside an OpenACC CTX. */
2715 if (!(is_gimple_omp (stmt)
2716 && is_gimple_omp_oacc (stmt)))
2718 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2719 if (is_gimple_omp (ctx_->stmt)
2720 && is_gimple_omp_oacc (ctx_->stmt))
2722 error_at (gimple_location (stmt),
2723 "non-OpenACC construct inside of OpenACC region");
2724 return false;
2728 if (ctx != NULL)
2730 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2731 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2733 error_at (gimple_location (stmt),
2734 "OpenMP constructs may not be nested inside simd region");
2735 return false;
2737 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2739 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2740 || (gimple_omp_for_kind (stmt)
2741 != GF_OMP_FOR_KIND_DISTRIBUTE))
2742 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2744 error_at (gimple_location (stmt),
2745 "only distribute or parallel constructs are allowed to "
2746 "be closely nested inside teams construct");
2747 return false;
2751 switch (gimple_code (stmt))
2753 case GIMPLE_OMP_FOR:
2754 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2755 return true;
2756 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2758 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2760 error_at (gimple_location (stmt),
2761 "distribute construct must be closely nested inside "
2762 "teams construct");
2763 return false;
2765 return true;
2767 /* FALLTHRU */
2768 case GIMPLE_CALL:
2769 if (is_gimple_call (stmt)
2770 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2771 == BUILT_IN_GOMP_CANCEL
2772 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2773 == BUILT_IN_GOMP_CANCELLATION_POINT))
2775 const char *bad = NULL;
2776 const char *kind = NULL;
2777 if (ctx == NULL)
2779 error_at (gimple_location (stmt), "orphaned %qs construct",
2780 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2781 == BUILT_IN_GOMP_CANCEL
2782 ? "#pragma omp cancel"
2783 : "#pragma omp cancellation point");
2784 return false;
2786 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2787 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2788 : 0)
2790 case 1:
2791 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2792 bad = "#pragma omp parallel";
2793 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2794 == BUILT_IN_GOMP_CANCEL
2795 && !integer_zerop (gimple_call_arg (stmt, 1)))
2796 ctx->cancellable = true;
2797 kind = "parallel";
2798 break;
2799 case 2:
2800 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2801 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2802 bad = "#pragma omp for";
2803 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2804 == BUILT_IN_GOMP_CANCEL
2805 && !integer_zerop (gimple_call_arg (stmt, 1)))
2807 ctx->cancellable = true;
2808 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2809 OMP_CLAUSE_NOWAIT))
2810 warning_at (gimple_location (stmt), 0,
2811 "%<#pragma omp cancel for%> inside "
2812 "%<nowait%> for construct");
2813 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2814 OMP_CLAUSE_ORDERED))
2815 warning_at (gimple_location (stmt), 0,
2816 "%<#pragma omp cancel for%> inside "
2817 "%<ordered%> for construct");
2819 kind = "for";
2820 break;
2821 case 4:
2822 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2823 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2824 bad = "#pragma omp sections";
2825 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2826 == BUILT_IN_GOMP_CANCEL
2827 && !integer_zerop (gimple_call_arg (stmt, 1)))
2829 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2831 ctx->cancellable = true;
2832 if (find_omp_clause (gimple_omp_sections_clauses
2833 (ctx->stmt),
2834 OMP_CLAUSE_NOWAIT))
2835 warning_at (gimple_location (stmt), 0,
2836 "%<#pragma omp cancel sections%> inside "
2837 "%<nowait%> sections construct");
2839 else
2841 gcc_assert (ctx->outer
2842 && gimple_code (ctx->outer->stmt)
2843 == GIMPLE_OMP_SECTIONS);
2844 ctx->outer->cancellable = true;
2845 if (find_omp_clause (gimple_omp_sections_clauses
2846 (ctx->outer->stmt),
2847 OMP_CLAUSE_NOWAIT))
2848 warning_at (gimple_location (stmt), 0,
2849 "%<#pragma omp cancel sections%> inside "
2850 "%<nowait%> sections construct");
2853 kind = "sections";
2854 break;
2855 case 8:
2856 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2857 bad = "#pragma omp task";
2858 else
2859 ctx->cancellable = true;
2860 kind = "taskgroup";
2861 break;
2862 default:
2863 error_at (gimple_location (stmt), "invalid arguments");
2864 return false;
2866 if (bad)
2868 error_at (gimple_location (stmt),
2869 "%<%s %s%> construct not closely nested inside of %qs",
2870 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2871 == BUILT_IN_GOMP_CANCEL
2872 ? "#pragma omp cancel"
2873 : "#pragma omp cancellation point", kind, bad);
2874 return false;
2877 /* FALLTHRU */
2878 case GIMPLE_OMP_SECTIONS:
2879 case GIMPLE_OMP_SINGLE:
2880 for (; ctx != NULL; ctx = ctx->outer)
2881 switch (gimple_code (ctx->stmt))
2883 case GIMPLE_OMP_FOR:
2884 case GIMPLE_OMP_SECTIONS:
2885 case GIMPLE_OMP_SINGLE:
2886 case GIMPLE_OMP_ORDERED:
2887 case GIMPLE_OMP_MASTER:
2888 case GIMPLE_OMP_TASK:
2889 case GIMPLE_OMP_CRITICAL:
2890 if (is_gimple_call (stmt))
2892 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2893 != BUILT_IN_GOMP_BARRIER)
2894 return true;
2895 error_at (gimple_location (stmt),
2896 "barrier region may not be closely nested inside "
2897 "of work-sharing, critical, ordered, master or "
2898 "explicit task region");
2899 return false;
2901 error_at (gimple_location (stmt),
2902 "work-sharing region may not be closely nested inside "
2903 "of work-sharing, critical, ordered, master or explicit "
2904 "task region");
2905 return false;
2906 case GIMPLE_OMP_PARALLEL:
2907 return true;
2908 default:
2909 break;
2911 break;
2912 case GIMPLE_OMP_MASTER:
2913 for (; ctx != NULL; ctx = ctx->outer)
2914 switch (gimple_code (ctx->stmt))
2916 case GIMPLE_OMP_FOR:
2917 case GIMPLE_OMP_SECTIONS:
2918 case GIMPLE_OMP_SINGLE:
2919 case GIMPLE_OMP_TASK:
2920 error_at (gimple_location (stmt),
2921 "master region may not be closely nested inside "
2922 "of work-sharing or explicit task region");
2923 return false;
2924 case GIMPLE_OMP_PARALLEL:
2925 return true;
2926 default:
2927 break;
2929 break;
2930 case GIMPLE_OMP_ORDERED:
2931 for (; ctx != NULL; ctx = ctx->outer)
2932 switch (gimple_code (ctx->stmt))
2934 case GIMPLE_OMP_CRITICAL:
2935 case GIMPLE_OMP_TASK:
2936 error_at (gimple_location (stmt),
2937 "ordered region may not be closely nested inside "
2938 "of critical or explicit task region");
2939 return false;
2940 case GIMPLE_OMP_FOR:
2941 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2942 OMP_CLAUSE_ORDERED) == NULL)
2944 error_at (gimple_location (stmt),
2945 "ordered region must be closely nested inside "
2946 "a loop region with an ordered clause");
2947 return false;
2949 return true;
2950 case GIMPLE_OMP_PARALLEL:
2951 error_at (gimple_location (stmt),
2952 "ordered region must be closely nested inside "
2953 "a loop region with an ordered clause");
2954 return false;
2955 default:
2956 break;
2958 break;
2959 case GIMPLE_OMP_CRITICAL:
2961 tree this_stmt_name
2962 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2963 for (; ctx != NULL; ctx = ctx->outer)
2964 if (gomp_critical *other_crit
2965 = dyn_cast <gomp_critical *> (ctx->stmt))
2966 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2968 error_at (gimple_location (stmt),
2969 "critical region may not be nested inside a critical "
2970 "region with the same name");
2971 return false;
2974 break;
2975 case GIMPLE_OMP_TEAMS:
2976 if (ctx == NULL
2977 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2978 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2980 error_at (gimple_location (stmt),
2981 "teams construct not closely nested inside of target "
2982 "region");
2983 return false;
2985 break;
2986 case GIMPLE_OMP_TARGET:
2987 for (; ctx != NULL; ctx = ctx->outer)
2989 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2991 if (is_gimple_omp (stmt)
2992 && is_gimple_omp_oacc (stmt)
2993 && is_gimple_omp (ctx->stmt))
2995 error_at (gimple_location (stmt),
2996 "OpenACC construct inside of non-OpenACC region");
2997 return false;
2999 continue;
3002 const char *stmt_name, *ctx_stmt_name;
3003 switch (gimple_omp_target_kind (stmt))
3005 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3006 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3007 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3008 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3009 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3010 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3011 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3012 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3013 default: gcc_unreachable ();
3015 switch (gimple_omp_target_kind (ctx->stmt))
3017 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3018 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3019 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3020 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3021 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3022 default: gcc_unreachable ();
3025 /* OpenACC/OpenMP mismatch? */
3026 if (is_gimple_omp_oacc (stmt)
3027 != is_gimple_omp_oacc (ctx->stmt))
3029 error_at (gimple_location (stmt),
3030 "%s %s construct inside of %s %s region",
3031 (is_gimple_omp_oacc (stmt)
3032 ? "OpenACC" : "OpenMP"), stmt_name,
3033 (is_gimple_omp_oacc (ctx->stmt)
3034 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3035 return false;
3037 if (is_gimple_omp_offloaded (ctx->stmt))
3039 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3040 if (is_gimple_omp_oacc (ctx->stmt))
3042 error_at (gimple_location (stmt),
3043 "%s construct inside of %s region",
3044 stmt_name, ctx_stmt_name);
3045 return false;
3047 else
3049 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3050 warning_at (gimple_location (stmt), 0,
3051 "%s construct inside of %s region",
3052 stmt_name, ctx_stmt_name);
3056 break;
3057 default:
3058 break;
3060 return true;
3064 /* Helper function scan_omp.
3066 Callback for walk_tree or operators in walk_gimple_stmt used to
3067 scan for OMP directives in TP. */
3069 static tree
3070 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3072 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3073 omp_context *ctx = (omp_context *) wi->info;
3074 tree t = *tp;
3076 switch (TREE_CODE (t))
3078 case VAR_DECL:
3079 case PARM_DECL:
3080 case LABEL_DECL:
3081 case RESULT_DECL:
3082 if (ctx)
3083 *tp = remap_decl (t, &ctx->cb);
3084 break;
3086 default:
3087 if (ctx && TYPE_P (t))
3088 *tp = remap_type (t, &ctx->cb);
3089 else if (!DECL_P (t))
3091 *walk_subtrees = 1;
3092 if (ctx)
3094 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3095 if (tem != TREE_TYPE (t))
3097 if (TREE_CODE (t) == INTEGER_CST)
3098 *tp = wide_int_to_tree (tem, t);
3099 else
3100 TREE_TYPE (t) = tem;
3104 break;
3107 return NULL_TREE;
3110 /* Return true if FNDECL is a setjmp or a longjmp. */
3112 static bool
3113 setjmp_or_longjmp_p (const_tree fndecl)
3115 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3116 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3117 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3118 return true;
3120 tree declname = DECL_NAME (fndecl);
3121 if (!declname)
3122 return false;
3123 const char *name = IDENTIFIER_POINTER (declname);
3124 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3128 /* Helper function for scan_omp.
3130 Callback for walk_gimple_stmt used to scan for OMP directives in
3131 the current statement in GSI. */
3133 static tree
3134 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3135 struct walk_stmt_info *wi)
3137 gimple stmt = gsi_stmt (*gsi);
3138 omp_context *ctx = (omp_context *) wi->info;
3140 if (gimple_has_location (stmt))
3141 input_location = gimple_location (stmt);
3143 /* Check the nesting restrictions. */
3144 bool remove = false;
3145 if (is_gimple_omp (stmt))
3146 remove = !check_omp_nesting_restrictions (stmt, ctx);
3147 else if (is_gimple_call (stmt))
3149 tree fndecl = gimple_call_fndecl (stmt);
3150 if (fndecl)
3152 if (setjmp_or_longjmp_p (fndecl)
3153 && ctx
3154 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3155 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3157 remove = true;
3158 error_at (gimple_location (stmt),
3159 "setjmp/longjmp inside simd construct");
3161 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3162 switch (DECL_FUNCTION_CODE (fndecl))
3164 case BUILT_IN_GOMP_BARRIER:
3165 case BUILT_IN_GOMP_CANCEL:
3166 case BUILT_IN_GOMP_CANCELLATION_POINT:
3167 case BUILT_IN_GOMP_TASKYIELD:
3168 case BUILT_IN_GOMP_TASKWAIT:
3169 case BUILT_IN_GOMP_TASKGROUP_START:
3170 case BUILT_IN_GOMP_TASKGROUP_END:
3171 remove = !check_omp_nesting_restrictions (stmt, ctx);
3172 break;
3173 default:
3174 break;
3178 if (remove)
3180 stmt = gimple_build_nop ();
3181 gsi_replace (gsi, stmt, false);
3184 *handled_ops_p = true;
3186 switch (gimple_code (stmt))
3188 case GIMPLE_OMP_PARALLEL:
3189 taskreg_nesting_level++;
3190 scan_omp_parallel (gsi, ctx);
3191 taskreg_nesting_level--;
3192 break;
3194 case GIMPLE_OMP_TASK:
3195 taskreg_nesting_level++;
3196 scan_omp_task (gsi, ctx);
3197 taskreg_nesting_level--;
3198 break;
3200 case GIMPLE_OMP_FOR:
3201 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3202 break;
3204 case GIMPLE_OMP_SECTIONS:
3205 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3206 break;
3208 case GIMPLE_OMP_SINGLE:
3209 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3210 break;
3212 case GIMPLE_OMP_SECTION:
3213 case GIMPLE_OMP_MASTER:
3214 case GIMPLE_OMP_TASKGROUP:
3215 case GIMPLE_OMP_ORDERED:
3216 case GIMPLE_OMP_CRITICAL:
3217 ctx = new_omp_context (stmt, ctx);
3218 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3219 break;
3221 case GIMPLE_OMP_TARGET:
3222 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3223 break;
3225 case GIMPLE_OMP_TEAMS:
3226 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3227 break;
3229 case GIMPLE_BIND:
3231 tree var;
3233 *handled_ops_p = false;
3234 if (ctx)
3235 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3236 var ;
3237 var = DECL_CHAIN (var))
3238 insert_decl_map (&ctx->cb, var, var);
3240 break;
3241 default:
3242 *handled_ops_p = false;
3243 break;
3246 return NULL_TREE;
3250 /* Scan all the statements starting at the current statement. CTX
3251 contains context information about the OMP directives and
3252 clauses found during the scan. */
3254 static void
3255 scan_omp (gimple_seq *body_p, omp_context *ctx)
3257 location_t saved_location;
3258 struct walk_stmt_info wi;
3260 memset (&wi, 0, sizeof (wi));
3261 wi.info = ctx;
3262 wi.want_locations = true;
3264 saved_location = input_location;
3265 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3266 input_location = saved_location;
3269 /* Re-gimplification and code generation routines. */
3271 /* Build a call to GOMP_barrier. */
3273 static gimple
3274 build_omp_barrier (tree lhs)
3276 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3277 : BUILT_IN_GOMP_BARRIER);
3278 gcall *g = gimple_build_call (fndecl, 0);
3279 if (lhs)
3280 gimple_call_set_lhs (g, lhs);
3281 return g;
3284 /* If a context was created for STMT when it was scanned, return it. */
3286 static omp_context *
3287 maybe_lookup_ctx (gimple stmt)
3289 splay_tree_node n;
3290 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3291 return n ? (omp_context *) n->value : NULL;
3295 /* Find the mapping for DECL in CTX or the immediately enclosing
3296 context that has a mapping for DECL.
3298 If CTX is a nested parallel directive, we may have to use the decl
3299 mappings created in CTX's parent context. Suppose that we have the
3300 following parallel nesting (variable UIDs showed for clarity):
3302 iD.1562 = 0;
3303 #omp parallel shared(iD.1562) -> outer parallel
3304 iD.1562 = iD.1562 + 1;
3306 #omp parallel shared (iD.1562) -> inner parallel
3307 iD.1562 = iD.1562 - 1;
3309 Each parallel structure will create a distinct .omp_data_s structure
3310 for copying iD.1562 in/out of the directive:
3312 outer parallel .omp_data_s.1.i -> iD.1562
3313 inner parallel .omp_data_s.2.i -> iD.1562
3315 A shared variable mapping will produce a copy-out operation before
3316 the parallel directive and a copy-in operation after it. So, in
3317 this case we would have:
3319 iD.1562 = 0;
3320 .omp_data_o.1.i = iD.1562;
3321 #omp parallel shared(iD.1562) -> outer parallel
3322 .omp_data_i.1 = &.omp_data_o.1
3323 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3325 .omp_data_o.2.i = iD.1562; -> **
3326 #omp parallel shared(iD.1562) -> inner parallel
3327 .omp_data_i.2 = &.omp_data_o.2
3328 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3331 ** This is a problem. The symbol iD.1562 cannot be referenced
3332 inside the body of the outer parallel region. But since we are
3333 emitting this copy operation while expanding the inner parallel
3334 directive, we need to access the CTX structure of the outer
3335 parallel directive to get the correct mapping:
3337 .omp_data_o.2.i = .omp_data_i.1->i
3339 Since there may be other workshare or parallel directives enclosing
3340 the parallel directive, it may be necessary to walk up the context
3341 parent chain. This is not a problem in general because nested
3342 parallelism happens only rarely. */
3344 static tree
3345 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3347 tree t;
3348 omp_context *up;
3350 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3351 t = maybe_lookup_decl (decl, up);
3353 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3355 return t ? t : decl;
3359 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3360 in outer contexts. */
3362 static tree
3363 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3365 tree t = NULL;
3366 omp_context *up;
3368 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3369 t = maybe_lookup_decl (decl, up);
3371 return t ? t : decl;
3375 /* Construct the initialization value for reduction CLAUSE. */
3377 tree
3378 omp_reduction_init (tree clause, tree type)
3380 location_t loc = OMP_CLAUSE_LOCATION (clause);
3381 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3383 case PLUS_EXPR:
3384 case MINUS_EXPR:
3385 case BIT_IOR_EXPR:
3386 case BIT_XOR_EXPR:
3387 case TRUTH_OR_EXPR:
3388 case TRUTH_ORIF_EXPR:
3389 case TRUTH_XOR_EXPR:
3390 case NE_EXPR:
3391 return build_zero_cst (type);
3393 case MULT_EXPR:
3394 case TRUTH_AND_EXPR:
3395 case TRUTH_ANDIF_EXPR:
3396 case EQ_EXPR:
3397 return fold_convert_loc (loc, type, integer_one_node);
3399 case BIT_AND_EXPR:
3400 return fold_convert_loc (loc, type, integer_minus_one_node);
3402 case MAX_EXPR:
3403 if (SCALAR_FLOAT_TYPE_P (type))
3405 REAL_VALUE_TYPE max, min;
3406 if (HONOR_INFINITIES (type))
3408 real_inf (&max);
3409 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3411 else
3412 real_maxval (&min, 1, TYPE_MODE (type));
3413 return build_real (type, min);
3415 else if (POINTER_TYPE_P (type))
3417 wide_int min
3418 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3419 return wide_int_to_tree (type, min);
3421 else
3423 gcc_assert (INTEGRAL_TYPE_P (type));
3424 return TYPE_MIN_VALUE (type);
3427 case MIN_EXPR:
3428 if (SCALAR_FLOAT_TYPE_P (type))
3430 REAL_VALUE_TYPE max;
3431 if (HONOR_INFINITIES (type))
3432 real_inf (&max);
3433 else
3434 real_maxval (&max, 0, TYPE_MODE (type));
3435 return build_real (type, max);
3437 else if (POINTER_TYPE_P (type))
3439 wide_int max
3440 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3441 return wide_int_to_tree (type, max);
3443 else
3445 gcc_assert (INTEGRAL_TYPE_P (type));
3446 return TYPE_MAX_VALUE (type);
3449 default:
3450 gcc_unreachable ();
3454 /* Return alignment to be assumed for var in CLAUSE, which should be
3455 OMP_CLAUSE_ALIGNED. */
3457 static tree
3458 omp_clause_aligned_alignment (tree clause)
3460 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3461 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3463 /* Otherwise return implementation defined alignment. */
3464 unsigned int al = 1;
3465 machine_mode mode, vmode;
3466 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3467 if (vs)
3468 vs = 1 << floor_log2 (vs);
3469 static enum mode_class classes[]
3470 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3471 for (int i = 0; i < 4; i += 2)
3472 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3473 mode != VOIDmode;
3474 mode = GET_MODE_WIDER_MODE (mode))
3476 vmode = targetm.vectorize.preferred_simd_mode (mode);
3477 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3478 continue;
3479 while (vs
3480 && GET_MODE_SIZE (vmode) < vs
3481 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3482 vmode = GET_MODE_2XWIDER_MODE (vmode);
3484 tree type = lang_hooks.types.type_for_mode (mode, 1);
3485 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3486 continue;
3487 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3488 / GET_MODE_SIZE (mode));
3489 if (TYPE_MODE (type) != vmode)
3490 continue;
3491 if (TYPE_ALIGN_UNIT (type) > al)
3492 al = TYPE_ALIGN_UNIT (type);
3494 return build_int_cst (integer_type_node, al);
3497 /* Return maximum possible vectorization factor for the target. */
3499 static int
3500 omp_max_vf (void)
3502 if (!optimize
3503 || optimize_debug
3504 || !flag_tree_loop_optimize
3505 || (!flag_tree_loop_vectorize
3506 && (global_options_set.x_flag_tree_loop_vectorize
3507 || global_options_set.x_flag_tree_vectorize)))
3508 return 1;
3510 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3511 if (vs)
3513 vs = 1 << floor_log2 (vs);
3514 return vs;
3516 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3517 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3518 return GET_MODE_NUNITS (vqimode);
3519 return 1;
3522 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3523 privatization. */
3525 static bool
3526 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3527 tree &idx, tree &lane, tree &ivar, tree &lvar)
3529 if (max_vf == 0)
3531 max_vf = omp_max_vf ();
3532 if (max_vf > 1)
3534 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3535 OMP_CLAUSE_SAFELEN);
3536 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3537 max_vf = 1;
3538 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3539 max_vf) == -1)
3540 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3542 if (max_vf > 1)
3544 idx = create_tmp_var (unsigned_type_node);
3545 lane = create_tmp_var (unsigned_type_node);
3548 if (max_vf == 1)
3549 return false;
3551 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3552 tree avar = create_tmp_var_raw (atype);
3553 if (TREE_ADDRESSABLE (new_var))
3554 TREE_ADDRESSABLE (avar) = 1;
3555 DECL_ATTRIBUTES (avar)
3556 = tree_cons (get_identifier ("omp simd array"), NULL,
3557 DECL_ATTRIBUTES (avar));
3558 gimple_add_tmp_var (avar);
3559 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3560 NULL_TREE, NULL_TREE);
3561 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3562 NULL_TREE, NULL_TREE);
3563 if (DECL_P (new_var))
3565 SET_DECL_VALUE_EXPR (new_var, lvar);
3566 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3568 return true;
3571 /* Helper function of lower_rec_input_clauses. For a reference
3572 in simd reduction, add an underlying variable it will reference. */
3574 static void
3575 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3577 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3578 if (TREE_CONSTANT (z))
3580 const char *name = NULL;
3581 if (DECL_NAME (new_vard))
3582 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3584 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3585 gimple_add_tmp_var (z);
3586 TREE_ADDRESSABLE (z) = 1;
3587 z = build_fold_addr_expr_loc (loc, z);
3588 gimplify_assign (new_vard, z, ilist);
3592 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3593 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3594 private variables. Initialization statements go in ILIST, while calls
3595 to destructors go in DLIST. */
3597 static void
3598 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3599 omp_context *ctx, struct omp_for_data *fd)
3601 tree c, dtor, copyin_seq, x, ptr;
3602 bool copyin_by_ref = false;
3603 bool lastprivate_firstprivate = false;
3604 bool reduction_omp_orig_ref = false;
3605 int pass;
3606 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3607 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3608 int max_vf = 0;
3609 tree lane = NULL_TREE, idx = NULL_TREE;
3610 tree ivar = NULL_TREE, lvar = NULL_TREE;
3611 gimple_seq llist[2] = { NULL, NULL };
3613 copyin_seq = NULL;
3615 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3616 with data sharing clauses referencing variable sized vars. That
3617 is unnecessarily hard to support and very unlikely to result in
3618 vectorized code anyway. */
3619 if (is_simd)
3620 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3621 switch (OMP_CLAUSE_CODE (c))
3623 case OMP_CLAUSE_LINEAR:
3624 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3625 max_vf = 1;
3626 /* FALLTHRU */
3627 case OMP_CLAUSE_REDUCTION:
3628 case OMP_CLAUSE_PRIVATE:
3629 case OMP_CLAUSE_FIRSTPRIVATE:
3630 case OMP_CLAUSE_LASTPRIVATE:
3631 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3632 max_vf = 1;
3633 break;
3634 default:
3635 continue;
3638 /* Do all the fixed sized types in the first pass, and the variable sized
3639 types in the second pass. This makes sure that the scalar arguments to
3640 the variable sized types are processed before we use them in the
3641 variable sized operations. */
3642 for (pass = 0; pass < 2; ++pass)
3644 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3646 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3647 tree var, new_var;
3648 bool by_ref;
3649 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3651 switch (c_kind)
3653 case OMP_CLAUSE_PRIVATE:
3654 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3655 continue;
3656 break;
3657 case OMP_CLAUSE_SHARED:
3658 /* Ignore shared directives in teams construct. */
3659 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3660 continue;
3661 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3663 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3664 continue;
3666 case OMP_CLAUSE_FIRSTPRIVATE:
3667 case OMP_CLAUSE_COPYIN:
3668 case OMP_CLAUSE_LINEAR:
3669 break;
3670 case OMP_CLAUSE_REDUCTION:
3671 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3672 reduction_omp_orig_ref = true;
3673 break;
3674 case OMP_CLAUSE__LOOPTEMP_:
3675 /* Handle _looptemp_ clauses only on parallel. */
3676 if (fd)
3677 continue;
3678 break;
3679 case OMP_CLAUSE_LASTPRIVATE:
3680 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3682 lastprivate_firstprivate = true;
3683 if (pass != 0)
3684 continue;
3686 /* Even without corresponding firstprivate, if
3687 decl is Fortran allocatable, it needs outer var
3688 reference. */
3689 else if (pass == 0
3690 && lang_hooks.decls.omp_private_outer_ref
3691 (OMP_CLAUSE_DECL (c)))
3692 lastprivate_firstprivate = true;
3693 break;
3694 case OMP_CLAUSE_ALIGNED:
3695 if (pass == 0)
3696 continue;
3697 var = OMP_CLAUSE_DECL (c);
3698 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3699 && !is_global_var (var))
3701 new_var = maybe_lookup_decl (var, ctx);
3702 if (new_var == NULL_TREE)
3703 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3704 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3705 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3706 omp_clause_aligned_alignment (c));
3707 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3708 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3709 gimplify_and_add (x, ilist);
3711 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3712 && is_global_var (var))
3714 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3715 new_var = lookup_decl (var, ctx);
3716 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3717 t = build_fold_addr_expr_loc (clause_loc, t);
3718 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3719 t = build_call_expr_loc (clause_loc, t2, 2, t,
3720 omp_clause_aligned_alignment (c));
3721 t = fold_convert_loc (clause_loc, ptype, t);
3722 x = create_tmp_var (ptype);
3723 t = build2 (MODIFY_EXPR, ptype, x, t);
3724 gimplify_and_add (t, ilist);
3725 t = build_simple_mem_ref_loc (clause_loc, x);
3726 SET_DECL_VALUE_EXPR (new_var, t);
3727 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3729 continue;
3730 default:
3731 continue;
3734 new_var = var = OMP_CLAUSE_DECL (c);
3735 if (c_kind != OMP_CLAUSE_COPYIN)
3736 new_var = lookup_decl (var, ctx);
3738 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3740 if (pass != 0)
3741 continue;
3743 else if (is_variable_sized (var))
3745 /* For variable sized types, we need to allocate the
3746 actual storage here. Call alloca and store the
3747 result in the pointer decl that we created elsewhere. */
3748 if (pass == 0)
3749 continue;
3751 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3753 gcall *stmt;
3754 tree tmp, atmp;
3756 ptr = DECL_VALUE_EXPR (new_var);
3757 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3758 ptr = TREE_OPERAND (ptr, 0);
3759 gcc_assert (DECL_P (ptr));
3760 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3762 /* void *tmp = __builtin_alloca */
3763 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3764 stmt = gimple_build_call (atmp, 1, x);
3765 tmp = create_tmp_var_raw (ptr_type_node);
3766 gimple_add_tmp_var (tmp);
3767 gimple_call_set_lhs (stmt, tmp);
3769 gimple_seq_add_stmt (ilist, stmt);
3771 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3772 gimplify_assign (ptr, x, ilist);
3775 else if (is_reference (var))
3777 /* For references that are being privatized for Fortran,
3778 allocate new backing storage for the new pointer
3779 variable. This allows us to avoid changing all the
3780 code that expects a pointer to something that expects
3781 a direct variable. */
3782 if (pass == 0)
3783 continue;
3785 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3786 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3788 x = build_receiver_ref (var, false, ctx);
3789 x = build_fold_addr_expr_loc (clause_loc, x);
3791 else if (TREE_CONSTANT (x))
3793 /* For reduction in SIMD loop, defer adding the
3794 initialization of the reference, because if we decide
3795 to use SIMD array for it, the initilization could cause
3796 expansion ICE. */
3797 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3798 x = NULL_TREE;
3799 else
3801 const char *name = NULL;
3802 if (DECL_NAME (var))
3803 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3805 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3806 name);
3807 gimple_add_tmp_var (x);
3808 TREE_ADDRESSABLE (x) = 1;
3809 x = build_fold_addr_expr_loc (clause_loc, x);
3812 else
3814 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3815 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3818 if (x)
3820 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3821 gimplify_assign (new_var, x, ilist);
3824 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3826 else if (c_kind == OMP_CLAUSE_REDUCTION
3827 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3829 if (pass == 0)
3830 continue;
3832 else if (pass != 0)
3833 continue;
3835 switch (OMP_CLAUSE_CODE (c))
3837 case OMP_CLAUSE_SHARED:
3838 /* Ignore shared directives in teams construct. */
3839 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3840 continue;
3841 /* Shared global vars are just accessed directly. */
3842 if (is_global_var (new_var))
3843 break;
3844 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3845 needs to be delayed until after fixup_child_record_type so
3846 that we get the correct type during the dereference. */
3847 by_ref = use_pointer_for_field (var, ctx);
3848 x = build_receiver_ref (var, by_ref, ctx);
3849 SET_DECL_VALUE_EXPR (new_var, x);
3850 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3852 /* ??? If VAR is not passed by reference, and the variable
3853 hasn't been initialized yet, then we'll get a warning for
3854 the store into the omp_data_s structure. Ideally, we'd be
3855 able to notice this and not store anything at all, but
3856 we're generating code too early. Suppress the warning. */
3857 if (!by_ref)
3858 TREE_NO_WARNING (var) = 1;
3859 break;
3861 case OMP_CLAUSE_LASTPRIVATE:
3862 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3863 break;
3864 /* FALLTHRU */
3866 case OMP_CLAUSE_PRIVATE:
3867 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3868 x = build_outer_var_ref (var, ctx);
3869 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3871 if (is_task_ctx (ctx))
3872 x = build_receiver_ref (var, false, ctx);
3873 else
3874 x = build_outer_var_ref (var, ctx);
3876 else
3877 x = NULL;
3878 do_private:
3879 tree nx;
3880 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3881 if (is_simd)
3883 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3884 if ((TREE_ADDRESSABLE (new_var) || nx || y
3885 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3886 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3887 idx, lane, ivar, lvar))
3889 if (nx)
3890 x = lang_hooks.decls.omp_clause_default_ctor
3891 (c, unshare_expr (ivar), x);
3892 if (nx && x)
3893 gimplify_and_add (x, &llist[0]);
3894 if (y)
3896 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3897 if (y)
3899 gimple_seq tseq = NULL;
3901 dtor = y;
3902 gimplify_stmt (&dtor, &tseq);
3903 gimple_seq_add_seq (&llist[1], tseq);
3906 break;
3909 if (nx)
3910 gimplify_and_add (nx, ilist);
3911 /* FALLTHRU */
3913 do_dtor:
3914 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3915 if (x)
3917 gimple_seq tseq = NULL;
3919 dtor = x;
3920 gimplify_stmt (&dtor, &tseq);
3921 gimple_seq_add_seq (dlist, tseq);
3923 break;
3925 case OMP_CLAUSE_LINEAR:
3926 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3927 goto do_firstprivate;
3928 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3929 x = NULL;
3930 else
3931 x = build_outer_var_ref (var, ctx);
3932 goto do_private;
3934 case OMP_CLAUSE_FIRSTPRIVATE:
3935 if (is_task_ctx (ctx))
3937 if (is_reference (var) || is_variable_sized (var))
3938 goto do_dtor;
3939 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3940 ctx))
3941 || use_pointer_for_field (var, NULL))
3943 x = build_receiver_ref (var, false, ctx);
3944 SET_DECL_VALUE_EXPR (new_var, x);
3945 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3946 goto do_dtor;
3949 do_firstprivate:
3950 x = build_outer_var_ref (var, ctx);
3951 if (is_simd)
3953 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3954 && gimple_omp_for_combined_into_p (ctx->stmt))
3956 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3957 tree stept = TREE_TYPE (t);
3958 tree ct = find_omp_clause (clauses,
3959 OMP_CLAUSE__LOOPTEMP_);
3960 gcc_assert (ct);
3961 tree l = OMP_CLAUSE_DECL (ct);
3962 tree n1 = fd->loop.n1;
3963 tree step = fd->loop.step;
3964 tree itype = TREE_TYPE (l);
3965 if (POINTER_TYPE_P (itype))
3966 itype = signed_type_for (itype);
3967 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3968 if (TYPE_UNSIGNED (itype)
3969 && fd->loop.cond_code == GT_EXPR)
3970 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3971 fold_build1 (NEGATE_EXPR, itype, l),
3972 fold_build1 (NEGATE_EXPR,
3973 itype, step));
3974 else
3975 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3976 t = fold_build2 (MULT_EXPR, stept,
3977 fold_convert (stept, l), t);
3979 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3981 x = lang_hooks.decls.omp_clause_linear_ctor
3982 (c, new_var, x, t);
3983 gimplify_and_add (x, ilist);
3984 goto do_dtor;
3987 if (POINTER_TYPE_P (TREE_TYPE (x)))
3988 x = fold_build2 (POINTER_PLUS_EXPR,
3989 TREE_TYPE (x), x, t);
3990 else
3991 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3994 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3995 || TREE_ADDRESSABLE (new_var))
3996 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3997 idx, lane, ivar, lvar))
3999 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4001 tree iv = create_tmp_var (TREE_TYPE (new_var));
4002 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4003 gimplify_and_add (x, ilist);
4004 gimple_stmt_iterator gsi
4005 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4006 gassign *g
4007 = gimple_build_assign (unshare_expr (lvar), iv);
4008 gsi_insert_before_without_update (&gsi, g,
4009 GSI_SAME_STMT);
4010 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4011 enum tree_code code = PLUS_EXPR;
4012 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4013 code = POINTER_PLUS_EXPR;
4014 g = gimple_build_assign (iv, code, iv, t);
4015 gsi_insert_before_without_update (&gsi, g,
4016 GSI_SAME_STMT);
4017 break;
4019 x = lang_hooks.decls.omp_clause_copy_ctor
4020 (c, unshare_expr (ivar), x);
4021 gimplify_and_add (x, &llist[0]);
4022 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4023 if (x)
4025 gimple_seq tseq = NULL;
4027 dtor = x;
4028 gimplify_stmt (&dtor, &tseq);
4029 gimple_seq_add_seq (&llist[1], tseq);
4031 break;
4034 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4035 gimplify_and_add (x, ilist);
4036 goto do_dtor;
4038 case OMP_CLAUSE__LOOPTEMP_:
4039 gcc_assert (is_parallel_ctx (ctx));
4040 x = build_outer_var_ref (var, ctx);
4041 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4042 gimplify_and_add (x, ilist);
4043 break;
4045 case OMP_CLAUSE_COPYIN:
4046 by_ref = use_pointer_for_field (var, NULL);
4047 x = build_receiver_ref (var, by_ref, ctx);
4048 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4049 append_to_statement_list (x, &copyin_seq);
4050 copyin_by_ref |= by_ref;
4051 break;
4053 case OMP_CLAUSE_REDUCTION:
4054 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4056 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4057 gimple tseq;
4058 x = build_outer_var_ref (var, ctx);
4060 if (is_reference (var)
4061 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4062 TREE_TYPE (x)))
4063 x = build_fold_addr_expr_loc (clause_loc, x);
4064 SET_DECL_VALUE_EXPR (placeholder, x);
4065 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4066 tree new_vard = new_var;
4067 if (is_reference (var))
4069 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4070 new_vard = TREE_OPERAND (new_var, 0);
4071 gcc_assert (DECL_P (new_vard));
4073 if (is_simd
4074 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4075 idx, lane, ivar, lvar))
4077 if (new_vard == new_var)
4079 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4080 SET_DECL_VALUE_EXPR (new_var, ivar);
4082 else
4084 SET_DECL_VALUE_EXPR (new_vard,
4085 build_fold_addr_expr (ivar));
4086 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4088 x = lang_hooks.decls.omp_clause_default_ctor
4089 (c, unshare_expr (ivar),
4090 build_outer_var_ref (var, ctx));
4091 if (x)
4092 gimplify_and_add (x, &llist[0]);
4093 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4095 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4096 lower_omp (&tseq, ctx);
4097 gimple_seq_add_seq (&llist[0], tseq);
4099 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4100 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4101 lower_omp (&tseq, ctx);
4102 gimple_seq_add_seq (&llist[1], tseq);
4103 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4104 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4105 if (new_vard == new_var)
4106 SET_DECL_VALUE_EXPR (new_var, lvar);
4107 else
4108 SET_DECL_VALUE_EXPR (new_vard,
4109 build_fold_addr_expr (lvar));
4110 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4111 if (x)
4113 tseq = NULL;
4114 dtor = x;
4115 gimplify_stmt (&dtor, &tseq);
4116 gimple_seq_add_seq (&llist[1], tseq);
4118 break;
4120 /* If this is a reference to constant size reduction var
4121 with placeholder, we haven't emitted the initializer
4122 for it because it is undesirable if SIMD arrays are used.
4123 But if they aren't used, we need to emit the deferred
4124 initialization now. */
4125 else if (is_reference (var) && is_simd)
4126 handle_simd_reference (clause_loc, new_vard, ilist);
4127 x = lang_hooks.decls.omp_clause_default_ctor
4128 (c, unshare_expr (new_var),
4129 build_outer_var_ref (var, ctx));
4130 if (x)
4131 gimplify_and_add (x, ilist);
4132 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4134 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4135 lower_omp (&tseq, ctx);
4136 gimple_seq_add_seq (ilist, tseq);
4138 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4139 if (is_simd)
4141 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4142 lower_omp (&tseq, ctx);
4143 gimple_seq_add_seq (dlist, tseq);
4144 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4146 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4147 goto do_dtor;
4149 else
4151 x = omp_reduction_init (c, TREE_TYPE (new_var));
4152 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4153 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4155 /* reduction(-:var) sums up the partial results, so it
4156 acts identically to reduction(+:var). */
4157 if (code == MINUS_EXPR)
4158 code = PLUS_EXPR;
4160 tree new_vard = new_var;
4161 if (is_simd && is_reference (var))
4163 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4164 new_vard = TREE_OPERAND (new_var, 0);
4165 gcc_assert (DECL_P (new_vard));
4167 if (is_simd
4168 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4169 idx, lane, ivar, lvar))
4171 tree ref = build_outer_var_ref (var, ctx);
4173 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4175 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4176 ref = build_outer_var_ref (var, ctx);
4177 gimplify_assign (ref, x, &llist[1]);
4179 if (new_vard != new_var)
4181 SET_DECL_VALUE_EXPR (new_vard,
4182 build_fold_addr_expr (lvar));
4183 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4186 else
4188 if (is_reference (var) && is_simd)
4189 handle_simd_reference (clause_loc, new_vard, ilist);
4190 gimplify_assign (new_var, x, ilist);
4191 if (is_simd)
4193 tree ref = build_outer_var_ref (var, ctx);
4195 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4196 ref = build_outer_var_ref (var, ctx);
4197 gimplify_assign (ref, x, dlist);
4201 break;
4203 default:
4204 gcc_unreachable ();
4209 if (lane)
4211 tree uid = create_tmp_var (ptr_type_node, "simduid");
4212 /* Don't want uninit warnings on simduid, it is always uninitialized,
4213 but we use it not for the value, but for the DECL_UID only. */
4214 TREE_NO_WARNING (uid) = 1;
4215 gimple g
4216 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4217 gimple_call_set_lhs (g, lane);
4218 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4219 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4220 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4221 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4222 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4223 gimple_omp_for_set_clauses (ctx->stmt, c);
4224 g = gimple_build_assign (lane, INTEGER_CST,
4225 build_int_cst (unsigned_type_node, 0));
4226 gimple_seq_add_stmt (ilist, g);
4227 for (int i = 0; i < 2; i++)
4228 if (llist[i])
4230 tree vf = create_tmp_var (unsigned_type_node);
4231 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4232 gimple_call_set_lhs (g, vf);
4233 gimple_seq *seq = i == 0 ? ilist : dlist;
4234 gimple_seq_add_stmt (seq, g);
4235 tree t = build_int_cst (unsigned_type_node, 0);
4236 g = gimple_build_assign (idx, INTEGER_CST, t);
4237 gimple_seq_add_stmt (seq, g);
4238 tree body = create_artificial_label (UNKNOWN_LOCATION);
4239 tree header = create_artificial_label (UNKNOWN_LOCATION);
4240 tree end = create_artificial_label (UNKNOWN_LOCATION);
4241 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4242 gimple_seq_add_stmt (seq, gimple_build_label (body));
4243 gimple_seq_add_seq (seq, llist[i]);
4244 t = build_int_cst (unsigned_type_node, 1);
4245 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4246 gimple_seq_add_stmt (seq, g);
4247 gimple_seq_add_stmt (seq, gimple_build_label (header));
4248 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4249 gimple_seq_add_stmt (seq, g);
4250 gimple_seq_add_stmt (seq, gimple_build_label (end));
4254 /* The copyin sequence is not to be executed by the main thread, since
4255 that would result in self-copies. Perhaps not visible to scalars,
4256 but it certainly is to C++ operator=. */
4257 if (copyin_seq)
4259 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4261 x = build2 (NE_EXPR, boolean_type_node, x,
4262 build_int_cst (TREE_TYPE (x), 0));
4263 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4264 gimplify_and_add (x, ilist);
4267 /* If any copyin variable is passed by reference, we must ensure the
4268 master thread doesn't modify it before it is copied over in all
4269 threads. Similarly for variables in both firstprivate and
4270 lastprivate clauses we need to ensure the lastprivate copying
4271 happens after firstprivate copying in all threads. And similarly
4272 for UDRs if initializer expression refers to omp_orig. */
4273 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4275 /* Don't add any barrier for #pragma omp simd or
4276 #pragma omp distribute. */
4277 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4278 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4279 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4282 /* If max_vf is non-zero, then we can use only a vectorization factor
4283 up to the max_vf we chose. So stick it into the safelen clause. */
4284 if (max_vf)
4286 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4287 OMP_CLAUSE_SAFELEN);
4288 if (c == NULL_TREE
4289 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4290 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4291 max_vf) == 1))
4293 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4294 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4295 max_vf);
4296 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4297 gimple_omp_for_set_clauses (ctx->stmt, c);
4303 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4304 both parallel and workshare constructs. PREDICATE may be NULL if it's
4305 always true. */
4307 static void
4308 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4309 omp_context *ctx)
4311 tree x, c, label = NULL, orig_clauses = clauses;
4312 bool par_clauses = false;
4313 tree simduid = NULL, lastlane = NULL;
4315 /* Early exit if there are no lastprivate or linear clauses. */
4316 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4317 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4318 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4319 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4320 break;
4321 if (clauses == NULL)
4323 /* If this was a workshare clause, see if it had been combined
4324 with its parallel. In that case, look for the clauses on the
4325 parallel statement itself. */
4326 if (is_parallel_ctx (ctx))
4327 return;
4329 ctx = ctx->outer;
4330 if (ctx == NULL || !is_parallel_ctx (ctx))
4331 return;
4333 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4334 OMP_CLAUSE_LASTPRIVATE);
4335 if (clauses == NULL)
4336 return;
4337 par_clauses = true;
4340 if (predicate)
4342 gcond *stmt;
4343 tree label_true, arm1, arm2;
4345 label = create_artificial_label (UNKNOWN_LOCATION);
4346 label_true = create_artificial_label (UNKNOWN_LOCATION);
4347 arm1 = TREE_OPERAND (predicate, 0);
4348 arm2 = TREE_OPERAND (predicate, 1);
4349 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4350 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4351 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4352 label_true, label);
4353 gimple_seq_add_stmt (stmt_list, stmt);
4354 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4357 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4358 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4360 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4361 if (simduid)
4362 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4365 for (c = clauses; c ;)
4367 tree var, new_var;
4368 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4370 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4371 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4372 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4374 var = OMP_CLAUSE_DECL (c);
4375 new_var = lookup_decl (var, ctx);
4377 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4379 tree val = DECL_VALUE_EXPR (new_var);
4380 if (TREE_CODE (val) == ARRAY_REF
4381 && VAR_P (TREE_OPERAND (val, 0))
4382 && lookup_attribute ("omp simd array",
4383 DECL_ATTRIBUTES (TREE_OPERAND (val,
4384 0))))
4386 if (lastlane == NULL)
4388 lastlane = create_tmp_var (unsigned_type_node);
4389 gcall *g
4390 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4391 2, simduid,
4392 TREE_OPERAND (val, 1));
4393 gimple_call_set_lhs (g, lastlane);
4394 gimple_seq_add_stmt (stmt_list, g);
4396 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4397 TREE_OPERAND (val, 0), lastlane,
4398 NULL_TREE, NULL_TREE);
4402 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4403 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4405 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4406 gimple_seq_add_seq (stmt_list,
4407 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4408 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4410 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4411 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4413 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4414 gimple_seq_add_seq (stmt_list,
4415 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4416 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4419 x = build_outer_var_ref (var, ctx);
4420 if (is_reference (var))
4421 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4422 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4423 gimplify_and_add (x, stmt_list);
4425 c = OMP_CLAUSE_CHAIN (c);
4426 if (c == NULL && !par_clauses)
4428 /* If this was a workshare clause, see if it had been combined
4429 with its parallel. In that case, continue looking for the
4430 clauses also on the parallel statement itself. */
4431 if (is_parallel_ctx (ctx))
4432 break;
4434 ctx = ctx->outer;
4435 if (ctx == NULL || !is_parallel_ctx (ctx))
4436 break;
4438 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4439 OMP_CLAUSE_LASTPRIVATE);
4440 par_clauses = true;
4444 if (label)
4445 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4448 static void
4449 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4450 tree tid, tree var, tree new_var)
4452 /* The atomic add at the end of the sum creates unnecessary
4453 write contention on accelerators. To work around this,
4454 create an array to store the partial reductions. Later, in
4455 lower_omp_for (for openacc), the values of array will be
4456 combined. */
4458 tree t = NULL_TREE, array, x;
4459 tree type = get_base_type (var);
4460 gimple stmt;
4462 /* Now insert the partial reductions into the array. */
4464 /* Find the reduction array. */
4466 tree ptype = build_pointer_type (type);
4468 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4469 t = build_receiver_ref (t, false, ctx->outer);
4471 array = create_tmp_var (ptype);
4472 gimplify_assign (array, t, stmt_seqp);
4474 tree ptr = create_tmp_var (TREE_TYPE (array));
4476 /* Find the reduction array. */
4478 /* testing a unary conversion. */
4479 tree offset = create_tmp_var (sizetype);
4480 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4481 stmt_seqp);
4482 t = create_tmp_var (sizetype);
4483 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4484 stmt_seqp);
4485 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4486 gimple_seq_add_stmt (stmt_seqp, stmt);
4488 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4489 of adding sizeof(var) to the array? */
4490 ptr = create_tmp_var (ptype);
4491 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4492 offset);
4493 gimple_seq_add_stmt (stmt_seqp, stmt);
4495 /* Move the local sum to gfc$sum[i]. */
4496 x = unshare_expr (build_simple_mem_ref (ptr));
4497 stmt = gimplify_assign (x, new_var, stmt_seqp);
4500 /* Generate code to implement the REDUCTION clauses. */
4502 static void
4503 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4505 gimple_seq sub_seq = NULL;
4506 gimple stmt;
4507 tree x, c, tid = NULL_TREE;
4508 int count = 0;
4510 /* SIMD reductions are handled in lower_rec_input_clauses. */
4511 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4512 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4513 return;
4515 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4516 update in that case, otherwise use a lock. */
4517 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4518 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4520 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4522 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4523 count = -1;
4524 break;
4526 count++;
4529 if (count == 0)
4530 return;
4532 /* Initialize thread info for OpenACC. */
4533 if (is_gimple_omp_oacc (ctx->stmt))
4535 /* Get the current thread id. */
4536 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4537 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4538 gimple stmt = gimple_build_call (call, 0);
4539 gimple_call_set_lhs (stmt, tid);
4540 gimple_seq_add_stmt (stmt_seqp, stmt);
4543 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4545 tree var, ref, new_var;
4546 enum tree_code code;
4547 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4549 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4550 continue;
4552 var = OMP_CLAUSE_DECL (c);
4553 new_var = lookup_decl (var, ctx);
4554 if (is_reference (var))
4555 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4556 ref = build_outer_var_ref (var, ctx);
4557 code = OMP_CLAUSE_REDUCTION_CODE (c);
4559 /* reduction(-:var) sums up the partial results, so it acts
4560 identically to reduction(+:var). */
4561 if (code == MINUS_EXPR)
4562 code = PLUS_EXPR;
4564 if (is_gimple_omp_oacc (ctx->stmt))
4566 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4568 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4570 else if (count == 1)
4572 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4574 addr = save_expr (addr);
4575 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4576 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4577 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4578 gimplify_and_add (x, stmt_seqp);
4579 return;
4581 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4583 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4585 if (is_reference (var)
4586 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4587 TREE_TYPE (ref)))
4588 ref = build_fold_addr_expr_loc (clause_loc, ref);
4589 SET_DECL_VALUE_EXPR (placeholder, ref);
4590 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4591 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4592 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4593 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4594 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4596 else
4598 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4599 ref = build_outer_var_ref (var, ctx);
4600 gimplify_assign (ref, x, &sub_seq);
4604 if (is_gimple_omp_oacc (ctx->stmt))
4605 return;
4607 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4609 gimple_seq_add_stmt (stmt_seqp, stmt);
4611 gimple_seq_add_seq (stmt_seqp, sub_seq);
4613 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4615 gimple_seq_add_stmt (stmt_seqp, stmt);
4619 /* Generate code to implement the COPYPRIVATE clauses. */
4621 static void
4622 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4623 omp_context *ctx)
4625 tree c;
4627 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4629 tree var, new_var, ref, x;
4630 bool by_ref;
4631 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4633 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4634 continue;
4636 var = OMP_CLAUSE_DECL (c);
4637 by_ref = use_pointer_for_field (var, NULL);
4639 ref = build_sender_ref (var, ctx);
4640 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4641 if (by_ref)
4643 x = build_fold_addr_expr_loc (clause_loc, new_var);
4644 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4646 gimplify_assign (ref, x, slist);
4648 ref = build_receiver_ref (var, false, ctx);
4649 if (by_ref)
4651 ref = fold_convert_loc (clause_loc,
4652 build_pointer_type (TREE_TYPE (new_var)),
4653 ref);
4654 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4656 if (is_reference (var))
4658 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4659 ref = build_simple_mem_ref_loc (clause_loc, ref);
4660 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4662 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4663 gimplify_and_add (x, rlist);
4668 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4669 and REDUCTION from the sender (aka parent) side. */
4671 static void
4672 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4673 omp_context *ctx)
4675 tree c;
4677 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4679 tree val, ref, x, var;
4680 bool by_ref, do_in = false, do_out = false;
4681 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4683 switch (OMP_CLAUSE_CODE (c))
4685 case OMP_CLAUSE_PRIVATE:
4686 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4687 break;
4688 continue;
4689 case OMP_CLAUSE_FIRSTPRIVATE:
4690 case OMP_CLAUSE_COPYIN:
4691 case OMP_CLAUSE_LASTPRIVATE:
4692 case OMP_CLAUSE_REDUCTION:
4693 case OMP_CLAUSE__LOOPTEMP_:
4694 break;
4695 default:
4696 continue;
4699 val = OMP_CLAUSE_DECL (c);
4700 var = lookup_decl_in_outer_ctx (val, ctx);
4702 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4703 && is_global_var (var))
4704 continue;
4705 if (is_variable_sized (val))
4706 continue;
4707 by_ref = use_pointer_for_field (val, NULL);
4709 switch (OMP_CLAUSE_CODE (c))
4711 case OMP_CLAUSE_PRIVATE:
4712 case OMP_CLAUSE_FIRSTPRIVATE:
4713 case OMP_CLAUSE_COPYIN:
4714 case OMP_CLAUSE__LOOPTEMP_:
4715 do_in = true;
4716 break;
4718 case OMP_CLAUSE_LASTPRIVATE:
4719 if (by_ref || is_reference (val))
4721 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4722 continue;
4723 do_in = true;
4725 else
4727 do_out = true;
4728 if (lang_hooks.decls.omp_private_outer_ref (val))
4729 do_in = true;
4731 break;
4733 case OMP_CLAUSE_REDUCTION:
4734 do_in = true;
4735 do_out = !(by_ref || is_reference (val));
4736 break;
4738 default:
4739 gcc_unreachable ();
4742 if (do_in)
4744 ref = build_sender_ref (val, ctx);
4745 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4746 gimplify_assign (ref, x, ilist);
4747 if (is_task_ctx (ctx))
4748 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4751 if (do_out)
4753 ref = build_sender_ref (val, ctx);
4754 gimplify_assign (var, ref, olist);
4759 /* Generate code to implement SHARED from the sender (aka parent)
4760 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4761 list things that got automatically shared. */
4763 static void
4764 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4766 tree var, ovar, nvar, f, x, record_type;
4768 if (ctx->record_type == NULL)
4769 return;
4771 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4772 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4774 ovar = DECL_ABSTRACT_ORIGIN (f);
4775 nvar = maybe_lookup_decl (ovar, ctx);
4776 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4777 continue;
4779 /* If CTX is a nested parallel directive. Find the immediately
4780 enclosing parallel or workshare construct that contains a
4781 mapping for OVAR. */
4782 var = lookup_decl_in_outer_ctx (ovar, ctx);
4784 if (use_pointer_for_field (ovar, ctx))
4786 x = build_sender_ref (ovar, ctx);
4787 var = build_fold_addr_expr (var);
4788 gimplify_assign (x, var, ilist);
4790 else
4792 x = build_sender_ref (ovar, ctx);
4793 gimplify_assign (x, var, ilist);
4795 if (!TREE_READONLY (var)
4796 /* We don't need to receive a new reference to a result
4797 or parm decl. In fact we may not store to it as we will
4798 invalidate any pending RSO and generate wrong gimple
4799 during inlining. */
4800 && !((TREE_CODE (var) == RESULT_DECL
4801 || TREE_CODE (var) == PARM_DECL)
4802 && DECL_BY_REFERENCE (var)))
4804 x = build_sender_ref (ovar, ctx);
4805 gimplify_assign (var, x, olist);
4812 /* A convenience function to build an empty GIMPLE_COND with just the
4813 condition. */
4815 static gcond *
4816 gimple_build_cond_empty (tree cond)
4818 enum tree_code pred_code;
4819 tree lhs, rhs;
4821 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4822 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4826 /* Build the function calls to GOMP_parallel_start etc to actually
4827 generate the parallel operation. REGION is the parallel region
4828 being expanded. BB is the block where to insert the code. WS_ARGS
4829 will be set if this is a call to a combined parallel+workshare
4830 construct, it contains the list of additional arguments needed by
4831 the workshare construct. */
4833 static void
4834 expand_parallel_call (struct omp_region *region, basic_block bb,
4835 gomp_parallel *entry_stmt,
4836 vec<tree, va_gc> *ws_args)
4838 tree t, t1, t2, val, cond, c, clauses, flags;
4839 gimple_stmt_iterator gsi;
4840 gimple stmt;
4841 enum built_in_function start_ix;
4842 int start_ix2;
4843 location_t clause_loc;
4844 vec<tree, va_gc> *args;
4846 clauses = gimple_omp_parallel_clauses (entry_stmt);
4848 /* Determine what flavor of GOMP_parallel we will be
4849 emitting. */
4850 start_ix = BUILT_IN_GOMP_PARALLEL;
4851 if (is_combined_parallel (region))
4853 switch (region->inner->type)
4855 case GIMPLE_OMP_FOR:
4856 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4857 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4858 + (region->inner->sched_kind
4859 == OMP_CLAUSE_SCHEDULE_RUNTIME
4860 ? 3 : region->inner->sched_kind));
4861 start_ix = (enum built_in_function)start_ix2;
4862 break;
4863 case GIMPLE_OMP_SECTIONS:
4864 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4865 break;
4866 default:
4867 gcc_unreachable ();
4871 /* By default, the value of NUM_THREADS is zero (selected at run time)
4872 and there is no conditional. */
4873 cond = NULL_TREE;
4874 val = build_int_cst (unsigned_type_node, 0);
4875 flags = build_int_cst (unsigned_type_node, 0);
4877 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4878 if (c)
4879 cond = OMP_CLAUSE_IF_EXPR (c);
4881 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4882 if (c)
4884 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4885 clause_loc = OMP_CLAUSE_LOCATION (c);
4887 else
4888 clause_loc = gimple_location (entry_stmt);
4890 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4891 if (c)
4892 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4894 /* Ensure 'val' is of the correct type. */
4895 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4897 /* If we found the clause 'if (cond)', build either
4898 (cond != 0) or (cond ? val : 1u). */
4899 if (cond)
4901 cond = gimple_boolify (cond);
4903 if (integer_zerop (val))
4904 val = fold_build2_loc (clause_loc,
4905 EQ_EXPR, unsigned_type_node, cond,
4906 build_int_cst (TREE_TYPE (cond), 0));
4907 else
4909 basic_block cond_bb, then_bb, else_bb;
4910 edge e, e_then, e_else;
4911 tree tmp_then, tmp_else, tmp_join, tmp_var;
4913 tmp_var = create_tmp_var (TREE_TYPE (val));
4914 if (gimple_in_ssa_p (cfun))
4916 tmp_then = make_ssa_name (tmp_var);
4917 tmp_else = make_ssa_name (tmp_var);
4918 tmp_join = make_ssa_name (tmp_var);
4920 else
4922 tmp_then = tmp_var;
4923 tmp_else = tmp_var;
4924 tmp_join = tmp_var;
4927 e = split_block_after_labels (bb);
4928 cond_bb = e->src;
4929 bb = e->dest;
4930 remove_edge (e);
4932 then_bb = create_empty_bb (cond_bb);
4933 else_bb = create_empty_bb (then_bb);
4934 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4935 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4937 stmt = gimple_build_cond_empty (cond);
4938 gsi = gsi_start_bb (cond_bb);
4939 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4941 gsi = gsi_start_bb (then_bb);
4942 stmt = gimple_build_assign (tmp_then, val);
4943 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4945 gsi = gsi_start_bb (else_bb);
4946 stmt = gimple_build_assign
4947 (tmp_else, build_int_cst (unsigned_type_node, 1));
4948 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4950 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4951 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4952 add_bb_to_loop (then_bb, cond_bb->loop_father);
4953 add_bb_to_loop (else_bb, cond_bb->loop_father);
4954 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4955 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4957 if (gimple_in_ssa_p (cfun))
4959 gphi *phi = create_phi_node (tmp_join, bb);
4960 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4961 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4964 val = tmp_join;
4967 gsi = gsi_start_bb (bb);
4968 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4969 false, GSI_CONTINUE_LINKING);
4972 gsi = gsi_last_bb (bb);
4973 t = gimple_omp_parallel_data_arg (entry_stmt);
4974 if (t == NULL)
4975 t1 = null_pointer_node;
4976 else
4977 t1 = build_fold_addr_expr (t);
4978 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4980 vec_alloc (args, 4 + vec_safe_length (ws_args));
4981 args->quick_push (t2);
4982 args->quick_push (t1);
4983 args->quick_push (val);
4984 if (ws_args)
4985 args->splice (*ws_args);
4986 args->quick_push (flags);
4988 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4989 builtin_decl_explicit (start_ix), args);
4991 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4992 false, GSI_CONTINUE_LINKING);
4995 /* Insert a function call whose name is FUNC_NAME with the information from
4996 ENTRY_STMT into the basic_block BB. */
4998 static void
4999 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
5000 vec <tree, va_gc> *ws_args)
5002 tree t, t1, t2;
5003 gimple_stmt_iterator gsi;
5004 vec <tree, va_gc> *args;
5006 gcc_assert (vec_safe_length (ws_args) == 2);
5007 tree func_name = (*ws_args)[0];
5008 tree grain = (*ws_args)[1];
5010 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5011 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5012 gcc_assert (count != NULL_TREE);
5013 count = OMP_CLAUSE_OPERAND (count, 0);
5015 gsi = gsi_last_bb (bb);
5016 t = gimple_omp_parallel_data_arg (entry_stmt);
5017 if (t == NULL)
5018 t1 = null_pointer_node;
5019 else
5020 t1 = build_fold_addr_expr (t);
5021 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5023 vec_alloc (args, 4);
5024 args->quick_push (t2);
5025 args->quick_push (t1);
5026 args->quick_push (count);
5027 args->quick_push (grain);
5028 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5030 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5031 GSI_CONTINUE_LINKING);
5034 /* Build the function call to GOMP_task to actually
5035 generate the task operation. BB is the block where to insert the code. */
5037 static void
5038 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5040 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5041 gimple_stmt_iterator gsi;
5042 location_t loc = gimple_location (entry_stmt);
5044 clauses = gimple_omp_task_clauses (entry_stmt);
5046 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5047 if (c)
5048 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5049 else
5050 cond = boolean_true_node;
5052 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5053 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5054 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5055 flags = build_int_cst (unsigned_type_node,
5056 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5058 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5059 if (c)
5061 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5062 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5063 build_int_cst (unsigned_type_node, 2),
5064 build_int_cst (unsigned_type_node, 0));
5065 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5067 if (depend)
5068 depend = OMP_CLAUSE_DECL (depend);
5069 else
5070 depend = build_int_cst (ptr_type_node, 0);
5072 gsi = gsi_last_bb (bb);
5073 t = gimple_omp_task_data_arg (entry_stmt);
5074 if (t == NULL)
5075 t2 = null_pointer_node;
5076 else
5077 t2 = build_fold_addr_expr_loc (loc, t);
5078 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5079 t = gimple_omp_task_copy_fn (entry_stmt);
5080 if (t == NULL)
5081 t3 = null_pointer_node;
5082 else
5083 t3 = build_fold_addr_expr_loc (loc, t);
5085 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5086 8, t1, t2, t3,
5087 gimple_omp_task_arg_size (entry_stmt),
5088 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5089 depend);
5091 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5092 false, GSI_CONTINUE_LINKING);
5096 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5097 catch handler and return it. This prevents programs from violating the
5098 structured block semantics with throws. */
5100 static gimple_seq
5101 maybe_catch_exception (gimple_seq body)
5103 gimple g;
5104 tree decl;
5106 if (!flag_exceptions)
5107 return body;
5109 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5110 decl = lang_hooks.eh_protect_cleanup_actions ();
5111 else
5112 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5114 g = gimple_build_eh_must_not_throw (decl);
5115 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5116 GIMPLE_TRY_CATCH);
5118 return gimple_seq_alloc_with_stmt (g);
5121 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5123 static tree
5124 vec2chain (vec<tree, va_gc> *v)
5126 tree chain = NULL_TREE, t;
5127 unsigned ix;
5129 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5131 DECL_CHAIN (t) = chain;
5132 chain = t;
5135 return chain;
5139 /* Remove barriers in REGION->EXIT's block. Note that this is only
5140 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5141 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5142 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5143 removed. */
5145 static void
5146 remove_exit_barrier (struct omp_region *region)
5148 gimple_stmt_iterator gsi;
5149 basic_block exit_bb;
5150 edge_iterator ei;
5151 edge e;
5152 gimple stmt;
5153 int any_addressable_vars = -1;
5155 exit_bb = region->exit;
5157 /* If the parallel region doesn't return, we don't have REGION->EXIT
5158 block at all. */
5159 if (! exit_bb)
5160 return;
5162 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5163 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5164 statements that can appear in between are extremely limited -- no
5165 memory operations at all. Here, we allow nothing at all, so the
5166 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5167 gsi = gsi_last_bb (exit_bb);
5168 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5169 gsi_prev (&gsi);
5170 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5171 return;
5173 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5175 gsi = gsi_last_bb (e->src);
5176 if (gsi_end_p (gsi))
5177 continue;
5178 stmt = gsi_stmt (gsi);
5179 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5180 && !gimple_omp_return_nowait_p (stmt))
5182 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5183 in many cases. If there could be tasks queued, the barrier
5184 might be needed to let the tasks run before some local
5185 variable of the parallel that the task uses as shared
5186 runs out of scope. The task can be spawned either
5187 from within current function (this would be easy to check)
5188 or from some function it calls and gets passed an address
5189 of such a variable. */
5190 if (any_addressable_vars < 0)
5192 gomp_parallel *parallel_stmt
5193 = as_a <gomp_parallel *> (last_stmt (region->entry));
5194 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5195 tree local_decls, block, decl;
5196 unsigned ix;
5198 any_addressable_vars = 0;
5199 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5200 if (TREE_ADDRESSABLE (decl))
5202 any_addressable_vars = 1;
5203 break;
5205 for (block = gimple_block (stmt);
5206 !any_addressable_vars
5207 && block
5208 && TREE_CODE (block) == BLOCK;
5209 block = BLOCK_SUPERCONTEXT (block))
5211 for (local_decls = BLOCK_VARS (block);
5212 local_decls;
5213 local_decls = DECL_CHAIN (local_decls))
5214 if (TREE_ADDRESSABLE (local_decls))
5216 any_addressable_vars = 1;
5217 break;
5219 if (block == gimple_block (parallel_stmt))
5220 break;
5223 if (!any_addressable_vars)
5224 gimple_omp_return_set_nowait (stmt);
5229 static void
5230 remove_exit_barriers (struct omp_region *region)
5232 if (region->type == GIMPLE_OMP_PARALLEL)
5233 remove_exit_barrier (region);
5235 if (region->inner)
5237 region = region->inner;
5238 remove_exit_barriers (region);
5239 while (region->next)
5241 region = region->next;
5242 remove_exit_barriers (region);
5247 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5248 calls. These can't be declared as const functions, but
5249 within one parallel body they are constant, so they can be
5250 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5251 which are declared const. Similarly for task body, except
5252 that in untied task omp_get_thread_num () can change at any task
5253 scheduling point. */
5255 static void
5256 optimize_omp_library_calls (gimple entry_stmt)
5258 basic_block bb;
5259 gimple_stmt_iterator gsi;
5260 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5261 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5262 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5263 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5264 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5265 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5266 OMP_CLAUSE_UNTIED) != NULL);
5268 FOR_EACH_BB_FN (bb, cfun)
5269 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5271 gimple call = gsi_stmt (gsi);
5272 tree decl;
5274 if (is_gimple_call (call)
5275 && (decl = gimple_call_fndecl (call))
5276 && DECL_EXTERNAL (decl)
5277 && TREE_PUBLIC (decl)
5278 && DECL_INITIAL (decl) == NULL)
5280 tree built_in;
5282 if (DECL_NAME (decl) == thr_num_id)
5284 /* In #pragma omp task untied omp_get_thread_num () can change
5285 during the execution of the task region. */
5286 if (untied_task)
5287 continue;
5288 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5290 else if (DECL_NAME (decl) == num_thr_id)
5291 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5292 else
5293 continue;
5295 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5296 || gimple_call_num_args (call) != 0)
5297 continue;
5299 if (flag_exceptions && !TREE_NOTHROW (decl))
5300 continue;
5302 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5303 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5304 TREE_TYPE (TREE_TYPE (built_in))))
5305 continue;
5307 gimple_call_set_fndecl (call, built_in);
5312 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5313 regimplified. */
5315 static tree
5316 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5318 tree t = *tp;
5320 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5321 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5322 return t;
5324 if (TREE_CODE (t) == ADDR_EXPR)
5325 recompute_tree_invariant_for_addr_expr (t);
5327 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5328 return NULL_TREE;
5331 /* Prepend TO = FROM assignment before *GSI_P. */
5333 static void
5334 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5336 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5337 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5338 true, GSI_SAME_STMT);
5339 gimple stmt = gimple_build_assign (to, from);
5340 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5341 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5342 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5344 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5345 gimple_regimplify_operands (stmt, &gsi);
5349 /* Expand the OpenMP parallel or task directive starting at REGION. */
5351 static void
5352 expand_omp_taskreg (struct omp_region *region)
5354 basic_block entry_bb, exit_bb, new_bb;
5355 struct function *child_cfun;
5356 tree child_fn, block, t;
5357 gimple_stmt_iterator gsi;
5358 gimple entry_stmt, stmt;
5359 edge e;
5360 vec<tree, va_gc> *ws_args;
5362 entry_stmt = last_stmt (region->entry);
5363 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5364 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5366 entry_bb = region->entry;
5367 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
5368 exit_bb = region->cont;
5369 else
5370 exit_bb = region->exit;
5372 bool is_cilk_for
5373 = (flag_cilkplus
5374 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5375 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5376 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5378 if (is_cilk_for)
5379 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5380 and the inner statement contains the name of the built-in function
5381 and grain. */
5382 ws_args = region->inner->ws_args;
5383 else if (is_combined_parallel (region))
5384 ws_args = region->ws_args;
5385 else
5386 ws_args = NULL;
5388 if (child_cfun->cfg)
5390 /* Due to inlining, it may happen that we have already outlined
5391 the region, in which case all we need to do is make the
5392 sub-graph unreachable and emit the parallel call. */
5393 edge entry_succ_e, exit_succ_e;
5395 entry_succ_e = single_succ_edge (entry_bb);
5397 gsi = gsi_last_bb (entry_bb);
5398 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5399 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5400 gsi_remove (&gsi, true);
5402 new_bb = entry_bb;
5403 if (exit_bb)
5405 exit_succ_e = single_succ_edge (exit_bb);
5406 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5408 remove_edge_and_dominated_blocks (entry_succ_e);
5410 else
5412 unsigned srcidx, dstidx, num;
5414 /* If the parallel region needs data sent from the parent
5415 function, then the very first statement (except possible
5416 tree profile counter updates) of the parallel body
5417 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5418 &.OMP_DATA_O is passed as an argument to the child function,
5419 we need to replace it with the argument as seen by the child
5420 function.
5422 In most cases, this will end up being the identity assignment
5423 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5424 a function call that has been inlined, the original PARM_DECL
5425 .OMP_DATA_I may have been converted into a different local
5426 variable. In which case, we need to keep the assignment. */
5427 if (gimple_omp_taskreg_data_arg (entry_stmt))
5429 basic_block entry_succ_bb
5430 = single_succ_p (entry_bb) ? single_succ (entry_bb)
5431 : FALLTHRU_EDGE (entry_bb)->dest;
5432 tree arg;
5433 gimple parcopy_stmt = NULL;
5435 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5437 gimple stmt;
5439 gcc_assert (!gsi_end_p (gsi));
5440 stmt = gsi_stmt (gsi);
5441 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5442 continue;
5444 if (gimple_num_ops (stmt) == 2)
5446 tree arg = gimple_assign_rhs1 (stmt);
5448 /* We're ignore the subcode because we're
5449 effectively doing a STRIP_NOPS. */
5451 if (TREE_CODE (arg) == ADDR_EXPR
5452 && TREE_OPERAND (arg, 0)
5453 == gimple_omp_taskreg_data_arg (entry_stmt))
5455 parcopy_stmt = stmt;
5456 break;
5461 gcc_assert (parcopy_stmt != NULL);
5462 arg = DECL_ARGUMENTS (child_fn);
5464 if (!gimple_in_ssa_p (cfun))
5466 if (gimple_assign_lhs (parcopy_stmt) == arg)
5467 gsi_remove (&gsi, true);
5468 else
5470 /* ?? Is setting the subcode really necessary ?? */
5471 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5472 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5475 else
5477 tree lhs = gimple_assign_lhs (parcopy_stmt);
5478 gcc_assert (SSA_NAME_VAR (lhs) == arg);
5479 /* We'd like to set the rhs to the default def in the child_fn,
5480 but it's too early to create ssa names in the child_fn.
5481 Instead, we set the rhs to the parm. In
5482 move_sese_region_to_fn, we introduce a default def for the
5483 parm, map the parm to it's default def, and once we encounter
5484 this stmt, replace the parm with the default def. */
5485 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5486 update_stmt (parcopy_stmt);
5490 /* Declare local variables needed in CHILD_CFUN. */
5491 block = DECL_INITIAL (child_fn);
5492 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5493 /* The gimplifier could record temporaries in parallel/task block
5494 rather than in containing function's local_decls chain,
5495 which would mean cgraph missed finalizing them. Do it now. */
5496 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5497 if (TREE_CODE (t) == VAR_DECL
5498 && TREE_STATIC (t)
5499 && !DECL_EXTERNAL (t))
5500 varpool_node::finalize_decl (t);
5501 DECL_SAVED_TREE (child_fn) = NULL;
5502 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5503 gimple_set_body (child_fn, NULL);
5504 TREE_USED (block) = 1;
5506 /* Reset DECL_CONTEXT on function arguments. */
5507 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5508 DECL_CONTEXT (t) = child_fn;
5510 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5511 so that it can be moved to the child function. */
5512 gsi = gsi_last_bb (entry_bb);
5513 stmt = gsi_stmt (gsi);
5514 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5515 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5516 e = split_block (entry_bb, stmt);
5517 gsi_remove (&gsi, true);
5518 entry_bb = e->dest;
5519 edge e2 = NULL;
5520 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5521 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5522 else
5524 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
5525 gcc_assert (e2->dest == region->exit);
5526 remove_edge (BRANCH_EDGE (entry_bb));
5527 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
5528 gsi = gsi_last_bb (region->exit);
5529 gcc_assert (!gsi_end_p (gsi)
5530 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5531 gsi_remove (&gsi, true);
5534 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5535 if (exit_bb)
5537 gsi = gsi_last_bb (exit_bb);
5538 gcc_assert (!gsi_end_p (gsi)
5539 && (gimple_code (gsi_stmt (gsi))
5540 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
5541 stmt = gimple_build_return (NULL);
5542 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5543 gsi_remove (&gsi, true);
5546 /* Move the parallel region into CHILD_CFUN. */
5548 if (gimple_in_ssa_p (cfun))
5550 init_tree_ssa (child_cfun);
5551 init_ssa_operands (child_cfun);
5552 child_cfun->gimple_df->in_ssa_p = true;
5553 block = NULL_TREE;
5555 else
5556 block = gimple_block (entry_stmt);
5558 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5559 if (exit_bb)
5560 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5561 if (e2)
5563 basic_block dest_bb = e2->dest;
5564 if (!exit_bb)
5565 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
5566 remove_edge (e2);
5567 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
5569 /* When the OMP expansion process cannot guarantee an up-to-date
5570 loop tree arrange for the child function to fixup loops. */
5571 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5572 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5574 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5575 num = vec_safe_length (child_cfun->local_decls);
5576 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5578 t = (*child_cfun->local_decls)[srcidx];
5579 if (DECL_CONTEXT (t) == cfun->decl)
5580 continue;
5581 if (srcidx != dstidx)
5582 (*child_cfun->local_decls)[dstidx] = t;
5583 dstidx++;
5585 if (dstidx != num)
5586 vec_safe_truncate (child_cfun->local_decls, dstidx);
5588 /* Inform the callgraph about the new function. */
5589 child_cfun->curr_properties = cfun->curr_properties;
5590 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
5591 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
5592 cgraph_node *node = cgraph_node::get_create (child_fn);
5593 node->parallelized_function = 1;
5594 cgraph_node::add_new_function (child_fn, true);
5596 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5597 fixed in a following pass. */
5598 push_cfun (child_cfun);
5599 if (optimize)
5600 optimize_omp_library_calls (entry_stmt);
5601 cgraph_edge::rebuild_edges ();
5603 /* Some EH regions might become dead, see PR34608. If
5604 pass_cleanup_cfg isn't the first pass to happen with the
5605 new child, these dead EH edges might cause problems.
5606 Clean them up now. */
5607 if (flag_exceptions)
5609 basic_block bb;
5610 bool changed = false;
5612 FOR_EACH_BB_FN (bb, cfun)
5613 changed |= gimple_purge_dead_eh_edges (bb);
5614 if (changed)
5615 cleanup_tree_cfg ();
5617 if (gimple_in_ssa_p (cfun))
5618 update_ssa (TODO_update_ssa);
5619 #ifdef ENABLE_CHECKING
5620 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5621 verify_loop_structure ();
5622 #endif
5623 pop_cfun ();
5626 /* Emit a library call to launch the children threads. */
5627 if (is_cilk_for)
5628 expand_cilk_for_call (new_bb,
5629 as_a <gomp_parallel *> (entry_stmt), ws_args);
5630 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5631 expand_parallel_call (region, new_bb,
5632 as_a <gomp_parallel *> (entry_stmt), ws_args);
5633 else
5634 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5635 if (gimple_in_ssa_p (cfun))
5636 update_ssa (TODO_update_ssa_only_virtuals);
5640 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5641 of the combined collapse > 1 loop constructs, generate code like:
5642 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5643 if (cond3 is <)
5644 adj = STEP3 - 1;
5645 else
5646 adj = STEP3 + 1;
5647 count3 = (adj + N32 - N31) / STEP3;
5648 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5649 if (cond2 is <)
5650 adj = STEP2 - 1;
5651 else
5652 adj = STEP2 + 1;
5653 count2 = (adj + N22 - N21) / STEP2;
5654 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5655 if (cond1 is <)
5656 adj = STEP1 - 1;
5657 else
5658 adj = STEP1 + 1;
5659 count1 = (adj + N12 - N11) / STEP1;
5660 count = count1 * count2 * count3;
5661 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5662 count = 0;
5663 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5664 of the combined loop constructs, just initialize COUNTS array
5665 from the _looptemp_ clauses. */
5667 /* NOTE: It *could* be better to moosh all of the BBs together,
5668 creating one larger BB with all the computation and the unexpected
5669 jump at the end. I.e.
5671 bool zero3, zero2, zero1, zero;
5673 zero3 = N32 c3 N31;
5674 count3 = (N32 - N31) /[cl] STEP3;
5675 zero2 = N22 c2 N21;
5676 count2 = (N22 - N21) /[cl] STEP2;
5677 zero1 = N12 c1 N11;
5678 count1 = (N12 - N11) /[cl] STEP1;
5679 zero = zero3 || zero2 || zero1;
5680 count = count1 * count2 * count3;
5681 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5683 After all, we expect the zero=false, and thus we expect to have to
5684 evaluate all of the comparison expressions, so short-circuiting
5685 oughtn't be a win. Since the condition isn't protecting a
5686 denominator, we're not concerned about divide-by-zero, so we can
5687 fully evaluate count even if a numerator turned out to be wrong.
5689 It seems like putting this all together would create much better
5690 scheduling opportunities, and less pressure on the chip's branch
5691 predictor. */
5693 static void
5694 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5695 basic_block &entry_bb, tree *counts,
5696 basic_block &zero_iter_bb, int &first_zero_iter,
5697 basic_block &l2_dom_bb)
5699 tree t, type = TREE_TYPE (fd->loop.v);
5700 edge e, ne;
5701 int i;
5703 /* Collapsed loops need work for expansion into SSA form. */
5704 gcc_assert (!gimple_in_ssa_p (cfun));
5706 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5707 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5709 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5710 isn't supposed to be handled, as the inner loop doesn't
5711 use it. */
5712 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5713 OMP_CLAUSE__LOOPTEMP_);
5714 gcc_assert (innerc);
5715 for (i = 0; i < fd->collapse; i++)
5717 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5718 OMP_CLAUSE__LOOPTEMP_);
5719 gcc_assert (innerc);
5720 if (i)
5721 counts[i] = OMP_CLAUSE_DECL (innerc);
5722 else
5723 counts[0] = NULL_TREE;
5725 return;
5728 for (i = 0; i < fd->collapse; i++)
5730 tree itype = TREE_TYPE (fd->loops[i].v);
5732 if (SSA_VAR_P (fd->loop.n2)
5733 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5734 fold_convert (itype, fd->loops[i].n1),
5735 fold_convert (itype, fd->loops[i].n2)))
5736 == NULL_TREE || !integer_onep (t)))
5738 gcond *cond_stmt;
5739 tree n1, n2;
5740 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5741 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5742 true, GSI_SAME_STMT);
5743 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5744 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5745 true, GSI_SAME_STMT);
5746 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5747 NULL_TREE, NULL_TREE);
5748 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5749 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5750 expand_omp_regimplify_p, NULL, NULL)
5751 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5752 expand_omp_regimplify_p, NULL, NULL))
5754 *gsi = gsi_for_stmt (cond_stmt);
5755 gimple_regimplify_operands (cond_stmt, gsi);
5757 e = split_block (entry_bb, cond_stmt);
5758 if (zero_iter_bb == NULL)
5760 gassign *assign_stmt;
5761 first_zero_iter = i;
5762 zero_iter_bb = create_empty_bb (entry_bb);
5763 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5764 *gsi = gsi_after_labels (zero_iter_bb);
5765 assign_stmt = gimple_build_assign (fd->loop.n2,
5766 build_zero_cst (type));
5767 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5768 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5769 entry_bb);
5771 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5772 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5773 e->flags = EDGE_TRUE_VALUE;
5774 e->probability = REG_BR_PROB_BASE - ne->probability;
5775 if (l2_dom_bb == NULL)
5776 l2_dom_bb = entry_bb;
5777 entry_bb = e->dest;
5778 *gsi = gsi_last_bb (entry_bb);
5781 if (POINTER_TYPE_P (itype))
5782 itype = signed_type_for (itype);
5783 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5784 ? -1 : 1));
5785 t = fold_build2 (PLUS_EXPR, itype,
5786 fold_convert (itype, fd->loops[i].step), t);
5787 t = fold_build2 (PLUS_EXPR, itype, t,
5788 fold_convert (itype, fd->loops[i].n2));
5789 t = fold_build2 (MINUS_EXPR, itype, t,
5790 fold_convert (itype, fd->loops[i].n1));
5791 /* ?? We could probably use CEIL_DIV_EXPR instead of
5792 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5793 generate the same code in the end because generically we
5794 don't know that the values involved must be negative for
5795 GT?? */
5796 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5797 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5798 fold_build1 (NEGATE_EXPR, itype, t),
5799 fold_build1 (NEGATE_EXPR, itype,
5800 fold_convert (itype,
5801 fd->loops[i].step)));
5802 else
5803 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5804 fold_convert (itype, fd->loops[i].step));
5805 t = fold_convert (type, t);
5806 if (TREE_CODE (t) == INTEGER_CST)
5807 counts[i] = t;
5808 else
5810 counts[i] = create_tmp_reg (type, ".count");
5811 expand_omp_build_assign (gsi, counts[i], t);
5813 if (SSA_VAR_P (fd->loop.n2))
5815 if (i == 0)
5816 t = counts[0];
5817 else
5818 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5819 expand_omp_build_assign (gsi, fd->loop.n2, t);
5825 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5826 T = V;
5827 V3 = N31 + (T % count3) * STEP3;
5828 T = T / count3;
5829 V2 = N21 + (T % count2) * STEP2;
5830 T = T / count2;
5831 V1 = N11 + T * STEP1;
5832 if this loop doesn't have an inner loop construct combined with it.
5833 If it does have an inner loop construct combined with it and the
5834 iteration count isn't known constant, store values from counts array
5835 into its _looptemp_ temporaries instead. */
5837 static void
5838 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5839 tree *counts, gimple inner_stmt, tree startvar)
5841 int i;
5842 if (gimple_omp_for_combined_p (fd->for_stmt))
5844 /* If fd->loop.n2 is constant, then no propagation of the counts
5845 is needed, they are constant. */
5846 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5847 return;
5849 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5850 ? gimple_omp_parallel_clauses (inner_stmt)
5851 : gimple_omp_for_clauses (inner_stmt);
5852 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5853 isn't supposed to be handled, as the inner loop doesn't
5854 use it. */
5855 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5856 gcc_assert (innerc);
5857 for (i = 0; i < fd->collapse; i++)
5859 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5860 OMP_CLAUSE__LOOPTEMP_);
5861 gcc_assert (innerc);
5862 if (i)
5864 tree tem = OMP_CLAUSE_DECL (innerc);
5865 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5866 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5867 false, GSI_CONTINUE_LINKING);
5868 gassign *stmt = gimple_build_assign (tem, t);
5869 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5872 return;
5875 tree type = TREE_TYPE (fd->loop.v);
5876 tree tem = create_tmp_reg (type, ".tem");
5877 gassign *stmt = gimple_build_assign (tem, startvar);
5878 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5880 for (i = fd->collapse - 1; i >= 0; i--)
5882 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5883 itype = vtype;
5884 if (POINTER_TYPE_P (vtype))
5885 itype = signed_type_for (vtype);
5886 if (i != 0)
5887 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5888 else
5889 t = tem;
5890 t = fold_convert (itype, t);
5891 t = fold_build2 (MULT_EXPR, itype, t,
5892 fold_convert (itype, fd->loops[i].step));
5893 if (POINTER_TYPE_P (vtype))
5894 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5895 else
5896 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5897 t = force_gimple_operand_gsi (gsi, t,
5898 DECL_P (fd->loops[i].v)
5899 && TREE_ADDRESSABLE (fd->loops[i].v),
5900 NULL_TREE, false,
5901 GSI_CONTINUE_LINKING);
5902 stmt = gimple_build_assign (fd->loops[i].v, t);
5903 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5904 if (i != 0)
5906 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5907 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5908 false, GSI_CONTINUE_LINKING);
5909 stmt = gimple_build_assign (tem, t);
5910 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5916 /* Helper function for expand_omp_for_*. Generate code like:
5917 L10:
5918 V3 += STEP3;
5919 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5920 L11:
5921 V3 = N31;
5922 V2 += STEP2;
5923 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5924 L12:
5925 V2 = N21;
5926 V1 += STEP1;
5927 goto BODY_BB; */
5929 static basic_block
5930 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5931 basic_block body_bb)
5933 basic_block last_bb, bb, collapse_bb = NULL;
5934 int i;
5935 gimple_stmt_iterator gsi;
5936 edge e;
5937 tree t;
5938 gimple stmt;
5940 last_bb = cont_bb;
5941 for (i = fd->collapse - 1; i >= 0; i--)
5943 tree vtype = TREE_TYPE (fd->loops[i].v);
5945 bb = create_empty_bb (last_bb);
5946 add_bb_to_loop (bb, last_bb->loop_father);
5947 gsi = gsi_start_bb (bb);
5949 if (i < fd->collapse - 1)
5951 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5952 e->probability = REG_BR_PROB_BASE / 8;
5954 t = fd->loops[i + 1].n1;
5955 t = force_gimple_operand_gsi (&gsi, t,
5956 DECL_P (fd->loops[i + 1].v)
5957 && TREE_ADDRESSABLE (fd->loops[i
5958 + 1].v),
5959 NULL_TREE, false,
5960 GSI_CONTINUE_LINKING);
5961 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5962 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5964 else
5965 collapse_bb = bb;
5967 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5969 if (POINTER_TYPE_P (vtype))
5970 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5971 else
5972 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5973 t = force_gimple_operand_gsi (&gsi, t,
5974 DECL_P (fd->loops[i].v)
5975 && TREE_ADDRESSABLE (fd->loops[i].v),
5976 NULL_TREE, false, GSI_CONTINUE_LINKING);
5977 stmt = gimple_build_assign (fd->loops[i].v, t);
5978 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5980 if (i > 0)
5982 t = fd->loops[i].n2;
5983 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5984 false, GSI_CONTINUE_LINKING);
5985 tree v = fd->loops[i].v;
5986 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5987 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5988 false, GSI_CONTINUE_LINKING);
5989 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5990 stmt = gimple_build_cond_empty (t);
5991 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5992 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5993 e->probability = REG_BR_PROB_BASE * 7 / 8;
5995 else
5996 make_edge (bb, body_bb, EDGE_FALLTHRU);
5997 last_bb = bb;
6000 return collapse_bb;
6004 /* A subroutine of expand_omp_for. Generate code for a parallel
6005 loop with any schedule. Given parameters:
6007 for (V = N1; V cond N2; V += STEP) BODY;
6009 where COND is "<" or ">", we generate pseudocode
6011 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
6012 if (more) goto L0; else goto L3;
6014 V = istart0;
6015 iend = iend0;
6017 BODY;
6018 V += STEP;
6019 if (V cond iend) goto L1; else goto L2;
6021 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6024 If this is a combined omp parallel loop, instead of the call to
6025 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6026 If this is gimple_omp_for_combined_p loop, then instead of assigning
6027 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6028 inner GIMPLE_OMP_FOR and V += STEP; and
6029 if (V cond iend) goto L1; else goto L2; are removed.
6031 For collapsed loops, given parameters:
6032 collapse(3)
6033 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6034 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6035 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6036 BODY;
6038 we generate pseudocode
6040 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6041 if (cond3 is <)
6042 adj = STEP3 - 1;
6043 else
6044 adj = STEP3 + 1;
6045 count3 = (adj + N32 - N31) / STEP3;
6046 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6047 if (cond2 is <)
6048 adj = STEP2 - 1;
6049 else
6050 adj = STEP2 + 1;
6051 count2 = (adj + N22 - N21) / STEP2;
6052 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6053 if (cond1 is <)
6054 adj = STEP1 - 1;
6055 else
6056 adj = STEP1 + 1;
6057 count1 = (adj + N12 - N11) / STEP1;
6058 count = count1 * count2 * count3;
6059 goto Z1;
6061 count = 0;
6063 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6064 if (more) goto L0; else goto L3;
6066 V = istart0;
6067 T = V;
6068 V3 = N31 + (T % count3) * STEP3;
6069 T = T / count3;
6070 V2 = N21 + (T % count2) * STEP2;
6071 T = T / count2;
6072 V1 = N11 + T * STEP1;
6073 iend = iend0;
6075 BODY;
6076 V += 1;
6077 if (V < iend) goto L10; else goto L2;
6078 L10:
6079 V3 += STEP3;
6080 if (V3 cond3 N32) goto L1; else goto L11;
6081 L11:
6082 V3 = N31;
6083 V2 += STEP2;
6084 if (V2 cond2 N22) goto L1; else goto L12;
6085 L12:
6086 V2 = N21;
6087 V1 += STEP1;
6088 goto L1;
6090 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6095 static void
6096 expand_omp_for_generic (struct omp_region *region,
6097 struct omp_for_data *fd,
6098 enum built_in_function start_fn,
6099 enum built_in_function next_fn,
6100 gimple inner_stmt)
6102 tree type, istart0, iend0, iend;
6103 tree t, vmain, vback, bias = NULL_TREE;
6104 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6105 basic_block l2_bb = NULL, l3_bb = NULL;
6106 gimple_stmt_iterator gsi;
6107 gassign *assign_stmt;
6108 bool in_combined_parallel = is_combined_parallel (region);
6109 bool broken_loop = region->cont == NULL;
6110 edge e, ne;
6111 tree *counts = NULL;
6112 int i;
6114 gcc_assert (!broken_loop || !in_combined_parallel);
6115 gcc_assert (fd->iter_type == long_integer_type_node
6116 || !in_combined_parallel);
6118 type = TREE_TYPE (fd->loop.v);
6119 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6120 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6121 TREE_ADDRESSABLE (istart0) = 1;
6122 TREE_ADDRESSABLE (iend0) = 1;
6124 /* See if we need to bias by LLONG_MIN. */
6125 if (fd->iter_type == long_long_unsigned_type_node
6126 && TREE_CODE (type) == INTEGER_TYPE
6127 && !TYPE_UNSIGNED (type))
6129 tree n1, n2;
6131 if (fd->loop.cond_code == LT_EXPR)
6133 n1 = fd->loop.n1;
6134 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6136 else
6138 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6139 n2 = fd->loop.n1;
6141 if (TREE_CODE (n1) != INTEGER_CST
6142 || TREE_CODE (n2) != INTEGER_CST
6143 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6144 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6147 entry_bb = region->entry;
6148 cont_bb = region->cont;
6149 collapse_bb = NULL;
6150 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6151 gcc_assert (broken_loop
6152 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6153 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6154 l1_bb = single_succ (l0_bb);
6155 if (!broken_loop)
6157 l2_bb = create_empty_bb (cont_bb);
6158 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6159 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6161 else
6162 l2_bb = NULL;
6163 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6164 exit_bb = region->exit;
6166 gsi = gsi_last_bb (entry_bb);
6168 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6169 if (fd->collapse > 1)
6171 int first_zero_iter = -1;
6172 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6174 counts = XALLOCAVEC (tree, fd->collapse);
6175 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6176 zero_iter_bb, first_zero_iter,
6177 l2_dom_bb);
6179 if (zero_iter_bb)
6181 /* Some counts[i] vars might be uninitialized if
6182 some loop has zero iterations. But the body shouldn't
6183 be executed in that case, so just avoid uninit warnings. */
6184 for (i = first_zero_iter; i < fd->collapse; i++)
6185 if (SSA_VAR_P (counts[i]))
6186 TREE_NO_WARNING (counts[i]) = 1;
6187 gsi_prev (&gsi);
6188 e = split_block (entry_bb, gsi_stmt (gsi));
6189 entry_bb = e->dest;
6190 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6191 gsi = gsi_last_bb (entry_bb);
6192 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6193 get_immediate_dominator (CDI_DOMINATORS,
6194 zero_iter_bb));
6197 if (in_combined_parallel)
6199 /* In a combined parallel loop, emit a call to
6200 GOMP_loop_foo_next. */
6201 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6202 build_fold_addr_expr (istart0),
6203 build_fold_addr_expr (iend0));
6205 else
6207 tree t0, t1, t2, t3, t4;
6208 /* If this is not a combined parallel loop, emit a call to
6209 GOMP_loop_foo_start in ENTRY_BB. */
6210 t4 = build_fold_addr_expr (iend0);
6211 t3 = build_fold_addr_expr (istart0);
6212 t2 = fold_convert (fd->iter_type, fd->loop.step);
6213 t1 = fd->loop.n2;
6214 t0 = fd->loop.n1;
6215 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6217 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6218 OMP_CLAUSE__LOOPTEMP_);
6219 gcc_assert (innerc);
6220 t0 = OMP_CLAUSE_DECL (innerc);
6221 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6222 OMP_CLAUSE__LOOPTEMP_);
6223 gcc_assert (innerc);
6224 t1 = OMP_CLAUSE_DECL (innerc);
6226 if (POINTER_TYPE_P (TREE_TYPE (t0))
6227 && TYPE_PRECISION (TREE_TYPE (t0))
6228 != TYPE_PRECISION (fd->iter_type))
6230 /* Avoid casting pointers to integer of a different size. */
6231 tree itype = signed_type_for (type);
6232 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6233 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6235 else
6237 t1 = fold_convert (fd->iter_type, t1);
6238 t0 = fold_convert (fd->iter_type, t0);
6240 if (bias)
6242 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6243 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6245 if (fd->iter_type == long_integer_type_node)
6247 if (fd->chunk_size)
6249 t = fold_convert (fd->iter_type, fd->chunk_size);
6250 t = build_call_expr (builtin_decl_explicit (start_fn),
6251 6, t0, t1, t2, t, t3, t4);
6253 else
6254 t = build_call_expr (builtin_decl_explicit (start_fn),
6255 5, t0, t1, t2, t3, t4);
6257 else
6259 tree t5;
6260 tree c_bool_type;
6261 tree bfn_decl;
6263 /* The GOMP_loop_ull_*start functions have additional boolean
6264 argument, true for < loops and false for > loops.
6265 In Fortran, the C bool type can be different from
6266 boolean_type_node. */
6267 bfn_decl = builtin_decl_explicit (start_fn);
6268 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6269 t5 = build_int_cst (c_bool_type,
6270 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6271 if (fd->chunk_size)
6273 tree bfn_decl = builtin_decl_explicit (start_fn);
6274 t = fold_convert (fd->iter_type, fd->chunk_size);
6275 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6277 else
6278 t = build_call_expr (builtin_decl_explicit (start_fn),
6279 6, t5, t0, t1, t2, t3, t4);
6282 if (TREE_TYPE (t) != boolean_type_node)
6283 t = fold_build2 (NE_EXPR, boolean_type_node,
6284 t, build_int_cst (TREE_TYPE (t), 0));
6285 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6286 true, GSI_SAME_STMT);
6287 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6289 /* Remove the GIMPLE_OMP_FOR statement. */
6290 gsi_remove (&gsi, true);
6292 /* Iteration setup for sequential loop goes in L0_BB. */
6293 tree startvar = fd->loop.v;
6294 tree endvar = NULL_TREE;
6296 if (gimple_omp_for_combined_p (fd->for_stmt))
6298 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6299 && gimple_omp_for_kind (inner_stmt)
6300 == GF_OMP_FOR_KIND_SIMD);
6301 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6302 OMP_CLAUSE__LOOPTEMP_);
6303 gcc_assert (innerc);
6304 startvar = OMP_CLAUSE_DECL (innerc);
6305 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6306 OMP_CLAUSE__LOOPTEMP_);
6307 gcc_assert (innerc);
6308 endvar = OMP_CLAUSE_DECL (innerc);
6311 gsi = gsi_start_bb (l0_bb);
6312 t = istart0;
6313 if (bias)
6314 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6315 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6316 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6317 t = fold_convert (TREE_TYPE (startvar), t);
6318 t = force_gimple_operand_gsi (&gsi, t,
6319 DECL_P (startvar)
6320 && TREE_ADDRESSABLE (startvar),
6321 NULL_TREE, false, GSI_CONTINUE_LINKING);
6322 assign_stmt = gimple_build_assign (startvar, t);
6323 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6325 t = iend0;
6326 if (bias)
6327 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6328 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6329 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6330 t = fold_convert (TREE_TYPE (startvar), t);
6331 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6332 false, GSI_CONTINUE_LINKING);
6333 if (endvar)
6335 assign_stmt = gimple_build_assign (endvar, iend);
6336 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6337 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6338 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6339 else
6340 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6341 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6343 if (fd->collapse > 1)
6344 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6346 if (!broken_loop)
6348 /* Code to control the increment and predicate for the sequential
6349 loop goes in the CONT_BB. */
6350 gsi = gsi_last_bb (cont_bb);
6351 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6352 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6353 vmain = gimple_omp_continue_control_use (cont_stmt);
6354 vback = gimple_omp_continue_control_def (cont_stmt);
6356 if (!gimple_omp_for_combined_p (fd->for_stmt))
6358 if (POINTER_TYPE_P (type))
6359 t = fold_build_pointer_plus (vmain, fd->loop.step);
6360 else
6361 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6362 t = force_gimple_operand_gsi (&gsi, t,
6363 DECL_P (vback)
6364 && TREE_ADDRESSABLE (vback),
6365 NULL_TREE, true, GSI_SAME_STMT);
6366 assign_stmt = gimple_build_assign (vback, t);
6367 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6369 t = build2 (fd->loop.cond_code, boolean_type_node,
6370 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6371 iend);
6372 gcond *cond_stmt = gimple_build_cond_empty (t);
6373 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6376 /* Remove GIMPLE_OMP_CONTINUE. */
6377 gsi_remove (&gsi, true);
6379 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6380 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6382 /* Emit code to get the next parallel iteration in L2_BB. */
6383 gsi = gsi_start_bb (l2_bb);
6385 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6386 build_fold_addr_expr (istart0),
6387 build_fold_addr_expr (iend0));
6388 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6389 false, GSI_CONTINUE_LINKING);
6390 if (TREE_TYPE (t) != boolean_type_node)
6391 t = fold_build2 (NE_EXPR, boolean_type_node,
6392 t, build_int_cst (TREE_TYPE (t), 0));
6393 gcond *cond_stmt = gimple_build_cond_empty (t);
6394 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6397 /* Add the loop cleanup function. */
6398 gsi = gsi_last_bb (exit_bb);
6399 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6400 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6401 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6402 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6403 else
6404 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6405 gcall *call_stmt = gimple_build_call (t, 0);
6406 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6407 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6408 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6409 gsi_remove (&gsi, true);
6411 /* Connect the new blocks. */
6412 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6413 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6415 if (!broken_loop)
6417 gimple_seq phis;
6419 e = find_edge (cont_bb, l3_bb);
6420 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6422 phis = phi_nodes (l3_bb);
6423 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6425 gimple phi = gsi_stmt (gsi);
6426 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6427 PHI_ARG_DEF_FROM_EDGE (phi, e));
6429 remove_edge (e);
6431 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6432 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6433 e = find_edge (cont_bb, l1_bb);
6434 if (gimple_omp_for_combined_p (fd->for_stmt))
6436 remove_edge (e);
6437 e = NULL;
6439 else if (fd->collapse > 1)
6441 remove_edge (e);
6442 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6444 else
6445 e->flags = EDGE_TRUE_VALUE;
6446 if (e)
6448 e->probability = REG_BR_PROB_BASE * 7 / 8;
6449 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6451 else
6453 e = find_edge (cont_bb, l2_bb);
6454 e->flags = EDGE_FALLTHRU;
6456 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6458 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6459 recompute_dominator (CDI_DOMINATORS, l2_bb));
6460 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6461 recompute_dominator (CDI_DOMINATORS, l3_bb));
6462 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6463 recompute_dominator (CDI_DOMINATORS, l0_bb));
6464 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6465 recompute_dominator (CDI_DOMINATORS, l1_bb));
6467 struct loop *outer_loop = alloc_loop ();
6468 outer_loop->header = l0_bb;
6469 outer_loop->latch = l2_bb;
6470 add_loop (outer_loop, l0_bb->loop_father);
6472 if (!gimple_omp_for_combined_p (fd->for_stmt))
6474 struct loop *loop = alloc_loop ();
6475 loop->header = l1_bb;
6476 /* The loop may have multiple latches. */
6477 add_loop (loop, outer_loop);
6483 /* A subroutine of expand_omp_for. Generate code for a parallel
6484 loop with static schedule and no specified chunk size. Given
6485 parameters:
6487 for (V = N1; V cond N2; V += STEP) BODY;
6489 where COND is "<" or ">", we generate pseudocode
6491 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6492 if (cond is <)
6493 adj = STEP - 1;
6494 else
6495 adj = STEP + 1;
6496 if ((__typeof (V)) -1 > 0 && cond is >)
6497 n = -(adj + N2 - N1) / -STEP;
6498 else
6499 n = (adj + N2 - N1) / STEP;
6500 q = n / nthreads;
6501 tt = n % nthreads;
6502 if (threadid < tt) goto L3; else goto L4;
6504 tt = 0;
6505 q = q + 1;
6507 s0 = q * threadid + tt;
6508 e0 = s0 + q;
6509 V = s0 * STEP + N1;
6510 if (s0 >= e0) goto L2; else goto L0;
6512 e = e0 * STEP + N1;
6514 BODY;
6515 V += STEP;
6516 if (V cond e) goto L1;
6520 static void
6521 expand_omp_for_static_nochunk (struct omp_region *region,
6522 struct omp_for_data *fd,
6523 gimple inner_stmt)
6525 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6526 tree type, itype, vmain, vback;
6527 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6528 basic_block body_bb, cont_bb, collapse_bb = NULL;
6529 basic_block fin_bb;
6530 gimple_stmt_iterator gsi;
6531 edge ep;
6532 bool broken_loop = region->cont == NULL;
6533 tree *counts = NULL;
6534 tree n1, n2, step;
6536 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6537 != GF_OMP_FOR_KIND_OACC_LOOP)
6538 || !inner_stmt);
6540 itype = type = TREE_TYPE (fd->loop.v);
6541 if (POINTER_TYPE_P (type))
6542 itype = signed_type_for (type);
6544 entry_bb = region->entry;
6545 cont_bb = region->cont;
6546 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6547 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6548 gcc_assert (broken_loop
6549 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6550 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6551 body_bb = single_succ (seq_start_bb);
6552 if (!broken_loop)
6554 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
6555 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
6556 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6558 exit_bb = region->exit;
6560 /* Iteration space partitioning goes in ENTRY_BB. */
6561 gsi = gsi_last_bb (entry_bb);
6562 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6564 if (fd->collapse > 1)
6566 int first_zero_iter = -1;
6567 basic_block l2_dom_bb = NULL;
6569 counts = XALLOCAVEC (tree, fd->collapse);
6570 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6571 fin_bb, first_zero_iter,
6572 l2_dom_bb);
6573 t = NULL_TREE;
6575 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6576 t = integer_one_node;
6577 else
6578 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6579 fold_convert (type, fd->loop.n1),
6580 fold_convert (type, fd->loop.n2));
6581 if (fd->collapse == 1
6582 && TYPE_UNSIGNED (type)
6583 && (t == NULL_TREE || !integer_onep (t)))
6585 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6586 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6587 true, GSI_SAME_STMT);
6588 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6589 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6590 true, GSI_SAME_STMT);
6591 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6592 NULL_TREE, NULL_TREE);
6593 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6594 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6595 expand_omp_regimplify_p, NULL, NULL)
6596 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6597 expand_omp_regimplify_p, NULL, NULL))
6599 gsi = gsi_for_stmt (cond_stmt);
6600 gimple_regimplify_operands (cond_stmt, &gsi);
6602 ep = split_block (entry_bb, cond_stmt);
6603 ep->flags = EDGE_TRUE_VALUE;
6604 entry_bb = ep->dest;
6605 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6606 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6607 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6608 if (gimple_in_ssa_p (cfun))
6610 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6611 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6612 !gsi_end_p (gpi); gsi_next (&gpi))
6614 gphi *phi = gpi.phi ();
6615 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6616 ep, UNKNOWN_LOCATION);
6619 gsi = gsi_last_bb (entry_bb);
6622 switch (gimple_omp_for_kind (fd->for_stmt))
6624 case GF_OMP_FOR_KIND_FOR:
6625 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6626 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6627 break;
6628 case GF_OMP_FOR_KIND_DISTRIBUTE:
6629 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6630 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6631 break;
6632 case GF_OMP_FOR_KIND_OACC_LOOP:
6633 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6634 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6635 break;
6636 default:
6637 gcc_unreachable ();
6639 nthreads = build_call_expr (nthreads, 0);
6640 nthreads = fold_convert (itype, nthreads);
6641 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6642 true, GSI_SAME_STMT);
6643 threadid = build_call_expr (threadid, 0);
6644 threadid = fold_convert (itype, threadid);
6645 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6646 true, GSI_SAME_STMT);
6648 n1 = fd->loop.n1;
6649 n2 = fd->loop.n2;
6650 step = fd->loop.step;
6651 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6653 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6654 OMP_CLAUSE__LOOPTEMP_);
6655 gcc_assert (innerc);
6656 n1 = OMP_CLAUSE_DECL (innerc);
6657 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6658 OMP_CLAUSE__LOOPTEMP_);
6659 gcc_assert (innerc);
6660 n2 = OMP_CLAUSE_DECL (innerc);
6662 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6663 true, NULL_TREE, true, GSI_SAME_STMT);
6664 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6665 true, NULL_TREE, true, GSI_SAME_STMT);
6666 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6667 true, NULL_TREE, true, GSI_SAME_STMT);
6669 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6670 t = fold_build2 (PLUS_EXPR, itype, step, t);
6671 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6672 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6673 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6674 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6675 fold_build1 (NEGATE_EXPR, itype, t),
6676 fold_build1 (NEGATE_EXPR, itype, step));
6677 else
6678 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6679 t = fold_convert (itype, t);
6680 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6682 q = create_tmp_reg (itype, "q");
6683 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6684 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6685 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6687 tt = create_tmp_reg (itype, "tt");
6688 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6689 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6690 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6692 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6693 gcond *cond_stmt = gimple_build_cond_empty (t);
6694 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6696 second_bb = split_block (entry_bb, cond_stmt)->dest;
6697 gsi = gsi_last_bb (second_bb);
6698 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6700 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6701 GSI_SAME_STMT);
6702 gassign *assign_stmt
6703 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6704 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6706 third_bb = split_block (second_bb, assign_stmt)->dest;
6707 gsi = gsi_last_bb (third_bb);
6708 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6710 t = build2 (MULT_EXPR, itype, q, threadid);
6711 t = build2 (PLUS_EXPR, itype, t, tt);
6712 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6714 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6715 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6717 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6718 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6720 /* Remove the GIMPLE_OMP_FOR statement. */
6721 gsi_remove (&gsi, true);
6723 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6724 gsi = gsi_start_bb (seq_start_bb);
6726 tree startvar = fd->loop.v;
6727 tree endvar = NULL_TREE;
6729 if (gimple_omp_for_combined_p (fd->for_stmt))
6731 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6732 ? gimple_omp_parallel_clauses (inner_stmt)
6733 : gimple_omp_for_clauses (inner_stmt);
6734 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6735 gcc_assert (innerc);
6736 startvar = OMP_CLAUSE_DECL (innerc);
6737 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6738 OMP_CLAUSE__LOOPTEMP_);
6739 gcc_assert (innerc);
6740 endvar = OMP_CLAUSE_DECL (innerc);
6742 t = fold_convert (itype, s0);
6743 t = fold_build2 (MULT_EXPR, itype, t, step);
6744 if (POINTER_TYPE_P (type))
6745 t = fold_build_pointer_plus (n1, t);
6746 else
6747 t = fold_build2 (PLUS_EXPR, type, t, n1);
6748 t = fold_convert (TREE_TYPE (startvar), t);
6749 t = force_gimple_operand_gsi (&gsi, t,
6750 DECL_P (startvar)
6751 && TREE_ADDRESSABLE (startvar),
6752 NULL_TREE, false, GSI_CONTINUE_LINKING);
6753 assign_stmt = gimple_build_assign (startvar, t);
6754 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6756 t = fold_convert (itype, e0);
6757 t = fold_build2 (MULT_EXPR, itype, t, step);
6758 if (POINTER_TYPE_P (type))
6759 t = fold_build_pointer_plus (n1, t);
6760 else
6761 t = fold_build2 (PLUS_EXPR, type, t, n1);
6762 t = fold_convert (TREE_TYPE (startvar), t);
6763 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6764 false, GSI_CONTINUE_LINKING);
6765 if (endvar)
6767 assign_stmt = gimple_build_assign (endvar, e);
6768 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6769 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6770 assign_stmt = gimple_build_assign (fd->loop.v, e);
6771 else
6772 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6773 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6775 if (fd->collapse > 1)
6776 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6778 if (!broken_loop)
6780 /* The code controlling the sequential loop replaces the
6781 GIMPLE_OMP_CONTINUE. */
6782 gsi = gsi_last_bb (cont_bb);
6783 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6784 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6785 vmain = gimple_omp_continue_control_use (cont_stmt);
6786 vback = gimple_omp_continue_control_def (cont_stmt);
6788 if (!gimple_omp_for_combined_p (fd->for_stmt))
6790 if (POINTER_TYPE_P (type))
6791 t = fold_build_pointer_plus (vmain, step);
6792 else
6793 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6794 t = force_gimple_operand_gsi (&gsi, t,
6795 DECL_P (vback)
6796 && TREE_ADDRESSABLE (vback),
6797 NULL_TREE, true, GSI_SAME_STMT);
6798 assign_stmt = gimple_build_assign (vback, t);
6799 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6801 t = build2 (fd->loop.cond_code, boolean_type_node,
6802 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6803 ? t : vback, e);
6804 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6807 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6808 gsi_remove (&gsi, true);
6810 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6811 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6814 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6815 gsi = gsi_last_bb (exit_bb);
6816 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6818 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6819 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6820 gcc_checking_assert (t == NULL_TREE);
6821 else
6822 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6824 gsi_remove (&gsi, true);
6826 /* Connect all the blocks. */
6827 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6828 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6829 ep = find_edge (entry_bb, second_bb);
6830 ep->flags = EDGE_TRUE_VALUE;
6831 ep->probability = REG_BR_PROB_BASE / 4;
6832 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6833 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6835 if (!broken_loop)
6837 ep = find_edge (cont_bb, body_bb);
6838 if (ep == NULL)
6840 ep = BRANCH_EDGE (cont_bb);
6841 gcc_assert (single_succ (ep->dest) == body_bb);
6843 if (gimple_omp_for_combined_p (fd->for_stmt))
6845 remove_edge (ep);
6846 ep = NULL;
6848 else if (fd->collapse > 1)
6850 remove_edge (ep);
6851 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6853 else
6854 ep->flags = EDGE_TRUE_VALUE;
6855 find_edge (cont_bb, fin_bb)->flags
6856 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6859 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6860 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6861 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6863 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6864 recompute_dominator (CDI_DOMINATORS, body_bb));
6865 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6866 recompute_dominator (CDI_DOMINATORS, fin_bb));
6868 struct loop *loop = body_bb->loop_father;
6869 if (loop != entry_bb->loop_father)
6871 gcc_assert (loop->header == body_bb);
6872 gcc_assert (broken_loop
6873 || loop->latch == region->cont
6874 || single_pred (loop->latch) == region->cont);
6875 return;
6878 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6880 loop = alloc_loop ();
6881 loop->header = body_bb;
6882 if (collapse_bb == NULL)
6883 loop->latch = cont_bb;
6884 add_loop (loop, body_bb->loop_father);
6888 /* Return phi in E->DEST with ARG on edge E. */
6890 static gphi *
6891 find_phi_with_arg_on_edge (tree arg, edge e)
6893 basic_block bb = e->dest;
6895 for (gphi_iterator gpi = gsi_start_phis (bb);
6896 !gsi_end_p (gpi);
6897 gsi_next (&gpi))
6899 gphi *phi = gpi.phi ();
6900 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
6901 return phi;
6904 return NULL;
6907 /* A subroutine of expand_omp_for. Generate code for a parallel
6908 loop with static schedule and a specified chunk size. Given
6909 parameters:
6911 for (V = N1; V cond N2; V += STEP) BODY;
6913 where COND is "<" or ">", we generate pseudocode
6915 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6916 if (cond is <)
6917 adj = STEP - 1;
6918 else
6919 adj = STEP + 1;
6920 if ((__typeof (V)) -1 > 0 && cond is >)
6921 n = -(adj + N2 - N1) / -STEP;
6922 else
6923 n = (adj + N2 - N1) / STEP;
6924 trip = 0;
6925 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6926 here so that V is defined
6927 if the loop is not entered
6929 s0 = (trip * nthreads + threadid) * CHUNK;
6930 e0 = min(s0 + CHUNK, n);
6931 if (s0 < n) goto L1; else goto L4;
6933 V = s0 * STEP + N1;
6934 e = e0 * STEP + N1;
6936 BODY;
6937 V += STEP;
6938 if (V cond e) goto L2; else goto L3;
6940 trip += 1;
6941 goto L0;
6945 static void
6946 expand_omp_for_static_chunk (struct omp_region *region,
6947 struct omp_for_data *fd, gimple inner_stmt)
6949 tree n, s0, e0, e, t;
6950 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6951 tree type, itype, vmain, vback, vextra;
6952 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6953 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6954 gimple_stmt_iterator gsi;
6955 edge se;
6956 bool broken_loop = region->cont == NULL;
6957 tree *counts = NULL;
6958 tree n1, n2, step;
6960 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6961 != GF_OMP_FOR_KIND_OACC_LOOP)
6962 || !inner_stmt);
6964 itype = type = TREE_TYPE (fd->loop.v);
6965 if (POINTER_TYPE_P (type))
6966 itype = signed_type_for (type);
6968 entry_bb = region->entry;
6969 se = split_block (entry_bb, last_stmt (entry_bb));
6970 entry_bb = se->src;
6971 iter_part_bb = se->dest;
6972 cont_bb = region->cont;
6973 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6974 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6975 gcc_assert (broken_loop
6976 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6977 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6978 body_bb = single_succ (seq_start_bb);
6979 if (!broken_loop)
6981 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
6982 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
6983 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6984 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6986 exit_bb = region->exit;
6988 /* Trip and adjustment setup goes in ENTRY_BB. */
6989 gsi = gsi_last_bb (entry_bb);
6990 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6992 if (fd->collapse > 1)
6994 int first_zero_iter = -1;
6995 basic_block l2_dom_bb = NULL;
6997 counts = XALLOCAVEC (tree, fd->collapse);
6998 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6999 fin_bb, first_zero_iter,
7000 l2_dom_bb);
7001 t = NULL_TREE;
7003 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
7004 t = integer_one_node;
7005 else
7006 t = fold_binary (fd->loop.cond_code, boolean_type_node,
7007 fold_convert (type, fd->loop.n1),
7008 fold_convert (type, fd->loop.n2));
7009 if (fd->collapse == 1
7010 && TYPE_UNSIGNED (type)
7011 && (t == NULL_TREE || !integer_onep (t)))
7013 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
7014 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
7015 true, GSI_SAME_STMT);
7016 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
7017 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
7018 true, GSI_SAME_STMT);
7019 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
7020 NULL_TREE, NULL_TREE);
7021 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
7022 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7023 expand_omp_regimplify_p, NULL, NULL)
7024 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7025 expand_omp_regimplify_p, NULL, NULL))
7027 gsi = gsi_for_stmt (cond_stmt);
7028 gimple_regimplify_operands (cond_stmt, &gsi);
7030 se = split_block (entry_bb, cond_stmt);
7031 se->flags = EDGE_TRUE_VALUE;
7032 entry_bb = se->dest;
7033 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
7034 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
7035 se->probability = REG_BR_PROB_BASE / 2000 - 1;
7036 if (gimple_in_ssa_p (cfun))
7038 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
7039 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
7040 !gsi_end_p (gpi); gsi_next (&gpi))
7042 gphi *phi = gpi.phi ();
7043 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
7044 se, UNKNOWN_LOCATION);
7047 gsi = gsi_last_bb (entry_bb);
7050 switch (gimple_omp_for_kind (fd->for_stmt))
7052 case GF_OMP_FOR_KIND_FOR:
7053 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7054 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7055 break;
7056 case GF_OMP_FOR_KIND_DISTRIBUTE:
7057 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7058 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7059 break;
7060 case GF_OMP_FOR_KIND_OACC_LOOP:
7061 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7062 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7063 break;
7064 default:
7065 gcc_unreachable ();
7067 nthreads = build_call_expr (nthreads, 0);
7068 nthreads = fold_convert (itype, nthreads);
7069 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7070 true, GSI_SAME_STMT);
7071 threadid = build_call_expr (threadid, 0);
7072 threadid = fold_convert (itype, threadid);
7073 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7074 true, GSI_SAME_STMT);
7076 n1 = fd->loop.n1;
7077 n2 = fd->loop.n2;
7078 step = fd->loop.step;
7079 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7081 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7082 OMP_CLAUSE__LOOPTEMP_);
7083 gcc_assert (innerc);
7084 n1 = OMP_CLAUSE_DECL (innerc);
7085 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7086 OMP_CLAUSE__LOOPTEMP_);
7087 gcc_assert (innerc);
7088 n2 = OMP_CLAUSE_DECL (innerc);
7090 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7091 true, NULL_TREE, true, GSI_SAME_STMT);
7092 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7093 true, NULL_TREE, true, GSI_SAME_STMT);
7094 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7095 true, NULL_TREE, true, GSI_SAME_STMT);
7096 fd->chunk_size
7097 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7098 true, NULL_TREE, true, GSI_SAME_STMT);
7100 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7101 t = fold_build2 (PLUS_EXPR, itype, step, t);
7102 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7103 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7104 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7105 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7106 fold_build1 (NEGATE_EXPR, itype, t),
7107 fold_build1 (NEGATE_EXPR, itype, step));
7108 else
7109 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7110 t = fold_convert (itype, t);
7111 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7112 true, GSI_SAME_STMT);
7114 trip_var = create_tmp_reg (itype, ".trip");
7115 if (gimple_in_ssa_p (cfun))
7117 trip_init = make_ssa_name (trip_var);
7118 trip_main = make_ssa_name (trip_var);
7119 trip_back = make_ssa_name (trip_var);
7121 else
7123 trip_init = trip_var;
7124 trip_main = trip_var;
7125 trip_back = trip_var;
7128 gassign *assign_stmt
7129 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7130 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7132 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7133 t = fold_build2 (MULT_EXPR, itype, t, step);
7134 if (POINTER_TYPE_P (type))
7135 t = fold_build_pointer_plus (n1, t);
7136 else
7137 t = fold_build2 (PLUS_EXPR, type, t, n1);
7138 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7139 true, GSI_SAME_STMT);
7141 /* Remove the GIMPLE_OMP_FOR. */
7142 gsi_remove (&gsi, true);
7144 /* Iteration space partitioning goes in ITER_PART_BB. */
7145 gsi = gsi_last_bb (iter_part_bb);
7147 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7148 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7149 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7150 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7151 false, GSI_CONTINUE_LINKING);
7153 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7154 t = fold_build2 (MIN_EXPR, itype, t, n);
7155 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7156 false, GSI_CONTINUE_LINKING);
7158 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7159 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7161 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7162 gsi = gsi_start_bb (seq_start_bb);
7164 tree startvar = fd->loop.v;
7165 tree endvar = NULL_TREE;
7167 if (gimple_omp_for_combined_p (fd->for_stmt))
7169 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7170 ? gimple_omp_parallel_clauses (inner_stmt)
7171 : gimple_omp_for_clauses (inner_stmt);
7172 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7173 gcc_assert (innerc);
7174 startvar = OMP_CLAUSE_DECL (innerc);
7175 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7176 OMP_CLAUSE__LOOPTEMP_);
7177 gcc_assert (innerc);
7178 endvar = OMP_CLAUSE_DECL (innerc);
7181 t = fold_convert (itype, s0);
7182 t = fold_build2 (MULT_EXPR, itype, t, step);
7183 if (POINTER_TYPE_P (type))
7184 t = fold_build_pointer_plus (n1, t);
7185 else
7186 t = fold_build2 (PLUS_EXPR, type, t, n1);
7187 t = fold_convert (TREE_TYPE (startvar), t);
7188 t = force_gimple_operand_gsi (&gsi, t,
7189 DECL_P (startvar)
7190 && TREE_ADDRESSABLE (startvar),
7191 NULL_TREE, false, GSI_CONTINUE_LINKING);
7192 assign_stmt = gimple_build_assign (startvar, t);
7193 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7195 t = fold_convert (itype, e0);
7196 t = fold_build2 (MULT_EXPR, itype, t, step);
7197 if (POINTER_TYPE_P (type))
7198 t = fold_build_pointer_plus (n1, t);
7199 else
7200 t = fold_build2 (PLUS_EXPR, type, t, n1);
7201 t = fold_convert (TREE_TYPE (startvar), t);
7202 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7203 false, GSI_CONTINUE_LINKING);
7204 if (endvar)
7206 assign_stmt = gimple_build_assign (endvar, e);
7207 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7208 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7209 assign_stmt = gimple_build_assign (fd->loop.v, e);
7210 else
7211 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7212 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7214 if (fd->collapse > 1)
7215 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7217 if (!broken_loop)
7219 /* The code controlling the sequential loop goes in CONT_BB,
7220 replacing the GIMPLE_OMP_CONTINUE. */
7221 gsi = gsi_last_bb (cont_bb);
7222 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7223 vmain = gimple_omp_continue_control_use (cont_stmt);
7224 vback = gimple_omp_continue_control_def (cont_stmt);
7226 if (!gimple_omp_for_combined_p (fd->for_stmt))
7228 if (POINTER_TYPE_P (type))
7229 t = fold_build_pointer_plus (vmain, step);
7230 else
7231 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7232 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7233 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7234 true, GSI_SAME_STMT);
7235 assign_stmt = gimple_build_assign (vback, t);
7236 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7238 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
7239 t = build2 (EQ_EXPR, boolean_type_node,
7240 build_int_cst (itype, 0),
7241 build_int_cst (itype, 1));
7242 else
7243 t = build2 (fd->loop.cond_code, boolean_type_node,
7244 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7245 ? t : vback, e);
7246 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7249 /* Remove GIMPLE_OMP_CONTINUE. */
7250 gsi_remove (&gsi, true);
7252 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7253 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7255 /* Trip update code goes into TRIP_UPDATE_BB. */
7256 gsi = gsi_start_bb (trip_update_bb);
7258 t = build_int_cst (itype, 1);
7259 t = build2 (PLUS_EXPR, itype, trip_main, t);
7260 assign_stmt = gimple_build_assign (trip_back, t);
7261 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7264 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7265 gsi = gsi_last_bb (exit_bb);
7266 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7268 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7269 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7270 gcc_checking_assert (t == NULL_TREE);
7271 else
7272 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7274 gsi_remove (&gsi, true);
7276 /* Connect the new blocks. */
7277 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7278 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7280 if (!broken_loop)
7282 se = find_edge (cont_bb, body_bb);
7283 if (se == NULL)
7285 se = BRANCH_EDGE (cont_bb);
7286 gcc_assert (single_succ (se->dest) == body_bb);
7288 if (gimple_omp_for_combined_p (fd->for_stmt))
7290 remove_edge (se);
7291 se = NULL;
7293 else if (fd->collapse > 1)
7295 remove_edge (se);
7296 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7298 else
7299 se->flags = EDGE_TRUE_VALUE;
7300 find_edge (cont_bb, trip_update_bb)->flags
7301 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7303 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7306 if (gimple_in_ssa_p (cfun))
7308 gphi_iterator psi;
7309 gphi *phi;
7310 edge re, ene;
7311 edge_var_map *vm;
7312 size_t i;
7314 gcc_assert (fd->collapse == 1 && !broken_loop);
7316 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7317 remove arguments of the phi nodes in fin_bb. We need to create
7318 appropriate phi nodes in iter_part_bb instead. */
7319 se = find_edge (iter_part_bb, fin_bb);
7320 re = single_succ_edge (trip_update_bb);
7321 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7322 ene = single_succ_edge (entry_bb);
7324 psi = gsi_start_phis (fin_bb);
7325 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7326 gsi_next (&psi), ++i)
7328 gphi *nphi;
7329 source_location locus;
7331 phi = psi.phi ();
7332 t = gimple_phi_result (phi);
7333 gcc_assert (t == redirect_edge_var_map_result (vm));
7335 if (!single_pred_p (fin_bb))
7336 t = copy_ssa_name (t, phi);
7338 nphi = create_phi_node (t, iter_part_bb);
7340 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7341 locus = gimple_phi_arg_location_from_edge (phi, se);
7343 /* A special case -- fd->loop.v is not yet computed in
7344 iter_part_bb, we need to use vextra instead. */
7345 if (t == fd->loop.v)
7346 t = vextra;
7347 add_phi_arg (nphi, t, ene, locus);
7348 locus = redirect_edge_var_map_location (vm);
7349 tree back_arg = redirect_edge_var_map_def (vm);
7350 add_phi_arg (nphi, back_arg, re, locus);
7351 edge ce = find_edge (cont_bb, body_bb);
7352 if (ce == NULL)
7354 ce = BRANCH_EDGE (cont_bb);
7355 gcc_assert (single_succ (ce->dest) == body_bb);
7356 ce = single_succ_edge (ce->dest);
7358 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
7359 gcc_assert (inner_loop_phi != NULL);
7360 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
7361 find_edge (seq_start_bb, body_bb), locus);
7363 if (!single_pred_p (fin_bb))
7364 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
7366 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
7367 redirect_edge_var_map_clear (re);
7368 if (single_pred_p (fin_bb))
7369 while (1)
7371 psi = gsi_start_phis (fin_bb);
7372 if (gsi_end_p (psi))
7373 break;
7374 remove_phi_node (&psi, false);
7377 /* Make phi node for trip. */
7378 phi = create_phi_node (trip_main, iter_part_bb);
7379 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7380 UNKNOWN_LOCATION);
7381 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7382 UNKNOWN_LOCATION);
7385 if (!broken_loop)
7386 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7387 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7388 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7389 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7390 recompute_dominator (CDI_DOMINATORS, fin_bb));
7391 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7392 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7393 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7394 recompute_dominator (CDI_DOMINATORS, body_bb));
7396 if (!broken_loop)
7398 struct loop *loop = body_bb->loop_father;
7399 struct loop *trip_loop = alloc_loop ();
7400 trip_loop->header = iter_part_bb;
7401 trip_loop->latch = trip_update_bb;
7402 add_loop (trip_loop, iter_part_bb->loop_father);
7404 if (loop != entry_bb->loop_father)
7406 gcc_assert (loop->header == body_bb);
7407 gcc_assert (loop->latch == region->cont
7408 || single_pred (loop->latch) == region->cont);
7409 trip_loop->inner = loop;
7410 return;
7413 if (!gimple_omp_for_combined_p (fd->for_stmt))
7415 loop = alloc_loop ();
7416 loop->header = body_bb;
7417 if (collapse_bb == NULL)
7418 loop->latch = cont_bb;
7419 add_loop (loop, trip_loop);
7424 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7425 Given parameters:
7426 for (V = N1; V cond N2; V += STEP) BODY;
7428 where COND is "<" or ">" or "!=", we generate pseudocode
7430 for (ind_var = low; ind_var < high; ind_var++)
7432 V = n1 + (ind_var * STEP)
7434 <BODY>
7437 In the above pseudocode, low and high are function parameters of the
7438 child function. In the function below, we are inserting a temp.
7439 variable that will be making a call to two OMP functions that will not be
7440 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7441 with _Cilk_for). These functions are replaced with low and high
7442 by the function that handles taskreg. */
7445 static void
7446 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7448 bool broken_loop = region->cont == NULL;
7449 basic_block entry_bb = region->entry;
7450 basic_block cont_bb = region->cont;
7452 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7453 gcc_assert (broken_loop
7454 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7455 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7456 basic_block l1_bb, l2_bb;
7458 if (!broken_loop)
7460 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7461 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7462 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7463 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7465 else
7467 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7468 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7469 l2_bb = single_succ (l1_bb);
7471 basic_block exit_bb = region->exit;
7472 basic_block l2_dom_bb = NULL;
7474 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7476 /* Below statements until the "tree high_val = ..." are pseudo statements
7477 used to pass information to be used by expand_omp_taskreg.
7478 low_val and high_val will be replaced by the __low and __high
7479 parameter from the child function.
7481 The call_exprs part is a place-holder, it is mainly used
7482 to distinctly identify to the top-level part that this is
7483 where we should put low and high (reasoning given in header
7484 comment). */
7486 tree child_fndecl
7487 = gimple_omp_parallel_child_fn (
7488 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7489 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7490 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7492 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7493 high_val = t;
7494 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7495 low_val = t;
7497 gcc_assert (low_val && high_val);
7499 tree type = TREE_TYPE (low_val);
7500 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7501 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7503 /* Not needed in SSA form right now. */
7504 gcc_assert (!gimple_in_ssa_p (cfun));
7505 if (l2_dom_bb == NULL)
7506 l2_dom_bb = l1_bb;
7508 tree n1 = low_val;
7509 tree n2 = high_val;
7511 gimple stmt = gimple_build_assign (ind_var, n1);
7513 /* Replace the GIMPLE_OMP_FOR statement. */
7514 gsi_replace (&gsi, stmt, true);
7516 if (!broken_loop)
7518 /* Code to control the increment goes in the CONT_BB. */
7519 gsi = gsi_last_bb (cont_bb);
7520 stmt = gsi_stmt (gsi);
7521 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7522 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7523 build_one_cst (type));
7525 /* Replace GIMPLE_OMP_CONTINUE. */
7526 gsi_replace (&gsi, stmt, true);
7529 /* Emit the condition in L1_BB. */
7530 gsi = gsi_after_labels (l1_bb);
7531 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7532 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7533 fd->loop.step);
7534 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7535 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7536 fd->loop.n1, fold_convert (sizetype, t));
7537 else
7538 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7539 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7540 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7541 expand_omp_build_assign (&gsi, fd->loop.v, t);
7543 /* The condition is always '<' since the runtime will fill in the low
7544 and high values. */
7545 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7546 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7548 /* Remove GIMPLE_OMP_RETURN. */
7549 gsi = gsi_last_bb (exit_bb);
7550 gsi_remove (&gsi, true);
7552 /* Connect the new blocks. */
7553 remove_edge (FALLTHRU_EDGE (entry_bb));
7555 edge e, ne;
7556 if (!broken_loop)
7558 remove_edge (BRANCH_EDGE (entry_bb));
7559 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7561 e = BRANCH_EDGE (l1_bb);
7562 ne = FALLTHRU_EDGE (l1_bb);
7563 e->flags = EDGE_TRUE_VALUE;
7565 else
7567 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7569 ne = single_succ_edge (l1_bb);
7570 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7573 ne->flags = EDGE_FALSE_VALUE;
7574 e->probability = REG_BR_PROB_BASE * 7 / 8;
7575 ne->probability = REG_BR_PROB_BASE / 8;
7577 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7578 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7579 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7581 if (!broken_loop)
7583 struct loop *loop = alloc_loop ();
7584 loop->header = l1_bb;
7585 loop->latch = cont_bb;
7586 add_loop (loop, l1_bb->loop_father);
7587 loop->safelen = INT_MAX;
7590 /* Pick the correct library function based on the precision of the
7591 induction variable type. */
7592 tree lib_fun = NULL_TREE;
7593 if (TYPE_PRECISION (type) == 32)
7594 lib_fun = cilk_for_32_fndecl;
7595 else if (TYPE_PRECISION (type) == 64)
7596 lib_fun = cilk_for_64_fndecl;
7597 else
7598 gcc_unreachable ();
7600 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7602 /* WS_ARGS contains the library function flavor to call:
7603 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7604 user-defined grain value. If the user does not define one, then zero
7605 is passed in by the parser. */
7606 vec_alloc (region->ws_args, 2);
7607 region->ws_args->quick_push (lib_fun);
7608 region->ws_args->quick_push (fd->chunk_size);
7611 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7612 loop. Given parameters:
7614 for (V = N1; V cond N2; V += STEP) BODY;
7616 where COND is "<" or ">", we generate pseudocode
7618 V = N1;
7619 goto L1;
7621 BODY;
7622 V += STEP;
7624 if (V cond N2) goto L0; else goto L2;
7627 For collapsed loops, given parameters:
7628 collapse(3)
7629 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7630 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7631 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7632 BODY;
7634 we generate pseudocode
7636 if (cond3 is <)
7637 adj = STEP3 - 1;
7638 else
7639 adj = STEP3 + 1;
7640 count3 = (adj + N32 - N31) / STEP3;
7641 if (cond2 is <)
7642 adj = STEP2 - 1;
7643 else
7644 adj = STEP2 + 1;
7645 count2 = (adj + N22 - N21) / STEP2;
7646 if (cond1 is <)
7647 adj = STEP1 - 1;
7648 else
7649 adj = STEP1 + 1;
7650 count1 = (adj + N12 - N11) / STEP1;
7651 count = count1 * count2 * count3;
7652 V = 0;
7653 V1 = N11;
7654 V2 = N21;
7655 V3 = N31;
7656 goto L1;
7658 BODY;
7659 V += 1;
7660 V3 += STEP3;
7661 V2 += (V3 cond3 N32) ? 0 : STEP2;
7662 V3 = (V3 cond3 N32) ? V3 : N31;
7663 V1 += (V2 cond2 N22) ? 0 : STEP1;
7664 V2 = (V2 cond2 N22) ? V2 : N21;
7666 if (V < count) goto L0; else goto L2;
7671 static void
7672 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7674 tree type, t;
7675 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7676 gimple_stmt_iterator gsi;
7677 gimple stmt;
7678 gcond *cond_stmt;
7679 bool broken_loop = region->cont == NULL;
7680 edge e, ne;
7681 tree *counts = NULL;
7682 int i;
7683 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7684 OMP_CLAUSE_SAFELEN);
7685 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7686 OMP_CLAUSE__SIMDUID_);
7687 tree n1, n2;
7689 type = TREE_TYPE (fd->loop.v);
7690 entry_bb = region->entry;
7691 cont_bb = region->cont;
7692 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7693 gcc_assert (broken_loop
7694 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7695 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7696 if (!broken_loop)
7698 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7699 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7700 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7701 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7703 else
7705 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7706 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7707 l2_bb = single_succ (l1_bb);
7709 exit_bb = region->exit;
7710 l2_dom_bb = NULL;
7712 gsi = gsi_last_bb (entry_bb);
7714 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7715 /* Not needed in SSA form right now. */
7716 gcc_assert (!gimple_in_ssa_p (cfun));
7717 if (fd->collapse > 1)
7719 int first_zero_iter = -1;
7720 basic_block zero_iter_bb = l2_bb;
7722 counts = XALLOCAVEC (tree, fd->collapse);
7723 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7724 zero_iter_bb, first_zero_iter,
7725 l2_dom_bb);
7727 if (l2_dom_bb == NULL)
7728 l2_dom_bb = l1_bb;
7730 n1 = fd->loop.n1;
7731 n2 = fd->loop.n2;
7732 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7734 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7735 OMP_CLAUSE__LOOPTEMP_);
7736 gcc_assert (innerc);
7737 n1 = OMP_CLAUSE_DECL (innerc);
7738 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7739 OMP_CLAUSE__LOOPTEMP_);
7740 gcc_assert (innerc);
7741 n2 = OMP_CLAUSE_DECL (innerc);
7742 expand_omp_build_assign (&gsi, fd->loop.v,
7743 fold_convert (type, n1));
7744 if (fd->collapse > 1)
7746 gsi_prev (&gsi);
7747 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7748 gsi_next (&gsi);
7751 else
7753 expand_omp_build_assign (&gsi, fd->loop.v,
7754 fold_convert (type, fd->loop.n1));
7755 if (fd->collapse > 1)
7756 for (i = 0; i < fd->collapse; i++)
7758 tree itype = TREE_TYPE (fd->loops[i].v);
7759 if (POINTER_TYPE_P (itype))
7760 itype = signed_type_for (itype);
7761 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7762 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7766 /* Remove the GIMPLE_OMP_FOR statement. */
7767 gsi_remove (&gsi, true);
7769 if (!broken_loop)
7771 /* Code to control the increment goes in the CONT_BB. */
7772 gsi = gsi_last_bb (cont_bb);
7773 stmt = gsi_stmt (gsi);
7774 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7776 if (POINTER_TYPE_P (type))
7777 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7778 else
7779 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7780 expand_omp_build_assign (&gsi, fd->loop.v, t);
7782 if (fd->collapse > 1)
7784 i = fd->collapse - 1;
7785 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7787 t = fold_convert (sizetype, fd->loops[i].step);
7788 t = fold_build_pointer_plus (fd->loops[i].v, t);
7790 else
7792 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7793 fd->loops[i].step);
7794 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7795 fd->loops[i].v, t);
7797 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7799 for (i = fd->collapse - 1; i > 0; i--)
7801 tree itype = TREE_TYPE (fd->loops[i].v);
7802 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7803 if (POINTER_TYPE_P (itype2))
7804 itype2 = signed_type_for (itype2);
7805 t = build3 (COND_EXPR, itype2,
7806 build2 (fd->loops[i].cond_code, boolean_type_node,
7807 fd->loops[i].v,
7808 fold_convert (itype, fd->loops[i].n2)),
7809 build_int_cst (itype2, 0),
7810 fold_convert (itype2, fd->loops[i - 1].step));
7811 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7812 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7813 else
7814 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7815 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7817 t = build3 (COND_EXPR, itype,
7818 build2 (fd->loops[i].cond_code, boolean_type_node,
7819 fd->loops[i].v,
7820 fold_convert (itype, fd->loops[i].n2)),
7821 fd->loops[i].v,
7822 fold_convert (itype, fd->loops[i].n1));
7823 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7827 /* Remove GIMPLE_OMP_CONTINUE. */
7828 gsi_remove (&gsi, true);
7831 /* Emit the condition in L1_BB. */
7832 gsi = gsi_start_bb (l1_bb);
7834 t = fold_convert (type, n2);
7835 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7836 false, GSI_CONTINUE_LINKING);
7837 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7838 cond_stmt = gimple_build_cond_empty (t);
7839 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7840 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7841 NULL, NULL)
7842 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7843 NULL, NULL))
7845 gsi = gsi_for_stmt (cond_stmt);
7846 gimple_regimplify_operands (cond_stmt, &gsi);
7849 /* Remove GIMPLE_OMP_RETURN. */
7850 gsi = gsi_last_bb (exit_bb);
7851 gsi_remove (&gsi, true);
7853 /* Connect the new blocks. */
7854 remove_edge (FALLTHRU_EDGE (entry_bb));
7856 if (!broken_loop)
7858 remove_edge (BRANCH_EDGE (entry_bb));
7859 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7861 e = BRANCH_EDGE (l1_bb);
7862 ne = FALLTHRU_EDGE (l1_bb);
7863 e->flags = EDGE_TRUE_VALUE;
7865 else
7867 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7869 ne = single_succ_edge (l1_bb);
7870 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7873 ne->flags = EDGE_FALSE_VALUE;
7874 e->probability = REG_BR_PROB_BASE * 7 / 8;
7875 ne->probability = REG_BR_PROB_BASE / 8;
7877 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7878 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7879 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7881 if (!broken_loop)
7883 struct loop *loop = alloc_loop ();
7884 loop->header = l1_bb;
7885 loop->latch = cont_bb;
7886 add_loop (loop, l1_bb->loop_father);
7887 if (safelen == NULL_TREE)
7888 loop->safelen = INT_MAX;
7889 else
7891 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7892 if (TREE_CODE (safelen) != INTEGER_CST)
7893 loop->safelen = 0;
7894 else if (!tree_fits_uhwi_p (safelen)
7895 || tree_to_uhwi (safelen) > INT_MAX)
7896 loop->safelen = INT_MAX;
7897 else
7898 loop->safelen = tree_to_uhwi (safelen);
7899 if (loop->safelen == 1)
7900 loop->safelen = 0;
7902 if (simduid)
7904 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7905 cfun->has_simduid_loops = true;
7907 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7908 the loop. */
7909 if ((flag_tree_loop_vectorize
7910 || (!global_options_set.x_flag_tree_loop_vectorize
7911 && !global_options_set.x_flag_tree_vectorize))
7912 && flag_tree_loop_optimize
7913 && loop->safelen > 1)
7915 loop->force_vectorize = true;
7916 cfun->has_force_vectorize_loops = true;
7919 else if (simduid)
7920 cfun->has_simduid_loops = true;
7924 /* Expand the OMP loop defined by REGION. */
7926 static void
7927 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7929 struct omp_for_data fd;
7930 struct omp_for_data_loop *loops;
7932 loops
7933 = (struct omp_for_data_loop *)
7934 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7935 * sizeof (struct omp_for_data_loop));
7936 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7937 &fd, loops);
7938 region->sched_kind = fd.sched_kind;
7940 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7941 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7942 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7943 if (region->cont)
7945 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7946 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7947 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7949 else
7950 /* If there isn't a continue then this is a degerate case where
7951 the introduction of abnormal edges during lowering will prevent
7952 original loops from being detected. Fix that up. */
7953 loops_state_set (LOOPS_NEED_FIXUP);
7955 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7956 expand_omp_simd (region, &fd);
7957 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7958 expand_cilk_for (region, &fd);
7959 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7960 && !fd.have_ordered)
7962 if (fd.chunk_size == NULL)
7963 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7964 else
7965 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7967 else
7969 int fn_index, start_ix, next_ix;
7971 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7972 == GF_OMP_FOR_KIND_FOR);
7973 if (fd.chunk_size == NULL
7974 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7975 fd.chunk_size = integer_zero_node;
7976 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7977 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7978 ? 3 : fd.sched_kind;
7979 fn_index += fd.have_ordered * 4;
7980 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7981 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7982 if (fd.iter_type == long_long_unsigned_type_node)
7984 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7985 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7986 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7987 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7989 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7990 (enum built_in_function) next_ix, inner_stmt);
7993 if (gimple_in_ssa_p (cfun))
7994 update_ssa (TODO_update_ssa_only_virtuals);
7998 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
8000 v = GOMP_sections_start (n);
8002 switch (v)
8004 case 0:
8005 goto L2;
8006 case 1:
8007 section 1;
8008 goto L1;
8009 case 2:
8011 case n:
8013 default:
8014 abort ();
8017 v = GOMP_sections_next ();
8018 goto L0;
8020 reduction;
8022 If this is a combined parallel sections, replace the call to
8023 GOMP_sections_start with call to GOMP_sections_next. */
8025 static void
8026 expand_omp_sections (struct omp_region *region)
8028 tree t, u, vin = NULL, vmain, vnext, l2;
8029 unsigned len;
8030 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
8031 gimple_stmt_iterator si, switch_si;
8032 gomp_sections *sections_stmt;
8033 gimple stmt;
8034 gomp_continue *cont;
8035 edge_iterator ei;
8036 edge e;
8037 struct omp_region *inner;
8038 unsigned i, casei;
8039 bool exit_reachable = region->cont != NULL;
8041 gcc_assert (region->exit != NULL);
8042 entry_bb = region->entry;
8043 l0_bb = single_succ (entry_bb);
8044 l1_bb = region->cont;
8045 l2_bb = region->exit;
8046 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
8047 l2 = gimple_block_label (l2_bb);
8048 else
8050 /* This can happen if there are reductions. */
8051 len = EDGE_COUNT (l0_bb->succs);
8052 gcc_assert (len > 0);
8053 e = EDGE_SUCC (l0_bb, len - 1);
8054 si = gsi_last_bb (e->dest);
8055 l2 = NULL_TREE;
8056 if (gsi_end_p (si)
8057 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
8058 l2 = gimple_block_label (e->dest);
8059 else
8060 FOR_EACH_EDGE (e, ei, l0_bb->succs)
8062 si = gsi_last_bb (e->dest);
8063 if (gsi_end_p (si)
8064 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
8066 l2 = gimple_block_label (e->dest);
8067 break;
8071 if (exit_reachable)
8072 default_bb = create_empty_bb (l1_bb->prev_bb);
8073 else
8074 default_bb = create_empty_bb (l0_bb);
8076 /* We will build a switch() with enough cases for all the
8077 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
8078 and a default case to abort if something goes wrong. */
8079 len = EDGE_COUNT (l0_bb->succs);
8081 /* Use vec::quick_push on label_vec throughout, since we know the size
8082 in advance. */
8083 auto_vec<tree> label_vec (len);
8085 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
8086 GIMPLE_OMP_SECTIONS statement. */
8087 si = gsi_last_bb (entry_bb);
8088 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
8089 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8090 vin = gimple_omp_sections_control (sections_stmt);
8091 if (!is_combined_parallel (region))
8093 /* If we are not inside a combined parallel+sections region,
8094 call GOMP_sections_start. */
8095 t = build_int_cst (unsigned_type_node, len - 1);
8096 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
8097 stmt = gimple_build_call (u, 1, t);
8099 else
8101 /* Otherwise, call GOMP_sections_next. */
8102 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8103 stmt = gimple_build_call (u, 0);
8105 gimple_call_set_lhs (stmt, vin);
8106 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8107 gsi_remove (&si, true);
8109 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8110 L0_BB. */
8111 switch_si = gsi_last_bb (l0_bb);
8112 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8113 if (exit_reachable)
8115 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8116 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8117 vmain = gimple_omp_continue_control_use (cont);
8118 vnext = gimple_omp_continue_control_def (cont);
8120 else
8122 vmain = vin;
8123 vnext = NULL_TREE;
8126 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8127 label_vec.quick_push (t);
8128 i = 1;
8130 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8131 for (inner = region->inner, casei = 1;
8132 inner;
8133 inner = inner->next, i++, casei++)
8135 basic_block s_entry_bb, s_exit_bb;
8137 /* Skip optional reduction region. */
8138 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8140 --i;
8141 --casei;
8142 continue;
8145 s_entry_bb = inner->entry;
8146 s_exit_bb = inner->exit;
8148 t = gimple_block_label (s_entry_bb);
8149 u = build_int_cst (unsigned_type_node, casei);
8150 u = build_case_label (u, NULL, t);
8151 label_vec.quick_push (u);
8153 si = gsi_last_bb (s_entry_bb);
8154 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8155 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8156 gsi_remove (&si, true);
8157 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8159 if (s_exit_bb == NULL)
8160 continue;
8162 si = gsi_last_bb (s_exit_bb);
8163 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8164 gsi_remove (&si, true);
8166 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8169 /* Error handling code goes in DEFAULT_BB. */
8170 t = gimple_block_label (default_bb);
8171 u = build_case_label (NULL, NULL, t);
8172 make_edge (l0_bb, default_bb, 0);
8173 add_bb_to_loop (default_bb, current_loops->tree_root);
8175 stmt = gimple_build_switch (vmain, u, label_vec);
8176 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8177 gsi_remove (&switch_si, true);
8179 si = gsi_start_bb (default_bb);
8180 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8181 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8183 if (exit_reachable)
8185 tree bfn_decl;
8187 /* Code to get the next section goes in L1_BB. */
8188 si = gsi_last_bb (l1_bb);
8189 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8191 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8192 stmt = gimple_build_call (bfn_decl, 0);
8193 gimple_call_set_lhs (stmt, vnext);
8194 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8195 gsi_remove (&si, true);
8197 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8200 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8201 si = gsi_last_bb (l2_bb);
8202 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8203 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8204 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8205 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8206 else
8207 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8208 stmt = gimple_build_call (t, 0);
8209 if (gimple_omp_return_lhs (gsi_stmt (si)))
8210 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8211 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8212 gsi_remove (&si, true);
8214 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8218 /* Expand code for an OpenMP single directive. We've already expanded
8219 much of the code, here we simply place the GOMP_barrier call. */
8221 static void
8222 expand_omp_single (struct omp_region *region)
8224 basic_block entry_bb, exit_bb;
8225 gimple_stmt_iterator si;
8227 entry_bb = region->entry;
8228 exit_bb = region->exit;
8230 si = gsi_last_bb (entry_bb);
8231 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8232 gsi_remove (&si, true);
8233 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8235 si = gsi_last_bb (exit_bb);
8236 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8238 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8239 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8241 gsi_remove (&si, true);
8242 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8246 /* Generic expansion for OpenMP synchronization directives: master,
8247 ordered and critical. All we need to do here is remove the entry
8248 and exit markers for REGION. */
8250 static void
8251 expand_omp_synch (struct omp_region *region)
8253 basic_block entry_bb, exit_bb;
8254 gimple_stmt_iterator si;
8256 entry_bb = region->entry;
8257 exit_bb = region->exit;
8259 si = gsi_last_bb (entry_bb);
8260 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8261 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8262 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8263 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8264 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8265 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8266 gsi_remove (&si, true);
8267 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8269 if (exit_bb)
8271 si = gsi_last_bb (exit_bb);
8272 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8273 gsi_remove (&si, true);
8274 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8278 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8279 operation as a normal volatile load. */
8281 static bool
8282 expand_omp_atomic_load (basic_block load_bb, tree addr,
8283 tree loaded_val, int index)
8285 enum built_in_function tmpbase;
8286 gimple_stmt_iterator gsi;
8287 basic_block store_bb;
8288 location_t loc;
8289 gimple stmt;
8290 tree decl, call, type, itype;
8292 gsi = gsi_last_bb (load_bb);
8293 stmt = gsi_stmt (gsi);
8294 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8295 loc = gimple_location (stmt);
8297 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8298 is smaller than word size, then expand_atomic_load assumes that the load
8299 is atomic. We could avoid the builtin entirely in this case. */
8301 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8302 decl = builtin_decl_explicit (tmpbase);
8303 if (decl == NULL_TREE)
8304 return false;
8306 type = TREE_TYPE (loaded_val);
8307 itype = TREE_TYPE (TREE_TYPE (decl));
8309 call = build_call_expr_loc (loc, decl, 2, addr,
8310 build_int_cst (NULL,
8311 gimple_omp_atomic_seq_cst_p (stmt)
8312 ? MEMMODEL_SEQ_CST
8313 : MEMMODEL_RELAXED));
8314 if (!useless_type_conversion_p (type, itype))
8315 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8316 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 store_bb = single_succ (load_bb);
8322 gsi = gsi_last_bb (store_bb);
8323 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8324 gsi_remove (&gsi, true);
8326 if (gimple_in_ssa_p (cfun))
8327 update_ssa (TODO_update_ssa_no_phi);
8329 return true;
8332 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8333 operation as a normal volatile store. */
8335 static bool
8336 expand_omp_atomic_store (basic_block load_bb, tree addr,
8337 tree loaded_val, tree stored_val, int index)
8339 enum built_in_function tmpbase;
8340 gimple_stmt_iterator gsi;
8341 basic_block store_bb = single_succ (load_bb);
8342 location_t loc;
8343 gimple stmt;
8344 tree decl, call, type, itype;
8345 machine_mode imode;
8346 bool exchange;
8348 gsi = gsi_last_bb (load_bb);
8349 stmt = gsi_stmt (gsi);
8350 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8352 /* If the load value is needed, then this isn't a store but an exchange. */
8353 exchange = gimple_omp_atomic_need_value_p (stmt);
8355 gsi = gsi_last_bb (store_bb);
8356 stmt = gsi_stmt (gsi);
8357 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8358 loc = gimple_location (stmt);
8360 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8361 is smaller than word size, then expand_atomic_store assumes that the store
8362 is atomic. We could avoid the builtin entirely in this case. */
8364 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8365 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8366 decl = builtin_decl_explicit (tmpbase);
8367 if (decl == NULL_TREE)
8368 return false;
8370 type = TREE_TYPE (stored_val);
8372 /* Dig out the type of the function's second argument. */
8373 itype = TREE_TYPE (decl);
8374 itype = TYPE_ARG_TYPES (itype);
8375 itype = TREE_CHAIN (itype);
8376 itype = TREE_VALUE (itype);
8377 imode = TYPE_MODE (itype);
8379 if (exchange && !can_atomic_exchange_p (imode, true))
8380 return false;
8382 if (!useless_type_conversion_p (itype, type))
8383 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8384 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8385 build_int_cst (NULL,
8386 gimple_omp_atomic_seq_cst_p (stmt)
8387 ? MEMMODEL_SEQ_CST
8388 : MEMMODEL_RELAXED));
8389 if (exchange)
8391 if (!useless_type_conversion_p (type, itype))
8392 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8393 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8396 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8397 gsi_remove (&gsi, true);
8399 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8400 gsi = gsi_last_bb (load_bb);
8401 gsi_remove (&gsi, true);
8403 if (gimple_in_ssa_p (cfun))
8404 update_ssa (TODO_update_ssa_no_phi);
8406 return true;
8409 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8410 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8411 size of the data type, and thus usable to find the index of the builtin
8412 decl. Returns false if the expression is not of the proper form. */
8414 static bool
8415 expand_omp_atomic_fetch_op (basic_block load_bb,
8416 tree addr, tree loaded_val,
8417 tree stored_val, int index)
8419 enum built_in_function oldbase, newbase, tmpbase;
8420 tree decl, itype, call;
8421 tree lhs, rhs;
8422 basic_block store_bb = single_succ (load_bb);
8423 gimple_stmt_iterator gsi;
8424 gimple stmt;
8425 location_t loc;
8426 enum tree_code code;
8427 bool need_old, need_new;
8428 machine_mode imode;
8429 bool seq_cst;
8431 /* We expect to find the following sequences:
8433 load_bb:
8434 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8436 store_bb:
8437 val = tmp OP something; (or: something OP tmp)
8438 GIMPLE_OMP_STORE (val)
8440 ???FIXME: Allow a more flexible sequence.
8441 Perhaps use data flow to pick the statements.
8445 gsi = gsi_after_labels (store_bb);
8446 stmt = gsi_stmt (gsi);
8447 loc = gimple_location (stmt);
8448 if (!is_gimple_assign (stmt))
8449 return false;
8450 gsi_next (&gsi);
8451 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8452 return false;
8453 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8454 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8455 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8456 gcc_checking_assert (!need_old || !need_new);
8458 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8459 return false;
8461 /* Check for one of the supported fetch-op operations. */
8462 code = gimple_assign_rhs_code (stmt);
8463 switch (code)
8465 case PLUS_EXPR:
8466 case POINTER_PLUS_EXPR:
8467 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8468 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8469 break;
8470 case MINUS_EXPR:
8471 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8472 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8473 break;
8474 case BIT_AND_EXPR:
8475 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8476 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8477 break;
8478 case BIT_IOR_EXPR:
8479 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8480 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8481 break;
8482 case BIT_XOR_EXPR:
8483 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8484 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8485 break;
8486 default:
8487 return false;
8490 /* Make sure the expression is of the proper form. */
8491 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8492 rhs = gimple_assign_rhs2 (stmt);
8493 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8494 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8495 rhs = gimple_assign_rhs1 (stmt);
8496 else
8497 return false;
8499 tmpbase = ((enum built_in_function)
8500 ((need_new ? newbase : oldbase) + index + 1));
8501 decl = builtin_decl_explicit (tmpbase);
8502 if (decl == NULL_TREE)
8503 return false;
8504 itype = TREE_TYPE (TREE_TYPE (decl));
8505 imode = TYPE_MODE (itype);
8507 /* We could test all of the various optabs involved, but the fact of the
8508 matter is that (with the exception of i486 vs i586 and xadd) all targets
8509 that support any atomic operaton optab also implements compare-and-swap.
8510 Let optabs.c take care of expanding any compare-and-swap loop. */
8511 if (!can_compare_and_swap_p (imode, true))
8512 return false;
8514 gsi = gsi_last_bb (load_bb);
8515 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8517 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8518 It only requires that the operation happen atomically. Thus we can
8519 use the RELAXED memory model. */
8520 call = build_call_expr_loc (loc, decl, 3, addr,
8521 fold_convert_loc (loc, itype, rhs),
8522 build_int_cst (NULL,
8523 seq_cst ? MEMMODEL_SEQ_CST
8524 : MEMMODEL_RELAXED));
8526 if (need_old || need_new)
8528 lhs = need_old ? loaded_val : stored_val;
8529 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8530 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8532 else
8533 call = fold_convert_loc (loc, void_type_node, call);
8534 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8535 gsi_remove (&gsi, true);
8537 gsi = gsi_last_bb (store_bb);
8538 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8539 gsi_remove (&gsi, true);
8540 gsi = gsi_last_bb (store_bb);
8541 gsi_remove (&gsi, true);
8543 if (gimple_in_ssa_p (cfun))
8544 update_ssa (TODO_update_ssa_no_phi);
8546 return true;
8549 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8551 oldval = *addr;
8552 repeat:
8553 newval = rhs; // with oldval replacing *addr in rhs
8554 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8555 if (oldval != newval)
8556 goto repeat;
8558 INDEX is log2 of the size of the data type, and thus usable to find the
8559 index of the builtin decl. */
8561 static bool
8562 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8563 tree addr, tree loaded_val, tree stored_val,
8564 int index)
8566 tree loadedi, storedi, initial, new_storedi, old_vali;
8567 tree type, itype, cmpxchg, iaddr;
8568 gimple_stmt_iterator si;
8569 basic_block loop_header = single_succ (load_bb);
8570 gimple phi, stmt;
8571 edge e;
8572 enum built_in_function fncode;
8574 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8575 order to use the RELAXED memory model effectively. */
8576 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8577 + index + 1);
8578 cmpxchg = builtin_decl_explicit (fncode);
8579 if (cmpxchg == NULL_TREE)
8580 return false;
8581 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8582 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8584 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8585 return false;
8587 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8588 si = gsi_last_bb (load_bb);
8589 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8591 /* For floating-point values, we'll need to view-convert them to integers
8592 so that we can perform the atomic compare and swap. Simplify the
8593 following code by always setting up the "i"ntegral variables. */
8594 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8596 tree iaddr_val;
8598 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8599 true));
8600 iaddr_val
8601 = force_gimple_operand_gsi (&si,
8602 fold_convert (TREE_TYPE (iaddr), addr),
8603 false, NULL_TREE, true, GSI_SAME_STMT);
8604 stmt = gimple_build_assign (iaddr, iaddr_val);
8605 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8606 loadedi = create_tmp_var (itype);
8607 if (gimple_in_ssa_p (cfun))
8608 loadedi = make_ssa_name (loadedi);
8610 else
8612 iaddr = addr;
8613 loadedi = loaded_val;
8616 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8617 tree loaddecl = builtin_decl_explicit (fncode);
8618 if (loaddecl)
8619 initial
8620 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8621 build_call_expr (loaddecl, 2, iaddr,
8622 build_int_cst (NULL_TREE,
8623 MEMMODEL_RELAXED)));
8624 else
8625 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8626 build_int_cst (TREE_TYPE (iaddr), 0));
8628 initial
8629 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8630 GSI_SAME_STMT);
8632 /* Move the value to the LOADEDI temporary. */
8633 if (gimple_in_ssa_p (cfun))
8635 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8636 phi = create_phi_node (loadedi, loop_header);
8637 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8638 initial);
8640 else
8641 gsi_insert_before (&si,
8642 gimple_build_assign (loadedi, initial),
8643 GSI_SAME_STMT);
8644 if (loadedi != loaded_val)
8646 gimple_stmt_iterator gsi2;
8647 tree x;
8649 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8650 gsi2 = gsi_start_bb (loop_header);
8651 if (gimple_in_ssa_p (cfun))
8653 gassign *stmt;
8654 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8655 true, GSI_SAME_STMT);
8656 stmt = gimple_build_assign (loaded_val, x);
8657 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8659 else
8661 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8662 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8663 true, GSI_SAME_STMT);
8666 gsi_remove (&si, true);
8668 si = gsi_last_bb (store_bb);
8669 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8671 if (iaddr == addr)
8672 storedi = stored_val;
8673 else
8674 storedi =
8675 force_gimple_operand_gsi (&si,
8676 build1 (VIEW_CONVERT_EXPR, itype,
8677 stored_val), true, NULL_TREE, true,
8678 GSI_SAME_STMT);
8680 /* Build the compare&swap statement. */
8681 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8682 new_storedi = force_gimple_operand_gsi (&si,
8683 fold_convert (TREE_TYPE (loadedi),
8684 new_storedi),
8685 true, NULL_TREE,
8686 true, GSI_SAME_STMT);
8688 if (gimple_in_ssa_p (cfun))
8689 old_vali = loadedi;
8690 else
8692 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8693 stmt = gimple_build_assign (old_vali, loadedi);
8694 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8696 stmt = gimple_build_assign (loadedi, new_storedi);
8697 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8700 /* Note that we always perform the comparison as an integer, even for
8701 floating point. This allows the atomic operation to properly
8702 succeed even with NaNs and -0.0. */
8703 stmt = gimple_build_cond_empty
8704 (build2 (NE_EXPR, boolean_type_node,
8705 new_storedi, old_vali));
8706 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8708 /* Update cfg. */
8709 e = single_succ_edge (store_bb);
8710 e->flags &= ~EDGE_FALLTHRU;
8711 e->flags |= EDGE_FALSE_VALUE;
8713 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8715 /* Copy the new value to loadedi (we already did that before the condition
8716 if we are not in SSA). */
8717 if (gimple_in_ssa_p (cfun))
8719 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8720 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8723 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8724 gsi_remove (&si, true);
8726 struct loop *loop = alloc_loop ();
8727 loop->header = loop_header;
8728 loop->latch = store_bb;
8729 add_loop (loop, loop_header->loop_father);
8731 if (gimple_in_ssa_p (cfun))
8732 update_ssa (TODO_update_ssa_no_phi);
8734 return true;
8737 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8739 GOMP_atomic_start ();
8740 *addr = rhs;
8741 GOMP_atomic_end ();
8743 The result is not globally atomic, but works so long as all parallel
8744 references are within #pragma omp atomic directives. According to
8745 responses received from omp@openmp.org, appears to be within spec.
8746 Which makes sense, since that's how several other compilers handle
8747 this situation as well.
8748 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8749 expanding. STORED_VAL is the operand of the matching
8750 GIMPLE_OMP_ATOMIC_STORE.
8752 We replace
8753 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8754 loaded_val = *addr;
8756 and replace
8757 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8758 *addr = stored_val;
8761 static bool
8762 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8763 tree addr, tree loaded_val, tree stored_val)
8765 gimple_stmt_iterator si;
8766 gassign *stmt;
8767 tree t;
8769 si = gsi_last_bb (load_bb);
8770 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8772 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8773 t = build_call_expr (t, 0);
8774 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8776 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8777 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8778 gsi_remove (&si, true);
8780 si = gsi_last_bb (store_bb);
8781 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8783 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8784 stored_val);
8785 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8787 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8788 t = build_call_expr (t, 0);
8789 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8790 gsi_remove (&si, true);
8792 if (gimple_in_ssa_p (cfun))
8793 update_ssa (TODO_update_ssa_no_phi);
8794 return true;
8797 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8798 using expand_omp_atomic_fetch_op. If it failed, we try to
8799 call expand_omp_atomic_pipeline, and if it fails too, the
8800 ultimate fallback is wrapping the operation in a mutex
8801 (expand_omp_atomic_mutex). REGION is the atomic region built
8802 by build_omp_regions_1(). */
8804 static void
8805 expand_omp_atomic (struct omp_region *region)
8807 basic_block load_bb = region->entry, store_bb = region->exit;
8808 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8809 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8810 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8811 tree addr = gimple_omp_atomic_load_rhs (load);
8812 tree stored_val = gimple_omp_atomic_store_val (store);
8813 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8814 HOST_WIDE_INT index;
8816 /* Make sure the type is one of the supported sizes. */
8817 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8818 index = exact_log2 (index);
8819 if (index >= 0 && index <= 4)
8821 unsigned int align = TYPE_ALIGN_UNIT (type);
8823 /* __sync builtins require strict data alignment. */
8824 if (exact_log2 (align) >= index)
8826 /* Atomic load. */
8827 if (loaded_val == stored_val
8828 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8829 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8830 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8831 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8832 return;
8834 /* Atomic store. */
8835 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8836 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8837 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8838 && store_bb == single_succ (load_bb)
8839 && first_stmt (store_bb) == store
8840 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8841 stored_val, index))
8842 return;
8844 /* When possible, use specialized atomic update functions. */
8845 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8846 && store_bb == single_succ (load_bb)
8847 && expand_omp_atomic_fetch_op (load_bb, addr,
8848 loaded_val, stored_val, index))
8849 return;
8851 /* If we don't have specialized __sync builtins, try and implement
8852 as a compare and swap loop. */
8853 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8854 loaded_val, stored_val, index))
8855 return;
8859 /* The ultimate fallback is wrapping the operation in a mutex. */
8860 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8864 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8866 static void
8867 expand_omp_target (struct omp_region *region)
8869 basic_block entry_bb, exit_bb, new_bb;
8870 struct function *child_cfun;
8871 tree child_fn, block, t;
8872 gimple_stmt_iterator gsi;
8873 gomp_target *entry_stmt;
8874 gimple stmt;
8875 edge e;
8876 bool offloaded, data_region;
8878 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8879 new_bb = region->entry;
8881 offloaded = is_gimple_omp_offloaded (entry_stmt);
8882 switch (gimple_omp_target_kind (entry_stmt))
8884 case GF_OMP_TARGET_KIND_REGION:
8885 case GF_OMP_TARGET_KIND_UPDATE:
8886 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8887 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8888 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8889 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8890 data_region = false;
8891 break;
8892 case GF_OMP_TARGET_KIND_DATA:
8893 case GF_OMP_TARGET_KIND_OACC_DATA:
8894 data_region = true;
8895 break;
8896 default:
8897 gcc_unreachable ();
8900 child_fn = NULL_TREE;
8901 child_cfun = NULL;
8902 if (offloaded)
8904 child_fn = gimple_omp_target_child_fn (entry_stmt);
8905 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8908 /* Supported by expand_omp_taskreg, but not here. */
8909 if (child_cfun != NULL)
8910 gcc_checking_assert (!child_cfun->cfg);
8911 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8913 entry_bb = region->entry;
8914 exit_bb = region->exit;
8916 if (offloaded)
8918 unsigned srcidx, dstidx, num;
8920 /* If the offloading region needs data sent from the parent
8921 function, then the very first statement (except possible
8922 tree profile counter updates) of the offloading body
8923 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8924 &.OMP_DATA_O is passed as an argument to the child function,
8925 we need to replace it with the argument as seen by the child
8926 function.
8928 In most cases, this will end up being the identity assignment
8929 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8930 a function call that has been inlined, the original PARM_DECL
8931 .OMP_DATA_I may have been converted into a different local
8932 variable. In which case, we need to keep the assignment. */
8933 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8934 if (data_arg)
8936 basic_block entry_succ_bb = single_succ (entry_bb);
8937 gimple_stmt_iterator gsi;
8938 tree arg;
8939 gimple tgtcopy_stmt = NULL;
8940 tree sender = TREE_VEC_ELT (data_arg, 0);
8942 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8944 gcc_assert (!gsi_end_p (gsi));
8945 stmt = gsi_stmt (gsi);
8946 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8947 continue;
8949 if (gimple_num_ops (stmt) == 2)
8951 tree arg = gimple_assign_rhs1 (stmt);
8953 /* We're ignoring the subcode because we're
8954 effectively doing a STRIP_NOPS. */
8956 if (TREE_CODE (arg) == ADDR_EXPR
8957 && TREE_OPERAND (arg, 0) == sender)
8959 tgtcopy_stmt = stmt;
8960 break;
8965 gcc_assert (tgtcopy_stmt != NULL);
8966 arg = DECL_ARGUMENTS (child_fn);
8968 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8969 gsi_remove (&gsi, true);
8972 /* Declare local variables needed in CHILD_CFUN. */
8973 block = DECL_INITIAL (child_fn);
8974 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8975 /* The gimplifier could record temporaries in the offloading block
8976 rather than in containing function's local_decls chain,
8977 which would mean cgraph missed finalizing them. Do it now. */
8978 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8979 if (TREE_CODE (t) == VAR_DECL
8980 && TREE_STATIC (t)
8981 && !DECL_EXTERNAL (t))
8982 varpool_node::finalize_decl (t);
8983 DECL_SAVED_TREE (child_fn) = NULL;
8984 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8985 gimple_set_body (child_fn, NULL);
8986 TREE_USED (block) = 1;
8988 /* Reset DECL_CONTEXT on function arguments. */
8989 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8990 DECL_CONTEXT (t) = child_fn;
8992 /* Split ENTRY_BB at GIMPLE_*,
8993 so that it can be moved to the child function. */
8994 gsi = gsi_last_bb (entry_bb);
8995 stmt = gsi_stmt (gsi);
8996 gcc_assert (stmt
8997 && gimple_code (stmt) == gimple_code (entry_stmt));
8998 e = split_block (entry_bb, stmt);
8999 gsi_remove (&gsi, true);
9000 entry_bb = e->dest;
9001 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
9003 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
9004 if (exit_bb)
9006 gsi = gsi_last_bb (exit_bb);
9007 gcc_assert (!gsi_end_p (gsi)
9008 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
9009 stmt = gimple_build_return (NULL);
9010 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
9011 gsi_remove (&gsi, true);
9014 /* Move the offloading region into CHILD_CFUN. */
9016 block = gimple_block (entry_stmt);
9018 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
9019 if (exit_bb)
9020 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
9021 /* When the OMP expansion process cannot guarantee an up-to-date
9022 loop tree arrange for the child function to fixup loops. */
9023 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
9024 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
9026 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
9027 num = vec_safe_length (child_cfun->local_decls);
9028 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
9030 t = (*child_cfun->local_decls)[srcidx];
9031 if (DECL_CONTEXT (t) == cfun->decl)
9032 continue;
9033 if (srcidx != dstidx)
9034 (*child_cfun->local_decls)[dstidx] = t;
9035 dstidx++;
9037 if (dstidx != num)
9038 vec_safe_truncate (child_cfun->local_decls, dstidx);
9040 /* Inform the callgraph about the new function. */
9041 child_cfun->curr_properties = cfun->curr_properties;
9042 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
9043 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
9044 cgraph_node *node = cgraph_node::get_create (child_fn);
9045 node->parallelized_function = 1;
9046 cgraph_node::add_new_function (child_fn, true);
9048 #ifdef ENABLE_OFFLOADING
9049 /* Add the new function to the offload table. */
9050 vec_safe_push (offload_funcs, child_fn);
9051 #endif
9053 /* Fix the callgraph edges for child_cfun. Those for cfun will be
9054 fixed in a following pass. */
9055 push_cfun (child_cfun);
9056 cgraph_edge::rebuild_edges ();
9058 #ifdef ENABLE_OFFLOADING
9059 /* Prevent IPA from removing child_fn as unreachable, since there are no
9060 refs from the parent function to child_fn in offload LTO mode. */
9061 cgraph_node::get (child_fn)->mark_force_output ();
9062 #endif
9064 /* Some EH regions might become dead, see PR34608. If
9065 pass_cleanup_cfg isn't the first pass to happen with the
9066 new child, these dead EH edges might cause problems.
9067 Clean them up now. */
9068 if (flag_exceptions)
9070 basic_block bb;
9071 bool changed = false;
9073 FOR_EACH_BB_FN (bb, cfun)
9074 changed |= gimple_purge_dead_eh_edges (bb);
9075 if (changed)
9076 cleanup_tree_cfg ();
9078 #ifdef ENABLE_CHECKING
9079 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
9080 verify_loop_structure ();
9081 #endif
9082 pop_cfun ();
9085 /* Emit a library call to launch the offloading region, or do data
9086 transfers. */
9087 tree t1, t2, t3, t4, device, cond, c, clauses;
9088 enum built_in_function start_ix;
9089 location_t clause_loc;
9091 switch (gimple_omp_target_kind (entry_stmt))
9093 case GF_OMP_TARGET_KIND_REGION:
9094 start_ix = BUILT_IN_GOMP_TARGET;
9095 break;
9096 case GF_OMP_TARGET_KIND_DATA:
9097 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9098 break;
9099 case GF_OMP_TARGET_KIND_UPDATE:
9100 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9101 break;
9102 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9103 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9104 start_ix = BUILT_IN_GOACC_PARALLEL;
9105 break;
9106 case GF_OMP_TARGET_KIND_OACC_DATA:
9107 start_ix = BUILT_IN_GOACC_DATA_START;
9108 break;
9109 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9110 start_ix = BUILT_IN_GOACC_UPDATE;
9111 break;
9112 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9113 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9114 break;
9115 default:
9116 gcc_unreachable ();
9119 clauses = gimple_omp_target_clauses (entry_stmt);
9121 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9122 library choose) and there is no conditional. */
9123 cond = NULL_TREE;
9124 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
9126 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9127 if (c)
9128 cond = OMP_CLAUSE_IF_EXPR (c);
9130 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9131 if (c)
9133 /* Even if we pass it to all library function calls, it is currently only
9134 defined/used for the OpenMP target ones. */
9135 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9136 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9137 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9139 device = OMP_CLAUSE_DEVICE_ID (c);
9140 clause_loc = OMP_CLAUSE_LOCATION (c);
9142 else
9143 clause_loc = gimple_location (entry_stmt);
9145 /* Ensure 'device' is of the correct type. */
9146 device = fold_convert_loc (clause_loc, integer_type_node, device);
9148 /* If we found the clause 'if (cond)', build
9149 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9150 if (cond)
9152 cond = gimple_boolify (cond);
9154 basic_block cond_bb, then_bb, else_bb;
9155 edge e;
9156 tree tmp_var;
9158 tmp_var = create_tmp_var (TREE_TYPE (device));
9159 if (offloaded)
9160 e = split_block_after_labels (new_bb);
9161 else
9163 gsi = gsi_last_bb (new_bb);
9164 gsi_prev (&gsi);
9165 e = split_block (new_bb, gsi_stmt (gsi));
9167 cond_bb = e->src;
9168 new_bb = e->dest;
9169 remove_edge (e);
9171 then_bb = create_empty_bb (cond_bb);
9172 else_bb = create_empty_bb (then_bb);
9173 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9174 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9176 stmt = gimple_build_cond_empty (cond);
9177 gsi = gsi_last_bb (cond_bb);
9178 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9180 gsi = gsi_start_bb (then_bb);
9181 stmt = gimple_build_assign (tmp_var, device);
9182 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9184 gsi = gsi_start_bb (else_bb);
9185 stmt = gimple_build_assign (tmp_var,
9186 build_int_cst (integer_type_node,
9187 GOMP_DEVICE_HOST_FALLBACK));
9188 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9190 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9191 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9192 add_bb_to_loop (then_bb, cond_bb->loop_father);
9193 add_bb_to_loop (else_bb, cond_bb->loop_father);
9194 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9195 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9197 device = tmp_var;
9200 gsi = gsi_last_bb (new_bb);
9201 t = gimple_omp_target_data_arg (entry_stmt);
9202 if (t == NULL)
9204 t1 = size_zero_node;
9205 t2 = build_zero_cst (ptr_type_node);
9206 t3 = t2;
9207 t4 = t2;
9209 else
9211 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9212 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9213 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9214 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9215 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9218 gimple g;
9219 /* The maximum number used by any start_ix, without varargs. */
9220 auto_vec<tree, 11> args;
9221 args.quick_push (device);
9222 if (offloaded)
9223 args.quick_push (build_fold_addr_expr (child_fn));
9224 switch (start_ix)
9226 case BUILT_IN_GOMP_TARGET:
9227 case BUILT_IN_GOMP_TARGET_DATA:
9228 case BUILT_IN_GOMP_TARGET_UPDATE:
9229 /* This const void * is part of the current ABI, but we're not actually
9230 using it. */
9231 args.quick_push (build_zero_cst (ptr_type_node));
9232 break;
9233 case BUILT_IN_GOACC_DATA_START:
9234 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9235 case BUILT_IN_GOACC_PARALLEL:
9236 case BUILT_IN_GOACC_UPDATE:
9237 break;
9238 default:
9239 gcc_unreachable ();
9241 args.quick_push (t1);
9242 args.quick_push (t2);
9243 args.quick_push (t3);
9244 args.quick_push (t4);
9245 switch (start_ix)
9247 case BUILT_IN_GOACC_DATA_START:
9248 case BUILT_IN_GOMP_TARGET:
9249 case BUILT_IN_GOMP_TARGET_DATA:
9250 case BUILT_IN_GOMP_TARGET_UPDATE:
9251 break;
9252 case BUILT_IN_GOACC_PARALLEL:
9254 tree t_num_gangs, t_num_workers, t_vector_length;
9256 /* Default values for num_gangs, num_workers, and vector_length. */
9257 t_num_gangs = t_num_workers = t_vector_length
9258 = fold_convert_loc (gimple_location (entry_stmt),
9259 integer_type_node, integer_one_node);
9260 /* ..., but if present, use the value specified by the respective
9261 clause, making sure that are of the correct type. */
9262 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9263 if (c)
9264 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9265 integer_type_node,
9266 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9267 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9268 if (c)
9269 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9270 integer_type_node,
9271 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9272 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9273 if (c)
9274 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9275 integer_type_node,
9276 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9277 args.quick_push (t_num_gangs);
9278 args.quick_push (t_num_workers);
9279 args.quick_push (t_vector_length);
9281 /* FALLTHRU */
9282 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9283 case BUILT_IN_GOACC_UPDATE:
9285 tree t_async;
9286 int t_wait_idx;
9288 /* Default values for t_async. */
9289 t_async = fold_convert_loc (gimple_location (entry_stmt),
9290 integer_type_node,
9291 build_int_cst (integer_type_node,
9292 GOMP_ASYNC_SYNC));
9293 /* ..., but if present, use the value specified by the respective
9294 clause, making sure that is of the correct type. */
9295 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9296 if (c)
9297 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9298 integer_type_node,
9299 OMP_CLAUSE_ASYNC_EXPR (c));
9301 args.quick_push (t_async);
9302 /* Save the index, and... */
9303 t_wait_idx = args.length ();
9304 /* ... push a default value. */
9305 args.quick_push (fold_convert_loc (gimple_location (entry_stmt),
9306 integer_type_node,
9307 integer_zero_node));
9308 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9309 if (c)
9311 int n = 0;
9313 for (; c; c = OMP_CLAUSE_CHAIN (c))
9315 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9317 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9318 integer_type_node,
9319 OMP_CLAUSE_WAIT_EXPR (c)));
9320 n++;
9324 /* Now that we know the number, replace the default value. */
9325 args.ordered_remove (t_wait_idx);
9326 args.quick_insert (t_wait_idx,
9327 fold_convert_loc (gimple_location (entry_stmt),
9328 integer_type_node,
9329 build_int_cst (integer_type_node, n)));
9332 break;
9333 default:
9334 gcc_unreachable ();
9337 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
9338 gimple_set_location (g, gimple_location (entry_stmt));
9339 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9340 if (!offloaded)
9342 g = gsi_stmt (gsi);
9343 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9344 gsi_remove (&gsi, true);
9346 if (data_region
9347 && region->exit)
9349 gsi = gsi_last_bb (region->exit);
9350 g = gsi_stmt (gsi);
9351 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9352 gsi_remove (&gsi, true);
9357 /* Expand the parallel region tree rooted at REGION. Expansion
9358 proceeds in depth-first order. Innermost regions are expanded
9359 first. This way, parallel regions that require a new function to
9360 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9361 internal dependencies in their body. */
9363 static void
9364 expand_omp (struct omp_region *region)
9366 while (region)
9368 location_t saved_location;
9369 gimple inner_stmt = NULL;
9371 /* First, determine whether this is a combined parallel+workshare
9372 region. */
9373 if (region->type == GIMPLE_OMP_PARALLEL)
9374 determine_parallel_type (region);
9376 if (region->type == GIMPLE_OMP_FOR
9377 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9378 inner_stmt = last_stmt (region->inner->entry);
9380 if (region->inner)
9381 expand_omp (region->inner);
9383 saved_location = input_location;
9384 if (gimple_has_location (last_stmt (region->entry)))
9385 input_location = gimple_location (last_stmt (region->entry));
9387 switch (region->type)
9389 case GIMPLE_OMP_PARALLEL:
9390 case GIMPLE_OMP_TASK:
9391 expand_omp_taskreg (region);
9392 break;
9394 case GIMPLE_OMP_FOR:
9395 expand_omp_for (region, inner_stmt);
9396 break;
9398 case GIMPLE_OMP_SECTIONS:
9399 expand_omp_sections (region);
9400 break;
9402 case GIMPLE_OMP_SECTION:
9403 /* Individual omp sections are handled together with their
9404 parent GIMPLE_OMP_SECTIONS region. */
9405 break;
9407 case GIMPLE_OMP_SINGLE:
9408 expand_omp_single (region);
9409 break;
9411 case GIMPLE_OMP_MASTER:
9412 case GIMPLE_OMP_TASKGROUP:
9413 case GIMPLE_OMP_ORDERED:
9414 case GIMPLE_OMP_CRITICAL:
9415 case GIMPLE_OMP_TEAMS:
9416 expand_omp_synch (region);
9417 break;
9419 case GIMPLE_OMP_ATOMIC_LOAD:
9420 expand_omp_atomic (region);
9421 break;
9423 case GIMPLE_OMP_TARGET:
9424 expand_omp_target (region);
9425 break;
9427 default:
9428 gcc_unreachable ();
9431 input_location = saved_location;
9432 region = region->next;
9437 /* Helper for build_omp_regions. Scan the dominator tree starting at
9438 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9439 true, the function ends once a single tree is built (otherwise, whole
9440 forest of OMP constructs may be built). */
9442 static void
9443 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9444 bool single_tree)
9446 gimple_stmt_iterator gsi;
9447 gimple stmt;
9448 basic_block son;
9450 gsi = gsi_last_bb (bb);
9451 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9453 struct omp_region *region;
9454 enum gimple_code code;
9456 stmt = gsi_stmt (gsi);
9457 code = gimple_code (stmt);
9458 if (code == GIMPLE_OMP_RETURN)
9460 /* STMT is the return point out of region PARENT. Mark it
9461 as the exit point and make PARENT the immediately
9462 enclosing region. */
9463 gcc_assert (parent);
9464 region = parent;
9465 region->exit = bb;
9466 parent = parent->outer;
9468 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9470 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9471 GIMPLE_OMP_RETURN, but matches with
9472 GIMPLE_OMP_ATOMIC_LOAD. */
9473 gcc_assert (parent);
9474 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9475 region = parent;
9476 region->exit = bb;
9477 parent = parent->outer;
9479 else if (code == GIMPLE_OMP_CONTINUE)
9481 gcc_assert (parent);
9482 parent->cont = bb;
9484 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9486 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9487 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9489 else
9491 region = new_omp_region (bb, code, parent);
9492 /* Otherwise... */
9493 if (code == GIMPLE_OMP_TARGET)
9495 switch (gimple_omp_target_kind (stmt))
9497 case GF_OMP_TARGET_KIND_REGION:
9498 case GF_OMP_TARGET_KIND_DATA:
9499 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9500 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9501 case GF_OMP_TARGET_KIND_OACC_DATA:
9502 break;
9503 case GF_OMP_TARGET_KIND_UPDATE:
9504 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9505 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9506 /* ..., other than for those stand-alone directives... */
9507 region = NULL;
9508 break;
9509 default:
9510 gcc_unreachable ();
9513 /* ..., this directive becomes the parent for a new region. */
9514 if (region)
9515 parent = region;
9519 if (single_tree && !parent)
9520 return;
9522 for (son = first_dom_son (CDI_DOMINATORS, bb);
9523 son;
9524 son = next_dom_son (CDI_DOMINATORS, son))
9525 build_omp_regions_1 (son, parent, single_tree);
9528 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9529 root_omp_region. */
9531 static void
9532 build_omp_regions_root (basic_block root)
9534 gcc_assert (root_omp_region == NULL);
9535 build_omp_regions_1 (root, NULL, true);
9536 gcc_assert (root_omp_region != NULL);
9539 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9541 void
9542 omp_expand_local (basic_block head)
9544 build_omp_regions_root (head);
9545 if (dump_file && (dump_flags & TDF_DETAILS))
9547 fprintf (dump_file, "\nOMP region tree\n\n");
9548 dump_omp_region (dump_file, root_omp_region, 0);
9549 fprintf (dump_file, "\n");
9552 remove_exit_barriers (root_omp_region);
9553 expand_omp (root_omp_region);
9555 free_omp_regions ();
9558 /* Scan the CFG and build a tree of OMP regions. Return the root of
9559 the OMP region tree. */
9561 static void
9562 build_omp_regions (void)
9564 gcc_assert (root_omp_region == NULL);
9565 calculate_dominance_info (CDI_DOMINATORS);
9566 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9569 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9571 static unsigned int
9572 execute_expand_omp (void)
9574 build_omp_regions ();
9576 if (!root_omp_region)
9577 return 0;
9579 if (dump_file)
9581 fprintf (dump_file, "\nOMP region tree\n\n");
9582 dump_omp_region (dump_file, root_omp_region, 0);
9583 fprintf (dump_file, "\n");
9586 remove_exit_barriers (root_omp_region);
9588 expand_omp (root_omp_region);
9590 #ifdef ENABLE_CHECKING
9591 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
9592 verify_loop_structure ();
9593 #endif
9594 cleanup_tree_cfg ();
9596 free_omp_regions ();
9598 return 0;
9601 /* OMP expansion -- the default pass, run before creation of SSA form. */
9603 namespace {
9605 const pass_data pass_data_expand_omp =
9607 GIMPLE_PASS, /* type */
9608 "ompexp", /* name */
9609 OPTGROUP_NONE, /* optinfo_flags */
9610 TV_NONE, /* tv_id */
9611 PROP_gimple_any, /* properties_required */
9612 PROP_gimple_eomp, /* properties_provided */
9613 0, /* properties_destroyed */
9614 0, /* todo_flags_start */
9615 0, /* todo_flags_finish */
9618 class pass_expand_omp : public gimple_opt_pass
9620 public:
9621 pass_expand_omp (gcc::context *ctxt)
9622 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9625 /* opt_pass methods: */
9626 virtual unsigned int execute (function *)
9628 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9629 || flag_openmp_simd != 0)
9630 && !seen_error ());
9632 /* This pass always runs, to provide PROP_gimple_eomp.
9633 But often, there is nothing to do. */
9634 if (!gate)
9635 return 0;
9637 return execute_expand_omp ();
9640 }; // class pass_expand_omp
9642 } // anon namespace
9644 gimple_opt_pass *
9645 make_pass_expand_omp (gcc::context *ctxt)
9647 return new pass_expand_omp (ctxt);
9650 namespace {
9652 const pass_data pass_data_expand_omp_ssa =
9654 GIMPLE_PASS, /* type */
9655 "ompexpssa", /* name */
9656 OPTGROUP_NONE, /* optinfo_flags */
9657 TV_NONE, /* tv_id */
9658 PROP_cfg | PROP_ssa, /* properties_required */
9659 PROP_gimple_eomp, /* properties_provided */
9660 0, /* properties_destroyed */
9661 0, /* todo_flags_start */
9662 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9665 class pass_expand_omp_ssa : public gimple_opt_pass
9667 public:
9668 pass_expand_omp_ssa (gcc::context *ctxt)
9669 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9672 /* opt_pass methods: */
9673 virtual bool gate (function *fun)
9675 return !(fun->curr_properties & PROP_gimple_eomp);
9677 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9679 }; // class pass_expand_omp_ssa
9681 } // anon namespace
9683 gimple_opt_pass *
9684 make_pass_expand_omp_ssa (gcc::context *ctxt)
9686 return new pass_expand_omp_ssa (ctxt);
9689 /* Routines to lower OMP directives into OMP-GIMPLE. */
9691 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9692 convert it to gimple. */
9693 static void
9694 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9696 gimple stmt;
9698 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9700 stmt = gimple_build_assign (dest, op, dest, src);
9701 gimple_seq_add_stmt (seq, stmt);
9702 return;
9705 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9706 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9707 gimplify_assign (t, rdest, seq);
9708 rdest = t;
9710 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9711 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9712 gimplify_assign (t, idest, seq);
9713 idest = t;
9715 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9716 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9717 gimplify_assign (t, rsrc, seq);
9718 rsrc = t;
9720 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9721 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9722 gimplify_assign (t, isrc, seq);
9723 isrc = t;
9725 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9726 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9727 tree result;
9729 if (op == PLUS_EXPR)
9731 stmt = gimple_build_assign (r, op, rdest, rsrc);
9732 gimple_seq_add_stmt (seq, stmt);
9734 stmt = gimple_build_assign (i, op, idest, isrc);
9735 gimple_seq_add_stmt (seq, stmt);
9737 else if (op == MULT_EXPR)
9739 /* Let x = a + ib = dest, y = c + id = src.
9740 x * y = (ac - bd) + i(ad + bc) */
9741 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9742 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9743 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9744 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9746 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9747 gimple_seq_add_stmt (seq, stmt);
9749 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9750 gimple_seq_add_stmt (seq, stmt);
9752 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9753 gimple_seq_add_stmt (seq, stmt);
9755 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9756 gimple_seq_add_stmt (seq, stmt);
9758 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9759 gimple_seq_add_stmt (seq, stmt);
9761 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9762 gimple_seq_add_stmt (seq, stmt);
9764 else
9765 gcc_unreachable ();
9767 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9768 gimplify_assign (dest, result, seq);
9771 /* Helper function to initialize local data for the reduction arrays.
9772 The reduction arrays need to be placed inside the calling function
9773 for accelerators, or else the host won't be able to preform the final
9774 reduction. */
9776 static void
9777 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9778 gimple_seq *stmt_seqp, omp_context *ctx)
9780 tree c, t, oc;
9781 gimple stmt;
9782 omp_context *octx;
9784 /* Find the innermost OpenACC parallel context. */
9785 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9786 && (gimple_omp_target_kind (ctx->stmt)
9787 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9788 octx = ctx;
9789 else
9790 octx = ctx->outer;
9791 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9792 && (gimple_omp_target_kind (octx->stmt)
9793 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9795 /* Extract the clauses. */
9796 oc = gimple_omp_target_clauses (octx->stmt);
9798 /* Find the last outer clause. */
9799 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9802 /* Allocate arrays for each reduction variable. */
9803 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9805 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9806 continue;
9808 tree var = OMP_CLAUSE_DECL (c);
9809 tree type = get_base_type (var);
9810 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9811 ctx);
9812 tree size, call;
9814 /* Calculate size of the reduction array. */
9815 t = create_tmp_var (TREE_TYPE (nthreads));
9816 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9817 fold_convert (TREE_TYPE (nthreads),
9818 TYPE_SIZE_UNIT (type)));
9819 gimple_seq_add_stmt (stmt_seqp, stmt);
9821 size = create_tmp_var (sizetype);
9822 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9824 /* Now allocate memory for it. */
9825 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9826 stmt = gimple_build_call (call, 1, size);
9827 gimple_call_set_lhs (stmt, array);
9828 gimple_seq_add_stmt (stmt_seqp, stmt);
9830 /* Map this array into the accelerator. */
9832 /* Add the reduction array to the list of clauses. */
9833 tree x = array;
9834 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9835 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9836 OMP_CLAUSE_DECL (t) = x;
9837 OMP_CLAUSE_CHAIN (t) = NULL;
9838 if (oc)
9839 OMP_CLAUSE_CHAIN (oc) = t;
9840 else
9841 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9842 OMP_CLAUSE_SIZE (t) = size;
9843 oc = t;
9847 /* Helper function to process the array of partial reductions. Nthreads
9848 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9849 cannot be used here, because nthreads on the host may be different than
9850 on the accelerator. */
9852 static void
9853 oacc_finalize_reduction_data (tree clauses, tree nthreads,
9854 gimple_seq *stmt_seqp, omp_context *ctx)
9856 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9857 gimple stmt;
9859 /* Create for loop.
9861 let var = the original reduction variable
9862 let array = reduction variable array
9864 for (i = 0; i < nthreads; i++)
9865 var op= array[i]
9868 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9869 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9870 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9872 /* Create and initialize an index variable. */
9873 tree ix = create_tmp_var (sizetype);
9874 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9875 stmt_seqp);
9877 /* Insert the loop header label here. */
9878 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9880 /* Exit loop if ix >= nthreads. */
9881 x = create_tmp_var (sizetype);
9882 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9883 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9884 gimple_seq_add_stmt (stmt_seqp, stmt);
9886 /* Insert the loop body label here. */
9887 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9889 /* Collapse each reduction array, one element at a time. */
9890 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9892 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9893 continue;
9895 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9897 /* reduction(-:var) sums up the partial results, so it acts
9898 identically to reduction(+:var). */
9899 if (reduction_code == MINUS_EXPR)
9900 reduction_code = PLUS_EXPR;
9902 /* Set up reduction variable var. */
9903 var = OMP_CLAUSE_DECL (c);
9904 type = get_base_type (var);
9905 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9906 (OMP_CLAUSE_DECL (c)), ctx);
9908 /* Calculate the array offset. */
9909 tree offset = create_tmp_var (sizetype);
9910 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9911 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9912 gimple_seq_add_stmt (stmt_seqp, stmt);
9914 tree ptr = create_tmp_var (TREE_TYPE (array));
9915 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9916 gimple_seq_add_stmt (stmt_seqp, stmt);
9918 /* Extract array[ix] into mem. */
9919 tree mem = create_tmp_var (type);
9920 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9922 /* Find the original reduction variable. */
9923 if (is_reference (var))
9924 var = build_simple_mem_ref (var);
9926 tree t = create_tmp_var (type);
9928 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9929 gimplify_and_add (unshare_expr(x), stmt_seqp);
9931 /* var = var op mem */
9932 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9934 case TRUTH_ANDIF_EXPR:
9935 case TRUTH_ORIF_EXPR:
9936 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9937 t, mem);
9938 gimplify_and_add (t, stmt_seqp);
9939 break;
9940 default:
9941 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9942 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9943 stmt_seqp);
9946 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9947 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9948 gimplify_and_add (unshare_expr(x), stmt_seqp);
9951 /* Increment the induction variable. */
9952 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9953 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9954 gimple_seq_add_stmt (stmt_seqp, stmt);
9956 /* Go back to the top of the loop. */
9957 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9959 /* Place the loop exit label here. */
9960 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9963 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9964 scan that for reductions. */
9966 static void
9967 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9968 gimple_seq *out_stmt_seqp, omp_context *ctx)
9970 gimple_stmt_iterator gsi;
9971 gimple_seq inner = NULL;
9973 /* A collapse clause may have inserted a new bind block. */
9974 gsi = gsi_start (*body);
9975 while (!gsi_end_p (gsi))
9977 gimple stmt = gsi_stmt (gsi);
9978 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9980 inner = gimple_bind_body (bind_stmt);
9981 body = &inner;
9982 gsi = gsi_start (*body);
9984 else if (dyn_cast <gomp_for *> (stmt))
9985 break;
9986 else
9987 gsi_next (&gsi);
9990 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9992 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9993 enter, exit;
9994 bool reduction_found = false;
9996 gimple stmt = gsi_stmt (gsi);
9998 switch (gimple_code (stmt))
10000 case GIMPLE_OMP_FOR:
10001 clauses = gimple_omp_for_clauses (stmt);
10003 /* Search for a reduction clause. */
10004 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10005 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
10007 reduction_found = true;
10008 break;
10011 if (!reduction_found)
10012 break;
10014 ctx = maybe_lookup_ctx (stmt);
10015 t = NULL_TREE;
10017 /* Extract the number of threads. */
10018 nthreads = create_tmp_var (sizetype);
10019 t = oacc_max_threads (ctx);
10020 gimplify_assign (nthreads, t, in_stmt_seqp);
10022 /* Determine if this is kernel will be executed on the host. */
10023 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
10024 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
10025 stmt = gimple_build_call (call, 0);
10026 gimple_call_set_lhs (stmt, acc_device);
10027 gimple_seq_add_stmt (in_stmt_seqp, stmt);
10029 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
10030 acc_device_host = create_tmp_var (integer_type_node,
10031 ".acc_device_host");
10032 gimplify_assign (acc_device_host,
10033 build_int_cst (integer_type_node,
10034 GOMP_DEVICE_HOST),
10035 in_stmt_seqp);
10037 enter = create_artificial_label (UNKNOWN_LOCATION);
10038 exit = create_artificial_label (UNKNOWN_LOCATION);
10040 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
10041 enter, exit);
10042 gimple_seq_add_stmt (in_stmt_seqp, stmt);
10043 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
10044 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
10045 integer_one_node),
10046 in_stmt_seqp);
10047 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
10049 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
10050 ctx);
10051 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
10052 break;
10053 default:
10054 // Scan for other directives which support reduction here.
10055 break;
10060 /* If ctx is a worksharing context inside of a cancellable parallel
10061 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
10062 and conditional branch to parallel's cancel_label to handle
10063 cancellation in the implicit barrier. */
10065 static void
10066 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
10068 gimple omp_return = gimple_seq_last_stmt (*body);
10069 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
10070 if (gimple_omp_return_nowait_p (omp_return))
10071 return;
10072 if (ctx->outer
10073 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
10074 && ctx->outer->cancellable)
10076 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
10077 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
10078 tree lhs = create_tmp_var (c_bool_type);
10079 gimple_omp_return_set_lhs (omp_return, lhs);
10080 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10081 gimple g = gimple_build_cond (NE_EXPR, lhs,
10082 fold_convert (c_bool_type,
10083 boolean_false_node),
10084 ctx->outer->cancel_label, fallthru_label);
10085 gimple_seq_add_stmt (body, g);
10086 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10090 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10091 CTX is the enclosing OMP context for the current statement. */
10093 static void
10094 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10096 tree block, control;
10097 gimple_stmt_iterator tgsi;
10098 gomp_sections *stmt;
10099 gimple t;
10100 gbind *new_stmt, *bind;
10101 gimple_seq ilist, dlist, olist, new_body;
10103 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
10105 push_gimplify_context ();
10107 dlist = NULL;
10108 ilist = NULL;
10109 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10110 &ilist, &dlist, ctx, NULL);
10112 new_body = gimple_omp_body (stmt);
10113 gimple_omp_set_body (stmt, NULL);
10114 tgsi = gsi_start (new_body);
10115 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10117 omp_context *sctx;
10118 gimple sec_start;
10120 sec_start = gsi_stmt (tgsi);
10121 sctx = maybe_lookup_ctx (sec_start);
10122 gcc_assert (sctx);
10124 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10125 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10126 GSI_CONTINUE_LINKING);
10127 gimple_omp_set_body (sec_start, NULL);
10129 if (gsi_one_before_end_p (tgsi))
10131 gimple_seq l = NULL;
10132 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10133 &l, ctx);
10134 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10135 gimple_omp_section_set_last (sec_start);
10138 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10139 GSI_CONTINUE_LINKING);
10142 block = make_node (BLOCK);
10143 bind = gimple_build_bind (NULL, new_body, block);
10145 olist = NULL;
10146 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10148 block = make_node (BLOCK);
10149 new_stmt = gimple_build_bind (NULL, NULL, block);
10150 gsi_replace (gsi_p, new_stmt, true);
10152 pop_gimplify_context (new_stmt);
10153 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10154 BLOCK_VARS (block) = gimple_bind_vars (bind);
10155 if (BLOCK_VARS (block))
10156 TREE_USED (block) = 1;
10158 new_body = NULL;
10159 gimple_seq_add_seq (&new_body, ilist);
10160 gimple_seq_add_stmt (&new_body, stmt);
10161 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10162 gimple_seq_add_stmt (&new_body, bind);
10164 control = create_tmp_var (unsigned_type_node, ".section");
10165 t = gimple_build_omp_continue (control, control);
10166 gimple_omp_sections_set_control (stmt, control);
10167 gimple_seq_add_stmt (&new_body, t);
10169 gimple_seq_add_seq (&new_body, olist);
10170 if (ctx->cancellable)
10171 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10172 gimple_seq_add_seq (&new_body, dlist);
10174 new_body = maybe_catch_exception (new_body);
10176 t = gimple_build_omp_return
10177 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10178 OMP_CLAUSE_NOWAIT));
10179 gimple_seq_add_stmt (&new_body, t);
10180 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10182 gimple_bind_set_body (new_stmt, new_body);
10186 /* A subroutine of lower_omp_single. Expand the simple form of
10187 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10189 if (GOMP_single_start ())
10190 BODY;
10191 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10193 FIXME. It may be better to delay expanding the logic of this until
10194 pass_expand_omp. The expanded logic may make the job more difficult
10195 to a synchronization analysis pass. */
10197 static void
10198 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10200 location_t loc = gimple_location (single_stmt);
10201 tree tlabel = create_artificial_label (loc);
10202 tree flabel = create_artificial_label (loc);
10203 gimple call, cond;
10204 tree lhs, decl;
10206 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10207 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10208 call = gimple_build_call (decl, 0);
10209 gimple_call_set_lhs (call, lhs);
10210 gimple_seq_add_stmt (pre_p, call);
10212 cond = gimple_build_cond (EQ_EXPR, lhs,
10213 fold_convert_loc (loc, TREE_TYPE (lhs),
10214 boolean_true_node),
10215 tlabel, flabel);
10216 gimple_seq_add_stmt (pre_p, cond);
10217 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10218 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10219 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10223 /* A subroutine of lower_omp_single. Expand the simple form of
10224 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10226 #pragma omp single copyprivate (a, b, c)
10228 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10231 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10233 BODY;
10234 copyout.a = a;
10235 copyout.b = b;
10236 copyout.c = c;
10237 GOMP_single_copy_end (&copyout);
10239 else
10241 a = copyout_p->a;
10242 b = copyout_p->b;
10243 c = copyout_p->c;
10245 GOMP_barrier ();
10248 FIXME. It may be better to delay expanding the logic of this until
10249 pass_expand_omp. The expanded logic may make the job more difficult
10250 to a synchronization analysis pass. */
10252 static void
10253 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10254 omp_context *ctx)
10256 tree ptr_type, t, l0, l1, l2, bfn_decl;
10257 gimple_seq copyin_seq;
10258 location_t loc = gimple_location (single_stmt);
10260 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10262 ptr_type = build_pointer_type (ctx->record_type);
10263 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10265 l0 = create_artificial_label (loc);
10266 l1 = create_artificial_label (loc);
10267 l2 = create_artificial_label (loc);
10269 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10270 t = build_call_expr_loc (loc, bfn_decl, 0);
10271 t = fold_convert_loc (loc, ptr_type, t);
10272 gimplify_assign (ctx->receiver_decl, t, pre_p);
10274 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10275 build_int_cst (ptr_type, 0));
10276 t = build3 (COND_EXPR, void_type_node, t,
10277 build_and_jump (&l0), build_and_jump (&l1));
10278 gimplify_and_add (t, pre_p);
10280 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10282 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10284 copyin_seq = NULL;
10285 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10286 &copyin_seq, ctx);
10288 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10289 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10290 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10291 gimplify_and_add (t, pre_p);
10293 t = build_and_jump (&l2);
10294 gimplify_and_add (t, pre_p);
10296 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10298 gimple_seq_add_seq (pre_p, copyin_seq);
10300 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10304 /* Expand code for an OpenMP single directive. */
10306 static void
10307 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10309 tree block;
10310 gimple t;
10311 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10312 gbind *bind;
10313 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10315 push_gimplify_context ();
10317 block = make_node (BLOCK);
10318 bind = gimple_build_bind (NULL, NULL, block);
10319 gsi_replace (gsi_p, bind, true);
10320 bind_body = NULL;
10321 dlist = NULL;
10322 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10323 &bind_body, &dlist, ctx, NULL);
10324 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10326 gimple_seq_add_stmt (&bind_body, single_stmt);
10328 if (ctx->record_type)
10329 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10330 else
10331 lower_omp_single_simple (single_stmt, &bind_body);
10333 gimple_omp_set_body (single_stmt, NULL);
10335 gimple_seq_add_seq (&bind_body, dlist);
10337 bind_body = maybe_catch_exception (bind_body);
10339 t = gimple_build_omp_return
10340 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10341 OMP_CLAUSE_NOWAIT));
10342 gimple_seq_add_stmt (&bind_body_tail, t);
10343 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10344 if (ctx->record_type)
10346 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10347 tree clobber = build_constructor (ctx->record_type, NULL);
10348 TREE_THIS_VOLATILE (clobber) = 1;
10349 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10350 clobber), GSI_SAME_STMT);
10352 gimple_seq_add_seq (&bind_body, bind_body_tail);
10353 gimple_bind_set_body (bind, bind_body);
10355 pop_gimplify_context (bind);
10357 gimple_bind_append_vars (bind, ctx->block_vars);
10358 BLOCK_VARS (block) = ctx->block_vars;
10359 if (BLOCK_VARS (block))
10360 TREE_USED (block) = 1;
10364 /* Expand code for an OpenMP master directive. */
10366 static void
10367 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10369 tree block, lab = NULL, x, bfn_decl;
10370 gimple stmt = gsi_stmt (*gsi_p);
10371 gbind *bind;
10372 location_t loc = gimple_location (stmt);
10373 gimple_seq tseq;
10375 push_gimplify_context ();
10377 block = make_node (BLOCK);
10378 bind = gimple_build_bind (NULL, NULL, block);
10379 gsi_replace (gsi_p, bind, true);
10380 gimple_bind_add_stmt (bind, stmt);
10382 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10383 x = build_call_expr_loc (loc, bfn_decl, 0);
10384 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10385 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10386 tseq = NULL;
10387 gimplify_and_add (x, &tseq);
10388 gimple_bind_add_seq (bind, tseq);
10390 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10391 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10392 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10393 gimple_omp_set_body (stmt, NULL);
10395 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10397 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10399 pop_gimplify_context (bind);
10401 gimple_bind_append_vars (bind, ctx->block_vars);
10402 BLOCK_VARS (block) = ctx->block_vars;
10406 /* Expand code for an OpenMP taskgroup directive. */
10408 static void
10409 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10411 gimple stmt = gsi_stmt (*gsi_p);
10412 gcall *x;
10413 gbind *bind;
10414 tree block = make_node (BLOCK);
10416 bind = gimple_build_bind (NULL, NULL, block);
10417 gsi_replace (gsi_p, bind, true);
10418 gimple_bind_add_stmt (bind, stmt);
10420 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10422 gimple_bind_add_stmt (bind, x);
10424 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10425 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10426 gimple_omp_set_body (stmt, NULL);
10428 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10430 gimple_bind_append_vars (bind, ctx->block_vars);
10431 BLOCK_VARS (block) = ctx->block_vars;
10435 /* Expand code for an OpenMP ordered directive. */
10437 static void
10438 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10440 tree block;
10441 gimple stmt = gsi_stmt (*gsi_p);
10442 gcall *x;
10443 gbind *bind;
10445 push_gimplify_context ();
10447 block = make_node (BLOCK);
10448 bind = gimple_build_bind (NULL, NULL, block);
10449 gsi_replace (gsi_p, bind, true);
10450 gimple_bind_add_stmt (bind, stmt);
10452 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10454 gimple_bind_add_stmt (bind, x);
10456 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10457 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10458 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10459 gimple_omp_set_body (stmt, NULL);
10461 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10462 gimple_bind_add_stmt (bind, x);
10464 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10466 pop_gimplify_context (bind);
10468 gimple_bind_append_vars (bind, ctx->block_vars);
10469 BLOCK_VARS (block) = gimple_bind_vars (bind);
10473 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10474 substitution of a couple of function calls. But in the NAMED case,
10475 requires that languages coordinate a symbol name. It is therefore
10476 best put here in common code. */
10478 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10480 static void
10481 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10483 tree block;
10484 tree name, lock, unlock;
10485 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10486 gbind *bind;
10487 location_t loc = gimple_location (stmt);
10488 gimple_seq tbody;
10490 name = gimple_omp_critical_name (stmt);
10491 if (name)
10493 tree decl;
10495 if (!critical_name_mutexes)
10496 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10498 tree *n = critical_name_mutexes->get (name);
10499 if (n == NULL)
10501 char *new_str;
10503 decl = create_tmp_var_raw (ptr_type_node);
10505 new_str = ACONCAT ((".gomp_critical_user_",
10506 IDENTIFIER_POINTER (name), NULL));
10507 DECL_NAME (decl) = get_identifier (new_str);
10508 TREE_PUBLIC (decl) = 1;
10509 TREE_STATIC (decl) = 1;
10510 DECL_COMMON (decl) = 1;
10511 DECL_ARTIFICIAL (decl) = 1;
10512 DECL_IGNORED_P (decl) = 1;
10514 varpool_node::finalize_decl (decl);
10516 critical_name_mutexes->put (name, decl);
10518 else
10519 decl = *n;
10521 /* If '#pragma omp critical' is inside offloaded region or
10522 inside function marked as offloadable, the symbol must be
10523 marked as offloadable too. */
10524 omp_context *octx;
10525 if (cgraph_node::get (current_function_decl)->offloadable)
10526 varpool_node::get_create (decl)->offloadable = 1;
10527 else
10528 for (octx = ctx->outer; octx; octx = octx->outer)
10529 if (is_gimple_omp_offloaded (octx->stmt))
10531 varpool_node::get_create (decl)->offloadable = 1;
10532 break;
10535 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10536 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10538 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10539 unlock = build_call_expr_loc (loc, unlock, 1,
10540 build_fold_addr_expr_loc (loc, decl));
10542 else
10544 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10545 lock = build_call_expr_loc (loc, lock, 0);
10547 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10548 unlock = build_call_expr_loc (loc, unlock, 0);
10551 push_gimplify_context ();
10553 block = make_node (BLOCK);
10554 bind = gimple_build_bind (NULL, NULL, block);
10555 gsi_replace (gsi_p, bind, true);
10556 gimple_bind_add_stmt (bind, stmt);
10558 tbody = gimple_bind_body (bind);
10559 gimplify_and_add (lock, &tbody);
10560 gimple_bind_set_body (bind, tbody);
10562 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10563 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10564 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10565 gimple_omp_set_body (stmt, NULL);
10567 tbody = gimple_bind_body (bind);
10568 gimplify_and_add (unlock, &tbody);
10569 gimple_bind_set_body (bind, tbody);
10571 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10573 pop_gimplify_context (bind);
10574 gimple_bind_append_vars (bind, ctx->block_vars);
10575 BLOCK_VARS (block) = gimple_bind_vars (bind);
10579 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10580 for a lastprivate clause. Given a loop control predicate of (V
10581 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10582 is appended to *DLIST, iterator initialization is appended to
10583 *BODY_P. */
10585 static void
10586 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10587 gimple_seq *dlist, struct omp_context *ctx)
10589 tree clauses, cond, vinit;
10590 enum tree_code cond_code;
10591 gimple_seq stmts;
10593 cond_code = fd->loop.cond_code;
10594 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10596 /* When possible, use a strict equality expression. This can let VRP
10597 type optimizations deduce the value and remove a copy. */
10598 if (tree_fits_shwi_p (fd->loop.step))
10600 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10601 if (step == 1 || step == -1)
10602 cond_code = EQ_EXPR;
10605 tree n2 = fd->loop.n2;
10606 if (fd->collapse > 1
10607 && TREE_CODE (n2) != INTEGER_CST
10608 && gimple_omp_for_combined_into_p (fd->for_stmt)
10609 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10611 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10612 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
10614 struct omp_for_data outer_fd;
10615 extract_omp_for_data (gfor, &outer_fd, NULL);
10616 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10619 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
10621 clauses = gimple_omp_for_clauses (fd->for_stmt);
10622 stmts = NULL;
10623 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10624 if (!gimple_seq_empty_p (stmts))
10626 gimple_seq_add_seq (&stmts, *dlist);
10627 *dlist = stmts;
10629 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10630 vinit = fd->loop.n1;
10631 if (cond_code == EQ_EXPR
10632 && tree_fits_shwi_p (fd->loop.n2)
10633 && ! integer_zerop (fd->loop.n2))
10634 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10635 else
10636 vinit = unshare_expr (vinit);
10638 /* Initialize the iterator variable, so that threads that don't execute
10639 any iterations don't execute the lastprivate clauses by accident. */
10640 gimplify_assign (fd->loop.v, vinit, body_p);
10645 /* Lower code for an OMP loop directive. */
10647 static void
10648 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10650 tree *rhs_p, block;
10651 struct omp_for_data fd, *fdp = NULL;
10652 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10653 gbind *new_stmt;
10654 gimple_seq omp_for_body, body, dlist;
10655 size_t i;
10657 push_gimplify_context ();
10659 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10661 block = make_node (BLOCK);
10662 new_stmt = gimple_build_bind (NULL, NULL, block);
10663 /* Replace at gsi right away, so that 'stmt' is no member
10664 of a sequence anymore as we're going to add to a different
10665 one below. */
10666 gsi_replace (gsi_p, new_stmt, true);
10668 /* Move declaration of temporaries in the loop body before we make
10669 it go away. */
10670 omp_for_body = gimple_omp_body (stmt);
10671 if (!gimple_seq_empty_p (omp_for_body)
10672 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10674 gbind *inner_bind
10675 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10676 tree vars = gimple_bind_vars (inner_bind);
10677 gimple_bind_append_vars (new_stmt, vars);
10678 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10679 keep them on the inner_bind and it's block. */
10680 gimple_bind_set_vars (inner_bind, NULL_TREE);
10681 if (gimple_bind_block (inner_bind))
10682 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10685 if (gimple_omp_for_combined_into_p (stmt))
10687 extract_omp_for_data (stmt, &fd, NULL);
10688 fdp = &fd;
10690 /* We need two temporaries with fd.loop.v type (istart/iend)
10691 and then (fd.collapse - 1) temporaries with the same
10692 type for count2 ... countN-1 vars if not constant. */
10693 size_t count = 2;
10694 tree type = fd.iter_type;
10695 if (fd.collapse > 1
10696 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10697 count += fd.collapse - 1;
10698 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10699 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10700 tree clauses = *pc;
10701 if (parallel_for)
10702 outerc
10703 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10704 OMP_CLAUSE__LOOPTEMP_);
10705 for (i = 0; i < count; i++)
10707 tree temp;
10708 if (parallel_for)
10710 gcc_assert (outerc);
10711 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10712 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10713 OMP_CLAUSE__LOOPTEMP_);
10715 else
10717 temp = create_tmp_var (type);
10718 insert_decl_map (&ctx->outer->cb, temp, temp);
10720 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10721 OMP_CLAUSE_DECL (*pc) = temp;
10722 pc = &OMP_CLAUSE_CHAIN (*pc);
10724 *pc = clauses;
10727 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10728 dlist = NULL;
10729 body = NULL;
10730 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10731 fdp);
10732 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10734 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10736 /* Lower the header expressions. At this point, we can assume that
10737 the header is of the form:
10739 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10741 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10742 using the .omp_data_s mapping, if needed. */
10743 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10745 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10746 if (!is_gimple_min_invariant (*rhs_p))
10747 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10749 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10750 if (!is_gimple_min_invariant (*rhs_p))
10751 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10753 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10754 if (!is_gimple_min_invariant (*rhs_p))
10755 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10758 /* Once lowered, extract the bounds and clauses. */
10759 extract_omp_for_data (stmt, &fd, NULL);
10761 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10763 gimple_seq_add_stmt (&body, stmt);
10764 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10766 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10767 fd.loop.v));
10769 /* After the loop, add exit clauses. */
10770 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10772 if (ctx->cancellable)
10773 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10775 gimple_seq_add_seq (&body, dlist);
10777 body = maybe_catch_exception (body);
10779 /* Region exit marker goes at the end of the loop body. */
10780 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10781 maybe_add_implicit_barrier_cancel (ctx, &body);
10782 pop_gimplify_context (new_stmt);
10784 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10785 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10786 if (BLOCK_VARS (block))
10787 TREE_USED (block) = 1;
10789 gimple_bind_set_body (new_stmt, body);
10790 gimple_omp_set_body (stmt, NULL);
10791 gimple_omp_for_set_pre_body (stmt, NULL);
10794 /* Callback for walk_stmts. Check if the current statement only contains
10795 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10797 static tree
10798 check_combined_parallel (gimple_stmt_iterator *gsi_p,
10799 bool *handled_ops_p,
10800 struct walk_stmt_info *wi)
10802 int *info = (int *) wi->info;
10803 gimple stmt = gsi_stmt (*gsi_p);
10805 *handled_ops_p = true;
10806 switch (gimple_code (stmt))
10808 WALK_SUBSTMTS;
10810 case GIMPLE_OMP_FOR:
10811 case GIMPLE_OMP_SECTIONS:
10812 *info = *info == 0 ? 1 : -1;
10813 break;
10814 default:
10815 *info = -1;
10816 break;
10818 return NULL;
10821 struct omp_taskcopy_context
10823 /* This field must be at the beginning, as we do "inheritance": Some
10824 callback functions for tree-inline.c (e.g., omp_copy_decl)
10825 receive a copy_body_data pointer that is up-casted to an
10826 omp_context pointer. */
10827 copy_body_data cb;
10828 omp_context *ctx;
10831 static tree
10832 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10834 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10836 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10837 return create_tmp_var (TREE_TYPE (var));
10839 return var;
10842 static tree
10843 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10845 tree name, new_fields = NULL, type, f;
10847 type = lang_hooks.types.make_type (RECORD_TYPE);
10848 name = DECL_NAME (TYPE_NAME (orig_type));
10849 name = build_decl (gimple_location (tcctx->ctx->stmt),
10850 TYPE_DECL, name, type);
10851 TYPE_NAME (type) = name;
10853 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10855 tree new_f = copy_node (f);
10856 DECL_CONTEXT (new_f) = type;
10857 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10858 TREE_CHAIN (new_f) = new_fields;
10859 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10860 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10861 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10862 &tcctx->cb, NULL);
10863 new_fields = new_f;
10864 tcctx->cb.decl_map->put (f, new_f);
10866 TYPE_FIELDS (type) = nreverse (new_fields);
10867 layout_type (type);
10868 return type;
10871 /* Create task copyfn. */
10873 static void
10874 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
10876 struct function *child_cfun;
10877 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10878 tree record_type, srecord_type, bind, list;
10879 bool record_needs_remap = false, srecord_needs_remap = false;
10880 splay_tree_node n;
10881 struct omp_taskcopy_context tcctx;
10882 location_t loc = gimple_location (task_stmt);
10884 child_fn = gimple_omp_task_copy_fn (task_stmt);
10885 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10886 gcc_assert (child_cfun->cfg == NULL);
10887 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10889 /* Reset DECL_CONTEXT on function arguments. */
10890 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10891 DECL_CONTEXT (t) = child_fn;
10893 /* Populate the function. */
10894 push_gimplify_context ();
10895 push_cfun (child_cfun);
10897 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10898 TREE_SIDE_EFFECTS (bind) = 1;
10899 list = NULL;
10900 DECL_SAVED_TREE (child_fn) = bind;
10901 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10903 /* Remap src and dst argument types if needed. */
10904 record_type = ctx->record_type;
10905 srecord_type = ctx->srecord_type;
10906 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10907 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10909 record_needs_remap = true;
10910 break;
10912 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10913 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10915 srecord_needs_remap = true;
10916 break;
10919 if (record_needs_remap || srecord_needs_remap)
10921 memset (&tcctx, '\0', sizeof (tcctx));
10922 tcctx.cb.src_fn = ctx->cb.src_fn;
10923 tcctx.cb.dst_fn = child_fn;
10924 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
10925 gcc_checking_assert (tcctx.cb.src_node);
10926 tcctx.cb.dst_node = tcctx.cb.src_node;
10927 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10928 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10929 tcctx.cb.eh_lp_nr = 0;
10930 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10931 tcctx.cb.decl_map = new hash_map<tree, tree>;
10932 tcctx.ctx = ctx;
10934 if (record_needs_remap)
10935 record_type = task_copyfn_remap_type (&tcctx, record_type);
10936 if (srecord_needs_remap)
10937 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10939 else
10940 tcctx.cb.decl_map = NULL;
10942 arg = DECL_ARGUMENTS (child_fn);
10943 TREE_TYPE (arg) = build_pointer_type (record_type);
10944 sarg = DECL_CHAIN (arg);
10945 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10947 /* First pass: initialize temporaries used in record_type and srecord_type
10948 sizes and field offsets. */
10949 if (tcctx.cb.decl_map)
10950 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10951 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10953 tree *p;
10955 decl = OMP_CLAUSE_DECL (c);
10956 p = tcctx.cb.decl_map->get (decl);
10957 if (p == NULL)
10958 continue;
10959 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10960 sf = (tree) n->value;
10961 sf = *tcctx.cb.decl_map->get (sf);
10962 src = build_simple_mem_ref_loc (loc, sarg);
10963 src = omp_build_component_ref (src, sf);
10964 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10965 append_to_statement_list (t, &list);
10968 /* Second pass: copy shared var pointers and copy construct non-VLA
10969 firstprivate vars. */
10970 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10971 switch (OMP_CLAUSE_CODE (c))
10973 case OMP_CLAUSE_SHARED:
10974 decl = OMP_CLAUSE_DECL (c);
10975 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10976 if (n == NULL)
10977 break;
10978 f = (tree) n->value;
10979 if (tcctx.cb.decl_map)
10980 f = *tcctx.cb.decl_map->get (f);
10981 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10982 sf = (tree) n->value;
10983 if (tcctx.cb.decl_map)
10984 sf = *tcctx.cb.decl_map->get (sf);
10985 src = build_simple_mem_ref_loc (loc, sarg);
10986 src = omp_build_component_ref (src, sf);
10987 dst = build_simple_mem_ref_loc (loc, arg);
10988 dst = omp_build_component_ref (dst, f);
10989 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10990 append_to_statement_list (t, &list);
10991 break;
10992 case OMP_CLAUSE_FIRSTPRIVATE:
10993 decl = OMP_CLAUSE_DECL (c);
10994 if (is_variable_sized (decl))
10995 break;
10996 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10997 if (n == NULL)
10998 break;
10999 f = (tree) n->value;
11000 if (tcctx.cb.decl_map)
11001 f = *tcctx.cb.decl_map->get (f);
11002 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11003 if (n != NULL)
11005 sf = (tree) n->value;
11006 if (tcctx.cb.decl_map)
11007 sf = *tcctx.cb.decl_map->get (sf);
11008 src = build_simple_mem_ref_loc (loc, sarg);
11009 src = omp_build_component_ref (src, sf);
11010 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
11011 src = build_simple_mem_ref_loc (loc, src);
11013 else
11014 src = decl;
11015 dst = build_simple_mem_ref_loc (loc, arg);
11016 dst = omp_build_component_ref (dst, f);
11017 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11018 append_to_statement_list (t, &list);
11019 break;
11020 case OMP_CLAUSE_PRIVATE:
11021 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
11022 break;
11023 decl = OMP_CLAUSE_DECL (c);
11024 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11025 f = (tree) n->value;
11026 if (tcctx.cb.decl_map)
11027 f = *tcctx.cb.decl_map->get (f);
11028 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11029 if (n != NULL)
11031 sf = (tree) n->value;
11032 if (tcctx.cb.decl_map)
11033 sf = *tcctx.cb.decl_map->get (sf);
11034 src = build_simple_mem_ref_loc (loc, sarg);
11035 src = omp_build_component_ref (src, sf);
11036 if (use_pointer_for_field (decl, NULL))
11037 src = build_simple_mem_ref_loc (loc, src);
11039 else
11040 src = decl;
11041 dst = build_simple_mem_ref_loc (loc, arg);
11042 dst = omp_build_component_ref (dst, f);
11043 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
11044 append_to_statement_list (t, &list);
11045 break;
11046 default:
11047 break;
11050 /* Last pass: handle VLA firstprivates. */
11051 if (tcctx.cb.decl_map)
11052 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
11053 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
11055 tree ind, ptr, df;
11057 decl = OMP_CLAUSE_DECL (c);
11058 if (!is_variable_sized (decl))
11059 continue;
11060 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11061 if (n == NULL)
11062 continue;
11063 f = (tree) n->value;
11064 f = *tcctx.cb.decl_map->get (f);
11065 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
11066 ind = DECL_VALUE_EXPR (decl);
11067 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
11068 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
11069 n = splay_tree_lookup (ctx->sfield_map,
11070 (splay_tree_key) TREE_OPERAND (ind, 0));
11071 sf = (tree) n->value;
11072 sf = *tcctx.cb.decl_map->get (sf);
11073 src = build_simple_mem_ref_loc (loc, sarg);
11074 src = omp_build_component_ref (src, sf);
11075 src = build_simple_mem_ref_loc (loc, src);
11076 dst = build_simple_mem_ref_loc (loc, arg);
11077 dst = omp_build_component_ref (dst, f);
11078 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11079 append_to_statement_list (t, &list);
11080 n = splay_tree_lookup (ctx->field_map,
11081 (splay_tree_key) TREE_OPERAND (ind, 0));
11082 df = (tree) n->value;
11083 df = *tcctx.cb.decl_map->get (df);
11084 ptr = build_simple_mem_ref_loc (loc, arg);
11085 ptr = omp_build_component_ref (ptr, df);
11086 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
11087 build_fold_addr_expr_loc (loc, dst));
11088 append_to_statement_list (t, &list);
11091 t = build1 (RETURN_EXPR, void_type_node, NULL);
11092 append_to_statement_list (t, &list);
11094 if (tcctx.cb.decl_map)
11095 delete tcctx.cb.decl_map;
11096 pop_gimplify_context (NULL);
11097 BIND_EXPR_BODY (bind) = list;
11098 pop_cfun ();
11101 static void
11102 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
11104 tree c, clauses;
11105 gimple g;
11106 size_t n_in = 0, n_out = 0, idx = 2, i;
11108 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11109 OMP_CLAUSE_DEPEND);
11110 gcc_assert (clauses);
11111 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11112 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11113 switch (OMP_CLAUSE_DEPEND_KIND (c))
11115 case OMP_CLAUSE_DEPEND_IN:
11116 n_in++;
11117 break;
11118 case OMP_CLAUSE_DEPEND_OUT:
11119 case OMP_CLAUSE_DEPEND_INOUT:
11120 n_out++;
11121 break;
11122 default:
11123 gcc_unreachable ();
11125 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11126 tree array = create_tmp_var (type);
11127 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11128 NULL_TREE);
11129 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11130 gimple_seq_add_stmt (iseq, g);
11131 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11132 NULL_TREE);
11133 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11134 gimple_seq_add_stmt (iseq, g);
11135 for (i = 0; i < 2; i++)
11137 if ((i ? n_in : n_out) == 0)
11138 continue;
11139 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11140 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11141 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11143 tree t = OMP_CLAUSE_DECL (c);
11144 t = fold_convert (ptr_type_node, t);
11145 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11146 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11147 NULL_TREE, NULL_TREE);
11148 g = gimple_build_assign (r, t);
11149 gimple_seq_add_stmt (iseq, g);
11152 tree *p = gimple_omp_task_clauses_ptr (stmt);
11153 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11154 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11155 OMP_CLAUSE_CHAIN (c) = *p;
11156 *p = c;
11157 tree clobber = build_constructor (type, NULL);
11158 TREE_THIS_VOLATILE (clobber) = 1;
11159 g = gimple_build_assign (array, clobber);
11160 gimple_seq_add_stmt (oseq, g);
11163 /* Lower the OpenMP parallel or task directive in the current statement
11164 in GSI_P. CTX holds context information for the directive. */
11166 static void
11167 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11169 tree clauses;
11170 tree child_fn, t;
11171 gimple stmt = gsi_stmt (*gsi_p);
11172 gbind *par_bind, *bind, *dep_bind = NULL;
11173 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11174 location_t loc = gimple_location (stmt);
11176 clauses = gimple_omp_taskreg_clauses (stmt);
11177 par_bind
11178 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11179 par_body = gimple_bind_body (par_bind);
11180 child_fn = ctx->cb.dst_fn;
11181 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11182 && !gimple_omp_parallel_combined_p (stmt))
11184 struct walk_stmt_info wi;
11185 int ws_num = 0;
11187 memset (&wi, 0, sizeof (wi));
11188 wi.info = &ws_num;
11189 wi.val_only = true;
11190 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11191 if (ws_num == 1)
11192 gimple_omp_parallel_set_combined_p (stmt, true);
11194 gimple_seq dep_ilist = NULL;
11195 gimple_seq dep_olist = NULL;
11196 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11197 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11199 push_gimplify_context ();
11200 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11201 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11204 if (ctx->srecord_type)
11205 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11207 push_gimplify_context ();
11209 par_olist = NULL;
11210 par_ilist = NULL;
11211 par_rlist = NULL;
11212 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11213 lower_omp (&par_body, ctx);
11214 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11215 lower_reduction_clauses (clauses, &par_rlist, ctx);
11217 /* Declare all the variables created by mapping and the variables
11218 declared in the scope of the parallel body. */
11219 record_vars_into (ctx->block_vars, child_fn);
11220 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11222 if (ctx->record_type)
11224 ctx->sender_decl
11225 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11226 : ctx->record_type, ".omp_data_o");
11227 DECL_NAMELESS (ctx->sender_decl) = 1;
11228 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11229 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11232 olist = NULL;
11233 ilist = NULL;
11234 lower_send_clauses (clauses, &ilist, &olist, ctx);
11235 lower_send_shared_vars (&ilist, &olist, ctx);
11237 if (ctx->record_type)
11239 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11240 TREE_THIS_VOLATILE (clobber) = 1;
11241 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11242 clobber));
11245 /* Once all the expansions are done, sequence all the different
11246 fragments inside gimple_omp_body. */
11248 new_body = NULL;
11250 if (ctx->record_type)
11252 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11253 /* fixup_child_record_type might have changed receiver_decl's type. */
11254 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11255 gimple_seq_add_stmt (&new_body,
11256 gimple_build_assign (ctx->receiver_decl, t));
11259 gimple_seq_add_seq (&new_body, par_ilist);
11260 gimple_seq_add_seq (&new_body, par_body);
11261 gimple_seq_add_seq (&new_body, par_rlist);
11262 if (ctx->cancellable)
11263 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11264 gimple_seq_add_seq (&new_body, par_olist);
11265 new_body = maybe_catch_exception (new_body);
11266 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
11267 gimple_seq_add_stmt (&new_body,
11268 gimple_build_omp_continue (integer_zero_node,
11269 integer_zero_node));
11270 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11271 gimple_omp_set_body (stmt, new_body);
11273 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11274 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11275 gimple_bind_add_seq (bind, ilist);
11276 gimple_bind_add_stmt (bind, stmt);
11277 gimple_bind_add_seq (bind, olist);
11279 pop_gimplify_context (NULL);
11281 if (dep_bind)
11283 gimple_bind_add_seq (dep_bind, dep_ilist);
11284 gimple_bind_add_stmt (dep_bind, bind);
11285 gimple_bind_add_seq (dep_bind, dep_olist);
11286 pop_gimplify_context (dep_bind);
11290 /* Lower the GIMPLE_OMP_TARGET in the current statement
11291 in GSI_P. CTX holds context information for the directive. */
11293 static void
11294 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11296 tree clauses;
11297 tree child_fn, t, c;
11298 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11299 gbind *tgt_bind, *bind;
11300 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11301 location_t loc = gimple_location (stmt);
11302 bool offloaded, data_region;
11303 unsigned int map_cnt = 0;
11305 offloaded = is_gimple_omp_offloaded (stmt);
11306 switch (gimple_omp_target_kind (stmt))
11308 case GF_OMP_TARGET_KIND_REGION:
11309 case GF_OMP_TARGET_KIND_UPDATE:
11310 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11311 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11312 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11313 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11314 data_region = false;
11315 break;
11316 case GF_OMP_TARGET_KIND_DATA:
11317 case GF_OMP_TARGET_KIND_OACC_DATA:
11318 data_region = true;
11319 break;
11320 default:
11321 gcc_unreachable ();
11324 clauses = gimple_omp_target_clauses (stmt);
11326 tgt_bind = NULL;
11327 tgt_body = NULL;
11328 if (offloaded)
11330 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11331 tgt_body = gimple_bind_body (tgt_bind);
11333 else if (data_region)
11334 tgt_body = gimple_omp_body (stmt);
11335 child_fn = ctx->cb.dst_fn;
11337 push_gimplify_context ();
11339 irlist = NULL;
11340 orlist = NULL;
11341 if (offloaded
11342 && is_gimple_omp_oacc (stmt))
11343 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11345 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11346 switch (OMP_CLAUSE_CODE (c))
11348 tree var, x;
11350 default:
11351 break;
11352 case OMP_CLAUSE_MAP:
11353 #ifdef ENABLE_CHECKING
11354 /* First check what we're prepared to handle in the following. */
11355 switch (OMP_CLAUSE_MAP_KIND (c))
11357 case GOMP_MAP_ALLOC:
11358 case GOMP_MAP_TO:
11359 case GOMP_MAP_FROM:
11360 case GOMP_MAP_TOFROM:
11361 case GOMP_MAP_POINTER:
11362 case GOMP_MAP_TO_PSET:
11363 break;
11364 case GOMP_MAP_FORCE_ALLOC:
11365 case GOMP_MAP_FORCE_TO:
11366 case GOMP_MAP_FORCE_FROM:
11367 case GOMP_MAP_FORCE_TOFROM:
11368 case GOMP_MAP_FORCE_PRESENT:
11369 case GOMP_MAP_FORCE_DEALLOC:
11370 case GOMP_MAP_FORCE_DEVICEPTR:
11371 gcc_assert (is_gimple_omp_oacc (stmt));
11372 break;
11373 default:
11374 gcc_unreachable ();
11376 #endif
11377 /* FALLTHRU */
11378 case OMP_CLAUSE_TO:
11379 case OMP_CLAUSE_FROM:
11380 var = OMP_CLAUSE_DECL (c);
11381 if (!DECL_P (var))
11383 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11384 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11385 map_cnt++;
11386 continue;
11389 if (DECL_SIZE (var)
11390 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11392 tree var2 = DECL_VALUE_EXPR (var);
11393 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11394 var2 = TREE_OPERAND (var2, 0);
11395 gcc_assert (DECL_P (var2));
11396 var = var2;
11399 if (!maybe_lookup_field (var, ctx))
11400 continue;
11402 if (offloaded)
11404 x = build_receiver_ref (var, true, ctx);
11405 tree new_var = lookup_decl (var, ctx);
11406 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11407 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11408 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11409 x = build_simple_mem_ref (x);
11410 SET_DECL_VALUE_EXPR (new_var, x);
11411 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11413 map_cnt++;
11416 if (offloaded)
11418 target_nesting_level++;
11419 lower_omp (&tgt_body, ctx);
11420 target_nesting_level--;
11422 else if (data_region)
11423 lower_omp (&tgt_body, ctx);
11425 if (offloaded)
11427 /* Declare all the variables created by mapping and the variables
11428 declared in the scope of the target body. */
11429 record_vars_into (ctx->block_vars, child_fn);
11430 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11433 olist = NULL;
11434 ilist = NULL;
11435 if (ctx->record_type)
11437 ctx->sender_decl
11438 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11439 DECL_NAMELESS (ctx->sender_decl) = 1;
11440 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11441 t = make_tree_vec (3);
11442 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11443 TREE_VEC_ELT (t, 1)
11444 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11445 ".omp_data_sizes");
11446 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11447 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11448 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11449 tree tkind_type;
11450 int talign_shift;
11451 if (is_gimple_omp_oacc (stmt))
11453 tkind_type = short_unsigned_type_node;
11454 talign_shift = 8;
11456 else
11458 tkind_type = unsigned_char_type_node;
11459 talign_shift = 3;
11461 TREE_VEC_ELT (t, 2)
11462 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11463 ".omp_data_kinds");
11464 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11465 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11466 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11467 gimple_omp_target_set_data_arg (stmt, t);
11469 vec<constructor_elt, va_gc> *vsize;
11470 vec<constructor_elt, va_gc> *vkind;
11471 vec_alloc (vsize, map_cnt);
11472 vec_alloc (vkind, map_cnt);
11473 unsigned int map_idx = 0;
11475 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11476 switch (OMP_CLAUSE_CODE (c))
11478 tree ovar, nc;
11480 default:
11481 break;
11482 case OMP_CLAUSE_MAP:
11483 case OMP_CLAUSE_TO:
11484 case OMP_CLAUSE_FROM:
11485 nc = c;
11486 ovar = OMP_CLAUSE_DECL (c);
11487 if (!DECL_P (ovar))
11489 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11490 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11492 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11493 == get_base_address (ovar));
11494 nc = OMP_CLAUSE_CHAIN (c);
11495 ovar = OMP_CLAUSE_DECL (nc);
11497 else
11499 tree x = build_sender_ref (ovar, ctx);
11500 tree v
11501 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11502 gimplify_assign (x, v, &ilist);
11503 nc = NULL_TREE;
11506 else
11508 if (DECL_SIZE (ovar)
11509 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11511 tree ovar2 = DECL_VALUE_EXPR (ovar);
11512 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11513 ovar2 = TREE_OPERAND (ovar2, 0);
11514 gcc_assert (DECL_P (ovar2));
11515 ovar = ovar2;
11517 if (!maybe_lookup_field (ovar, ctx))
11518 continue;
11521 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11522 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11523 talign = DECL_ALIGN_UNIT (ovar);
11524 if (nc)
11526 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11527 tree x = build_sender_ref (ovar, ctx);
11528 if (maybe_lookup_oacc_reduction (var, ctx))
11530 gcc_checking_assert (offloaded
11531 && is_gimple_omp_oacc (stmt));
11532 gimplify_assign (x, var, &ilist);
11534 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11535 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11536 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11537 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11539 gcc_assert (offloaded);
11540 tree avar
11541 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11542 mark_addressable (avar);
11543 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11544 talign = DECL_ALIGN_UNIT (avar);
11545 avar = build_fold_addr_expr (avar);
11546 gimplify_assign (x, avar, &ilist);
11548 else if (is_gimple_reg (var))
11550 gcc_assert (offloaded);
11551 tree avar = create_tmp_var (TREE_TYPE (var));
11552 mark_addressable (avar);
11553 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11554 if (GOMP_MAP_COPY_TO_P (map_kind)
11555 || map_kind == GOMP_MAP_POINTER
11556 || map_kind == GOMP_MAP_TO_PSET
11557 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11558 gimplify_assign (avar, var, &ilist);
11559 avar = build_fold_addr_expr (avar);
11560 gimplify_assign (x, avar, &ilist);
11561 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11562 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11563 && !TYPE_READONLY (TREE_TYPE (var)))
11565 x = build_sender_ref (ovar, ctx);
11566 x = build_simple_mem_ref (x);
11567 gimplify_assign (var, x, &olist);
11570 else
11572 var = build_fold_addr_expr (var);
11573 gimplify_assign (x, var, &ilist);
11576 tree s = OMP_CLAUSE_SIZE (c);
11577 if (s == NULL_TREE)
11578 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11579 s = fold_convert (size_type_node, s);
11580 tree purpose = size_int (map_idx++);
11581 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11582 if (TREE_CODE (s) != INTEGER_CST)
11583 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11585 unsigned HOST_WIDE_INT tkind;
11586 switch (OMP_CLAUSE_CODE (c))
11588 case OMP_CLAUSE_MAP:
11589 tkind = OMP_CLAUSE_MAP_KIND (c);
11590 break;
11591 case OMP_CLAUSE_TO:
11592 tkind = GOMP_MAP_TO;
11593 break;
11594 case OMP_CLAUSE_FROM:
11595 tkind = GOMP_MAP_FROM;
11596 break;
11597 default:
11598 gcc_unreachable ();
11600 gcc_checking_assert (tkind
11601 < (HOST_WIDE_INT_C (1U) << talign_shift));
11602 talign = ceil_log2 (talign);
11603 tkind |= talign << talign_shift;
11604 gcc_checking_assert (tkind
11605 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11606 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11607 build_int_cstu (tkind_type, tkind));
11608 if (nc && nc != c)
11609 c = nc;
11612 gcc_assert (map_idx == map_cnt);
11614 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11615 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11616 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11617 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11618 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11620 gimple_seq initlist = NULL;
11621 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11622 TREE_VEC_ELT (t, 1)),
11623 &initlist, true, NULL_TREE);
11624 gimple_seq_add_seq (&ilist, initlist);
11626 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11627 NULL);
11628 TREE_THIS_VOLATILE (clobber) = 1;
11629 gimple_seq_add_stmt (&olist,
11630 gimple_build_assign (TREE_VEC_ELT (t, 1),
11631 clobber));
11634 tree clobber = build_constructor (ctx->record_type, NULL);
11635 TREE_THIS_VOLATILE (clobber) = 1;
11636 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11637 clobber));
11640 /* Once all the expansions are done, sequence all the different
11641 fragments inside gimple_omp_body. */
11643 new_body = NULL;
11645 if (offloaded
11646 && ctx->record_type)
11648 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11649 /* fixup_child_record_type might have changed receiver_decl's type. */
11650 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11651 gimple_seq_add_stmt (&new_body,
11652 gimple_build_assign (ctx->receiver_decl, t));
11655 if (offloaded)
11657 gimple_seq_add_seq (&new_body, tgt_body);
11658 new_body = maybe_catch_exception (new_body);
11660 else if (data_region)
11661 new_body = tgt_body;
11662 if (offloaded || data_region)
11664 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11665 gimple_omp_set_body (stmt, new_body);
11668 bind = gimple_build_bind (NULL, NULL,
11669 tgt_bind ? gimple_bind_block (tgt_bind)
11670 : NULL_TREE);
11671 gsi_replace (gsi_p, bind, true);
11672 gimple_bind_add_seq (bind, irlist);
11673 gimple_bind_add_seq (bind, ilist);
11674 gimple_bind_add_stmt (bind, stmt);
11675 gimple_bind_add_seq (bind, olist);
11676 gimple_bind_add_seq (bind, orlist);
11678 pop_gimplify_context (NULL);
11681 /* Expand code for an OpenMP teams directive. */
11683 static void
11684 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11686 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11687 push_gimplify_context ();
11689 tree block = make_node (BLOCK);
11690 gbind *bind = gimple_build_bind (NULL, NULL, block);
11691 gsi_replace (gsi_p, bind, true);
11692 gimple_seq bind_body = NULL;
11693 gimple_seq dlist = NULL;
11694 gimple_seq olist = NULL;
11696 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11697 OMP_CLAUSE_NUM_TEAMS);
11698 if (num_teams == NULL_TREE)
11699 num_teams = build_int_cst (unsigned_type_node, 0);
11700 else
11702 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11703 num_teams = fold_convert (unsigned_type_node, num_teams);
11704 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11706 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11707 OMP_CLAUSE_THREAD_LIMIT);
11708 if (thread_limit == NULL_TREE)
11709 thread_limit = build_int_cst (unsigned_type_node, 0);
11710 else
11712 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11713 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11714 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11715 fb_rvalue);
11718 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11719 &bind_body, &dlist, ctx, NULL);
11720 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11721 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11722 gimple_seq_add_stmt (&bind_body, teams_stmt);
11724 location_t loc = gimple_location (teams_stmt);
11725 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11726 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11727 gimple_set_location (call, loc);
11728 gimple_seq_add_stmt (&bind_body, call);
11730 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11731 gimple_omp_set_body (teams_stmt, NULL);
11732 gimple_seq_add_seq (&bind_body, olist);
11733 gimple_seq_add_seq (&bind_body, dlist);
11734 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11735 gimple_bind_set_body (bind, bind_body);
11737 pop_gimplify_context (bind);
11739 gimple_bind_append_vars (bind, ctx->block_vars);
11740 BLOCK_VARS (block) = ctx->block_vars;
11741 if (BLOCK_VARS (block))
11742 TREE_USED (block) = 1;
11746 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11747 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11748 of OMP context, but with task_shared_vars set. */
11750 static tree
11751 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11752 void *data)
11754 tree t = *tp;
11756 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11757 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11758 return t;
11760 if (task_shared_vars
11761 && DECL_P (t)
11762 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11763 return t;
11765 /* If a global variable has been privatized, TREE_CONSTANT on
11766 ADDR_EXPR might be wrong. */
11767 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11768 recompute_tree_invariant_for_addr_expr (t);
11770 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11771 return NULL_TREE;
11774 static void
11775 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11777 gimple stmt = gsi_stmt (*gsi_p);
11778 struct walk_stmt_info wi;
11779 gcall *call_stmt;
11781 if (gimple_has_location (stmt))
11782 input_location = gimple_location (stmt);
11784 if (task_shared_vars)
11785 memset (&wi, '\0', sizeof (wi));
11787 /* If we have issued syntax errors, avoid doing any heavy lifting.
11788 Just replace the OMP directives with a NOP to avoid
11789 confusing RTL expansion. */
11790 if (seen_error () && is_gimple_omp (stmt))
11792 gsi_replace (gsi_p, gimple_build_nop (), true);
11793 return;
11796 switch (gimple_code (stmt))
11798 case GIMPLE_COND:
11800 gcond *cond_stmt = as_a <gcond *> (stmt);
11801 if ((ctx || task_shared_vars)
11802 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11803 lower_omp_regimplify_p,
11804 ctx ? NULL : &wi, NULL)
11805 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11806 lower_omp_regimplify_p,
11807 ctx ? NULL : &wi, NULL)))
11808 gimple_regimplify_operands (cond_stmt, gsi_p);
11810 break;
11811 case GIMPLE_CATCH:
11812 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
11813 break;
11814 case GIMPLE_EH_FILTER:
11815 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
11816 break;
11817 case GIMPLE_TRY:
11818 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11819 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
11820 break;
11821 case GIMPLE_TRANSACTION:
11822 lower_omp (gimple_transaction_body_ptr (
11823 as_a <gtransaction *> (stmt)),
11824 ctx);
11825 break;
11826 case GIMPLE_BIND:
11827 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
11828 break;
11829 case GIMPLE_OMP_PARALLEL:
11830 case GIMPLE_OMP_TASK:
11831 ctx = maybe_lookup_ctx (stmt);
11832 gcc_assert (ctx);
11833 if (ctx->cancellable)
11834 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11835 lower_omp_taskreg (gsi_p, ctx);
11836 break;
11837 case GIMPLE_OMP_FOR:
11838 ctx = maybe_lookup_ctx (stmt);
11839 gcc_assert (ctx);
11840 if (ctx->cancellable)
11841 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11842 lower_omp_for (gsi_p, ctx);
11843 break;
11844 case GIMPLE_OMP_SECTIONS:
11845 ctx = maybe_lookup_ctx (stmt);
11846 gcc_assert (ctx);
11847 if (ctx->cancellable)
11848 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11849 lower_omp_sections (gsi_p, ctx);
11850 break;
11851 case GIMPLE_OMP_SINGLE:
11852 ctx = maybe_lookup_ctx (stmt);
11853 gcc_assert (ctx);
11854 lower_omp_single (gsi_p, ctx);
11855 break;
11856 case GIMPLE_OMP_MASTER:
11857 ctx = maybe_lookup_ctx (stmt);
11858 gcc_assert (ctx);
11859 lower_omp_master (gsi_p, ctx);
11860 break;
11861 case GIMPLE_OMP_TASKGROUP:
11862 ctx = maybe_lookup_ctx (stmt);
11863 gcc_assert (ctx);
11864 lower_omp_taskgroup (gsi_p, ctx);
11865 break;
11866 case GIMPLE_OMP_ORDERED:
11867 ctx = maybe_lookup_ctx (stmt);
11868 gcc_assert (ctx);
11869 lower_omp_ordered (gsi_p, ctx);
11870 break;
11871 case GIMPLE_OMP_CRITICAL:
11872 ctx = maybe_lookup_ctx (stmt);
11873 gcc_assert (ctx);
11874 lower_omp_critical (gsi_p, ctx);
11875 break;
11876 case GIMPLE_OMP_ATOMIC_LOAD:
11877 if ((ctx || task_shared_vars)
11878 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11879 as_a <gomp_atomic_load *> (stmt)),
11880 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11881 gimple_regimplify_operands (stmt, gsi_p);
11882 break;
11883 case GIMPLE_OMP_TARGET:
11884 ctx = maybe_lookup_ctx (stmt);
11885 gcc_assert (ctx);
11886 lower_omp_target (gsi_p, ctx);
11887 break;
11888 case GIMPLE_OMP_TEAMS:
11889 ctx = maybe_lookup_ctx (stmt);
11890 gcc_assert (ctx);
11891 lower_omp_teams (gsi_p, ctx);
11892 break;
11893 case GIMPLE_CALL:
11894 tree fndecl;
11895 call_stmt = as_a <gcall *> (stmt);
11896 fndecl = gimple_call_fndecl (call_stmt);
11897 if (fndecl
11898 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11899 switch (DECL_FUNCTION_CODE (fndecl))
11901 case BUILT_IN_GOMP_BARRIER:
11902 if (ctx == NULL)
11903 break;
11904 /* FALLTHRU */
11905 case BUILT_IN_GOMP_CANCEL:
11906 case BUILT_IN_GOMP_CANCELLATION_POINT:
11907 omp_context *cctx;
11908 cctx = ctx;
11909 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11910 cctx = cctx->outer;
11911 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
11912 if (!cctx->cancellable)
11914 if (DECL_FUNCTION_CODE (fndecl)
11915 == BUILT_IN_GOMP_CANCELLATION_POINT)
11917 stmt = gimple_build_nop ();
11918 gsi_replace (gsi_p, stmt, false);
11920 break;
11922 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11924 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
11925 gimple_call_set_fndecl (call_stmt, fndecl);
11926 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
11928 tree lhs;
11929 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
11930 gimple_call_set_lhs (call_stmt, lhs);
11931 tree fallthru_label;
11932 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11933 gimple g;
11934 g = gimple_build_label (fallthru_label);
11935 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11936 g = gimple_build_cond (NE_EXPR, lhs,
11937 fold_convert (TREE_TYPE (lhs),
11938 boolean_false_node),
11939 cctx->cancel_label, fallthru_label);
11940 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11941 break;
11942 default:
11943 break;
11945 /* FALLTHRU */
11946 default:
11947 if ((ctx || task_shared_vars)
11948 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11949 ctx ? NULL : &wi))
11951 /* Just remove clobbers, this should happen only if we have
11952 "privatized" local addressable variables in SIMD regions,
11953 the clobber isn't needed in that case and gimplifying address
11954 of the ARRAY_REF into a pointer and creating MEM_REF based
11955 clobber would create worse code than we get with the clobber
11956 dropped. */
11957 if (gimple_clobber_p (stmt))
11959 gsi_replace (gsi_p, gimple_build_nop (), true);
11960 break;
11962 gimple_regimplify_operands (stmt, gsi_p);
11964 break;
11968 static void
11969 lower_omp (gimple_seq *body, omp_context *ctx)
11971 location_t saved_location = input_location;
11972 gimple_stmt_iterator gsi;
11973 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11974 lower_omp_1 (&gsi, ctx);
11975 /* During gimplification, we haven't folded statments inside offloading
11976 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
11977 if (target_nesting_level || taskreg_nesting_level)
11978 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11979 fold_stmt (&gsi);
11980 input_location = saved_location;
11983 /* Main entry point. */
11985 static unsigned int
11986 execute_lower_omp (void)
11988 gimple_seq body;
11989 int i;
11990 omp_context *ctx;
11992 /* This pass always runs, to provide PROP_gimple_lomp.
11993 But often, there is nothing to do. */
11994 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11995 && flag_openmp_simd == 0)
11996 return 0;
11998 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11999 delete_omp_context);
12001 body = gimple_body (current_function_decl);
12002 scan_omp (&body, NULL);
12003 gcc_assert (taskreg_nesting_level == 0);
12004 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
12005 finish_taskreg_scan (ctx);
12006 taskreg_contexts.release ();
12008 if (all_contexts->root)
12010 if (task_shared_vars)
12011 push_gimplify_context ();
12012 lower_omp (&body, NULL);
12013 if (task_shared_vars)
12014 pop_gimplify_context (NULL);
12017 if (all_contexts)
12019 splay_tree_delete (all_contexts);
12020 all_contexts = NULL;
12022 BITMAP_FREE (task_shared_vars);
12023 return 0;
12026 namespace {
12028 const pass_data pass_data_lower_omp =
12030 GIMPLE_PASS, /* type */
12031 "omplower", /* name */
12032 OPTGROUP_NONE, /* optinfo_flags */
12033 TV_NONE, /* tv_id */
12034 PROP_gimple_any, /* properties_required */
12035 PROP_gimple_lomp, /* properties_provided */
12036 0, /* properties_destroyed */
12037 0, /* todo_flags_start */
12038 0, /* todo_flags_finish */
12041 class pass_lower_omp : public gimple_opt_pass
12043 public:
12044 pass_lower_omp (gcc::context *ctxt)
12045 : gimple_opt_pass (pass_data_lower_omp, ctxt)
12048 /* opt_pass methods: */
12049 virtual unsigned int execute (function *) { return execute_lower_omp (); }
12051 }; // class pass_lower_omp
12053 } // anon namespace
12055 gimple_opt_pass *
12056 make_pass_lower_omp (gcc::context *ctxt)
12058 return new pass_lower_omp (ctxt);
12061 /* The following is a utility to diagnose structured block violations.
12062 It is not part of the "omplower" pass, as that's invoked too late. It
12063 should be invoked by the respective front ends after gimplification. */
12065 static splay_tree all_labels;
12067 /* Check for mismatched contexts and generate an error if needed. Return
12068 true if an error is detected. */
12070 static bool
12071 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
12072 gimple branch_ctx, gimple label_ctx)
12074 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
12075 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
12077 if (label_ctx == branch_ctx)
12078 return false;
12080 const char* kind = NULL;
12082 if (flag_cilkplus)
12084 if ((branch_ctx
12085 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12086 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12087 || (label_ctx
12088 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12089 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12090 kind = "Cilk Plus";
12092 if (flag_openacc)
12094 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
12095 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
12097 gcc_checking_assert (kind == NULL);
12098 kind = "OpenACC";
12101 if (kind == NULL)
12103 gcc_checking_assert (flag_openmp);
12104 kind = "OpenMP";
12108 Previously we kept track of the label's entire context in diagnose_sb_[12]
12109 so we could traverse it and issue a correct "exit" or "enter" error
12110 message upon a structured block violation.
12112 We built the context by building a list with tree_cons'ing, but there is
12113 no easy counterpart in gimple tuples. It seems like far too much work
12114 for issuing exit/enter error messages. If someone really misses the
12115 distinct error message... patches welcome.
12118 #if 0
12119 /* Try to avoid confusing the user by producing and error message
12120 with correct "exit" or "enter" verbiage. We prefer "exit"
12121 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12122 if (branch_ctx == NULL)
12123 exit_p = false;
12124 else
12126 while (label_ctx)
12128 if (TREE_VALUE (label_ctx) == branch_ctx)
12130 exit_p = false;
12131 break;
12133 label_ctx = TREE_CHAIN (label_ctx);
12137 if (exit_p)
12138 error ("invalid exit from %s structured block", kind);
12139 else
12140 error ("invalid entry to %s structured block", kind);
12141 #endif
12143 /* If it's obvious we have an invalid entry, be specific about the error. */
12144 if (branch_ctx == NULL)
12145 error ("invalid entry to %s structured block", kind);
12146 else
12148 /* Otherwise, be vague and lazy, but efficient. */
12149 error ("invalid branch to/from %s structured block", kind);
12152 gsi_replace (gsi_p, gimple_build_nop (), false);
12153 return true;
12156 /* Pass 1: Create a minimal tree of structured blocks, and record
12157 where each label is found. */
12159 static tree
12160 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12161 struct walk_stmt_info *wi)
12163 gimple context = (gimple) wi->info;
12164 gimple inner_context;
12165 gimple stmt = gsi_stmt (*gsi_p);
12167 *handled_ops_p = true;
12169 switch (gimple_code (stmt))
12171 WALK_SUBSTMTS;
12173 case GIMPLE_OMP_PARALLEL:
12174 case GIMPLE_OMP_TASK:
12175 case GIMPLE_OMP_SECTIONS:
12176 case GIMPLE_OMP_SINGLE:
12177 case GIMPLE_OMP_SECTION:
12178 case GIMPLE_OMP_MASTER:
12179 case GIMPLE_OMP_ORDERED:
12180 case GIMPLE_OMP_CRITICAL:
12181 case GIMPLE_OMP_TARGET:
12182 case GIMPLE_OMP_TEAMS:
12183 case GIMPLE_OMP_TASKGROUP:
12184 /* The minimal context here is just the current OMP construct. */
12185 inner_context = stmt;
12186 wi->info = inner_context;
12187 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12188 wi->info = context;
12189 break;
12191 case GIMPLE_OMP_FOR:
12192 inner_context = stmt;
12193 wi->info = inner_context;
12194 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12195 walk them. */
12196 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12197 diagnose_sb_1, NULL, wi);
12198 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12199 wi->info = context;
12200 break;
12202 case GIMPLE_LABEL:
12203 splay_tree_insert (all_labels,
12204 (splay_tree_key) gimple_label_label (
12205 as_a <glabel *> (stmt)),
12206 (splay_tree_value) context);
12207 break;
12209 default:
12210 break;
12213 return NULL_TREE;
12216 /* Pass 2: Check each branch and see if its context differs from that of
12217 the destination label's context. */
12219 static tree
12220 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12221 struct walk_stmt_info *wi)
12223 gimple context = (gimple) wi->info;
12224 splay_tree_node n;
12225 gimple stmt = gsi_stmt (*gsi_p);
12227 *handled_ops_p = true;
12229 switch (gimple_code (stmt))
12231 WALK_SUBSTMTS;
12233 case GIMPLE_OMP_PARALLEL:
12234 case GIMPLE_OMP_TASK:
12235 case GIMPLE_OMP_SECTIONS:
12236 case GIMPLE_OMP_SINGLE:
12237 case GIMPLE_OMP_SECTION:
12238 case GIMPLE_OMP_MASTER:
12239 case GIMPLE_OMP_ORDERED:
12240 case GIMPLE_OMP_CRITICAL:
12241 case GIMPLE_OMP_TARGET:
12242 case GIMPLE_OMP_TEAMS:
12243 case GIMPLE_OMP_TASKGROUP:
12244 wi->info = stmt;
12245 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12246 wi->info = context;
12247 break;
12249 case GIMPLE_OMP_FOR:
12250 wi->info = stmt;
12251 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12252 walk them. */
12253 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12254 diagnose_sb_2, NULL, wi);
12255 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12256 wi->info = context;
12257 break;
12259 case GIMPLE_COND:
12261 gcond *cond_stmt = as_a <gcond *> (stmt);
12262 tree lab = gimple_cond_true_label (cond_stmt);
12263 if (lab)
12265 n = splay_tree_lookup (all_labels,
12266 (splay_tree_key) lab);
12267 diagnose_sb_0 (gsi_p, context,
12268 n ? (gimple) n->value : NULL);
12270 lab = gimple_cond_false_label (cond_stmt);
12271 if (lab)
12273 n = splay_tree_lookup (all_labels,
12274 (splay_tree_key) lab);
12275 diagnose_sb_0 (gsi_p, context,
12276 n ? (gimple) n->value : NULL);
12279 break;
12281 case GIMPLE_GOTO:
12283 tree lab = gimple_goto_dest (stmt);
12284 if (TREE_CODE (lab) != LABEL_DECL)
12285 break;
12287 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12288 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
12290 break;
12292 case GIMPLE_SWITCH:
12294 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12295 unsigned int i;
12296 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12298 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12299 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12300 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
12301 break;
12304 break;
12306 case GIMPLE_RETURN:
12307 diagnose_sb_0 (gsi_p, context, NULL);
12308 break;
12310 default:
12311 break;
12314 return NULL_TREE;
12317 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12318 GIMPLE_* codes. */
12319 bool
12320 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12321 int *region_idx)
12323 gimple last = last_stmt (bb);
12324 enum gimple_code code = gimple_code (last);
12325 struct omp_region *cur_region = *region;
12326 bool fallthru = false;
12328 switch (code)
12330 case GIMPLE_OMP_PARALLEL:
12331 case GIMPLE_OMP_TASK:
12332 case GIMPLE_OMP_FOR:
12333 case GIMPLE_OMP_SINGLE:
12334 case GIMPLE_OMP_TEAMS:
12335 case GIMPLE_OMP_MASTER:
12336 case GIMPLE_OMP_TASKGROUP:
12337 case GIMPLE_OMP_ORDERED:
12338 case GIMPLE_OMP_CRITICAL:
12339 case GIMPLE_OMP_SECTION:
12340 cur_region = new_omp_region (bb, code, cur_region);
12341 fallthru = true;
12342 break;
12344 case GIMPLE_OMP_TARGET:
12345 cur_region = new_omp_region (bb, code, cur_region);
12346 fallthru = true;
12347 switch (gimple_omp_target_kind (last))
12349 case GF_OMP_TARGET_KIND_REGION:
12350 case GF_OMP_TARGET_KIND_DATA:
12351 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12352 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12353 case GF_OMP_TARGET_KIND_OACC_DATA:
12354 break;
12355 case GF_OMP_TARGET_KIND_UPDATE:
12356 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12357 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12358 cur_region = cur_region->outer;
12359 break;
12360 default:
12361 gcc_unreachable ();
12363 break;
12365 case GIMPLE_OMP_SECTIONS:
12366 cur_region = new_omp_region (bb, code, cur_region);
12367 fallthru = true;
12368 break;
12370 case GIMPLE_OMP_SECTIONS_SWITCH:
12371 fallthru = false;
12372 break;
12374 case GIMPLE_OMP_ATOMIC_LOAD:
12375 case GIMPLE_OMP_ATOMIC_STORE:
12376 fallthru = true;
12377 break;
12379 case GIMPLE_OMP_RETURN:
12380 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12381 somewhere other than the next block. This will be
12382 created later. */
12383 cur_region->exit = bb;
12384 if (cur_region->type == GIMPLE_OMP_TASK)
12385 /* Add an edge corresponding to not scheduling the task
12386 immediately. */
12387 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
12388 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12389 cur_region = cur_region->outer;
12390 break;
12392 case GIMPLE_OMP_CONTINUE:
12393 cur_region->cont = bb;
12394 switch (cur_region->type)
12396 case GIMPLE_OMP_FOR:
12397 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12398 succs edges as abnormal to prevent splitting
12399 them. */
12400 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12401 /* Make the loopback edge. */
12402 make_edge (bb, single_succ (cur_region->entry),
12403 EDGE_ABNORMAL);
12405 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12406 corresponds to the case that the body of the loop
12407 is not executed at all. */
12408 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12409 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12410 fallthru = false;
12411 break;
12413 case GIMPLE_OMP_SECTIONS:
12414 /* Wire up the edges into and out of the nested sections. */
12416 basic_block switch_bb = single_succ (cur_region->entry);
12418 struct omp_region *i;
12419 for (i = cur_region->inner; i ; i = i->next)
12421 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12422 make_edge (switch_bb, i->entry, 0);
12423 make_edge (i->exit, bb, EDGE_FALLTHRU);
12426 /* Make the loopback edge to the block with
12427 GIMPLE_OMP_SECTIONS_SWITCH. */
12428 make_edge (bb, switch_bb, 0);
12430 /* Make the edge from the switch to exit. */
12431 make_edge (switch_bb, bb->next_bb, 0);
12432 fallthru = false;
12434 break;
12436 case GIMPLE_OMP_TASK:
12437 fallthru = true;
12438 break;
12440 default:
12441 gcc_unreachable ();
12443 break;
12445 default:
12446 gcc_unreachable ();
12449 if (*region != cur_region)
12451 *region = cur_region;
12452 if (cur_region)
12453 *region_idx = cur_region->entry->index;
12454 else
12455 *region_idx = 0;
12458 return fallthru;
12461 static unsigned int
12462 diagnose_omp_structured_block_errors (void)
12464 struct walk_stmt_info wi;
12465 gimple_seq body = gimple_body (current_function_decl);
12467 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12469 memset (&wi, 0, sizeof (wi));
12470 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12472 memset (&wi, 0, sizeof (wi));
12473 wi.want_locations = true;
12474 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12476 gimple_set_body (current_function_decl, body);
12478 splay_tree_delete (all_labels);
12479 all_labels = NULL;
12481 return 0;
12484 namespace {
12486 const pass_data pass_data_diagnose_omp_blocks =
12488 GIMPLE_PASS, /* type */
12489 "*diagnose_omp_blocks", /* name */
12490 OPTGROUP_NONE, /* optinfo_flags */
12491 TV_NONE, /* tv_id */
12492 PROP_gimple_any, /* properties_required */
12493 0, /* properties_provided */
12494 0, /* properties_destroyed */
12495 0, /* todo_flags_start */
12496 0, /* todo_flags_finish */
12499 class pass_diagnose_omp_blocks : public gimple_opt_pass
12501 public:
12502 pass_diagnose_omp_blocks (gcc::context *ctxt)
12503 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12506 /* opt_pass methods: */
12507 virtual bool gate (function *)
12509 return flag_cilkplus || flag_openacc || flag_openmp;
12511 virtual unsigned int execute (function *)
12513 return diagnose_omp_structured_block_errors ();
12516 }; // class pass_diagnose_omp_blocks
12518 } // anon namespace
12520 gimple_opt_pass *
12521 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12523 return new pass_diagnose_omp_blocks (ctxt);
12526 /* SIMD clone supporting code. */
12528 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12529 of arguments to reserve space for. */
12531 static struct cgraph_simd_clone *
12532 simd_clone_struct_alloc (int nargs)
12534 struct cgraph_simd_clone *clone_info;
12535 size_t len = (sizeof (struct cgraph_simd_clone)
12536 + nargs * sizeof (struct cgraph_simd_clone_arg));
12537 clone_info = (struct cgraph_simd_clone *)
12538 ggc_internal_cleared_alloc (len);
12539 return clone_info;
12542 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12544 static inline void
12545 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12546 struct cgraph_simd_clone *from)
12548 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12549 + ((from->nargs - from->inbranch)
12550 * sizeof (struct cgraph_simd_clone_arg))));
12553 /* Return vector of parameter types of function FNDECL. This uses
12554 TYPE_ARG_TYPES if available, otherwise falls back to types of
12555 DECL_ARGUMENTS types. */
12557 vec<tree>
12558 simd_clone_vector_of_formal_parm_types (tree fndecl)
12560 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12561 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12562 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12563 unsigned int i;
12564 tree arg;
12565 FOR_EACH_VEC_ELT (args, i, arg)
12566 args[i] = TREE_TYPE (args[i]);
12567 return args;
12570 /* Given a simd function in NODE, extract the simd specific
12571 information from the OMP clauses passed in CLAUSES, and return
12572 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12573 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12574 otherwise set to FALSE. */
12576 static struct cgraph_simd_clone *
12577 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12578 bool *inbranch_specified)
12580 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12581 tree t;
12582 int n;
12583 *inbranch_specified = false;
12585 n = args.length ();
12586 if (n > 0 && args.last () == void_type_node)
12587 n--;
12589 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12590 be cloned have a distinctive artificial label in addition to "omp
12591 declare simd". */
12592 bool cilk_clone
12593 = (flag_cilkplus
12594 && lookup_attribute ("cilk simd function",
12595 DECL_ATTRIBUTES (node->decl)));
12597 /* Allocate one more than needed just in case this is an in-branch
12598 clone which will require a mask argument. */
12599 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12600 clone_info->nargs = n;
12601 clone_info->cilk_elemental = cilk_clone;
12603 if (!clauses)
12605 args.release ();
12606 return clone_info;
12608 clauses = TREE_VALUE (clauses);
12609 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12610 return clone_info;
12612 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12614 switch (OMP_CLAUSE_CODE (t))
12616 case OMP_CLAUSE_INBRANCH:
12617 clone_info->inbranch = 1;
12618 *inbranch_specified = true;
12619 break;
12620 case OMP_CLAUSE_NOTINBRANCH:
12621 clone_info->inbranch = 0;
12622 *inbranch_specified = true;
12623 break;
12624 case OMP_CLAUSE_SIMDLEN:
12625 clone_info->simdlen
12626 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12627 break;
12628 case OMP_CLAUSE_LINEAR:
12630 tree decl = OMP_CLAUSE_DECL (t);
12631 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12632 int argno = TREE_INT_CST_LOW (decl);
12633 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12635 clone_info->args[argno].arg_type
12636 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12637 clone_info->args[argno].linear_step = tree_to_shwi (step);
12638 gcc_assert (clone_info->args[argno].linear_step >= 0
12639 && clone_info->args[argno].linear_step < n);
12641 else
12643 if (POINTER_TYPE_P (args[argno]))
12644 step = fold_convert (ssizetype, step);
12645 if (!tree_fits_shwi_p (step))
12647 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12648 "ignoring large linear step");
12649 args.release ();
12650 return NULL;
12652 else if (integer_zerop (step))
12654 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12655 "ignoring zero linear step");
12656 args.release ();
12657 return NULL;
12659 else
12661 clone_info->args[argno].arg_type
12662 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12663 clone_info->args[argno].linear_step = tree_to_shwi (step);
12666 break;
12668 case OMP_CLAUSE_UNIFORM:
12670 tree decl = OMP_CLAUSE_DECL (t);
12671 int argno = tree_to_uhwi (decl);
12672 clone_info->args[argno].arg_type
12673 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12674 break;
12676 case OMP_CLAUSE_ALIGNED:
12678 tree decl = OMP_CLAUSE_DECL (t);
12679 int argno = tree_to_uhwi (decl);
12680 clone_info->args[argno].alignment
12681 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12682 break;
12684 default:
12685 break;
12688 args.release ();
12689 return clone_info;
12692 /* Given a SIMD clone in NODE, calculate the characteristic data
12693 type and return the coresponding type. The characteristic data
12694 type is computed as described in the Intel Vector ABI. */
12696 static tree
12697 simd_clone_compute_base_data_type (struct cgraph_node *node,
12698 struct cgraph_simd_clone *clone_info)
12700 tree type = integer_type_node;
12701 tree fndecl = node->decl;
12703 /* a) For non-void function, the characteristic data type is the
12704 return type. */
12705 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12706 type = TREE_TYPE (TREE_TYPE (fndecl));
12708 /* b) If the function has any non-uniform, non-linear parameters,
12709 then the characteristic data type is the type of the first
12710 such parameter. */
12711 else
12713 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12714 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12715 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12717 type = map[i];
12718 break;
12720 map.release ();
12723 /* c) If the characteristic data type determined by a) or b) above
12724 is struct, union, or class type which is pass-by-value (except
12725 for the type that maps to the built-in complex data type), the
12726 characteristic data type is int. */
12727 if (RECORD_OR_UNION_TYPE_P (type)
12728 && !aggregate_value_p (type, NULL)
12729 && TREE_CODE (type) != COMPLEX_TYPE)
12730 return integer_type_node;
12732 /* d) If none of the above three classes is applicable, the
12733 characteristic data type is int. */
12735 return type;
12737 /* e) For Intel Xeon Phi native and offload compilation, if the
12738 resulting characteristic data type is 8-bit or 16-bit integer
12739 data type, the characteristic data type is int. */
12740 /* Well, we don't handle Xeon Phi yet. */
12743 static tree
12744 simd_clone_mangle (struct cgraph_node *node,
12745 struct cgraph_simd_clone *clone_info)
12747 char vecsize_mangle = clone_info->vecsize_mangle;
12748 char mask = clone_info->inbranch ? 'M' : 'N';
12749 unsigned int simdlen = clone_info->simdlen;
12750 unsigned int n;
12751 pretty_printer pp;
12753 gcc_assert (vecsize_mangle && simdlen);
12755 pp_string (&pp, "_ZGV");
12756 pp_character (&pp, vecsize_mangle);
12757 pp_character (&pp, mask);
12758 pp_decimal_int (&pp, simdlen);
12760 for (n = 0; n < clone_info->nargs; ++n)
12762 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12764 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12765 pp_character (&pp, 'u');
12766 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12768 gcc_assert (arg.linear_step != 0);
12769 pp_character (&pp, 'l');
12770 if (arg.linear_step > 1)
12771 pp_unsigned_wide_integer (&pp, arg.linear_step);
12772 else if (arg.linear_step < 0)
12774 pp_character (&pp, 'n');
12775 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12776 arg.linear_step));
12779 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12781 pp_character (&pp, 's');
12782 pp_unsigned_wide_integer (&pp, arg.linear_step);
12784 else
12785 pp_character (&pp, 'v');
12786 if (arg.alignment)
12788 pp_character (&pp, 'a');
12789 pp_decimal_int (&pp, arg.alignment);
12793 pp_underscore (&pp);
12794 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12795 if (*str == '*')
12796 ++str;
12797 pp_string (&pp, str);
12798 str = pp_formatted_text (&pp);
12800 /* If there already is a SIMD clone with the same mangled name, don't
12801 add another one. This can happen e.g. for
12802 #pragma omp declare simd
12803 #pragma omp declare simd simdlen(8)
12804 int foo (int, int);
12805 if the simdlen is assumed to be 8 for the first one, etc. */
12806 for (struct cgraph_node *clone = node->simd_clones; clone;
12807 clone = clone->simdclone->next_clone)
12808 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12809 str) == 0)
12810 return NULL_TREE;
12812 return get_identifier (str);
12815 /* Create a simd clone of OLD_NODE and return it. */
12817 static struct cgraph_node *
12818 simd_clone_create (struct cgraph_node *old_node)
12820 struct cgraph_node *new_node;
12821 if (old_node->definition)
12823 if (!old_node->has_gimple_body_p ())
12824 return NULL;
12825 old_node->get_body ();
12826 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12827 false, NULL, NULL,
12828 "simdclone");
12830 else
12832 tree old_decl = old_node->decl;
12833 tree new_decl = copy_node (old_node->decl);
12834 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12835 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12836 SET_DECL_RTL (new_decl, NULL);
12837 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12838 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
12839 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
12840 symtab->call_cgraph_insertion_hooks (new_node);
12842 if (new_node == NULL)
12843 return new_node;
12845 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12847 /* The function cgraph_function_versioning () will force the new
12848 symbol local. Undo this, and inherit external visability from
12849 the old node. */
12850 new_node->local.local = old_node->local.local;
12851 new_node->externally_visible = old_node->externally_visible;
12853 return new_node;
12856 /* Adjust the return type of the given function to its appropriate
12857 vector counterpart. Returns a simd array to be used throughout the
12858 function as a return value. */
12860 static tree
12861 simd_clone_adjust_return_type (struct cgraph_node *node)
12863 tree fndecl = node->decl;
12864 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12865 unsigned int veclen;
12866 tree t;
12868 /* Adjust the function return type. */
12869 if (orig_rettype == void_type_node)
12870 return NULL_TREE;
12871 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
12872 t = TREE_TYPE (TREE_TYPE (fndecl));
12873 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
12874 veclen = node->simdclone->vecsize_int;
12875 else
12876 veclen = node->simdclone->vecsize_float;
12877 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
12878 if (veclen > node->simdclone->simdlen)
12879 veclen = node->simdclone->simdlen;
12880 if (POINTER_TYPE_P (t))
12881 t = pointer_sized_int_node;
12882 if (veclen == node->simdclone->simdlen)
12883 t = build_vector_type (t, node->simdclone->simdlen);
12884 else
12886 t = build_vector_type (t, veclen);
12887 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
12889 TREE_TYPE (TREE_TYPE (fndecl)) = t;
12890 if (!node->definition)
12891 return NULL_TREE;
12893 t = DECL_RESULT (fndecl);
12894 /* Adjust the DECL_RESULT. */
12895 gcc_assert (TREE_TYPE (t) != void_type_node);
12896 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12897 relayout_decl (t);
12899 tree atype = build_array_type_nelts (orig_rettype,
12900 node->simdclone->simdlen);
12901 if (veclen != node->simdclone->simdlen)
12902 return build1 (VIEW_CONVERT_EXPR, atype, t);
12904 /* Set up a SIMD array to use as the return value. */
12905 tree retval = create_tmp_var_raw (atype, "retval");
12906 gimple_add_tmp_var (retval);
12907 return retval;
12910 /* Each vector argument has a corresponding array to be used locally
12911 as part of the eventual loop. Create such temporary array and
12912 return it.
12914 PREFIX is the prefix to be used for the temporary.
12916 TYPE is the inner element type.
12918 SIMDLEN is the number of elements. */
12920 static tree
12921 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12923 tree atype = build_array_type_nelts (type, simdlen);
12924 tree avar = create_tmp_var_raw (atype, prefix);
12925 gimple_add_tmp_var (avar);
12926 return avar;
12929 /* Modify the function argument types to their corresponding vector
12930 counterparts if appropriate. Also, create one array for each simd
12931 argument to be used locally when using the function arguments as
12932 part of the loop.
12934 NODE is the function whose arguments are to be adjusted.
12936 Returns an adjustment vector that will be filled describing how the
12937 argument types will be adjusted. */
12939 static ipa_parm_adjustment_vec
12940 simd_clone_adjust_argument_types (struct cgraph_node *node)
12942 vec<tree> args;
12943 ipa_parm_adjustment_vec adjustments;
12945 if (node->definition)
12946 args = ipa_get_vector_of_formal_parms (node->decl);
12947 else
12948 args = simd_clone_vector_of_formal_parm_types (node->decl);
12949 adjustments.create (args.length ());
12950 unsigned i, j, veclen;
12951 struct ipa_parm_adjustment adj;
12952 for (i = 0; i < node->simdclone->nargs; ++i)
12954 memset (&adj, 0, sizeof (adj));
12955 tree parm = args[i];
12956 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12957 adj.base_index = i;
12958 adj.base = parm;
12960 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12961 node->simdclone->args[i].orig_type = parm_type;
12963 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12965 /* No adjustment necessary for scalar arguments. */
12966 adj.op = IPA_PARM_OP_COPY;
12968 else
12970 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12971 veclen = node->simdclone->vecsize_int;
12972 else
12973 veclen = node->simdclone->vecsize_float;
12974 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12975 if (veclen > node->simdclone->simdlen)
12976 veclen = node->simdclone->simdlen;
12977 adj.arg_prefix = "simd";
12978 if (POINTER_TYPE_P (parm_type))
12979 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12980 else
12981 adj.type = build_vector_type (parm_type, veclen);
12982 node->simdclone->args[i].vector_type = adj.type;
12983 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12985 adjustments.safe_push (adj);
12986 if (j == veclen)
12988 memset (&adj, 0, sizeof (adj));
12989 adj.op = IPA_PARM_OP_NEW;
12990 adj.arg_prefix = "simd";
12991 adj.base_index = i;
12992 adj.type = node->simdclone->args[i].vector_type;
12996 if (node->definition)
12997 node->simdclone->args[i].simd_array
12998 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12999 parm_type, node->simdclone->simdlen);
13001 adjustments.safe_push (adj);
13004 if (node->simdclone->inbranch)
13006 tree base_type
13007 = simd_clone_compute_base_data_type (node->simdclone->origin,
13008 node->simdclone);
13010 memset (&adj, 0, sizeof (adj));
13011 adj.op = IPA_PARM_OP_NEW;
13012 adj.arg_prefix = "mask";
13014 adj.base_index = i;
13015 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
13016 veclen = node->simdclone->vecsize_int;
13017 else
13018 veclen = node->simdclone->vecsize_float;
13019 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
13020 if (veclen > node->simdclone->simdlen)
13021 veclen = node->simdclone->simdlen;
13022 if (POINTER_TYPE_P (base_type))
13023 adj.type = build_vector_type (pointer_sized_int_node, veclen);
13024 else
13025 adj.type = build_vector_type (base_type, veclen);
13026 adjustments.safe_push (adj);
13028 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
13029 adjustments.safe_push (adj);
13031 /* We have previously allocated one extra entry for the mask. Use
13032 it and fill it. */
13033 struct cgraph_simd_clone *sc = node->simdclone;
13034 sc->nargs++;
13035 if (node->definition)
13037 sc->args[i].orig_arg
13038 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
13039 sc->args[i].simd_array
13040 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
13042 sc->args[i].orig_type = base_type;
13043 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
13046 if (node->definition)
13047 ipa_modify_formal_parameters (node->decl, adjustments);
13048 else
13050 tree new_arg_types = NULL_TREE, new_reversed;
13051 bool last_parm_void = false;
13052 if (args.length () > 0 && args.last () == void_type_node)
13053 last_parm_void = true;
13055 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
13056 j = adjustments.length ();
13057 for (i = 0; i < j; i++)
13059 struct ipa_parm_adjustment *adj = &adjustments[i];
13060 tree ptype;
13061 if (adj->op == IPA_PARM_OP_COPY)
13062 ptype = args[adj->base_index];
13063 else
13064 ptype = adj->type;
13065 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
13067 new_reversed = nreverse (new_arg_types);
13068 if (last_parm_void)
13070 if (new_reversed)
13071 TREE_CHAIN (new_arg_types) = void_list_node;
13072 else
13073 new_reversed = void_list_node;
13076 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
13077 TYPE_ARG_TYPES (new_type) = new_reversed;
13078 TREE_TYPE (node->decl) = new_type;
13080 adjustments.release ();
13082 args.release ();
13083 return adjustments;
13086 /* Initialize and copy the function arguments in NODE to their
13087 corresponding local simd arrays. Returns a fresh gimple_seq with
13088 the instruction sequence generated. */
13090 static gimple_seq
13091 simd_clone_init_simd_arrays (struct cgraph_node *node,
13092 ipa_parm_adjustment_vec adjustments)
13094 gimple_seq seq = NULL;
13095 unsigned i = 0, j = 0, k;
13097 for (tree arg = DECL_ARGUMENTS (node->decl);
13098 arg;
13099 arg = DECL_CHAIN (arg), i++, j++)
13101 if (adjustments[j].op == IPA_PARM_OP_COPY)
13102 continue;
13104 node->simdclone->args[i].vector_arg = arg;
13106 tree array = node->simdclone->args[i].simd_array;
13107 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13109 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13110 tree ptr = build_fold_addr_expr (array);
13111 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13112 build_int_cst (ptype, 0));
13113 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13114 gimplify_and_add (t, &seq);
13116 else
13118 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13119 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13120 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13122 tree ptr = build_fold_addr_expr (array);
13123 int elemsize;
13124 if (k)
13126 arg = DECL_CHAIN (arg);
13127 j++;
13129 elemsize
13130 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13131 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13132 build_int_cst (ptype, k * elemsize));
13133 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13134 gimplify_and_add (t, &seq);
13138 return seq;
13141 /* Callback info for ipa_simd_modify_stmt_ops below. */
13143 struct modify_stmt_info {
13144 ipa_parm_adjustment_vec adjustments;
13145 gimple stmt;
13146 /* True if the parent statement was modified by
13147 ipa_simd_modify_stmt_ops. */
13148 bool modified;
13151 /* Callback for walk_gimple_op.
13153 Adjust operands from a given statement as specified in the
13154 adjustments vector in the callback data. */
13156 static tree
13157 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13159 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13160 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13161 tree *orig_tp = tp;
13162 if (TREE_CODE (*tp) == ADDR_EXPR)
13163 tp = &TREE_OPERAND (*tp, 0);
13164 struct ipa_parm_adjustment *cand = NULL;
13165 if (TREE_CODE (*tp) == PARM_DECL)
13166 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13167 else
13169 if (TYPE_P (*tp))
13170 *walk_subtrees = 0;
13173 tree repl = NULL_TREE;
13174 if (cand)
13175 repl = unshare_expr (cand->new_decl);
13176 else
13178 if (tp != orig_tp)
13180 *walk_subtrees = 0;
13181 bool modified = info->modified;
13182 info->modified = false;
13183 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13184 if (!info->modified)
13186 info->modified = modified;
13187 return NULL_TREE;
13189 info->modified = modified;
13190 repl = *tp;
13192 else
13193 return NULL_TREE;
13196 if (tp != orig_tp)
13198 repl = build_fold_addr_expr (repl);
13199 gimple stmt;
13200 if (is_gimple_debug (info->stmt))
13202 tree vexpr = make_node (DEBUG_EXPR_DECL);
13203 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13204 DECL_ARTIFICIAL (vexpr) = 1;
13205 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13206 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13207 repl = vexpr;
13209 else
13211 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13212 repl = gimple_assign_lhs (stmt);
13214 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13215 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13216 *orig_tp = repl;
13218 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13220 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13221 *tp = vce;
13223 else
13224 *tp = repl;
13226 info->modified = true;
13227 return NULL_TREE;
13230 /* Traverse the function body and perform all modifications as
13231 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13232 modified such that the replacement/reduction value will now be an
13233 offset into the corresponding simd_array.
13235 This function will replace all function argument uses with their
13236 corresponding simd array elements, and ajust the return values
13237 accordingly. */
13239 static void
13240 ipa_simd_modify_function_body (struct cgraph_node *node,
13241 ipa_parm_adjustment_vec adjustments,
13242 tree retval_array, tree iter)
13244 basic_block bb;
13245 unsigned int i, j, l;
13247 /* Re-use the adjustments array, but this time use it to replace
13248 every function argument use to an offset into the corresponding
13249 simd_array. */
13250 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13252 if (!node->simdclone->args[i].vector_arg)
13253 continue;
13255 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13256 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13257 adjustments[j].new_decl
13258 = build4 (ARRAY_REF,
13259 basetype,
13260 node->simdclone->args[i].simd_array,
13261 iter,
13262 NULL_TREE, NULL_TREE);
13263 if (adjustments[j].op == IPA_PARM_OP_NONE
13264 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13265 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13268 l = adjustments.length ();
13269 for (i = 1; i < num_ssa_names; i++)
13271 tree name = ssa_name (i);
13272 if (name
13273 && SSA_NAME_VAR (name)
13274 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13276 for (j = 0; j < l; j++)
13277 if (SSA_NAME_VAR (name) == adjustments[j].base
13278 && adjustments[j].new_decl)
13280 tree base_var;
13281 if (adjustments[j].new_ssa_base == NULL_TREE)
13283 base_var
13284 = copy_var_decl (adjustments[j].base,
13285 DECL_NAME (adjustments[j].base),
13286 TREE_TYPE (adjustments[j].base));
13287 adjustments[j].new_ssa_base = base_var;
13289 else
13290 base_var = adjustments[j].new_ssa_base;
13291 if (SSA_NAME_IS_DEFAULT_DEF (name))
13293 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13294 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13295 tree new_decl = unshare_expr (adjustments[j].new_decl);
13296 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13297 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13298 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13299 gimple stmt = gimple_build_assign (name, new_decl);
13300 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13302 else
13303 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13308 struct modify_stmt_info info;
13309 info.adjustments = adjustments;
13311 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13313 gimple_stmt_iterator gsi;
13315 gsi = gsi_start_bb (bb);
13316 while (!gsi_end_p (gsi))
13318 gimple stmt = gsi_stmt (gsi);
13319 info.stmt = stmt;
13320 struct walk_stmt_info wi;
13322 memset (&wi, 0, sizeof (wi));
13323 info.modified = false;
13324 wi.info = &info;
13325 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13327 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13329 tree retval = gimple_return_retval (return_stmt);
13330 if (!retval)
13332 gsi_remove (&gsi, true);
13333 continue;
13336 /* Replace `return foo' with `retval_array[iter] = foo'. */
13337 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13338 retval_array, iter, NULL, NULL);
13339 stmt = gimple_build_assign (ref, retval);
13340 gsi_replace (&gsi, stmt, true);
13341 info.modified = true;
13344 if (info.modified)
13346 update_stmt (stmt);
13347 if (maybe_clean_eh_stmt (stmt))
13348 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13350 gsi_next (&gsi);
13355 /* Adjust the argument types in NODE to their appropriate vector
13356 counterparts. */
13358 static void
13359 simd_clone_adjust (struct cgraph_node *node)
13361 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13363 targetm.simd_clone.adjust (node);
13365 tree retval = simd_clone_adjust_return_type (node);
13366 ipa_parm_adjustment_vec adjustments
13367 = simd_clone_adjust_argument_types (node);
13369 push_gimplify_context ();
13371 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13373 /* Adjust all uses of vector arguments accordingly. Adjust all
13374 return values accordingly. */
13375 tree iter = create_tmp_var (unsigned_type_node, "iter");
13376 tree iter1 = make_ssa_name (iter);
13377 tree iter2 = make_ssa_name (iter);
13378 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13380 /* Initialize the iteration variable. */
13381 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13382 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13383 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13384 /* Insert the SIMD array and iv initialization at function
13385 entry. */
13386 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13388 pop_gimplify_context (NULL);
13390 /* Create a new BB right before the original exit BB, to hold the
13391 iteration increment and the condition/branch. */
13392 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13393 basic_block incr_bb = create_empty_bb (orig_exit);
13394 add_bb_to_loop (incr_bb, body_bb->loop_father);
13395 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13396 flag. Set it now to be a FALLTHRU_EDGE. */
13397 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13398 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13399 for (unsigned i = 0;
13400 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13402 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13403 redirect_edge_succ (e, incr_bb);
13405 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13406 e->probability = REG_BR_PROB_BASE;
13407 gsi = gsi_last_bb (incr_bb);
13408 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13409 build_int_cst (unsigned_type_node, 1));
13410 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13412 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13413 struct loop *loop = alloc_loop ();
13414 cfun->has_force_vectorize_loops = true;
13415 loop->safelen = node->simdclone->simdlen;
13416 loop->force_vectorize = true;
13417 loop->header = body_bb;
13419 /* Branch around the body if the mask applies. */
13420 if (node->simdclone->inbranch)
13422 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13423 tree mask_array
13424 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13425 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13426 tree aref = build4 (ARRAY_REF,
13427 TREE_TYPE (TREE_TYPE (mask_array)),
13428 mask_array, iter1,
13429 NULL, NULL);
13430 g = gimple_build_assign (mask, aref);
13431 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13432 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13433 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13435 aref = build1 (VIEW_CONVERT_EXPR,
13436 build_nonstandard_integer_type (bitsize, 0), mask);
13437 mask = make_ssa_name (TREE_TYPE (aref));
13438 g = gimple_build_assign (mask, aref);
13439 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13442 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13443 NULL, NULL);
13444 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13445 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13446 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13449 /* Generate the condition. */
13450 g = gimple_build_cond (LT_EXPR,
13451 iter2,
13452 build_int_cst (unsigned_type_node,
13453 node->simdclone->simdlen),
13454 NULL, NULL);
13455 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13456 e = split_block (incr_bb, gsi_stmt (gsi));
13457 basic_block latch_bb = e->dest;
13458 basic_block new_exit_bb;
13459 new_exit_bb = split_block_after_labels (latch_bb)->dest;
13460 loop->latch = latch_bb;
13462 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13464 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13465 /* The successor of incr_bb is already pointing to latch_bb; just
13466 change the flags.
13467 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13468 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13470 gphi *phi = create_phi_node (iter1, body_bb);
13471 edge preheader_edge = find_edge (entry_bb, body_bb);
13472 edge latch_edge = single_succ_edge (latch_bb);
13473 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13474 UNKNOWN_LOCATION);
13475 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13477 /* Generate the new return. */
13478 gsi = gsi_last_bb (new_exit_bb);
13479 if (retval
13480 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13481 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13482 retval = TREE_OPERAND (retval, 0);
13483 else if (retval)
13485 retval = build1 (VIEW_CONVERT_EXPR,
13486 TREE_TYPE (TREE_TYPE (node->decl)),
13487 retval);
13488 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13489 false, GSI_CONTINUE_LINKING);
13491 g = gimple_build_return (retval);
13492 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13494 /* Handle aligned clauses by replacing default defs of the aligned
13495 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13496 lhs. Handle linear by adding PHIs. */
13497 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13498 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13499 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
13500 || !is_gimple_reg_type
13501 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
13503 tree orig_arg = node->simdclone->args[i].orig_arg;
13504 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
13505 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
13506 else
13508 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
13509 gimple_add_tmp_var (iter1);
13511 gsi = gsi_after_labels (entry_bb);
13512 g = gimple_build_assign (iter1, orig_arg);
13513 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13514 gsi = gsi_after_labels (body_bb);
13515 g = gimple_build_assign (orig_arg, iter1);
13516 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13518 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13519 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
13520 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13521 == REFERENCE_TYPE
13522 && TREE_ADDRESSABLE
13523 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
13525 tree orig_arg = node->simdclone->args[i].orig_arg;
13526 tree def = ssa_default_def (cfun, orig_arg);
13527 if (def && !has_zero_uses (def))
13529 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
13530 gimple_add_tmp_var (iter1);
13531 gsi = gsi_after_labels (entry_bb);
13532 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
13533 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13534 gsi = gsi_after_labels (body_bb);
13535 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
13536 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13539 else if (node->simdclone->args[i].alignment
13540 && node->simdclone->args[i].arg_type
13541 == SIMD_CLONE_ARG_TYPE_UNIFORM
13542 && (node->simdclone->args[i].alignment
13543 & (node->simdclone->args[i].alignment - 1)) == 0
13544 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13545 == POINTER_TYPE)
13547 unsigned int alignment = node->simdclone->args[i].alignment;
13548 tree orig_arg = node->simdclone->args[i].orig_arg;
13549 tree def = ssa_default_def (cfun, orig_arg);
13550 if (def && !has_zero_uses (def))
13552 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13553 gimple_seq seq = NULL;
13554 bool need_cvt = false;
13555 gcall *call
13556 = gimple_build_call (fn, 2, def, size_int (alignment));
13557 g = call;
13558 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13559 ptr_type_node))
13560 need_cvt = true;
13561 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13562 gimple_call_set_lhs (g, t);
13563 gimple_seq_add_stmt_without_update (&seq, g);
13564 if (need_cvt)
13566 t = make_ssa_name (orig_arg);
13567 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13568 gimple_seq_add_stmt_without_update (&seq, g);
13570 gsi_insert_seq_on_edge_immediate
13571 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13573 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13574 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13575 entry_bb);
13576 node->create_edge (cgraph_node::get_create (fn),
13577 call, entry_bb->count, freq);
13579 imm_use_iterator iter;
13580 use_operand_p use_p;
13581 gimple use_stmt;
13582 tree repl = gimple_get_lhs (g);
13583 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13584 if (is_gimple_debug (use_stmt) || use_stmt == call)
13585 continue;
13586 else
13587 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13588 SET_USE (use_p, repl);
13591 else if (node->simdclone->args[i].arg_type
13592 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13594 tree orig_arg = node->simdclone->args[i].orig_arg;
13595 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13596 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13597 tree def = NULL_TREE;
13598 if (TREE_ADDRESSABLE (orig_arg))
13600 def = make_ssa_name (TREE_TYPE (orig_arg));
13601 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
13602 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
13603 gsi = gsi_after_labels (entry_bb);
13604 g = gimple_build_assign (def, orig_arg);
13605 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13607 else
13609 def = ssa_default_def (cfun, orig_arg);
13610 if (!def || has_zero_uses (def))
13611 def = NULL_TREE;
13612 else
13614 iter1 = make_ssa_name (orig_arg);
13615 iter2 = make_ssa_name (orig_arg);
13618 if (def)
13620 phi = create_phi_node (iter1, body_bb);
13621 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13622 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13623 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13624 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13625 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13626 ? TREE_TYPE (orig_arg) : sizetype;
13627 tree addcst
13628 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13629 g = gimple_build_assign (iter2, code, iter1, addcst);
13630 gsi = gsi_last_bb (incr_bb);
13631 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13633 imm_use_iterator iter;
13634 use_operand_p use_p;
13635 gimple use_stmt;
13636 if (TREE_ADDRESSABLE (orig_arg))
13638 gsi = gsi_after_labels (body_bb);
13639 g = gimple_build_assign (orig_arg, iter1);
13640 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13642 else
13643 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13644 if (use_stmt == phi)
13645 continue;
13646 else
13647 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13648 SET_USE (use_p, iter1);
13652 calculate_dominance_info (CDI_DOMINATORS);
13653 add_loop (loop, loop->header->loop_father);
13654 update_ssa (TODO_update_ssa);
13656 pop_cfun ();
13659 /* If the function in NODE is tagged as an elemental SIMD function,
13660 create the appropriate SIMD clones. */
13662 static void
13663 expand_simd_clones (struct cgraph_node *node)
13665 tree attr = lookup_attribute ("omp declare simd",
13666 DECL_ATTRIBUTES (node->decl));
13667 if (attr == NULL_TREE
13668 || node->global.inlined_to
13669 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13670 return;
13672 /* Ignore
13673 #pragma omp declare simd
13674 extern int foo ();
13675 in C, there we don't know the argument types at all. */
13676 if (!node->definition
13677 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13678 return;
13682 /* Start with parsing the "omp declare simd" attribute(s). */
13683 bool inbranch_clause_specified;
13684 struct cgraph_simd_clone *clone_info
13685 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13686 &inbranch_clause_specified);
13687 if (clone_info == NULL)
13688 continue;
13690 int orig_simdlen = clone_info->simdlen;
13691 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13692 /* The target can return 0 (no simd clones should be created),
13693 1 (just one ISA of simd clones should be created) or higher
13694 count of ISA variants. In that case, clone_info is initialized
13695 for the first ISA variant. */
13696 int count
13697 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13698 base_type, 0);
13699 if (count == 0)
13700 continue;
13702 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13703 also create one inbranch and one !inbranch clone of it. */
13704 for (int i = 0; i < count * 2; i++)
13706 struct cgraph_simd_clone *clone = clone_info;
13707 if (inbranch_clause_specified && (i & 1) != 0)
13708 continue;
13710 if (i != 0)
13712 clone = simd_clone_struct_alloc (clone_info->nargs
13713 + ((i & 1) != 0));
13714 simd_clone_struct_copy (clone, clone_info);
13715 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13716 and simd_clone_adjust_argument_types did to the first
13717 clone's info. */
13718 clone->nargs -= clone_info->inbranch;
13719 clone->simdlen = orig_simdlen;
13720 /* And call the target hook again to get the right ISA. */
13721 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13722 base_type,
13723 i / 2);
13724 if ((i & 1) != 0)
13725 clone->inbranch = 1;
13728 /* simd_clone_mangle might fail if such a clone has been created
13729 already. */
13730 tree id = simd_clone_mangle (node, clone);
13731 if (id == NULL_TREE)
13732 continue;
13734 /* Only when we are sure we want to create the clone actually
13735 clone the function (or definitions) or create another
13736 extern FUNCTION_DECL (for prototypes without definitions). */
13737 struct cgraph_node *n = simd_clone_create (node);
13738 if (n == NULL)
13739 continue;
13741 n->simdclone = clone;
13742 clone->origin = node;
13743 clone->next_clone = NULL;
13744 if (node->simd_clones == NULL)
13746 clone->prev_clone = n;
13747 node->simd_clones = n;
13749 else
13751 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13752 clone->prev_clone->simdclone->next_clone = n;
13753 node->simd_clones->simdclone->prev_clone = n;
13755 symtab->change_decl_assembler_name (n->decl, id);
13756 /* And finally adjust the return type, parameters and for
13757 definitions also function body. */
13758 if (node->definition)
13759 simd_clone_adjust (n);
13760 else
13762 simd_clone_adjust_return_type (n);
13763 simd_clone_adjust_argument_types (n);
13767 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13770 /* Entry point for IPA simd clone creation pass. */
13772 static unsigned int
13773 ipa_omp_simd_clone (void)
13775 struct cgraph_node *node;
13776 FOR_EACH_FUNCTION (node)
13777 expand_simd_clones (node);
13778 return 0;
13781 namespace {
13783 const pass_data pass_data_omp_simd_clone =
13785 SIMPLE_IPA_PASS, /* type */
13786 "simdclone", /* name */
13787 OPTGROUP_NONE, /* optinfo_flags */
13788 TV_NONE, /* tv_id */
13789 ( PROP_ssa | PROP_cfg ), /* properties_required */
13790 0, /* properties_provided */
13791 0, /* properties_destroyed */
13792 0, /* todo_flags_start */
13793 0, /* todo_flags_finish */
13796 class pass_omp_simd_clone : public simple_ipa_opt_pass
13798 public:
13799 pass_omp_simd_clone(gcc::context *ctxt)
13800 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13803 /* opt_pass methods: */
13804 virtual bool gate (function *);
13805 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
13808 bool
13809 pass_omp_simd_clone::gate (function *)
13811 return ((flag_openmp || flag_openmp_simd
13812 || flag_cilkplus
13813 || (in_lto_p && !flag_wpa))
13814 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13817 } // anon namespace
13819 simple_ipa_opt_pass *
13820 make_pass_omp_simd_clone (gcc::context *ctxt)
13822 return new pass_omp_simd_clone (ctxt);
13825 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13826 adds their addresses and sizes to constructor-vector V_CTOR. */
13827 static void
13828 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13829 vec<constructor_elt, va_gc> *v_ctor)
13831 unsigned len = vec_safe_length (v_decls);
13832 for (unsigned i = 0; i < len; i++)
13834 tree it = (*v_decls)[i];
13835 bool is_function = TREE_CODE (it) != VAR_DECL;
13837 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13838 if (!is_function)
13839 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13840 fold_convert (const_ptr_type_node,
13841 DECL_SIZE_UNIT (it)));
13845 /* Create new symbols containing (address, size) pairs for global variables,
13846 marked with "omp declare target" attribute, as well as addresses for the
13847 functions, which are outlined offloading regions. */
13848 void
13849 omp_finish_file (void)
13851 unsigned num_funcs = vec_safe_length (offload_funcs);
13852 unsigned num_vars = vec_safe_length (offload_vars);
13854 if (num_funcs == 0 && num_vars == 0)
13855 return;
13857 if (targetm_common.have_named_sections)
13859 vec<constructor_elt, va_gc> *v_f, *v_v;
13860 vec_alloc (v_f, num_funcs);
13861 vec_alloc (v_v, num_vars * 2);
13863 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13864 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13866 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13867 num_vars * 2);
13868 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13869 num_funcs);
13870 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13871 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13872 tree ctor_v = build_constructor (vars_decl_type, v_v);
13873 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13874 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13875 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13876 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13877 get_identifier (".offload_func_table"),
13878 funcs_decl_type);
13879 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13880 get_identifier (".offload_var_table"),
13881 vars_decl_type);
13882 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13883 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13884 otherwise a joint table in a binary will contain padding between
13885 tables from multiple object files. */
13886 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13887 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13888 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13889 DECL_INITIAL (funcs_decl) = ctor_f;
13890 DECL_INITIAL (vars_decl) = ctor_v;
13891 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13892 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13894 varpool_node::finalize_decl (vars_decl);
13895 varpool_node::finalize_decl (funcs_decl);
13897 else
13899 for (unsigned i = 0; i < num_funcs; i++)
13901 tree it = (*offload_funcs)[i];
13902 targetm.record_offload_symbol (it);
13904 for (unsigned i = 0; i < num_vars; i++)
13906 tree it = (*offload_vars)[i];
13907 targetm.record_offload_symbol (it);
13912 #include "gt-omp-low.h"