2015-09-25 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / gcc / omp-low.c
blobcb007582cf29d8ee8375c4c863bdc058bdd951d9
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 operation OP. */
3377 tree
3378 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
3380 switch (op)
3382 case PLUS_EXPR:
3383 case MINUS_EXPR:
3384 case BIT_IOR_EXPR:
3385 case BIT_XOR_EXPR:
3386 case TRUTH_OR_EXPR:
3387 case TRUTH_ORIF_EXPR:
3388 case TRUTH_XOR_EXPR:
3389 case NE_EXPR:
3390 return build_zero_cst (type);
3392 case MULT_EXPR:
3393 case TRUTH_AND_EXPR:
3394 case TRUTH_ANDIF_EXPR:
3395 case EQ_EXPR:
3396 return fold_convert_loc (loc, type, integer_one_node);
3398 case BIT_AND_EXPR:
3399 return fold_convert_loc (loc, type, integer_minus_one_node);
3401 case MAX_EXPR:
3402 if (SCALAR_FLOAT_TYPE_P (type))
3404 REAL_VALUE_TYPE max, min;
3405 if (HONOR_INFINITIES (type))
3407 real_inf (&max);
3408 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3410 else
3411 real_maxval (&min, 1, TYPE_MODE (type));
3412 return build_real (type, min);
3414 else if (POINTER_TYPE_P (type))
3416 wide_int min
3417 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3418 return wide_int_to_tree (type, min);
3420 else
3422 gcc_assert (INTEGRAL_TYPE_P (type));
3423 return TYPE_MIN_VALUE (type);
3426 case MIN_EXPR:
3427 if (SCALAR_FLOAT_TYPE_P (type))
3429 REAL_VALUE_TYPE max;
3430 if (HONOR_INFINITIES (type))
3431 real_inf (&max);
3432 else
3433 real_maxval (&max, 0, TYPE_MODE (type));
3434 return build_real (type, max);
3436 else if (POINTER_TYPE_P (type))
3438 wide_int max
3439 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3440 return wide_int_to_tree (type, max);
3442 else
3444 gcc_assert (INTEGRAL_TYPE_P (type));
3445 return TYPE_MAX_VALUE (type);
3448 default:
3449 gcc_unreachable ();
3453 /* Construct the initialization value for reduction CLAUSE. */
3455 tree
3456 omp_reduction_init (tree clause, tree type)
3458 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
3459 OMP_CLAUSE_REDUCTION_CODE (clause), type);
3462 /* Return alignment to be assumed for var in CLAUSE, which should be
3463 OMP_CLAUSE_ALIGNED. */
3465 static tree
3466 omp_clause_aligned_alignment (tree clause)
3468 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3469 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3471 /* Otherwise return implementation defined alignment. */
3472 unsigned int al = 1;
3473 machine_mode mode, vmode;
3474 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3475 if (vs)
3476 vs = 1 << floor_log2 (vs);
3477 static enum mode_class classes[]
3478 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3479 for (int i = 0; i < 4; i += 2)
3480 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3481 mode != VOIDmode;
3482 mode = GET_MODE_WIDER_MODE (mode))
3484 vmode = targetm.vectorize.preferred_simd_mode (mode);
3485 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3486 continue;
3487 while (vs
3488 && GET_MODE_SIZE (vmode) < vs
3489 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3490 vmode = GET_MODE_2XWIDER_MODE (vmode);
3492 tree type = lang_hooks.types.type_for_mode (mode, 1);
3493 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3494 continue;
3495 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3496 / GET_MODE_SIZE (mode));
3497 if (TYPE_MODE (type) != vmode)
3498 continue;
3499 if (TYPE_ALIGN_UNIT (type) > al)
3500 al = TYPE_ALIGN_UNIT (type);
3502 return build_int_cst (integer_type_node, al);
3505 /* Return maximum possible vectorization factor for the target. */
3507 static int
3508 omp_max_vf (void)
3510 if (!optimize
3511 || optimize_debug
3512 || !flag_tree_loop_optimize
3513 || (!flag_tree_loop_vectorize
3514 && (global_options_set.x_flag_tree_loop_vectorize
3515 || global_options_set.x_flag_tree_vectorize)))
3516 return 1;
3518 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3519 if (vs)
3521 vs = 1 << floor_log2 (vs);
3522 return vs;
3524 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3525 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3526 return GET_MODE_NUNITS (vqimode);
3527 return 1;
3530 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3531 privatization. */
3533 static bool
3534 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3535 tree &idx, tree &lane, tree &ivar, tree &lvar)
3537 if (max_vf == 0)
3539 max_vf = omp_max_vf ();
3540 if (max_vf > 1)
3542 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3543 OMP_CLAUSE_SAFELEN);
3544 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3545 max_vf = 1;
3546 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3547 max_vf) == -1)
3548 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3550 if (max_vf > 1)
3552 idx = create_tmp_var (unsigned_type_node);
3553 lane = create_tmp_var (unsigned_type_node);
3556 if (max_vf == 1)
3557 return false;
3559 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3560 tree avar = create_tmp_var_raw (atype);
3561 if (TREE_ADDRESSABLE (new_var))
3562 TREE_ADDRESSABLE (avar) = 1;
3563 DECL_ATTRIBUTES (avar)
3564 = tree_cons (get_identifier ("omp simd array"), NULL,
3565 DECL_ATTRIBUTES (avar));
3566 gimple_add_tmp_var (avar);
3567 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3568 NULL_TREE, NULL_TREE);
3569 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3570 NULL_TREE, NULL_TREE);
3571 if (DECL_P (new_var))
3573 SET_DECL_VALUE_EXPR (new_var, lvar);
3574 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3576 return true;
3579 /* Helper function of lower_rec_input_clauses. For a reference
3580 in simd reduction, add an underlying variable it will reference. */
3582 static void
3583 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3585 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3586 if (TREE_CONSTANT (z))
3588 const char *name = NULL;
3589 if (DECL_NAME (new_vard))
3590 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3592 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3593 gimple_add_tmp_var (z);
3594 TREE_ADDRESSABLE (z) = 1;
3595 z = build_fold_addr_expr_loc (loc, z);
3596 gimplify_assign (new_vard, z, ilist);
3600 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3601 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3602 private variables. Initialization statements go in ILIST, while calls
3603 to destructors go in DLIST. */
3605 static void
3606 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3607 omp_context *ctx, struct omp_for_data *fd)
3609 tree c, dtor, copyin_seq, x, ptr;
3610 bool copyin_by_ref = false;
3611 bool lastprivate_firstprivate = false;
3612 bool reduction_omp_orig_ref = false;
3613 int pass;
3614 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3615 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3616 int max_vf = 0;
3617 tree lane = NULL_TREE, idx = NULL_TREE;
3618 tree ivar = NULL_TREE, lvar = NULL_TREE;
3619 gimple_seq llist[2] = { NULL, NULL };
3621 copyin_seq = NULL;
3623 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3624 with data sharing clauses referencing variable sized vars. That
3625 is unnecessarily hard to support and very unlikely to result in
3626 vectorized code anyway. */
3627 if (is_simd)
3628 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3629 switch (OMP_CLAUSE_CODE (c))
3631 case OMP_CLAUSE_LINEAR:
3632 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3633 max_vf = 1;
3634 /* FALLTHRU */
3635 case OMP_CLAUSE_REDUCTION:
3636 case OMP_CLAUSE_PRIVATE:
3637 case OMP_CLAUSE_FIRSTPRIVATE:
3638 case OMP_CLAUSE_LASTPRIVATE:
3639 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3640 max_vf = 1;
3641 break;
3642 default:
3643 continue;
3646 /* Do all the fixed sized types in the first pass, and the variable sized
3647 types in the second pass. This makes sure that the scalar arguments to
3648 the variable sized types are processed before we use them in the
3649 variable sized operations. */
3650 for (pass = 0; pass < 2; ++pass)
3652 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3654 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3655 tree var, new_var;
3656 bool by_ref;
3657 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3659 switch (c_kind)
3661 case OMP_CLAUSE_PRIVATE:
3662 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3663 continue;
3664 break;
3665 case OMP_CLAUSE_SHARED:
3666 /* Ignore shared directives in teams construct. */
3667 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3668 continue;
3669 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3671 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3672 continue;
3674 case OMP_CLAUSE_FIRSTPRIVATE:
3675 case OMP_CLAUSE_COPYIN:
3676 case OMP_CLAUSE_LINEAR:
3677 break;
3678 case OMP_CLAUSE_REDUCTION:
3679 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3680 reduction_omp_orig_ref = true;
3681 break;
3682 case OMP_CLAUSE__LOOPTEMP_:
3683 /* Handle _looptemp_ clauses only on parallel. */
3684 if (fd)
3685 continue;
3686 break;
3687 case OMP_CLAUSE_LASTPRIVATE:
3688 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3690 lastprivate_firstprivate = true;
3691 if (pass != 0)
3692 continue;
3694 /* Even without corresponding firstprivate, if
3695 decl is Fortran allocatable, it needs outer var
3696 reference. */
3697 else if (pass == 0
3698 && lang_hooks.decls.omp_private_outer_ref
3699 (OMP_CLAUSE_DECL (c)))
3700 lastprivate_firstprivate = true;
3701 break;
3702 case OMP_CLAUSE_ALIGNED:
3703 if (pass == 0)
3704 continue;
3705 var = OMP_CLAUSE_DECL (c);
3706 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3707 && !is_global_var (var))
3709 new_var = maybe_lookup_decl (var, ctx);
3710 if (new_var == NULL_TREE)
3711 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3712 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3713 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3714 omp_clause_aligned_alignment (c));
3715 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3716 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3717 gimplify_and_add (x, ilist);
3719 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3720 && is_global_var (var))
3722 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3723 new_var = lookup_decl (var, ctx);
3724 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3725 t = build_fold_addr_expr_loc (clause_loc, t);
3726 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3727 t = build_call_expr_loc (clause_loc, t2, 2, t,
3728 omp_clause_aligned_alignment (c));
3729 t = fold_convert_loc (clause_loc, ptype, t);
3730 x = create_tmp_var (ptype);
3731 t = build2 (MODIFY_EXPR, ptype, x, t);
3732 gimplify_and_add (t, ilist);
3733 t = build_simple_mem_ref_loc (clause_loc, x);
3734 SET_DECL_VALUE_EXPR (new_var, t);
3735 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3737 continue;
3738 default:
3739 continue;
3742 new_var = var = OMP_CLAUSE_DECL (c);
3743 if (c_kind != OMP_CLAUSE_COPYIN)
3744 new_var = lookup_decl (var, ctx);
3746 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3748 if (pass != 0)
3749 continue;
3751 else if (is_variable_sized (var))
3753 /* For variable sized types, we need to allocate the
3754 actual storage here. Call alloca and store the
3755 result in the pointer decl that we created elsewhere. */
3756 if (pass == 0)
3757 continue;
3759 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3761 gcall *stmt;
3762 tree tmp, atmp;
3764 ptr = DECL_VALUE_EXPR (new_var);
3765 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3766 ptr = TREE_OPERAND (ptr, 0);
3767 gcc_assert (DECL_P (ptr));
3768 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3770 /* void *tmp = __builtin_alloca */
3771 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3772 stmt = gimple_build_call (atmp, 1, x);
3773 tmp = create_tmp_var_raw (ptr_type_node);
3774 gimple_add_tmp_var (tmp);
3775 gimple_call_set_lhs (stmt, tmp);
3777 gimple_seq_add_stmt (ilist, stmt);
3779 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3780 gimplify_assign (ptr, x, ilist);
3783 else if (is_reference (var))
3785 /* For references that are being privatized for Fortran,
3786 allocate new backing storage for the new pointer
3787 variable. This allows us to avoid changing all the
3788 code that expects a pointer to something that expects
3789 a direct variable. */
3790 if (pass == 0)
3791 continue;
3793 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3794 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3796 x = build_receiver_ref (var, false, ctx);
3797 x = build_fold_addr_expr_loc (clause_loc, x);
3799 else if (TREE_CONSTANT (x))
3801 /* For reduction in SIMD loop, defer adding the
3802 initialization of the reference, because if we decide
3803 to use SIMD array for it, the initilization could cause
3804 expansion ICE. */
3805 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3806 x = NULL_TREE;
3807 else
3809 const char *name = NULL;
3810 if (DECL_NAME (var))
3811 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3813 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3814 name);
3815 gimple_add_tmp_var (x);
3816 TREE_ADDRESSABLE (x) = 1;
3817 x = build_fold_addr_expr_loc (clause_loc, x);
3820 else
3822 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3823 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3826 if (x)
3828 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3829 gimplify_assign (new_var, x, ilist);
3832 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3834 else if (c_kind == OMP_CLAUSE_REDUCTION
3835 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3837 if (pass == 0)
3838 continue;
3840 else if (pass != 0)
3841 continue;
3843 switch (OMP_CLAUSE_CODE (c))
3845 case OMP_CLAUSE_SHARED:
3846 /* Ignore shared directives in teams construct. */
3847 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3848 continue;
3849 /* Shared global vars are just accessed directly. */
3850 if (is_global_var (new_var))
3851 break;
3852 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3853 needs to be delayed until after fixup_child_record_type so
3854 that we get the correct type during the dereference. */
3855 by_ref = use_pointer_for_field (var, ctx);
3856 x = build_receiver_ref (var, by_ref, ctx);
3857 SET_DECL_VALUE_EXPR (new_var, x);
3858 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3860 /* ??? If VAR is not passed by reference, and the variable
3861 hasn't been initialized yet, then we'll get a warning for
3862 the store into the omp_data_s structure. Ideally, we'd be
3863 able to notice this and not store anything at all, but
3864 we're generating code too early. Suppress the warning. */
3865 if (!by_ref)
3866 TREE_NO_WARNING (var) = 1;
3867 break;
3869 case OMP_CLAUSE_LASTPRIVATE:
3870 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3871 break;
3872 /* FALLTHRU */
3874 case OMP_CLAUSE_PRIVATE:
3875 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3876 x = build_outer_var_ref (var, ctx);
3877 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3879 if (is_task_ctx (ctx))
3880 x = build_receiver_ref (var, false, ctx);
3881 else
3882 x = build_outer_var_ref (var, ctx);
3884 else
3885 x = NULL;
3886 do_private:
3887 tree nx;
3888 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3889 if (is_simd)
3891 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3892 if ((TREE_ADDRESSABLE (new_var) || nx || y
3893 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3894 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3895 idx, lane, ivar, lvar))
3897 if (nx)
3898 x = lang_hooks.decls.omp_clause_default_ctor
3899 (c, unshare_expr (ivar), x);
3900 if (nx && x)
3901 gimplify_and_add (x, &llist[0]);
3902 if (y)
3904 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3905 if (y)
3907 gimple_seq tseq = NULL;
3909 dtor = y;
3910 gimplify_stmt (&dtor, &tseq);
3911 gimple_seq_add_seq (&llist[1], tseq);
3914 break;
3917 if (nx)
3918 gimplify_and_add (nx, ilist);
3919 /* FALLTHRU */
3921 do_dtor:
3922 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3923 if (x)
3925 gimple_seq tseq = NULL;
3927 dtor = x;
3928 gimplify_stmt (&dtor, &tseq);
3929 gimple_seq_add_seq (dlist, tseq);
3931 break;
3933 case OMP_CLAUSE_LINEAR:
3934 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3935 goto do_firstprivate;
3936 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3937 x = NULL;
3938 else
3939 x = build_outer_var_ref (var, ctx);
3940 goto do_private;
3942 case OMP_CLAUSE_FIRSTPRIVATE:
3943 if (is_task_ctx (ctx))
3945 if (is_reference (var) || is_variable_sized (var))
3946 goto do_dtor;
3947 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3948 ctx))
3949 || use_pointer_for_field (var, NULL))
3951 x = build_receiver_ref (var, false, ctx);
3952 SET_DECL_VALUE_EXPR (new_var, x);
3953 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3954 goto do_dtor;
3957 do_firstprivate:
3958 x = build_outer_var_ref (var, ctx);
3959 if (is_simd)
3961 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3962 && gimple_omp_for_combined_into_p (ctx->stmt))
3964 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3965 tree stept = TREE_TYPE (t);
3966 tree ct = find_omp_clause (clauses,
3967 OMP_CLAUSE__LOOPTEMP_);
3968 gcc_assert (ct);
3969 tree l = OMP_CLAUSE_DECL (ct);
3970 tree n1 = fd->loop.n1;
3971 tree step = fd->loop.step;
3972 tree itype = TREE_TYPE (l);
3973 if (POINTER_TYPE_P (itype))
3974 itype = signed_type_for (itype);
3975 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3976 if (TYPE_UNSIGNED (itype)
3977 && fd->loop.cond_code == GT_EXPR)
3978 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3979 fold_build1 (NEGATE_EXPR, itype, l),
3980 fold_build1 (NEGATE_EXPR,
3981 itype, step));
3982 else
3983 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3984 t = fold_build2 (MULT_EXPR, stept,
3985 fold_convert (stept, l), t);
3987 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3989 x = lang_hooks.decls.omp_clause_linear_ctor
3990 (c, new_var, x, t);
3991 gimplify_and_add (x, ilist);
3992 goto do_dtor;
3995 if (POINTER_TYPE_P (TREE_TYPE (x)))
3996 x = fold_build2 (POINTER_PLUS_EXPR,
3997 TREE_TYPE (x), x, t);
3998 else
3999 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4002 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4003 || TREE_ADDRESSABLE (new_var))
4004 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4005 idx, lane, ivar, lvar))
4007 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4009 tree iv = create_tmp_var (TREE_TYPE (new_var));
4010 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4011 gimplify_and_add (x, ilist);
4012 gimple_stmt_iterator gsi
4013 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4014 gassign *g
4015 = gimple_build_assign (unshare_expr (lvar), iv);
4016 gsi_insert_before_without_update (&gsi, g,
4017 GSI_SAME_STMT);
4018 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4019 enum tree_code code = PLUS_EXPR;
4020 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4021 code = POINTER_PLUS_EXPR;
4022 g = gimple_build_assign (iv, code, iv, t);
4023 gsi_insert_before_without_update (&gsi, g,
4024 GSI_SAME_STMT);
4025 break;
4027 x = lang_hooks.decls.omp_clause_copy_ctor
4028 (c, unshare_expr (ivar), x);
4029 gimplify_and_add (x, &llist[0]);
4030 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4031 if (x)
4033 gimple_seq tseq = NULL;
4035 dtor = x;
4036 gimplify_stmt (&dtor, &tseq);
4037 gimple_seq_add_seq (&llist[1], tseq);
4039 break;
4042 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4043 gimplify_and_add (x, ilist);
4044 goto do_dtor;
4046 case OMP_CLAUSE__LOOPTEMP_:
4047 gcc_assert (is_parallel_ctx (ctx));
4048 x = build_outer_var_ref (var, ctx);
4049 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4050 gimplify_and_add (x, ilist);
4051 break;
4053 case OMP_CLAUSE_COPYIN:
4054 by_ref = use_pointer_for_field (var, NULL);
4055 x = build_receiver_ref (var, by_ref, ctx);
4056 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4057 append_to_statement_list (x, &copyin_seq);
4058 copyin_by_ref |= by_ref;
4059 break;
4061 case OMP_CLAUSE_REDUCTION:
4062 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4064 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4065 gimple *tseq;
4066 x = build_outer_var_ref (var, ctx);
4068 if (is_reference (var)
4069 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4070 TREE_TYPE (x)))
4071 x = build_fold_addr_expr_loc (clause_loc, x);
4072 SET_DECL_VALUE_EXPR (placeholder, x);
4073 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4074 tree new_vard = new_var;
4075 if (is_reference (var))
4077 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4078 new_vard = TREE_OPERAND (new_var, 0);
4079 gcc_assert (DECL_P (new_vard));
4081 if (is_simd
4082 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4083 idx, lane, ivar, lvar))
4085 if (new_vard == new_var)
4087 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4088 SET_DECL_VALUE_EXPR (new_var, ivar);
4090 else
4092 SET_DECL_VALUE_EXPR (new_vard,
4093 build_fold_addr_expr (ivar));
4094 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4096 x = lang_hooks.decls.omp_clause_default_ctor
4097 (c, unshare_expr (ivar),
4098 build_outer_var_ref (var, ctx));
4099 if (x)
4100 gimplify_and_add (x, &llist[0]);
4101 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4103 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4104 lower_omp (&tseq, ctx);
4105 gimple_seq_add_seq (&llist[0], tseq);
4107 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4108 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4109 lower_omp (&tseq, ctx);
4110 gimple_seq_add_seq (&llist[1], tseq);
4111 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4112 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4113 if (new_vard == new_var)
4114 SET_DECL_VALUE_EXPR (new_var, lvar);
4115 else
4116 SET_DECL_VALUE_EXPR (new_vard,
4117 build_fold_addr_expr (lvar));
4118 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4119 if (x)
4121 tseq = NULL;
4122 dtor = x;
4123 gimplify_stmt (&dtor, &tseq);
4124 gimple_seq_add_seq (&llist[1], tseq);
4126 break;
4128 /* If this is a reference to constant size reduction var
4129 with placeholder, we haven't emitted the initializer
4130 for it because it is undesirable if SIMD arrays are used.
4131 But if they aren't used, we need to emit the deferred
4132 initialization now. */
4133 else if (is_reference (var) && is_simd)
4134 handle_simd_reference (clause_loc, new_vard, ilist);
4135 x = lang_hooks.decls.omp_clause_default_ctor
4136 (c, unshare_expr (new_var),
4137 build_outer_var_ref (var, ctx));
4138 if (x)
4139 gimplify_and_add (x, ilist);
4140 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4142 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4143 lower_omp (&tseq, ctx);
4144 gimple_seq_add_seq (ilist, tseq);
4146 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4147 if (is_simd)
4149 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4150 lower_omp (&tseq, ctx);
4151 gimple_seq_add_seq (dlist, tseq);
4152 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4154 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4155 goto do_dtor;
4157 else
4159 x = omp_reduction_init (c, TREE_TYPE (new_var));
4160 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4161 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4163 /* reduction(-:var) sums up the partial results, so it
4164 acts identically to reduction(+:var). */
4165 if (code == MINUS_EXPR)
4166 code = PLUS_EXPR;
4168 tree new_vard = new_var;
4169 if (is_simd && is_reference (var))
4171 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4172 new_vard = TREE_OPERAND (new_var, 0);
4173 gcc_assert (DECL_P (new_vard));
4175 if (is_simd
4176 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4177 idx, lane, ivar, lvar))
4179 tree ref = build_outer_var_ref (var, ctx);
4181 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4183 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4184 ref = build_outer_var_ref (var, ctx);
4185 gimplify_assign (ref, x, &llist[1]);
4187 if (new_vard != new_var)
4189 SET_DECL_VALUE_EXPR (new_vard,
4190 build_fold_addr_expr (lvar));
4191 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4194 else
4196 if (is_reference (var) && is_simd)
4197 handle_simd_reference (clause_loc, new_vard, ilist);
4198 gimplify_assign (new_var, x, ilist);
4199 if (is_simd)
4201 tree ref = build_outer_var_ref (var, ctx);
4203 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4204 ref = build_outer_var_ref (var, ctx);
4205 gimplify_assign (ref, x, dlist);
4209 break;
4211 default:
4212 gcc_unreachable ();
4217 if (lane)
4219 tree uid = create_tmp_var (ptr_type_node, "simduid");
4220 /* Don't want uninit warnings on simduid, it is always uninitialized,
4221 but we use it not for the value, but for the DECL_UID only. */
4222 TREE_NO_WARNING (uid) = 1;
4223 gimple *g
4224 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4225 gimple_call_set_lhs (g, lane);
4226 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4227 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4228 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4229 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4230 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4231 gimple_omp_for_set_clauses (ctx->stmt, c);
4232 g = gimple_build_assign (lane, INTEGER_CST,
4233 build_int_cst (unsigned_type_node, 0));
4234 gimple_seq_add_stmt (ilist, g);
4235 for (int i = 0; i < 2; i++)
4236 if (llist[i])
4238 tree vf = create_tmp_var (unsigned_type_node);
4239 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4240 gimple_call_set_lhs (g, vf);
4241 gimple_seq *seq = i == 0 ? ilist : dlist;
4242 gimple_seq_add_stmt (seq, g);
4243 tree t = build_int_cst (unsigned_type_node, 0);
4244 g = gimple_build_assign (idx, INTEGER_CST, t);
4245 gimple_seq_add_stmt (seq, g);
4246 tree body = create_artificial_label (UNKNOWN_LOCATION);
4247 tree header = create_artificial_label (UNKNOWN_LOCATION);
4248 tree end = create_artificial_label (UNKNOWN_LOCATION);
4249 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4250 gimple_seq_add_stmt (seq, gimple_build_label (body));
4251 gimple_seq_add_seq (seq, llist[i]);
4252 t = build_int_cst (unsigned_type_node, 1);
4253 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4254 gimple_seq_add_stmt (seq, g);
4255 gimple_seq_add_stmt (seq, gimple_build_label (header));
4256 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4257 gimple_seq_add_stmt (seq, g);
4258 gimple_seq_add_stmt (seq, gimple_build_label (end));
4262 /* The copyin sequence is not to be executed by the main thread, since
4263 that would result in self-copies. Perhaps not visible to scalars,
4264 but it certainly is to C++ operator=. */
4265 if (copyin_seq)
4267 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4269 x = build2 (NE_EXPR, boolean_type_node, x,
4270 build_int_cst (TREE_TYPE (x), 0));
4271 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4272 gimplify_and_add (x, ilist);
4275 /* If any copyin variable is passed by reference, we must ensure the
4276 master thread doesn't modify it before it is copied over in all
4277 threads. Similarly for variables in both firstprivate and
4278 lastprivate clauses we need to ensure the lastprivate copying
4279 happens after firstprivate copying in all threads. And similarly
4280 for UDRs if initializer expression refers to omp_orig. */
4281 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4283 /* Don't add any barrier for #pragma omp simd or
4284 #pragma omp distribute. */
4285 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4286 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4287 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4290 /* If max_vf is non-zero, then we can use only a vectorization factor
4291 up to the max_vf we chose. So stick it into the safelen clause. */
4292 if (max_vf)
4294 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4295 OMP_CLAUSE_SAFELEN);
4296 if (c == NULL_TREE
4297 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4298 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4299 max_vf) == 1))
4301 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4302 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4303 max_vf);
4304 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4305 gimple_omp_for_set_clauses (ctx->stmt, c);
4311 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4312 both parallel and workshare constructs. PREDICATE may be NULL if it's
4313 always true. */
4315 static void
4316 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4317 omp_context *ctx)
4319 tree x, c, label = NULL, orig_clauses = clauses;
4320 bool par_clauses = false;
4321 tree simduid = NULL, lastlane = NULL;
4323 /* Early exit if there are no lastprivate or linear clauses. */
4324 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4325 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4326 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4327 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4328 break;
4329 if (clauses == NULL)
4331 /* If this was a workshare clause, see if it had been combined
4332 with its parallel. In that case, look for the clauses on the
4333 parallel statement itself. */
4334 if (is_parallel_ctx (ctx))
4335 return;
4337 ctx = ctx->outer;
4338 if (ctx == NULL || !is_parallel_ctx (ctx))
4339 return;
4341 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4342 OMP_CLAUSE_LASTPRIVATE);
4343 if (clauses == NULL)
4344 return;
4345 par_clauses = true;
4348 if (predicate)
4350 gcond *stmt;
4351 tree label_true, arm1, arm2;
4353 label = create_artificial_label (UNKNOWN_LOCATION);
4354 label_true = create_artificial_label (UNKNOWN_LOCATION);
4355 arm1 = TREE_OPERAND (predicate, 0);
4356 arm2 = TREE_OPERAND (predicate, 1);
4357 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4358 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4359 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4360 label_true, label);
4361 gimple_seq_add_stmt (stmt_list, stmt);
4362 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4365 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4366 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4368 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4369 if (simduid)
4370 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4373 for (c = clauses; c ;)
4375 tree var, new_var;
4376 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4378 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4379 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4380 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4382 var = OMP_CLAUSE_DECL (c);
4383 new_var = lookup_decl (var, ctx);
4385 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4387 tree val = DECL_VALUE_EXPR (new_var);
4388 if (TREE_CODE (val) == ARRAY_REF
4389 && VAR_P (TREE_OPERAND (val, 0))
4390 && lookup_attribute ("omp simd array",
4391 DECL_ATTRIBUTES (TREE_OPERAND (val,
4392 0))))
4394 if (lastlane == NULL)
4396 lastlane = create_tmp_var (unsigned_type_node);
4397 gcall *g
4398 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4399 2, simduid,
4400 TREE_OPERAND (val, 1));
4401 gimple_call_set_lhs (g, lastlane);
4402 gimple_seq_add_stmt (stmt_list, g);
4404 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4405 TREE_OPERAND (val, 0), lastlane,
4406 NULL_TREE, NULL_TREE);
4410 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4411 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4413 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4414 gimple_seq_add_seq (stmt_list,
4415 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4416 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4418 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4419 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4421 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4422 gimple_seq_add_seq (stmt_list,
4423 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4424 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4427 x = build_outer_var_ref (var, ctx);
4428 if (is_reference (var))
4429 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4430 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4431 gimplify_and_add (x, stmt_list);
4433 c = OMP_CLAUSE_CHAIN (c);
4434 if (c == NULL && !par_clauses)
4436 /* If this was a workshare clause, see if it had been combined
4437 with its parallel. In that case, continue looking for the
4438 clauses also on the parallel statement itself. */
4439 if (is_parallel_ctx (ctx))
4440 break;
4442 ctx = ctx->outer;
4443 if (ctx == NULL || !is_parallel_ctx (ctx))
4444 break;
4446 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4447 OMP_CLAUSE_LASTPRIVATE);
4448 par_clauses = true;
4452 if (label)
4453 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4456 static void
4457 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4458 tree tid, tree var, tree new_var)
4460 /* The atomic add at the end of the sum creates unnecessary
4461 write contention on accelerators. To work around this,
4462 create an array to store the partial reductions. Later, in
4463 lower_omp_for (for openacc), the values of array will be
4464 combined. */
4466 tree t = NULL_TREE, array, x;
4467 tree type = get_base_type (var);
4468 gimple *stmt;
4470 /* Now insert the partial reductions into the array. */
4472 /* Find the reduction array. */
4474 tree ptype = build_pointer_type (type);
4476 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4477 t = build_receiver_ref (t, false, ctx->outer);
4479 array = create_tmp_var (ptype);
4480 gimplify_assign (array, t, stmt_seqp);
4482 tree ptr = create_tmp_var (TREE_TYPE (array));
4484 /* Find the reduction array. */
4486 /* testing a unary conversion. */
4487 tree offset = create_tmp_var (sizetype);
4488 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4489 stmt_seqp);
4490 t = create_tmp_var (sizetype);
4491 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4492 stmt_seqp);
4493 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4494 gimple_seq_add_stmt (stmt_seqp, stmt);
4496 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4497 of adding sizeof(var) to the array? */
4498 ptr = create_tmp_var (ptype);
4499 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4500 offset);
4501 gimple_seq_add_stmt (stmt_seqp, stmt);
4503 /* Move the local sum to gfc$sum[i]. */
4504 x = unshare_expr (build_simple_mem_ref (ptr));
4505 stmt = gimplify_assign (x, new_var, stmt_seqp);
4508 /* Generate code to implement the REDUCTION clauses. */
4510 static void
4511 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4513 gimple_seq sub_seq = NULL;
4514 gimple *stmt;
4515 tree x, c, tid = NULL_TREE;
4516 int count = 0;
4518 /* SIMD reductions are handled in lower_rec_input_clauses. */
4519 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4520 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4521 return;
4523 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4524 update in that case, otherwise use a lock. */
4525 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4526 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4528 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4530 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4531 count = -1;
4532 break;
4534 count++;
4537 if (count == 0)
4538 return;
4540 /* Initialize thread info for OpenACC. */
4541 if (is_gimple_omp_oacc (ctx->stmt))
4543 /* Get the current thread id. */
4544 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4545 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4546 gimple *stmt = gimple_build_call (call, 0);
4547 gimple_call_set_lhs (stmt, tid);
4548 gimple_seq_add_stmt (stmt_seqp, stmt);
4551 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4553 tree var, ref, new_var;
4554 enum tree_code code;
4555 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4557 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4558 continue;
4560 var = OMP_CLAUSE_DECL (c);
4561 new_var = lookup_decl (var, ctx);
4562 if (is_reference (var))
4563 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4564 ref = build_outer_var_ref (var, ctx);
4565 code = OMP_CLAUSE_REDUCTION_CODE (c);
4567 /* reduction(-:var) sums up the partial results, so it acts
4568 identically to reduction(+:var). */
4569 if (code == MINUS_EXPR)
4570 code = PLUS_EXPR;
4572 if (is_gimple_omp_oacc (ctx->stmt))
4574 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4576 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4578 else if (count == 1)
4580 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4582 addr = save_expr (addr);
4583 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4584 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4585 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4586 gimplify_and_add (x, stmt_seqp);
4587 return;
4589 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4591 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4593 if (is_reference (var)
4594 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4595 TREE_TYPE (ref)))
4596 ref = build_fold_addr_expr_loc (clause_loc, ref);
4597 SET_DECL_VALUE_EXPR (placeholder, ref);
4598 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4599 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4600 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4601 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4602 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4604 else
4606 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4607 ref = build_outer_var_ref (var, ctx);
4608 gimplify_assign (ref, x, &sub_seq);
4612 if (is_gimple_omp_oacc (ctx->stmt))
4613 return;
4615 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4617 gimple_seq_add_stmt (stmt_seqp, stmt);
4619 gimple_seq_add_seq (stmt_seqp, sub_seq);
4621 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4623 gimple_seq_add_stmt (stmt_seqp, stmt);
4627 /* Generate code to implement the COPYPRIVATE clauses. */
4629 static void
4630 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4631 omp_context *ctx)
4633 tree c;
4635 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4637 tree var, new_var, ref, x;
4638 bool by_ref;
4639 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4641 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4642 continue;
4644 var = OMP_CLAUSE_DECL (c);
4645 by_ref = use_pointer_for_field (var, NULL);
4647 ref = build_sender_ref (var, ctx);
4648 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4649 if (by_ref)
4651 x = build_fold_addr_expr_loc (clause_loc, new_var);
4652 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4654 gimplify_assign (ref, x, slist);
4656 ref = build_receiver_ref (var, false, ctx);
4657 if (by_ref)
4659 ref = fold_convert_loc (clause_loc,
4660 build_pointer_type (TREE_TYPE (new_var)),
4661 ref);
4662 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4664 if (is_reference (var))
4666 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4667 ref = build_simple_mem_ref_loc (clause_loc, ref);
4668 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4670 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4671 gimplify_and_add (x, rlist);
4676 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4677 and REDUCTION from the sender (aka parent) side. */
4679 static void
4680 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4681 omp_context *ctx)
4683 tree c;
4685 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4687 tree val, ref, x, var;
4688 bool by_ref, do_in = false, do_out = false;
4689 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4691 switch (OMP_CLAUSE_CODE (c))
4693 case OMP_CLAUSE_PRIVATE:
4694 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4695 break;
4696 continue;
4697 case OMP_CLAUSE_FIRSTPRIVATE:
4698 case OMP_CLAUSE_COPYIN:
4699 case OMP_CLAUSE_LASTPRIVATE:
4700 case OMP_CLAUSE_REDUCTION:
4701 case OMP_CLAUSE__LOOPTEMP_:
4702 break;
4703 default:
4704 continue;
4707 val = OMP_CLAUSE_DECL (c);
4708 var = lookup_decl_in_outer_ctx (val, ctx);
4710 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4711 && is_global_var (var))
4712 continue;
4713 if (is_variable_sized (val))
4714 continue;
4715 by_ref = use_pointer_for_field (val, NULL);
4717 switch (OMP_CLAUSE_CODE (c))
4719 case OMP_CLAUSE_PRIVATE:
4720 case OMP_CLAUSE_FIRSTPRIVATE:
4721 case OMP_CLAUSE_COPYIN:
4722 case OMP_CLAUSE__LOOPTEMP_:
4723 do_in = true;
4724 break;
4726 case OMP_CLAUSE_LASTPRIVATE:
4727 if (by_ref || is_reference (val))
4729 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4730 continue;
4731 do_in = true;
4733 else
4735 do_out = true;
4736 if (lang_hooks.decls.omp_private_outer_ref (val))
4737 do_in = true;
4739 break;
4741 case OMP_CLAUSE_REDUCTION:
4742 do_in = true;
4743 do_out = !(by_ref || is_reference (val));
4744 break;
4746 default:
4747 gcc_unreachable ();
4750 if (do_in)
4752 ref = build_sender_ref (val, ctx);
4753 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4754 gimplify_assign (ref, x, ilist);
4755 if (is_task_ctx (ctx))
4756 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4759 if (do_out)
4761 ref = build_sender_ref (val, ctx);
4762 gimplify_assign (var, ref, olist);
4767 /* Generate code to implement SHARED from the sender (aka parent)
4768 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4769 list things that got automatically shared. */
4771 static void
4772 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4774 tree var, ovar, nvar, f, x, record_type;
4776 if (ctx->record_type == NULL)
4777 return;
4779 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4780 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4782 ovar = DECL_ABSTRACT_ORIGIN (f);
4783 nvar = maybe_lookup_decl (ovar, ctx);
4784 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4785 continue;
4787 /* If CTX is a nested parallel directive. Find the immediately
4788 enclosing parallel or workshare construct that contains a
4789 mapping for OVAR. */
4790 var = lookup_decl_in_outer_ctx (ovar, ctx);
4792 if (use_pointer_for_field (ovar, ctx))
4794 x = build_sender_ref (ovar, ctx);
4795 var = build_fold_addr_expr (var);
4796 gimplify_assign (x, var, ilist);
4798 else
4800 x = build_sender_ref (ovar, ctx);
4801 gimplify_assign (x, var, ilist);
4803 if (!TREE_READONLY (var)
4804 /* We don't need to receive a new reference to a result
4805 or parm decl. In fact we may not store to it as we will
4806 invalidate any pending RSO and generate wrong gimple
4807 during inlining. */
4808 && !((TREE_CODE (var) == RESULT_DECL
4809 || TREE_CODE (var) == PARM_DECL)
4810 && DECL_BY_REFERENCE (var)))
4812 x = build_sender_ref (ovar, ctx);
4813 gimplify_assign (var, x, olist);
4820 /* A convenience function to build an empty GIMPLE_COND with just the
4821 condition. */
4823 static gcond *
4824 gimple_build_cond_empty (tree cond)
4826 enum tree_code pred_code;
4827 tree lhs, rhs;
4829 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4830 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4834 /* Build the function calls to GOMP_parallel_start etc to actually
4835 generate the parallel operation. REGION is the parallel region
4836 being expanded. BB is the block where to insert the code. WS_ARGS
4837 will be set if this is a call to a combined parallel+workshare
4838 construct, it contains the list of additional arguments needed by
4839 the workshare construct. */
4841 static void
4842 expand_parallel_call (struct omp_region *region, basic_block bb,
4843 gomp_parallel *entry_stmt,
4844 vec<tree, va_gc> *ws_args)
4846 tree t, t1, t2, val, cond, c, clauses, flags;
4847 gimple_stmt_iterator gsi;
4848 gimple *stmt;
4849 enum built_in_function start_ix;
4850 int start_ix2;
4851 location_t clause_loc;
4852 vec<tree, va_gc> *args;
4854 clauses = gimple_omp_parallel_clauses (entry_stmt);
4856 /* Determine what flavor of GOMP_parallel we will be
4857 emitting. */
4858 start_ix = BUILT_IN_GOMP_PARALLEL;
4859 if (is_combined_parallel (region))
4861 switch (region->inner->type)
4863 case GIMPLE_OMP_FOR:
4864 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4865 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4866 + (region->inner->sched_kind
4867 == OMP_CLAUSE_SCHEDULE_RUNTIME
4868 ? 3 : region->inner->sched_kind));
4869 start_ix = (enum built_in_function)start_ix2;
4870 break;
4871 case GIMPLE_OMP_SECTIONS:
4872 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4873 break;
4874 default:
4875 gcc_unreachable ();
4879 /* By default, the value of NUM_THREADS is zero (selected at run time)
4880 and there is no conditional. */
4881 cond = NULL_TREE;
4882 val = build_int_cst (unsigned_type_node, 0);
4883 flags = build_int_cst (unsigned_type_node, 0);
4885 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4886 if (c)
4887 cond = OMP_CLAUSE_IF_EXPR (c);
4889 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4890 if (c)
4892 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4893 clause_loc = OMP_CLAUSE_LOCATION (c);
4895 else
4896 clause_loc = gimple_location (entry_stmt);
4898 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4899 if (c)
4900 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4902 /* Ensure 'val' is of the correct type. */
4903 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4905 /* If we found the clause 'if (cond)', build either
4906 (cond != 0) or (cond ? val : 1u). */
4907 if (cond)
4909 cond = gimple_boolify (cond);
4911 if (integer_zerop (val))
4912 val = fold_build2_loc (clause_loc,
4913 EQ_EXPR, unsigned_type_node, cond,
4914 build_int_cst (TREE_TYPE (cond), 0));
4915 else
4917 basic_block cond_bb, then_bb, else_bb;
4918 edge e, e_then, e_else;
4919 tree tmp_then, tmp_else, tmp_join, tmp_var;
4921 tmp_var = create_tmp_var (TREE_TYPE (val));
4922 if (gimple_in_ssa_p (cfun))
4924 tmp_then = make_ssa_name (tmp_var);
4925 tmp_else = make_ssa_name (tmp_var);
4926 tmp_join = make_ssa_name (tmp_var);
4928 else
4930 tmp_then = tmp_var;
4931 tmp_else = tmp_var;
4932 tmp_join = tmp_var;
4935 e = split_block_after_labels (bb);
4936 cond_bb = e->src;
4937 bb = e->dest;
4938 remove_edge (e);
4940 then_bb = create_empty_bb (cond_bb);
4941 else_bb = create_empty_bb (then_bb);
4942 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4943 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4945 stmt = gimple_build_cond_empty (cond);
4946 gsi = gsi_start_bb (cond_bb);
4947 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4949 gsi = gsi_start_bb (then_bb);
4950 stmt = gimple_build_assign (tmp_then, val);
4951 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4953 gsi = gsi_start_bb (else_bb);
4954 stmt = gimple_build_assign
4955 (tmp_else, build_int_cst (unsigned_type_node, 1));
4956 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4958 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4959 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4960 add_bb_to_loop (then_bb, cond_bb->loop_father);
4961 add_bb_to_loop (else_bb, cond_bb->loop_father);
4962 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4963 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4965 if (gimple_in_ssa_p (cfun))
4967 gphi *phi = create_phi_node (tmp_join, bb);
4968 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4969 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4972 val = tmp_join;
4975 gsi = gsi_start_bb (bb);
4976 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4977 false, GSI_CONTINUE_LINKING);
4980 gsi = gsi_last_bb (bb);
4981 t = gimple_omp_parallel_data_arg (entry_stmt);
4982 if (t == NULL)
4983 t1 = null_pointer_node;
4984 else
4985 t1 = build_fold_addr_expr (t);
4986 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4988 vec_alloc (args, 4 + vec_safe_length (ws_args));
4989 args->quick_push (t2);
4990 args->quick_push (t1);
4991 args->quick_push (val);
4992 if (ws_args)
4993 args->splice (*ws_args);
4994 args->quick_push (flags);
4996 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4997 builtin_decl_explicit (start_ix), args);
4999 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5000 false, GSI_CONTINUE_LINKING);
5003 /* Insert a function call whose name is FUNC_NAME with the information from
5004 ENTRY_STMT into the basic_block BB. */
5006 static void
5007 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
5008 vec <tree, va_gc> *ws_args)
5010 tree t, t1, t2;
5011 gimple_stmt_iterator gsi;
5012 vec <tree, va_gc> *args;
5014 gcc_assert (vec_safe_length (ws_args) == 2);
5015 tree func_name = (*ws_args)[0];
5016 tree grain = (*ws_args)[1];
5018 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5019 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5020 gcc_assert (count != NULL_TREE);
5021 count = OMP_CLAUSE_OPERAND (count, 0);
5023 gsi = gsi_last_bb (bb);
5024 t = gimple_omp_parallel_data_arg (entry_stmt);
5025 if (t == NULL)
5026 t1 = null_pointer_node;
5027 else
5028 t1 = build_fold_addr_expr (t);
5029 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5031 vec_alloc (args, 4);
5032 args->quick_push (t2);
5033 args->quick_push (t1);
5034 args->quick_push (count);
5035 args->quick_push (grain);
5036 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5038 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5039 GSI_CONTINUE_LINKING);
5042 /* Build the function call to GOMP_task to actually
5043 generate the task operation. BB is the block where to insert the code. */
5045 static void
5046 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5048 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5049 gimple_stmt_iterator gsi;
5050 location_t loc = gimple_location (entry_stmt);
5052 clauses = gimple_omp_task_clauses (entry_stmt);
5054 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5055 if (c)
5056 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5057 else
5058 cond = boolean_true_node;
5060 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5061 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5062 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5063 flags = build_int_cst (unsigned_type_node,
5064 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5066 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5067 if (c)
5069 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5070 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5071 build_int_cst (unsigned_type_node, 2),
5072 build_int_cst (unsigned_type_node, 0));
5073 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5075 if (depend)
5076 depend = OMP_CLAUSE_DECL (depend);
5077 else
5078 depend = build_int_cst (ptr_type_node, 0);
5080 gsi = gsi_last_bb (bb);
5081 t = gimple_omp_task_data_arg (entry_stmt);
5082 if (t == NULL)
5083 t2 = null_pointer_node;
5084 else
5085 t2 = build_fold_addr_expr_loc (loc, t);
5086 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5087 t = gimple_omp_task_copy_fn (entry_stmt);
5088 if (t == NULL)
5089 t3 = null_pointer_node;
5090 else
5091 t3 = build_fold_addr_expr_loc (loc, t);
5093 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5094 8, t1, t2, t3,
5095 gimple_omp_task_arg_size (entry_stmt),
5096 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5097 depend);
5099 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5100 false, GSI_CONTINUE_LINKING);
5104 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5105 catch handler and return it. This prevents programs from violating the
5106 structured block semantics with throws. */
5108 static gimple_seq
5109 maybe_catch_exception (gimple_seq body)
5111 gimple *g;
5112 tree decl;
5114 if (!flag_exceptions)
5115 return body;
5117 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5118 decl = lang_hooks.eh_protect_cleanup_actions ();
5119 else
5120 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5122 g = gimple_build_eh_must_not_throw (decl);
5123 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5124 GIMPLE_TRY_CATCH);
5126 return gimple_seq_alloc_with_stmt (g);
5129 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5131 static tree
5132 vec2chain (vec<tree, va_gc> *v)
5134 tree chain = NULL_TREE, t;
5135 unsigned ix;
5137 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5139 DECL_CHAIN (t) = chain;
5140 chain = t;
5143 return chain;
5147 /* Remove barriers in REGION->EXIT's block. Note that this is only
5148 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5149 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5150 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5151 removed. */
5153 static void
5154 remove_exit_barrier (struct omp_region *region)
5156 gimple_stmt_iterator gsi;
5157 basic_block exit_bb;
5158 edge_iterator ei;
5159 edge e;
5160 gimple *stmt;
5161 int any_addressable_vars = -1;
5163 exit_bb = region->exit;
5165 /* If the parallel region doesn't return, we don't have REGION->EXIT
5166 block at all. */
5167 if (! exit_bb)
5168 return;
5170 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5171 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5172 statements that can appear in between are extremely limited -- no
5173 memory operations at all. Here, we allow nothing at all, so the
5174 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5175 gsi = gsi_last_bb (exit_bb);
5176 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5177 gsi_prev (&gsi);
5178 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5179 return;
5181 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5183 gsi = gsi_last_bb (e->src);
5184 if (gsi_end_p (gsi))
5185 continue;
5186 stmt = gsi_stmt (gsi);
5187 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5188 && !gimple_omp_return_nowait_p (stmt))
5190 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5191 in many cases. If there could be tasks queued, the barrier
5192 might be needed to let the tasks run before some local
5193 variable of the parallel that the task uses as shared
5194 runs out of scope. The task can be spawned either
5195 from within current function (this would be easy to check)
5196 or from some function it calls and gets passed an address
5197 of such a variable. */
5198 if (any_addressable_vars < 0)
5200 gomp_parallel *parallel_stmt
5201 = as_a <gomp_parallel *> (last_stmt (region->entry));
5202 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5203 tree local_decls, block, decl;
5204 unsigned ix;
5206 any_addressable_vars = 0;
5207 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5208 if (TREE_ADDRESSABLE (decl))
5210 any_addressable_vars = 1;
5211 break;
5213 for (block = gimple_block (stmt);
5214 !any_addressable_vars
5215 && block
5216 && TREE_CODE (block) == BLOCK;
5217 block = BLOCK_SUPERCONTEXT (block))
5219 for (local_decls = BLOCK_VARS (block);
5220 local_decls;
5221 local_decls = DECL_CHAIN (local_decls))
5222 if (TREE_ADDRESSABLE (local_decls))
5224 any_addressable_vars = 1;
5225 break;
5227 if (block == gimple_block (parallel_stmt))
5228 break;
5231 if (!any_addressable_vars)
5232 gimple_omp_return_set_nowait (stmt);
5237 static void
5238 remove_exit_barriers (struct omp_region *region)
5240 if (region->type == GIMPLE_OMP_PARALLEL)
5241 remove_exit_barrier (region);
5243 if (region->inner)
5245 region = region->inner;
5246 remove_exit_barriers (region);
5247 while (region->next)
5249 region = region->next;
5250 remove_exit_barriers (region);
5255 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5256 calls. These can't be declared as const functions, but
5257 within one parallel body they are constant, so they can be
5258 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5259 which are declared const. Similarly for task body, except
5260 that in untied task omp_get_thread_num () can change at any task
5261 scheduling point. */
5263 static void
5264 optimize_omp_library_calls (gimple *entry_stmt)
5266 basic_block bb;
5267 gimple_stmt_iterator gsi;
5268 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5269 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5270 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5271 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5272 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5273 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5274 OMP_CLAUSE_UNTIED) != NULL);
5276 FOR_EACH_BB_FN (bb, cfun)
5277 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5279 gimple *call = gsi_stmt (gsi);
5280 tree decl;
5282 if (is_gimple_call (call)
5283 && (decl = gimple_call_fndecl (call))
5284 && DECL_EXTERNAL (decl)
5285 && TREE_PUBLIC (decl)
5286 && DECL_INITIAL (decl) == NULL)
5288 tree built_in;
5290 if (DECL_NAME (decl) == thr_num_id)
5292 /* In #pragma omp task untied omp_get_thread_num () can change
5293 during the execution of the task region. */
5294 if (untied_task)
5295 continue;
5296 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5298 else if (DECL_NAME (decl) == num_thr_id)
5299 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5300 else
5301 continue;
5303 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5304 || gimple_call_num_args (call) != 0)
5305 continue;
5307 if (flag_exceptions && !TREE_NOTHROW (decl))
5308 continue;
5310 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5311 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5312 TREE_TYPE (TREE_TYPE (built_in))))
5313 continue;
5315 gimple_call_set_fndecl (call, built_in);
5320 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5321 regimplified. */
5323 static tree
5324 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5326 tree t = *tp;
5328 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5329 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5330 return t;
5332 if (TREE_CODE (t) == ADDR_EXPR)
5333 recompute_tree_invariant_for_addr_expr (t);
5335 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5336 return NULL_TREE;
5339 /* Prepend TO = FROM assignment before *GSI_P. */
5341 static void
5342 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5344 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5345 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5346 true, GSI_SAME_STMT);
5347 gimple *stmt = gimple_build_assign (to, from);
5348 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5349 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5350 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5352 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5353 gimple_regimplify_operands (stmt, &gsi);
5357 /* Expand the OpenMP parallel or task directive starting at REGION. */
5359 static void
5360 expand_omp_taskreg (struct omp_region *region)
5362 basic_block entry_bb, exit_bb, new_bb;
5363 struct function *child_cfun;
5364 tree child_fn, block, t;
5365 gimple_stmt_iterator gsi;
5366 gimple *entry_stmt, *stmt;
5367 edge e;
5368 vec<tree, va_gc> *ws_args;
5370 entry_stmt = last_stmt (region->entry);
5371 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5372 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5374 entry_bb = region->entry;
5375 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
5376 exit_bb = region->cont;
5377 else
5378 exit_bb = region->exit;
5380 bool is_cilk_for
5381 = (flag_cilkplus
5382 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5383 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5384 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5386 if (is_cilk_for)
5387 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5388 and the inner statement contains the name of the built-in function
5389 and grain. */
5390 ws_args = region->inner->ws_args;
5391 else if (is_combined_parallel (region))
5392 ws_args = region->ws_args;
5393 else
5394 ws_args = NULL;
5396 if (child_cfun->cfg)
5398 /* Due to inlining, it may happen that we have already outlined
5399 the region, in which case all we need to do is make the
5400 sub-graph unreachable and emit the parallel call. */
5401 edge entry_succ_e, exit_succ_e;
5403 entry_succ_e = single_succ_edge (entry_bb);
5405 gsi = gsi_last_bb (entry_bb);
5406 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5407 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5408 gsi_remove (&gsi, true);
5410 new_bb = entry_bb;
5411 if (exit_bb)
5413 exit_succ_e = single_succ_edge (exit_bb);
5414 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5416 remove_edge_and_dominated_blocks (entry_succ_e);
5418 else
5420 unsigned srcidx, dstidx, num;
5422 /* If the parallel region needs data sent from the parent
5423 function, then the very first statement (except possible
5424 tree profile counter updates) of the parallel body
5425 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5426 &.OMP_DATA_O is passed as an argument to the child function,
5427 we need to replace it with the argument as seen by the child
5428 function.
5430 In most cases, this will end up being the identity assignment
5431 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5432 a function call that has been inlined, the original PARM_DECL
5433 .OMP_DATA_I may have been converted into a different local
5434 variable. In which case, we need to keep the assignment. */
5435 if (gimple_omp_taskreg_data_arg (entry_stmt))
5437 basic_block entry_succ_bb
5438 = single_succ_p (entry_bb) ? single_succ (entry_bb)
5439 : FALLTHRU_EDGE (entry_bb)->dest;
5440 tree arg;
5441 gimple *parcopy_stmt = NULL;
5443 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5445 gimple *stmt;
5447 gcc_assert (!gsi_end_p (gsi));
5448 stmt = gsi_stmt (gsi);
5449 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5450 continue;
5452 if (gimple_num_ops (stmt) == 2)
5454 tree arg = gimple_assign_rhs1 (stmt);
5456 /* We're ignore the subcode because we're
5457 effectively doing a STRIP_NOPS. */
5459 if (TREE_CODE (arg) == ADDR_EXPR
5460 && TREE_OPERAND (arg, 0)
5461 == gimple_omp_taskreg_data_arg (entry_stmt))
5463 parcopy_stmt = stmt;
5464 break;
5469 gcc_assert (parcopy_stmt != NULL);
5470 arg = DECL_ARGUMENTS (child_fn);
5472 if (!gimple_in_ssa_p (cfun))
5474 if (gimple_assign_lhs (parcopy_stmt) == arg)
5475 gsi_remove (&gsi, true);
5476 else
5478 /* ?? Is setting the subcode really necessary ?? */
5479 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5480 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5483 else
5485 tree lhs = gimple_assign_lhs (parcopy_stmt);
5486 gcc_assert (SSA_NAME_VAR (lhs) == arg);
5487 /* We'd like to set the rhs to the default def in the child_fn,
5488 but it's too early to create ssa names in the child_fn.
5489 Instead, we set the rhs to the parm. In
5490 move_sese_region_to_fn, we introduce a default def for the
5491 parm, map the parm to it's default def, and once we encounter
5492 this stmt, replace the parm with the default def. */
5493 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5494 update_stmt (parcopy_stmt);
5498 /* Declare local variables needed in CHILD_CFUN. */
5499 block = DECL_INITIAL (child_fn);
5500 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5501 /* The gimplifier could record temporaries in parallel/task block
5502 rather than in containing function's local_decls chain,
5503 which would mean cgraph missed finalizing them. Do it now. */
5504 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5505 if (TREE_CODE (t) == VAR_DECL
5506 && TREE_STATIC (t)
5507 && !DECL_EXTERNAL (t))
5508 varpool_node::finalize_decl (t);
5509 DECL_SAVED_TREE (child_fn) = NULL;
5510 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5511 gimple_set_body (child_fn, NULL);
5512 TREE_USED (block) = 1;
5514 /* Reset DECL_CONTEXT on function arguments. */
5515 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5516 DECL_CONTEXT (t) = child_fn;
5518 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5519 so that it can be moved to the child function. */
5520 gsi = gsi_last_bb (entry_bb);
5521 stmt = gsi_stmt (gsi);
5522 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5523 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5524 e = split_block (entry_bb, stmt);
5525 gsi_remove (&gsi, true);
5526 entry_bb = e->dest;
5527 edge e2 = NULL;
5528 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5529 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5530 else
5532 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
5533 gcc_assert (e2->dest == region->exit);
5534 remove_edge (BRANCH_EDGE (entry_bb));
5535 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
5536 gsi = gsi_last_bb (region->exit);
5537 gcc_assert (!gsi_end_p (gsi)
5538 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5539 gsi_remove (&gsi, true);
5542 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5543 if (exit_bb)
5545 gsi = gsi_last_bb (exit_bb);
5546 gcc_assert (!gsi_end_p (gsi)
5547 && (gimple_code (gsi_stmt (gsi))
5548 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
5549 stmt = gimple_build_return (NULL);
5550 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5551 gsi_remove (&gsi, true);
5554 /* Move the parallel region into CHILD_CFUN. */
5556 if (gimple_in_ssa_p (cfun))
5558 init_tree_ssa (child_cfun);
5559 init_ssa_operands (child_cfun);
5560 child_cfun->gimple_df->in_ssa_p = true;
5561 block = NULL_TREE;
5563 else
5564 block = gimple_block (entry_stmt);
5566 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5567 if (exit_bb)
5568 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5569 if (e2)
5571 basic_block dest_bb = e2->dest;
5572 if (!exit_bb)
5573 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
5574 remove_edge (e2);
5575 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
5577 /* When the OMP expansion process cannot guarantee an up-to-date
5578 loop tree arrange for the child function to fixup loops. */
5579 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5580 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5582 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5583 num = vec_safe_length (child_cfun->local_decls);
5584 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5586 t = (*child_cfun->local_decls)[srcidx];
5587 if (DECL_CONTEXT (t) == cfun->decl)
5588 continue;
5589 if (srcidx != dstidx)
5590 (*child_cfun->local_decls)[dstidx] = t;
5591 dstidx++;
5593 if (dstidx != num)
5594 vec_safe_truncate (child_cfun->local_decls, dstidx);
5596 /* Inform the callgraph about the new function. */
5597 child_cfun->curr_properties = cfun->curr_properties;
5598 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
5599 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
5600 cgraph_node *node = cgraph_node::get_create (child_fn);
5601 node->parallelized_function = 1;
5602 cgraph_node::add_new_function (child_fn, true);
5604 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5605 fixed in a following pass. */
5606 push_cfun (child_cfun);
5607 if (optimize)
5608 optimize_omp_library_calls (entry_stmt);
5609 cgraph_edge::rebuild_edges ();
5611 /* Some EH regions might become dead, see PR34608. If
5612 pass_cleanup_cfg isn't the first pass to happen with the
5613 new child, these dead EH edges might cause problems.
5614 Clean them up now. */
5615 if (flag_exceptions)
5617 basic_block bb;
5618 bool changed = false;
5620 FOR_EACH_BB_FN (bb, cfun)
5621 changed |= gimple_purge_dead_eh_edges (bb);
5622 if (changed)
5623 cleanup_tree_cfg ();
5625 if (gimple_in_ssa_p (cfun))
5626 update_ssa (TODO_update_ssa);
5627 #ifdef ENABLE_CHECKING
5628 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5629 verify_loop_structure ();
5630 #endif
5631 pop_cfun ();
5634 /* Emit a library call to launch the children threads. */
5635 if (is_cilk_for)
5636 expand_cilk_for_call (new_bb,
5637 as_a <gomp_parallel *> (entry_stmt), ws_args);
5638 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5639 expand_parallel_call (region, new_bb,
5640 as_a <gomp_parallel *> (entry_stmt), ws_args);
5641 else
5642 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5643 if (gimple_in_ssa_p (cfun))
5644 update_ssa (TODO_update_ssa_only_virtuals);
5648 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5649 of the combined collapse > 1 loop constructs, generate code like:
5650 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5651 if (cond3 is <)
5652 adj = STEP3 - 1;
5653 else
5654 adj = STEP3 + 1;
5655 count3 = (adj + N32 - N31) / STEP3;
5656 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5657 if (cond2 is <)
5658 adj = STEP2 - 1;
5659 else
5660 adj = STEP2 + 1;
5661 count2 = (adj + N22 - N21) / STEP2;
5662 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5663 if (cond1 is <)
5664 adj = STEP1 - 1;
5665 else
5666 adj = STEP1 + 1;
5667 count1 = (adj + N12 - N11) / STEP1;
5668 count = count1 * count2 * count3;
5669 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5670 count = 0;
5671 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5672 of the combined loop constructs, just initialize COUNTS array
5673 from the _looptemp_ clauses. */
5675 /* NOTE: It *could* be better to moosh all of the BBs together,
5676 creating one larger BB with all the computation and the unexpected
5677 jump at the end. I.e.
5679 bool zero3, zero2, zero1, zero;
5681 zero3 = N32 c3 N31;
5682 count3 = (N32 - N31) /[cl] STEP3;
5683 zero2 = N22 c2 N21;
5684 count2 = (N22 - N21) /[cl] STEP2;
5685 zero1 = N12 c1 N11;
5686 count1 = (N12 - N11) /[cl] STEP1;
5687 zero = zero3 || zero2 || zero1;
5688 count = count1 * count2 * count3;
5689 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5691 After all, we expect the zero=false, and thus we expect to have to
5692 evaluate all of the comparison expressions, so short-circuiting
5693 oughtn't be a win. Since the condition isn't protecting a
5694 denominator, we're not concerned about divide-by-zero, so we can
5695 fully evaluate count even if a numerator turned out to be wrong.
5697 It seems like putting this all together would create much better
5698 scheduling opportunities, and less pressure on the chip's branch
5699 predictor. */
5701 static void
5702 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5703 basic_block &entry_bb, tree *counts,
5704 basic_block &zero_iter_bb, int &first_zero_iter,
5705 basic_block &l2_dom_bb)
5707 tree t, type = TREE_TYPE (fd->loop.v);
5708 edge e, ne;
5709 int i;
5711 /* Collapsed loops need work for expansion into SSA form. */
5712 gcc_assert (!gimple_in_ssa_p (cfun));
5714 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5715 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5717 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5718 isn't supposed to be handled, as the inner loop doesn't
5719 use it. */
5720 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5721 OMP_CLAUSE__LOOPTEMP_);
5722 gcc_assert (innerc);
5723 for (i = 0; i < fd->collapse; i++)
5725 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5726 OMP_CLAUSE__LOOPTEMP_);
5727 gcc_assert (innerc);
5728 if (i)
5729 counts[i] = OMP_CLAUSE_DECL (innerc);
5730 else
5731 counts[0] = NULL_TREE;
5733 return;
5736 for (i = 0; i < fd->collapse; i++)
5738 tree itype = TREE_TYPE (fd->loops[i].v);
5740 if (SSA_VAR_P (fd->loop.n2)
5741 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5742 fold_convert (itype, fd->loops[i].n1),
5743 fold_convert (itype, fd->loops[i].n2)))
5744 == NULL_TREE || !integer_onep (t)))
5746 gcond *cond_stmt;
5747 tree n1, n2;
5748 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5749 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5750 true, GSI_SAME_STMT);
5751 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5752 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5753 true, GSI_SAME_STMT);
5754 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5755 NULL_TREE, NULL_TREE);
5756 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5757 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5758 expand_omp_regimplify_p, NULL, NULL)
5759 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5760 expand_omp_regimplify_p, NULL, NULL))
5762 *gsi = gsi_for_stmt (cond_stmt);
5763 gimple_regimplify_operands (cond_stmt, gsi);
5765 e = split_block (entry_bb, cond_stmt);
5766 if (zero_iter_bb == NULL)
5768 gassign *assign_stmt;
5769 first_zero_iter = i;
5770 zero_iter_bb = create_empty_bb (entry_bb);
5771 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5772 *gsi = gsi_after_labels (zero_iter_bb);
5773 assign_stmt = gimple_build_assign (fd->loop.n2,
5774 build_zero_cst (type));
5775 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5776 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5777 entry_bb);
5779 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5780 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5781 e->flags = EDGE_TRUE_VALUE;
5782 e->probability = REG_BR_PROB_BASE - ne->probability;
5783 if (l2_dom_bb == NULL)
5784 l2_dom_bb = entry_bb;
5785 entry_bb = e->dest;
5786 *gsi = gsi_last_bb (entry_bb);
5789 if (POINTER_TYPE_P (itype))
5790 itype = signed_type_for (itype);
5791 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5792 ? -1 : 1));
5793 t = fold_build2 (PLUS_EXPR, itype,
5794 fold_convert (itype, fd->loops[i].step), t);
5795 t = fold_build2 (PLUS_EXPR, itype, t,
5796 fold_convert (itype, fd->loops[i].n2));
5797 t = fold_build2 (MINUS_EXPR, itype, t,
5798 fold_convert (itype, fd->loops[i].n1));
5799 /* ?? We could probably use CEIL_DIV_EXPR instead of
5800 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5801 generate the same code in the end because generically we
5802 don't know that the values involved must be negative for
5803 GT?? */
5804 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5805 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5806 fold_build1 (NEGATE_EXPR, itype, t),
5807 fold_build1 (NEGATE_EXPR, itype,
5808 fold_convert (itype,
5809 fd->loops[i].step)));
5810 else
5811 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5812 fold_convert (itype, fd->loops[i].step));
5813 t = fold_convert (type, t);
5814 if (TREE_CODE (t) == INTEGER_CST)
5815 counts[i] = t;
5816 else
5818 counts[i] = create_tmp_reg (type, ".count");
5819 expand_omp_build_assign (gsi, counts[i], t);
5821 if (SSA_VAR_P (fd->loop.n2))
5823 if (i == 0)
5824 t = counts[0];
5825 else
5826 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5827 expand_omp_build_assign (gsi, fd->loop.n2, t);
5833 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5834 T = V;
5835 V3 = N31 + (T % count3) * STEP3;
5836 T = T / count3;
5837 V2 = N21 + (T % count2) * STEP2;
5838 T = T / count2;
5839 V1 = N11 + T * STEP1;
5840 if this loop doesn't have an inner loop construct combined with it.
5841 If it does have an inner loop construct combined with it and the
5842 iteration count isn't known constant, store values from counts array
5843 into its _looptemp_ temporaries instead. */
5845 static void
5846 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5847 tree *counts, gimple *inner_stmt, tree startvar)
5849 int i;
5850 if (gimple_omp_for_combined_p (fd->for_stmt))
5852 /* If fd->loop.n2 is constant, then no propagation of the counts
5853 is needed, they are constant. */
5854 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5855 return;
5857 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5858 ? gimple_omp_parallel_clauses (inner_stmt)
5859 : gimple_omp_for_clauses (inner_stmt);
5860 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5861 isn't supposed to be handled, as the inner loop doesn't
5862 use it. */
5863 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5864 gcc_assert (innerc);
5865 for (i = 0; i < fd->collapse; i++)
5867 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5868 OMP_CLAUSE__LOOPTEMP_);
5869 gcc_assert (innerc);
5870 if (i)
5872 tree tem = OMP_CLAUSE_DECL (innerc);
5873 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5874 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5875 false, GSI_CONTINUE_LINKING);
5876 gassign *stmt = gimple_build_assign (tem, t);
5877 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5880 return;
5883 tree type = TREE_TYPE (fd->loop.v);
5884 tree tem = create_tmp_reg (type, ".tem");
5885 gassign *stmt = gimple_build_assign (tem, startvar);
5886 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5888 for (i = fd->collapse - 1; i >= 0; i--)
5890 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5891 itype = vtype;
5892 if (POINTER_TYPE_P (vtype))
5893 itype = signed_type_for (vtype);
5894 if (i != 0)
5895 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5896 else
5897 t = tem;
5898 t = fold_convert (itype, t);
5899 t = fold_build2 (MULT_EXPR, itype, t,
5900 fold_convert (itype, fd->loops[i].step));
5901 if (POINTER_TYPE_P (vtype))
5902 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5903 else
5904 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5905 t = force_gimple_operand_gsi (gsi, t,
5906 DECL_P (fd->loops[i].v)
5907 && TREE_ADDRESSABLE (fd->loops[i].v),
5908 NULL_TREE, false,
5909 GSI_CONTINUE_LINKING);
5910 stmt = gimple_build_assign (fd->loops[i].v, t);
5911 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5912 if (i != 0)
5914 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5915 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5916 false, GSI_CONTINUE_LINKING);
5917 stmt = gimple_build_assign (tem, t);
5918 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5924 /* Helper function for expand_omp_for_*. Generate code like:
5925 L10:
5926 V3 += STEP3;
5927 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5928 L11:
5929 V3 = N31;
5930 V2 += STEP2;
5931 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5932 L12:
5933 V2 = N21;
5934 V1 += STEP1;
5935 goto BODY_BB; */
5937 static basic_block
5938 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5939 basic_block body_bb)
5941 basic_block last_bb, bb, collapse_bb = NULL;
5942 int i;
5943 gimple_stmt_iterator gsi;
5944 edge e;
5945 tree t;
5946 gimple *stmt;
5948 last_bb = cont_bb;
5949 for (i = fd->collapse - 1; i >= 0; i--)
5951 tree vtype = TREE_TYPE (fd->loops[i].v);
5953 bb = create_empty_bb (last_bb);
5954 add_bb_to_loop (bb, last_bb->loop_father);
5955 gsi = gsi_start_bb (bb);
5957 if (i < fd->collapse - 1)
5959 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5960 e->probability = REG_BR_PROB_BASE / 8;
5962 t = fd->loops[i + 1].n1;
5963 t = force_gimple_operand_gsi (&gsi, t,
5964 DECL_P (fd->loops[i + 1].v)
5965 && TREE_ADDRESSABLE (fd->loops[i
5966 + 1].v),
5967 NULL_TREE, false,
5968 GSI_CONTINUE_LINKING);
5969 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5970 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5972 else
5973 collapse_bb = bb;
5975 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5977 if (POINTER_TYPE_P (vtype))
5978 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5979 else
5980 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5981 t = force_gimple_operand_gsi (&gsi, t,
5982 DECL_P (fd->loops[i].v)
5983 && TREE_ADDRESSABLE (fd->loops[i].v),
5984 NULL_TREE, false, GSI_CONTINUE_LINKING);
5985 stmt = gimple_build_assign (fd->loops[i].v, t);
5986 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5988 if (i > 0)
5990 t = fd->loops[i].n2;
5991 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5992 false, GSI_CONTINUE_LINKING);
5993 tree v = fd->loops[i].v;
5994 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5995 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5996 false, GSI_CONTINUE_LINKING);
5997 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5998 stmt = gimple_build_cond_empty (t);
5999 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6000 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
6001 e->probability = REG_BR_PROB_BASE * 7 / 8;
6003 else
6004 make_edge (bb, body_bb, EDGE_FALLTHRU);
6005 last_bb = bb;
6008 return collapse_bb;
6012 /* A subroutine of expand_omp_for. Generate code for a parallel
6013 loop with any schedule. Given parameters:
6015 for (V = N1; V cond N2; V += STEP) BODY;
6017 where COND is "<" or ">", we generate pseudocode
6019 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
6020 if (more) goto L0; else goto L3;
6022 V = istart0;
6023 iend = iend0;
6025 BODY;
6026 V += STEP;
6027 if (V cond iend) goto L1; else goto L2;
6029 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6032 If this is a combined omp parallel loop, instead of the call to
6033 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6034 If this is gimple_omp_for_combined_p loop, then instead of assigning
6035 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6036 inner GIMPLE_OMP_FOR and V += STEP; and
6037 if (V cond iend) goto L1; else goto L2; are removed.
6039 For collapsed loops, given parameters:
6040 collapse(3)
6041 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6042 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6043 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6044 BODY;
6046 we generate pseudocode
6048 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6049 if (cond3 is <)
6050 adj = STEP3 - 1;
6051 else
6052 adj = STEP3 + 1;
6053 count3 = (adj + N32 - N31) / STEP3;
6054 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6055 if (cond2 is <)
6056 adj = STEP2 - 1;
6057 else
6058 adj = STEP2 + 1;
6059 count2 = (adj + N22 - N21) / STEP2;
6060 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6061 if (cond1 is <)
6062 adj = STEP1 - 1;
6063 else
6064 adj = STEP1 + 1;
6065 count1 = (adj + N12 - N11) / STEP1;
6066 count = count1 * count2 * count3;
6067 goto Z1;
6069 count = 0;
6071 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6072 if (more) goto L0; else goto L3;
6074 V = istart0;
6075 T = V;
6076 V3 = N31 + (T % count3) * STEP3;
6077 T = T / count3;
6078 V2 = N21 + (T % count2) * STEP2;
6079 T = T / count2;
6080 V1 = N11 + T * STEP1;
6081 iend = iend0;
6083 BODY;
6084 V += 1;
6085 if (V < iend) goto L10; else goto L2;
6086 L10:
6087 V3 += STEP3;
6088 if (V3 cond3 N32) goto L1; else goto L11;
6089 L11:
6090 V3 = N31;
6091 V2 += STEP2;
6092 if (V2 cond2 N22) goto L1; else goto L12;
6093 L12:
6094 V2 = N21;
6095 V1 += STEP1;
6096 goto L1;
6098 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6103 static void
6104 expand_omp_for_generic (struct omp_region *region,
6105 struct omp_for_data *fd,
6106 enum built_in_function start_fn,
6107 enum built_in_function next_fn,
6108 gimple *inner_stmt)
6110 tree type, istart0, iend0, iend;
6111 tree t, vmain, vback, bias = NULL_TREE;
6112 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6113 basic_block l2_bb = NULL, l3_bb = NULL;
6114 gimple_stmt_iterator gsi;
6115 gassign *assign_stmt;
6116 bool in_combined_parallel = is_combined_parallel (region);
6117 bool broken_loop = region->cont == NULL;
6118 edge e, ne;
6119 tree *counts = NULL;
6120 int i;
6122 gcc_assert (!broken_loop || !in_combined_parallel);
6123 gcc_assert (fd->iter_type == long_integer_type_node
6124 || !in_combined_parallel);
6126 type = TREE_TYPE (fd->loop.v);
6127 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6128 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6129 TREE_ADDRESSABLE (istart0) = 1;
6130 TREE_ADDRESSABLE (iend0) = 1;
6132 /* See if we need to bias by LLONG_MIN. */
6133 if (fd->iter_type == long_long_unsigned_type_node
6134 && TREE_CODE (type) == INTEGER_TYPE
6135 && !TYPE_UNSIGNED (type))
6137 tree n1, n2;
6139 if (fd->loop.cond_code == LT_EXPR)
6141 n1 = fd->loop.n1;
6142 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6144 else
6146 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6147 n2 = fd->loop.n1;
6149 if (TREE_CODE (n1) != INTEGER_CST
6150 || TREE_CODE (n2) != INTEGER_CST
6151 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6152 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6155 entry_bb = region->entry;
6156 cont_bb = region->cont;
6157 collapse_bb = NULL;
6158 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6159 gcc_assert (broken_loop
6160 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6161 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6162 l1_bb = single_succ (l0_bb);
6163 if (!broken_loop)
6165 l2_bb = create_empty_bb (cont_bb);
6166 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6167 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6169 else
6170 l2_bb = NULL;
6171 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6172 exit_bb = region->exit;
6174 gsi = gsi_last_bb (entry_bb);
6176 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6177 if (fd->collapse > 1)
6179 int first_zero_iter = -1;
6180 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6182 counts = XALLOCAVEC (tree, fd->collapse);
6183 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6184 zero_iter_bb, first_zero_iter,
6185 l2_dom_bb);
6187 if (zero_iter_bb)
6189 /* Some counts[i] vars might be uninitialized if
6190 some loop has zero iterations. But the body shouldn't
6191 be executed in that case, so just avoid uninit warnings. */
6192 for (i = first_zero_iter; i < fd->collapse; i++)
6193 if (SSA_VAR_P (counts[i]))
6194 TREE_NO_WARNING (counts[i]) = 1;
6195 gsi_prev (&gsi);
6196 e = split_block (entry_bb, gsi_stmt (gsi));
6197 entry_bb = e->dest;
6198 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6199 gsi = gsi_last_bb (entry_bb);
6200 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6201 get_immediate_dominator (CDI_DOMINATORS,
6202 zero_iter_bb));
6205 if (in_combined_parallel)
6207 /* In a combined parallel loop, emit a call to
6208 GOMP_loop_foo_next. */
6209 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6210 build_fold_addr_expr (istart0),
6211 build_fold_addr_expr (iend0));
6213 else
6215 tree t0, t1, t2, t3, t4;
6216 /* If this is not a combined parallel loop, emit a call to
6217 GOMP_loop_foo_start in ENTRY_BB. */
6218 t4 = build_fold_addr_expr (iend0);
6219 t3 = build_fold_addr_expr (istart0);
6220 t2 = fold_convert (fd->iter_type, fd->loop.step);
6221 t1 = fd->loop.n2;
6222 t0 = fd->loop.n1;
6223 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6225 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6226 OMP_CLAUSE__LOOPTEMP_);
6227 gcc_assert (innerc);
6228 t0 = OMP_CLAUSE_DECL (innerc);
6229 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6230 OMP_CLAUSE__LOOPTEMP_);
6231 gcc_assert (innerc);
6232 t1 = OMP_CLAUSE_DECL (innerc);
6234 if (POINTER_TYPE_P (TREE_TYPE (t0))
6235 && TYPE_PRECISION (TREE_TYPE (t0))
6236 != TYPE_PRECISION (fd->iter_type))
6238 /* Avoid casting pointers to integer of a different size. */
6239 tree itype = signed_type_for (type);
6240 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6241 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6243 else
6245 t1 = fold_convert (fd->iter_type, t1);
6246 t0 = fold_convert (fd->iter_type, t0);
6248 if (bias)
6250 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6251 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6253 if (fd->iter_type == long_integer_type_node)
6255 if (fd->chunk_size)
6257 t = fold_convert (fd->iter_type, fd->chunk_size);
6258 t = build_call_expr (builtin_decl_explicit (start_fn),
6259 6, t0, t1, t2, t, t3, t4);
6261 else
6262 t = build_call_expr (builtin_decl_explicit (start_fn),
6263 5, t0, t1, t2, t3, t4);
6265 else
6267 tree t5;
6268 tree c_bool_type;
6269 tree bfn_decl;
6271 /* The GOMP_loop_ull_*start functions have additional boolean
6272 argument, true for < loops and false for > loops.
6273 In Fortran, the C bool type can be different from
6274 boolean_type_node. */
6275 bfn_decl = builtin_decl_explicit (start_fn);
6276 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6277 t5 = build_int_cst (c_bool_type,
6278 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6279 if (fd->chunk_size)
6281 tree bfn_decl = builtin_decl_explicit (start_fn);
6282 t = fold_convert (fd->iter_type, fd->chunk_size);
6283 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6285 else
6286 t = build_call_expr (builtin_decl_explicit (start_fn),
6287 6, t5, t0, t1, t2, t3, t4);
6290 if (TREE_TYPE (t) != boolean_type_node)
6291 t = fold_build2 (NE_EXPR, boolean_type_node,
6292 t, build_int_cst (TREE_TYPE (t), 0));
6293 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6294 true, GSI_SAME_STMT);
6295 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6297 /* Remove the GIMPLE_OMP_FOR statement. */
6298 gsi_remove (&gsi, true);
6300 /* Iteration setup for sequential loop goes in L0_BB. */
6301 tree startvar = fd->loop.v;
6302 tree endvar = NULL_TREE;
6304 if (gimple_omp_for_combined_p (fd->for_stmt))
6306 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6307 && gimple_omp_for_kind (inner_stmt)
6308 == GF_OMP_FOR_KIND_SIMD);
6309 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6310 OMP_CLAUSE__LOOPTEMP_);
6311 gcc_assert (innerc);
6312 startvar = OMP_CLAUSE_DECL (innerc);
6313 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6314 OMP_CLAUSE__LOOPTEMP_);
6315 gcc_assert (innerc);
6316 endvar = OMP_CLAUSE_DECL (innerc);
6319 gsi = gsi_start_bb (l0_bb);
6320 t = istart0;
6321 if (bias)
6322 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6323 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6324 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6325 t = fold_convert (TREE_TYPE (startvar), t);
6326 t = force_gimple_operand_gsi (&gsi, t,
6327 DECL_P (startvar)
6328 && TREE_ADDRESSABLE (startvar),
6329 NULL_TREE, false, GSI_CONTINUE_LINKING);
6330 assign_stmt = gimple_build_assign (startvar, t);
6331 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6333 t = iend0;
6334 if (bias)
6335 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6336 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6337 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6338 t = fold_convert (TREE_TYPE (startvar), t);
6339 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6340 false, GSI_CONTINUE_LINKING);
6341 if (endvar)
6343 assign_stmt = gimple_build_assign (endvar, iend);
6344 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6345 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6346 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6347 else
6348 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6349 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6351 if (fd->collapse > 1)
6352 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6354 if (!broken_loop)
6356 /* Code to control the increment and predicate for the sequential
6357 loop goes in the CONT_BB. */
6358 gsi = gsi_last_bb (cont_bb);
6359 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6360 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6361 vmain = gimple_omp_continue_control_use (cont_stmt);
6362 vback = gimple_omp_continue_control_def (cont_stmt);
6364 if (!gimple_omp_for_combined_p (fd->for_stmt))
6366 if (POINTER_TYPE_P (type))
6367 t = fold_build_pointer_plus (vmain, fd->loop.step);
6368 else
6369 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6370 t = force_gimple_operand_gsi (&gsi, t,
6371 DECL_P (vback)
6372 && TREE_ADDRESSABLE (vback),
6373 NULL_TREE, true, GSI_SAME_STMT);
6374 assign_stmt = gimple_build_assign (vback, t);
6375 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6377 t = build2 (fd->loop.cond_code, boolean_type_node,
6378 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6379 iend);
6380 gcond *cond_stmt = gimple_build_cond_empty (t);
6381 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6384 /* Remove GIMPLE_OMP_CONTINUE. */
6385 gsi_remove (&gsi, true);
6387 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6388 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6390 /* Emit code to get the next parallel iteration in L2_BB. */
6391 gsi = gsi_start_bb (l2_bb);
6393 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6394 build_fold_addr_expr (istart0),
6395 build_fold_addr_expr (iend0));
6396 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6397 false, GSI_CONTINUE_LINKING);
6398 if (TREE_TYPE (t) != boolean_type_node)
6399 t = fold_build2 (NE_EXPR, boolean_type_node,
6400 t, build_int_cst (TREE_TYPE (t), 0));
6401 gcond *cond_stmt = gimple_build_cond_empty (t);
6402 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6405 /* Add the loop cleanup function. */
6406 gsi = gsi_last_bb (exit_bb);
6407 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6408 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6409 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6410 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6411 else
6412 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6413 gcall *call_stmt = gimple_build_call (t, 0);
6414 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6415 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6416 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6417 gsi_remove (&gsi, true);
6419 /* Connect the new blocks. */
6420 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6421 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6423 if (!broken_loop)
6425 gimple_seq phis;
6427 e = find_edge (cont_bb, l3_bb);
6428 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6430 phis = phi_nodes (l3_bb);
6431 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6433 gimple *phi = gsi_stmt (gsi);
6434 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6435 PHI_ARG_DEF_FROM_EDGE (phi, e));
6437 remove_edge (e);
6439 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6440 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6441 e = find_edge (cont_bb, l1_bb);
6442 if (gimple_omp_for_combined_p (fd->for_stmt))
6444 remove_edge (e);
6445 e = NULL;
6447 else if (fd->collapse > 1)
6449 remove_edge (e);
6450 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6452 else
6453 e->flags = EDGE_TRUE_VALUE;
6454 if (e)
6456 e->probability = REG_BR_PROB_BASE * 7 / 8;
6457 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6459 else
6461 e = find_edge (cont_bb, l2_bb);
6462 e->flags = EDGE_FALLTHRU;
6464 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6466 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6467 recompute_dominator (CDI_DOMINATORS, l2_bb));
6468 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6469 recompute_dominator (CDI_DOMINATORS, l3_bb));
6470 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6471 recompute_dominator (CDI_DOMINATORS, l0_bb));
6472 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6473 recompute_dominator (CDI_DOMINATORS, l1_bb));
6475 struct loop *outer_loop = alloc_loop ();
6476 outer_loop->header = l0_bb;
6477 outer_loop->latch = l2_bb;
6478 add_loop (outer_loop, l0_bb->loop_father);
6480 if (!gimple_omp_for_combined_p (fd->for_stmt))
6482 struct loop *loop = alloc_loop ();
6483 loop->header = l1_bb;
6484 /* The loop may have multiple latches. */
6485 add_loop (loop, outer_loop);
6491 /* A subroutine of expand_omp_for. Generate code for a parallel
6492 loop with static schedule and no specified chunk size. Given
6493 parameters:
6495 for (V = N1; V cond N2; V += STEP) BODY;
6497 where COND is "<" or ">", we generate pseudocode
6499 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6500 if (cond is <)
6501 adj = STEP - 1;
6502 else
6503 adj = STEP + 1;
6504 if ((__typeof (V)) -1 > 0 && cond is >)
6505 n = -(adj + N2 - N1) / -STEP;
6506 else
6507 n = (adj + N2 - N1) / STEP;
6508 q = n / nthreads;
6509 tt = n % nthreads;
6510 if (threadid < tt) goto L3; else goto L4;
6512 tt = 0;
6513 q = q + 1;
6515 s0 = q * threadid + tt;
6516 e0 = s0 + q;
6517 V = s0 * STEP + N1;
6518 if (s0 >= e0) goto L2; else goto L0;
6520 e = e0 * STEP + N1;
6522 BODY;
6523 V += STEP;
6524 if (V cond e) goto L1;
6528 static void
6529 expand_omp_for_static_nochunk (struct omp_region *region,
6530 struct omp_for_data *fd,
6531 gimple *inner_stmt)
6533 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6534 tree type, itype, vmain, vback;
6535 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6536 basic_block body_bb, cont_bb, collapse_bb = NULL;
6537 basic_block fin_bb;
6538 gimple_stmt_iterator gsi;
6539 edge ep;
6540 bool broken_loop = region->cont == NULL;
6541 tree *counts = NULL;
6542 tree n1, n2, step;
6544 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6545 != GF_OMP_FOR_KIND_OACC_LOOP)
6546 || !inner_stmt);
6548 itype = type = TREE_TYPE (fd->loop.v);
6549 if (POINTER_TYPE_P (type))
6550 itype = signed_type_for (type);
6552 entry_bb = region->entry;
6553 cont_bb = region->cont;
6554 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6555 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6556 gcc_assert (broken_loop
6557 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6558 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6559 body_bb = single_succ (seq_start_bb);
6560 if (!broken_loop)
6562 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
6563 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
6564 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6566 exit_bb = region->exit;
6568 /* Iteration space partitioning goes in ENTRY_BB. */
6569 gsi = gsi_last_bb (entry_bb);
6570 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6572 if (fd->collapse > 1)
6574 int first_zero_iter = -1;
6575 basic_block l2_dom_bb = NULL;
6577 counts = XALLOCAVEC (tree, fd->collapse);
6578 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6579 fin_bb, first_zero_iter,
6580 l2_dom_bb);
6581 t = NULL_TREE;
6583 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6584 t = integer_one_node;
6585 else
6586 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6587 fold_convert (type, fd->loop.n1),
6588 fold_convert (type, fd->loop.n2));
6589 if (fd->collapse == 1
6590 && TYPE_UNSIGNED (type)
6591 && (t == NULL_TREE || !integer_onep (t)))
6593 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6594 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6595 true, GSI_SAME_STMT);
6596 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6597 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6598 true, GSI_SAME_STMT);
6599 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6600 NULL_TREE, NULL_TREE);
6601 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6602 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6603 expand_omp_regimplify_p, NULL, NULL)
6604 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6605 expand_omp_regimplify_p, NULL, NULL))
6607 gsi = gsi_for_stmt (cond_stmt);
6608 gimple_regimplify_operands (cond_stmt, &gsi);
6610 ep = split_block (entry_bb, cond_stmt);
6611 ep->flags = EDGE_TRUE_VALUE;
6612 entry_bb = ep->dest;
6613 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6614 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6615 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6616 if (gimple_in_ssa_p (cfun))
6618 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6619 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6620 !gsi_end_p (gpi); gsi_next (&gpi))
6622 gphi *phi = gpi.phi ();
6623 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6624 ep, UNKNOWN_LOCATION);
6627 gsi = gsi_last_bb (entry_bb);
6630 switch (gimple_omp_for_kind (fd->for_stmt))
6632 case GF_OMP_FOR_KIND_FOR:
6633 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6634 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6635 break;
6636 case GF_OMP_FOR_KIND_DISTRIBUTE:
6637 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6638 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6639 break;
6640 case GF_OMP_FOR_KIND_OACC_LOOP:
6641 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6642 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6643 break;
6644 default:
6645 gcc_unreachable ();
6647 nthreads = build_call_expr (nthreads, 0);
6648 nthreads = fold_convert (itype, nthreads);
6649 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6650 true, GSI_SAME_STMT);
6651 threadid = build_call_expr (threadid, 0);
6652 threadid = fold_convert (itype, threadid);
6653 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6654 true, GSI_SAME_STMT);
6656 n1 = fd->loop.n1;
6657 n2 = fd->loop.n2;
6658 step = fd->loop.step;
6659 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6661 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6662 OMP_CLAUSE__LOOPTEMP_);
6663 gcc_assert (innerc);
6664 n1 = OMP_CLAUSE_DECL (innerc);
6665 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6666 OMP_CLAUSE__LOOPTEMP_);
6667 gcc_assert (innerc);
6668 n2 = OMP_CLAUSE_DECL (innerc);
6670 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6671 true, NULL_TREE, true, GSI_SAME_STMT);
6672 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6673 true, NULL_TREE, true, GSI_SAME_STMT);
6674 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6675 true, NULL_TREE, true, GSI_SAME_STMT);
6677 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6678 t = fold_build2 (PLUS_EXPR, itype, step, t);
6679 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6680 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6681 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6682 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6683 fold_build1 (NEGATE_EXPR, itype, t),
6684 fold_build1 (NEGATE_EXPR, itype, step));
6685 else
6686 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6687 t = fold_convert (itype, t);
6688 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6690 q = create_tmp_reg (itype, "q");
6691 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6692 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6693 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6695 tt = create_tmp_reg (itype, "tt");
6696 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6697 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6698 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6700 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6701 gcond *cond_stmt = gimple_build_cond_empty (t);
6702 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6704 second_bb = split_block (entry_bb, cond_stmt)->dest;
6705 gsi = gsi_last_bb (second_bb);
6706 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6708 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6709 GSI_SAME_STMT);
6710 gassign *assign_stmt
6711 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6712 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6714 third_bb = split_block (second_bb, assign_stmt)->dest;
6715 gsi = gsi_last_bb (third_bb);
6716 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6718 t = build2 (MULT_EXPR, itype, q, threadid);
6719 t = build2 (PLUS_EXPR, itype, t, tt);
6720 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6722 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6723 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6725 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6726 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6728 /* Remove the GIMPLE_OMP_FOR statement. */
6729 gsi_remove (&gsi, true);
6731 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6732 gsi = gsi_start_bb (seq_start_bb);
6734 tree startvar = fd->loop.v;
6735 tree endvar = NULL_TREE;
6737 if (gimple_omp_for_combined_p (fd->for_stmt))
6739 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6740 ? gimple_omp_parallel_clauses (inner_stmt)
6741 : gimple_omp_for_clauses (inner_stmt);
6742 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6743 gcc_assert (innerc);
6744 startvar = OMP_CLAUSE_DECL (innerc);
6745 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6746 OMP_CLAUSE__LOOPTEMP_);
6747 gcc_assert (innerc);
6748 endvar = OMP_CLAUSE_DECL (innerc);
6750 t = fold_convert (itype, s0);
6751 t = fold_build2 (MULT_EXPR, itype, t, step);
6752 if (POINTER_TYPE_P (type))
6753 t = fold_build_pointer_plus (n1, t);
6754 else
6755 t = fold_build2 (PLUS_EXPR, type, t, n1);
6756 t = fold_convert (TREE_TYPE (startvar), t);
6757 t = force_gimple_operand_gsi (&gsi, t,
6758 DECL_P (startvar)
6759 && TREE_ADDRESSABLE (startvar),
6760 NULL_TREE, false, GSI_CONTINUE_LINKING);
6761 assign_stmt = gimple_build_assign (startvar, t);
6762 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6764 t = fold_convert (itype, e0);
6765 t = fold_build2 (MULT_EXPR, itype, t, step);
6766 if (POINTER_TYPE_P (type))
6767 t = fold_build_pointer_plus (n1, t);
6768 else
6769 t = fold_build2 (PLUS_EXPR, type, t, n1);
6770 t = fold_convert (TREE_TYPE (startvar), t);
6771 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6772 false, GSI_CONTINUE_LINKING);
6773 if (endvar)
6775 assign_stmt = gimple_build_assign (endvar, e);
6776 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6777 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6778 assign_stmt = gimple_build_assign (fd->loop.v, e);
6779 else
6780 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6781 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6783 if (fd->collapse > 1)
6784 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6786 if (!broken_loop)
6788 /* The code controlling the sequential loop replaces the
6789 GIMPLE_OMP_CONTINUE. */
6790 gsi = gsi_last_bb (cont_bb);
6791 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6792 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6793 vmain = gimple_omp_continue_control_use (cont_stmt);
6794 vback = gimple_omp_continue_control_def (cont_stmt);
6796 if (!gimple_omp_for_combined_p (fd->for_stmt))
6798 if (POINTER_TYPE_P (type))
6799 t = fold_build_pointer_plus (vmain, step);
6800 else
6801 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6802 t = force_gimple_operand_gsi (&gsi, t,
6803 DECL_P (vback)
6804 && TREE_ADDRESSABLE (vback),
6805 NULL_TREE, true, GSI_SAME_STMT);
6806 assign_stmt = gimple_build_assign (vback, t);
6807 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6809 t = build2 (fd->loop.cond_code, boolean_type_node,
6810 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6811 ? t : vback, e);
6812 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6815 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6816 gsi_remove (&gsi, true);
6818 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6819 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6822 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6823 gsi = gsi_last_bb (exit_bb);
6824 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6826 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6827 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6828 gcc_checking_assert (t == NULL_TREE);
6829 else
6830 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6832 gsi_remove (&gsi, true);
6834 /* Connect all the blocks. */
6835 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6836 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6837 ep = find_edge (entry_bb, second_bb);
6838 ep->flags = EDGE_TRUE_VALUE;
6839 ep->probability = REG_BR_PROB_BASE / 4;
6840 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6841 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6843 if (!broken_loop)
6845 ep = find_edge (cont_bb, body_bb);
6846 if (ep == NULL)
6848 ep = BRANCH_EDGE (cont_bb);
6849 gcc_assert (single_succ (ep->dest) == body_bb);
6851 if (gimple_omp_for_combined_p (fd->for_stmt))
6853 remove_edge (ep);
6854 ep = NULL;
6856 else if (fd->collapse > 1)
6858 remove_edge (ep);
6859 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6861 else
6862 ep->flags = EDGE_TRUE_VALUE;
6863 find_edge (cont_bb, fin_bb)->flags
6864 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6867 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6868 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6869 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6871 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6872 recompute_dominator (CDI_DOMINATORS, body_bb));
6873 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6874 recompute_dominator (CDI_DOMINATORS, fin_bb));
6876 struct loop *loop = body_bb->loop_father;
6877 if (loop != entry_bb->loop_father)
6879 gcc_assert (loop->header == body_bb);
6880 gcc_assert (broken_loop
6881 || loop->latch == region->cont
6882 || single_pred (loop->latch) == region->cont);
6883 return;
6886 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6888 loop = alloc_loop ();
6889 loop->header = body_bb;
6890 if (collapse_bb == NULL)
6891 loop->latch = cont_bb;
6892 add_loop (loop, body_bb->loop_father);
6896 /* Return phi in E->DEST with ARG on edge E. */
6898 static gphi *
6899 find_phi_with_arg_on_edge (tree arg, edge e)
6901 basic_block bb = e->dest;
6903 for (gphi_iterator gpi = gsi_start_phis (bb);
6904 !gsi_end_p (gpi);
6905 gsi_next (&gpi))
6907 gphi *phi = gpi.phi ();
6908 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
6909 return phi;
6912 return NULL;
6915 /* A subroutine of expand_omp_for. Generate code for a parallel
6916 loop with static schedule and a specified chunk size. Given
6917 parameters:
6919 for (V = N1; V cond N2; V += STEP) BODY;
6921 where COND is "<" or ">", we generate pseudocode
6923 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6924 if (cond is <)
6925 adj = STEP - 1;
6926 else
6927 adj = STEP + 1;
6928 if ((__typeof (V)) -1 > 0 && cond is >)
6929 n = -(adj + N2 - N1) / -STEP;
6930 else
6931 n = (adj + N2 - N1) / STEP;
6932 trip = 0;
6933 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6934 here so that V is defined
6935 if the loop is not entered
6937 s0 = (trip * nthreads + threadid) * CHUNK;
6938 e0 = min(s0 + CHUNK, n);
6939 if (s0 < n) goto L1; else goto L4;
6941 V = s0 * STEP + N1;
6942 e = e0 * STEP + N1;
6944 BODY;
6945 V += STEP;
6946 if (V cond e) goto L2; else goto L3;
6948 trip += 1;
6949 goto L0;
6953 static void
6954 expand_omp_for_static_chunk (struct omp_region *region,
6955 struct omp_for_data *fd, gimple *inner_stmt)
6957 tree n, s0, e0, e, t;
6958 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6959 tree type, itype, vmain, vback, vextra;
6960 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6961 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6962 gimple_stmt_iterator gsi;
6963 edge se;
6964 bool broken_loop = region->cont == NULL;
6965 tree *counts = NULL;
6966 tree n1, n2, step;
6968 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6969 != GF_OMP_FOR_KIND_OACC_LOOP)
6970 || !inner_stmt);
6972 itype = type = TREE_TYPE (fd->loop.v);
6973 if (POINTER_TYPE_P (type))
6974 itype = signed_type_for (type);
6976 entry_bb = region->entry;
6977 se = split_block (entry_bb, last_stmt (entry_bb));
6978 entry_bb = se->src;
6979 iter_part_bb = se->dest;
6980 cont_bb = region->cont;
6981 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6982 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6983 gcc_assert (broken_loop
6984 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6985 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6986 body_bb = single_succ (seq_start_bb);
6987 if (!broken_loop)
6989 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
6990 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
6991 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6992 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6994 exit_bb = region->exit;
6996 /* Trip and adjustment setup goes in ENTRY_BB. */
6997 gsi = gsi_last_bb (entry_bb);
6998 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7000 if (fd->collapse > 1)
7002 int first_zero_iter = -1;
7003 basic_block l2_dom_bb = NULL;
7005 counts = XALLOCAVEC (tree, fd->collapse);
7006 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7007 fin_bb, first_zero_iter,
7008 l2_dom_bb);
7009 t = NULL_TREE;
7011 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
7012 t = integer_one_node;
7013 else
7014 t = fold_binary (fd->loop.cond_code, boolean_type_node,
7015 fold_convert (type, fd->loop.n1),
7016 fold_convert (type, fd->loop.n2));
7017 if (fd->collapse == 1
7018 && TYPE_UNSIGNED (type)
7019 && (t == NULL_TREE || !integer_onep (t)))
7021 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
7022 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
7023 true, GSI_SAME_STMT);
7024 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
7025 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
7026 true, GSI_SAME_STMT);
7027 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
7028 NULL_TREE, NULL_TREE);
7029 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
7030 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7031 expand_omp_regimplify_p, NULL, NULL)
7032 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7033 expand_omp_regimplify_p, NULL, NULL))
7035 gsi = gsi_for_stmt (cond_stmt);
7036 gimple_regimplify_operands (cond_stmt, &gsi);
7038 se = split_block (entry_bb, cond_stmt);
7039 se->flags = EDGE_TRUE_VALUE;
7040 entry_bb = se->dest;
7041 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
7042 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
7043 se->probability = REG_BR_PROB_BASE / 2000 - 1;
7044 if (gimple_in_ssa_p (cfun))
7046 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
7047 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
7048 !gsi_end_p (gpi); gsi_next (&gpi))
7050 gphi *phi = gpi.phi ();
7051 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
7052 se, UNKNOWN_LOCATION);
7055 gsi = gsi_last_bb (entry_bb);
7058 switch (gimple_omp_for_kind (fd->for_stmt))
7060 case GF_OMP_FOR_KIND_FOR:
7061 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7062 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7063 break;
7064 case GF_OMP_FOR_KIND_DISTRIBUTE:
7065 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7066 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7067 break;
7068 case GF_OMP_FOR_KIND_OACC_LOOP:
7069 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7070 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7071 break;
7072 default:
7073 gcc_unreachable ();
7075 nthreads = build_call_expr (nthreads, 0);
7076 nthreads = fold_convert (itype, nthreads);
7077 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7078 true, GSI_SAME_STMT);
7079 threadid = build_call_expr (threadid, 0);
7080 threadid = fold_convert (itype, threadid);
7081 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7082 true, GSI_SAME_STMT);
7084 n1 = fd->loop.n1;
7085 n2 = fd->loop.n2;
7086 step = fd->loop.step;
7087 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7089 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7090 OMP_CLAUSE__LOOPTEMP_);
7091 gcc_assert (innerc);
7092 n1 = OMP_CLAUSE_DECL (innerc);
7093 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7094 OMP_CLAUSE__LOOPTEMP_);
7095 gcc_assert (innerc);
7096 n2 = OMP_CLAUSE_DECL (innerc);
7098 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7099 true, NULL_TREE, true, GSI_SAME_STMT);
7100 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7101 true, NULL_TREE, true, GSI_SAME_STMT);
7102 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7103 true, NULL_TREE, true, GSI_SAME_STMT);
7104 fd->chunk_size
7105 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7106 true, NULL_TREE, true, GSI_SAME_STMT);
7108 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7109 t = fold_build2 (PLUS_EXPR, itype, step, t);
7110 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7111 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7112 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7113 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7114 fold_build1 (NEGATE_EXPR, itype, t),
7115 fold_build1 (NEGATE_EXPR, itype, step));
7116 else
7117 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7118 t = fold_convert (itype, t);
7119 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7120 true, GSI_SAME_STMT);
7122 trip_var = create_tmp_reg (itype, ".trip");
7123 if (gimple_in_ssa_p (cfun))
7125 trip_init = make_ssa_name (trip_var);
7126 trip_main = make_ssa_name (trip_var);
7127 trip_back = make_ssa_name (trip_var);
7129 else
7131 trip_init = trip_var;
7132 trip_main = trip_var;
7133 trip_back = trip_var;
7136 gassign *assign_stmt
7137 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7138 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7140 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7141 t = fold_build2 (MULT_EXPR, itype, t, step);
7142 if (POINTER_TYPE_P (type))
7143 t = fold_build_pointer_plus (n1, t);
7144 else
7145 t = fold_build2 (PLUS_EXPR, type, t, n1);
7146 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7147 true, GSI_SAME_STMT);
7149 /* Remove the GIMPLE_OMP_FOR. */
7150 gsi_remove (&gsi, true);
7152 /* Iteration space partitioning goes in ITER_PART_BB. */
7153 gsi = gsi_last_bb (iter_part_bb);
7155 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7156 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7157 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7158 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7159 false, GSI_CONTINUE_LINKING);
7161 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7162 t = fold_build2 (MIN_EXPR, itype, t, n);
7163 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7164 false, GSI_CONTINUE_LINKING);
7166 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7167 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7169 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7170 gsi = gsi_start_bb (seq_start_bb);
7172 tree startvar = fd->loop.v;
7173 tree endvar = NULL_TREE;
7175 if (gimple_omp_for_combined_p (fd->for_stmt))
7177 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7178 ? gimple_omp_parallel_clauses (inner_stmt)
7179 : gimple_omp_for_clauses (inner_stmt);
7180 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7181 gcc_assert (innerc);
7182 startvar = OMP_CLAUSE_DECL (innerc);
7183 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7184 OMP_CLAUSE__LOOPTEMP_);
7185 gcc_assert (innerc);
7186 endvar = OMP_CLAUSE_DECL (innerc);
7189 t = fold_convert (itype, s0);
7190 t = fold_build2 (MULT_EXPR, itype, t, step);
7191 if (POINTER_TYPE_P (type))
7192 t = fold_build_pointer_plus (n1, t);
7193 else
7194 t = fold_build2 (PLUS_EXPR, type, t, n1);
7195 t = fold_convert (TREE_TYPE (startvar), t);
7196 t = force_gimple_operand_gsi (&gsi, t,
7197 DECL_P (startvar)
7198 && TREE_ADDRESSABLE (startvar),
7199 NULL_TREE, false, GSI_CONTINUE_LINKING);
7200 assign_stmt = gimple_build_assign (startvar, t);
7201 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7203 t = fold_convert (itype, e0);
7204 t = fold_build2 (MULT_EXPR, itype, t, step);
7205 if (POINTER_TYPE_P (type))
7206 t = fold_build_pointer_plus (n1, t);
7207 else
7208 t = fold_build2 (PLUS_EXPR, type, t, n1);
7209 t = fold_convert (TREE_TYPE (startvar), t);
7210 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7211 false, GSI_CONTINUE_LINKING);
7212 if (endvar)
7214 assign_stmt = gimple_build_assign (endvar, e);
7215 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7216 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7217 assign_stmt = gimple_build_assign (fd->loop.v, e);
7218 else
7219 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7220 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7222 if (fd->collapse > 1)
7223 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7225 if (!broken_loop)
7227 /* The code controlling the sequential loop goes in CONT_BB,
7228 replacing the GIMPLE_OMP_CONTINUE. */
7229 gsi = gsi_last_bb (cont_bb);
7230 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7231 vmain = gimple_omp_continue_control_use (cont_stmt);
7232 vback = gimple_omp_continue_control_def (cont_stmt);
7234 if (!gimple_omp_for_combined_p (fd->for_stmt))
7236 if (POINTER_TYPE_P (type))
7237 t = fold_build_pointer_plus (vmain, step);
7238 else
7239 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7240 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7241 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7242 true, GSI_SAME_STMT);
7243 assign_stmt = gimple_build_assign (vback, t);
7244 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7246 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
7247 t = build2 (EQ_EXPR, boolean_type_node,
7248 build_int_cst (itype, 0),
7249 build_int_cst (itype, 1));
7250 else
7251 t = build2 (fd->loop.cond_code, boolean_type_node,
7252 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7253 ? t : vback, e);
7254 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7257 /* Remove GIMPLE_OMP_CONTINUE. */
7258 gsi_remove (&gsi, true);
7260 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7261 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7263 /* Trip update code goes into TRIP_UPDATE_BB. */
7264 gsi = gsi_start_bb (trip_update_bb);
7266 t = build_int_cst (itype, 1);
7267 t = build2 (PLUS_EXPR, itype, trip_main, t);
7268 assign_stmt = gimple_build_assign (trip_back, t);
7269 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7272 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7273 gsi = gsi_last_bb (exit_bb);
7274 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7276 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7277 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7278 gcc_checking_assert (t == NULL_TREE);
7279 else
7280 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7282 gsi_remove (&gsi, true);
7284 /* Connect the new blocks. */
7285 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7286 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7288 if (!broken_loop)
7290 se = find_edge (cont_bb, body_bb);
7291 if (se == NULL)
7293 se = BRANCH_EDGE (cont_bb);
7294 gcc_assert (single_succ (se->dest) == body_bb);
7296 if (gimple_omp_for_combined_p (fd->for_stmt))
7298 remove_edge (se);
7299 se = NULL;
7301 else if (fd->collapse > 1)
7303 remove_edge (se);
7304 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7306 else
7307 se->flags = EDGE_TRUE_VALUE;
7308 find_edge (cont_bb, trip_update_bb)->flags
7309 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7311 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7314 if (gimple_in_ssa_p (cfun))
7316 gphi_iterator psi;
7317 gphi *phi;
7318 edge re, ene;
7319 edge_var_map *vm;
7320 size_t i;
7322 gcc_assert (fd->collapse == 1 && !broken_loop);
7324 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7325 remove arguments of the phi nodes in fin_bb. We need to create
7326 appropriate phi nodes in iter_part_bb instead. */
7327 se = find_edge (iter_part_bb, fin_bb);
7328 re = single_succ_edge (trip_update_bb);
7329 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7330 ene = single_succ_edge (entry_bb);
7332 psi = gsi_start_phis (fin_bb);
7333 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7334 gsi_next (&psi), ++i)
7336 gphi *nphi;
7337 source_location locus;
7339 phi = psi.phi ();
7340 t = gimple_phi_result (phi);
7341 gcc_assert (t == redirect_edge_var_map_result (vm));
7343 if (!single_pred_p (fin_bb))
7344 t = copy_ssa_name (t, phi);
7346 nphi = create_phi_node (t, iter_part_bb);
7348 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7349 locus = gimple_phi_arg_location_from_edge (phi, se);
7351 /* A special case -- fd->loop.v is not yet computed in
7352 iter_part_bb, we need to use vextra instead. */
7353 if (t == fd->loop.v)
7354 t = vextra;
7355 add_phi_arg (nphi, t, ene, locus);
7356 locus = redirect_edge_var_map_location (vm);
7357 tree back_arg = redirect_edge_var_map_def (vm);
7358 add_phi_arg (nphi, back_arg, re, locus);
7359 edge ce = find_edge (cont_bb, body_bb);
7360 if (ce == NULL)
7362 ce = BRANCH_EDGE (cont_bb);
7363 gcc_assert (single_succ (ce->dest) == body_bb);
7364 ce = single_succ_edge (ce->dest);
7366 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
7367 gcc_assert (inner_loop_phi != NULL);
7368 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
7369 find_edge (seq_start_bb, body_bb), locus);
7371 if (!single_pred_p (fin_bb))
7372 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
7374 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
7375 redirect_edge_var_map_clear (re);
7376 if (single_pred_p (fin_bb))
7377 while (1)
7379 psi = gsi_start_phis (fin_bb);
7380 if (gsi_end_p (psi))
7381 break;
7382 remove_phi_node (&psi, false);
7385 /* Make phi node for trip. */
7386 phi = create_phi_node (trip_main, iter_part_bb);
7387 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7388 UNKNOWN_LOCATION);
7389 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7390 UNKNOWN_LOCATION);
7393 if (!broken_loop)
7394 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7395 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7396 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7397 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7398 recompute_dominator (CDI_DOMINATORS, fin_bb));
7399 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7400 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7401 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7402 recompute_dominator (CDI_DOMINATORS, body_bb));
7404 if (!broken_loop)
7406 struct loop *loop = body_bb->loop_father;
7407 struct loop *trip_loop = alloc_loop ();
7408 trip_loop->header = iter_part_bb;
7409 trip_loop->latch = trip_update_bb;
7410 add_loop (trip_loop, iter_part_bb->loop_father);
7412 if (loop != entry_bb->loop_father)
7414 gcc_assert (loop->header == body_bb);
7415 gcc_assert (loop->latch == region->cont
7416 || single_pred (loop->latch) == region->cont);
7417 trip_loop->inner = loop;
7418 return;
7421 if (!gimple_omp_for_combined_p (fd->for_stmt))
7423 loop = alloc_loop ();
7424 loop->header = body_bb;
7425 if (collapse_bb == NULL)
7426 loop->latch = cont_bb;
7427 add_loop (loop, trip_loop);
7432 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7433 Given parameters:
7434 for (V = N1; V cond N2; V += STEP) BODY;
7436 where COND is "<" or ">" or "!=", we generate pseudocode
7438 for (ind_var = low; ind_var < high; ind_var++)
7440 V = n1 + (ind_var * STEP)
7442 <BODY>
7445 In the above pseudocode, low and high are function parameters of the
7446 child function. In the function below, we are inserting a temp.
7447 variable that will be making a call to two OMP functions that will not be
7448 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7449 with _Cilk_for). These functions are replaced with low and high
7450 by the function that handles taskreg. */
7453 static void
7454 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7456 bool broken_loop = region->cont == NULL;
7457 basic_block entry_bb = region->entry;
7458 basic_block cont_bb = region->cont;
7460 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7461 gcc_assert (broken_loop
7462 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7463 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7464 basic_block l1_bb, l2_bb;
7466 if (!broken_loop)
7468 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7469 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7470 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7471 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7473 else
7475 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7476 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7477 l2_bb = single_succ (l1_bb);
7479 basic_block exit_bb = region->exit;
7480 basic_block l2_dom_bb = NULL;
7482 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7484 /* Below statements until the "tree high_val = ..." are pseudo statements
7485 used to pass information to be used by expand_omp_taskreg.
7486 low_val and high_val will be replaced by the __low and __high
7487 parameter from the child function.
7489 The call_exprs part is a place-holder, it is mainly used
7490 to distinctly identify to the top-level part that this is
7491 where we should put low and high (reasoning given in header
7492 comment). */
7494 tree child_fndecl
7495 = gimple_omp_parallel_child_fn (
7496 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7497 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7498 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7500 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7501 high_val = t;
7502 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7503 low_val = t;
7505 gcc_assert (low_val && high_val);
7507 tree type = TREE_TYPE (low_val);
7508 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7509 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7511 /* Not needed in SSA form right now. */
7512 gcc_assert (!gimple_in_ssa_p (cfun));
7513 if (l2_dom_bb == NULL)
7514 l2_dom_bb = l1_bb;
7516 tree n1 = low_val;
7517 tree n2 = high_val;
7519 gimple *stmt = gimple_build_assign (ind_var, n1);
7521 /* Replace the GIMPLE_OMP_FOR statement. */
7522 gsi_replace (&gsi, stmt, true);
7524 if (!broken_loop)
7526 /* Code to control the increment goes in the CONT_BB. */
7527 gsi = gsi_last_bb (cont_bb);
7528 stmt = gsi_stmt (gsi);
7529 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7530 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7531 build_one_cst (type));
7533 /* Replace GIMPLE_OMP_CONTINUE. */
7534 gsi_replace (&gsi, stmt, true);
7537 /* Emit the condition in L1_BB. */
7538 gsi = gsi_after_labels (l1_bb);
7539 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7540 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7541 fd->loop.step);
7542 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7543 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7544 fd->loop.n1, fold_convert (sizetype, t));
7545 else
7546 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7547 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7548 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7549 expand_omp_build_assign (&gsi, fd->loop.v, t);
7551 /* The condition is always '<' since the runtime will fill in the low
7552 and high values. */
7553 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7554 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7556 /* Remove GIMPLE_OMP_RETURN. */
7557 gsi = gsi_last_bb (exit_bb);
7558 gsi_remove (&gsi, true);
7560 /* Connect the new blocks. */
7561 remove_edge (FALLTHRU_EDGE (entry_bb));
7563 edge e, ne;
7564 if (!broken_loop)
7566 remove_edge (BRANCH_EDGE (entry_bb));
7567 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7569 e = BRANCH_EDGE (l1_bb);
7570 ne = FALLTHRU_EDGE (l1_bb);
7571 e->flags = EDGE_TRUE_VALUE;
7573 else
7575 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7577 ne = single_succ_edge (l1_bb);
7578 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7581 ne->flags = EDGE_FALSE_VALUE;
7582 e->probability = REG_BR_PROB_BASE * 7 / 8;
7583 ne->probability = REG_BR_PROB_BASE / 8;
7585 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7586 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7587 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7589 if (!broken_loop)
7591 struct loop *loop = alloc_loop ();
7592 loop->header = l1_bb;
7593 loop->latch = cont_bb;
7594 add_loop (loop, l1_bb->loop_father);
7595 loop->safelen = INT_MAX;
7598 /* Pick the correct library function based on the precision of the
7599 induction variable type. */
7600 tree lib_fun = NULL_TREE;
7601 if (TYPE_PRECISION (type) == 32)
7602 lib_fun = cilk_for_32_fndecl;
7603 else if (TYPE_PRECISION (type) == 64)
7604 lib_fun = cilk_for_64_fndecl;
7605 else
7606 gcc_unreachable ();
7608 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7610 /* WS_ARGS contains the library function flavor to call:
7611 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7612 user-defined grain value. If the user does not define one, then zero
7613 is passed in by the parser. */
7614 vec_alloc (region->ws_args, 2);
7615 region->ws_args->quick_push (lib_fun);
7616 region->ws_args->quick_push (fd->chunk_size);
7619 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7620 loop. Given parameters:
7622 for (V = N1; V cond N2; V += STEP) BODY;
7624 where COND is "<" or ">", we generate pseudocode
7626 V = N1;
7627 goto L1;
7629 BODY;
7630 V += STEP;
7632 if (V cond N2) goto L0; else goto L2;
7635 For collapsed loops, given parameters:
7636 collapse(3)
7637 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7638 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7639 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7640 BODY;
7642 we generate pseudocode
7644 if (cond3 is <)
7645 adj = STEP3 - 1;
7646 else
7647 adj = STEP3 + 1;
7648 count3 = (adj + N32 - N31) / STEP3;
7649 if (cond2 is <)
7650 adj = STEP2 - 1;
7651 else
7652 adj = STEP2 + 1;
7653 count2 = (adj + N22 - N21) / STEP2;
7654 if (cond1 is <)
7655 adj = STEP1 - 1;
7656 else
7657 adj = STEP1 + 1;
7658 count1 = (adj + N12 - N11) / STEP1;
7659 count = count1 * count2 * count3;
7660 V = 0;
7661 V1 = N11;
7662 V2 = N21;
7663 V3 = N31;
7664 goto L1;
7666 BODY;
7667 V += 1;
7668 V3 += STEP3;
7669 V2 += (V3 cond3 N32) ? 0 : STEP2;
7670 V3 = (V3 cond3 N32) ? V3 : N31;
7671 V1 += (V2 cond2 N22) ? 0 : STEP1;
7672 V2 = (V2 cond2 N22) ? V2 : N21;
7674 if (V < count) goto L0; else goto L2;
7679 static void
7680 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7682 tree type, t;
7683 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7684 gimple_stmt_iterator gsi;
7685 gimple *stmt;
7686 gcond *cond_stmt;
7687 bool broken_loop = region->cont == NULL;
7688 edge e, ne;
7689 tree *counts = NULL;
7690 int i;
7691 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7692 OMP_CLAUSE_SAFELEN);
7693 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7694 OMP_CLAUSE__SIMDUID_);
7695 tree n1, n2;
7697 type = TREE_TYPE (fd->loop.v);
7698 entry_bb = region->entry;
7699 cont_bb = region->cont;
7700 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7701 gcc_assert (broken_loop
7702 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7703 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7704 if (!broken_loop)
7706 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7707 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7708 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7709 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7711 else
7713 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7714 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7715 l2_bb = single_succ (l1_bb);
7717 exit_bb = region->exit;
7718 l2_dom_bb = NULL;
7720 gsi = gsi_last_bb (entry_bb);
7722 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7723 /* Not needed in SSA form right now. */
7724 gcc_assert (!gimple_in_ssa_p (cfun));
7725 if (fd->collapse > 1)
7727 int first_zero_iter = -1;
7728 basic_block zero_iter_bb = l2_bb;
7730 counts = XALLOCAVEC (tree, fd->collapse);
7731 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7732 zero_iter_bb, first_zero_iter,
7733 l2_dom_bb);
7735 if (l2_dom_bb == NULL)
7736 l2_dom_bb = l1_bb;
7738 n1 = fd->loop.n1;
7739 n2 = fd->loop.n2;
7740 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7742 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7743 OMP_CLAUSE__LOOPTEMP_);
7744 gcc_assert (innerc);
7745 n1 = OMP_CLAUSE_DECL (innerc);
7746 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7747 OMP_CLAUSE__LOOPTEMP_);
7748 gcc_assert (innerc);
7749 n2 = OMP_CLAUSE_DECL (innerc);
7750 expand_omp_build_assign (&gsi, fd->loop.v,
7751 fold_convert (type, n1));
7752 if (fd->collapse > 1)
7754 gsi_prev (&gsi);
7755 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7756 gsi_next (&gsi);
7759 else
7761 expand_omp_build_assign (&gsi, fd->loop.v,
7762 fold_convert (type, fd->loop.n1));
7763 if (fd->collapse > 1)
7764 for (i = 0; i < fd->collapse; i++)
7766 tree itype = TREE_TYPE (fd->loops[i].v);
7767 if (POINTER_TYPE_P (itype))
7768 itype = signed_type_for (itype);
7769 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7770 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7774 /* Remove the GIMPLE_OMP_FOR statement. */
7775 gsi_remove (&gsi, true);
7777 if (!broken_loop)
7779 /* Code to control the increment goes in the CONT_BB. */
7780 gsi = gsi_last_bb (cont_bb);
7781 stmt = gsi_stmt (gsi);
7782 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7784 if (POINTER_TYPE_P (type))
7785 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7786 else
7787 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7788 expand_omp_build_assign (&gsi, fd->loop.v, t);
7790 if (fd->collapse > 1)
7792 i = fd->collapse - 1;
7793 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7795 t = fold_convert (sizetype, fd->loops[i].step);
7796 t = fold_build_pointer_plus (fd->loops[i].v, t);
7798 else
7800 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7801 fd->loops[i].step);
7802 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7803 fd->loops[i].v, t);
7805 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7807 for (i = fd->collapse - 1; i > 0; i--)
7809 tree itype = TREE_TYPE (fd->loops[i].v);
7810 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7811 if (POINTER_TYPE_P (itype2))
7812 itype2 = signed_type_for (itype2);
7813 t = build3 (COND_EXPR, itype2,
7814 build2 (fd->loops[i].cond_code, boolean_type_node,
7815 fd->loops[i].v,
7816 fold_convert (itype, fd->loops[i].n2)),
7817 build_int_cst (itype2, 0),
7818 fold_convert (itype2, fd->loops[i - 1].step));
7819 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7820 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7821 else
7822 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7823 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7825 t = build3 (COND_EXPR, itype,
7826 build2 (fd->loops[i].cond_code, boolean_type_node,
7827 fd->loops[i].v,
7828 fold_convert (itype, fd->loops[i].n2)),
7829 fd->loops[i].v,
7830 fold_convert (itype, fd->loops[i].n1));
7831 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7835 /* Remove GIMPLE_OMP_CONTINUE. */
7836 gsi_remove (&gsi, true);
7839 /* Emit the condition in L1_BB. */
7840 gsi = gsi_start_bb (l1_bb);
7842 t = fold_convert (type, n2);
7843 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7844 false, GSI_CONTINUE_LINKING);
7845 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7846 cond_stmt = gimple_build_cond_empty (t);
7847 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7848 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7849 NULL, NULL)
7850 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7851 NULL, NULL))
7853 gsi = gsi_for_stmt (cond_stmt);
7854 gimple_regimplify_operands (cond_stmt, &gsi);
7857 /* Remove GIMPLE_OMP_RETURN. */
7858 gsi = gsi_last_bb (exit_bb);
7859 gsi_remove (&gsi, true);
7861 /* Connect the new blocks. */
7862 remove_edge (FALLTHRU_EDGE (entry_bb));
7864 if (!broken_loop)
7866 remove_edge (BRANCH_EDGE (entry_bb));
7867 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7869 e = BRANCH_EDGE (l1_bb);
7870 ne = FALLTHRU_EDGE (l1_bb);
7871 e->flags = EDGE_TRUE_VALUE;
7873 else
7875 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7877 ne = single_succ_edge (l1_bb);
7878 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7881 ne->flags = EDGE_FALSE_VALUE;
7882 e->probability = REG_BR_PROB_BASE * 7 / 8;
7883 ne->probability = REG_BR_PROB_BASE / 8;
7885 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7886 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7887 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7889 if (!broken_loop)
7891 struct loop *loop = alloc_loop ();
7892 loop->header = l1_bb;
7893 loop->latch = cont_bb;
7894 add_loop (loop, l1_bb->loop_father);
7895 if (safelen == NULL_TREE)
7896 loop->safelen = INT_MAX;
7897 else
7899 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7900 if (TREE_CODE (safelen) != INTEGER_CST)
7901 loop->safelen = 0;
7902 else if (!tree_fits_uhwi_p (safelen)
7903 || tree_to_uhwi (safelen) > INT_MAX)
7904 loop->safelen = INT_MAX;
7905 else
7906 loop->safelen = tree_to_uhwi (safelen);
7907 if (loop->safelen == 1)
7908 loop->safelen = 0;
7910 if (simduid)
7912 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7913 cfun->has_simduid_loops = true;
7915 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7916 the loop. */
7917 if ((flag_tree_loop_vectorize
7918 || (!global_options_set.x_flag_tree_loop_vectorize
7919 && !global_options_set.x_flag_tree_vectorize))
7920 && flag_tree_loop_optimize
7921 && loop->safelen > 1)
7923 loop->force_vectorize = true;
7924 cfun->has_force_vectorize_loops = true;
7927 else if (simduid)
7928 cfun->has_simduid_loops = true;
7932 /* Expand the OMP loop defined by REGION. */
7934 static void
7935 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
7937 struct omp_for_data fd;
7938 struct omp_for_data_loop *loops;
7940 loops
7941 = (struct omp_for_data_loop *)
7942 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7943 * sizeof (struct omp_for_data_loop));
7944 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7945 &fd, loops);
7946 region->sched_kind = fd.sched_kind;
7948 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7949 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7950 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7951 if (region->cont)
7953 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7954 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7955 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7957 else
7958 /* If there isn't a continue then this is a degerate case where
7959 the introduction of abnormal edges during lowering will prevent
7960 original loops from being detected. Fix that up. */
7961 loops_state_set (LOOPS_NEED_FIXUP);
7963 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7964 expand_omp_simd (region, &fd);
7965 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7966 expand_cilk_for (region, &fd);
7967 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7968 && !fd.have_ordered)
7970 if (fd.chunk_size == NULL)
7971 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7972 else
7973 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7975 else
7977 int fn_index, start_ix, next_ix;
7979 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7980 == GF_OMP_FOR_KIND_FOR);
7981 if (fd.chunk_size == NULL
7982 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7983 fd.chunk_size = integer_zero_node;
7984 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7985 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7986 ? 3 : fd.sched_kind;
7987 fn_index += fd.have_ordered * 4;
7988 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7989 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7990 if (fd.iter_type == long_long_unsigned_type_node)
7992 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7993 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7994 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7995 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7997 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7998 (enum built_in_function) next_ix, inner_stmt);
8001 if (gimple_in_ssa_p (cfun))
8002 update_ssa (TODO_update_ssa_only_virtuals);
8006 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
8008 v = GOMP_sections_start (n);
8010 switch (v)
8012 case 0:
8013 goto L2;
8014 case 1:
8015 section 1;
8016 goto L1;
8017 case 2:
8019 case n:
8021 default:
8022 abort ();
8025 v = GOMP_sections_next ();
8026 goto L0;
8028 reduction;
8030 If this is a combined parallel sections, replace the call to
8031 GOMP_sections_start with call to GOMP_sections_next. */
8033 static void
8034 expand_omp_sections (struct omp_region *region)
8036 tree t, u, vin = NULL, vmain, vnext, l2;
8037 unsigned len;
8038 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
8039 gimple_stmt_iterator si, switch_si;
8040 gomp_sections *sections_stmt;
8041 gimple *stmt;
8042 gomp_continue *cont;
8043 edge_iterator ei;
8044 edge e;
8045 struct omp_region *inner;
8046 unsigned i, casei;
8047 bool exit_reachable = region->cont != NULL;
8049 gcc_assert (region->exit != NULL);
8050 entry_bb = region->entry;
8051 l0_bb = single_succ (entry_bb);
8052 l1_bb = region->cont;
8053 l2_bb = region->exit;
8054 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
8055 l2 = gimple_block_label (l2_bb);
8056 else
8058 /* This can happen if there are reductions. */
8059 len = EDGE_COUNT (l0_bb->succs);
8060 gcc_assert (len > 0);
8061 e = EDGE_SUCC (l0_bb, len - 1);
8062 si = gsi_last_bb (e->dest);
8063 l2 = NULL_TREE;
8064 if (gsi_end_p (si)
8065 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
8066 l2 = gimple_block_label (e->dest);
8067 else
8068 FOR_EACH_EDGE (e, ei, l0_bb->succs)
8070 si = gsi_last_bb (e->dest);
8071 if (gsi_end_p (si)
8072 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
8074 l2 = gimple_block_label (e->dest);
8075 break;
8079 if (exit_reachable)
8080 default_bb = create_empty_bb (l1_bb->prev_bb);
8081 else
8082 default_bb = create_empty_bb (l0_bb);
8084 /* We will build a switch() with enough cases for all the
8085 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
8086 and a default case to abort if something goes wrong. */
8087 len = EDGE_COUNT (l0_bb->succs);
8089 /* Use vec::quick_push on label_vec throughout, since we know the size
8090 in advance. */
8091 auto_vec<tree> label_vec (len);
8093 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
8094 GIMPLE_OMP_SECTIONS statement. */
8095 si = gsi_last_bb (entry_bb);
8096 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
8097 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8098 vin = gimple_omp_sections_control (sections_stmt);
8099 if (!is_combined_parallel (region))
8101 /* If we are not inside a combined parallel+sections region,
8102 call GOMP_sections_start. */
8103 t = build_int_cst (unsigned_type_node, len - 1);
8104 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
8105 stmt = gimple_build_call (u, 1, t);
8107 else
8109 /* Otherwise, call GOMP_sections_next. */
8110 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8111 stmt = gimple_build_call (u, 0);
8113 gimple_call_set_lhs (stmt, vin);
8114 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8115 gsi_remove (&si, true);
8117 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8118 L0_BB. */
8119 switch_si = gsi_last_bb (l0_bb);
8120 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8121 if (exit_reachable)
8123 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8124 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8125 vmain = gimple_omp_continue_control_use (cont);
8126 vnext = gimple_omp_continue_control_def (cont);
8128 else
8130 vmain = vin;
8131 vnext = NULL_TREE;
8134 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8135 label_vec.quick_push (t);
8136 i = 1;
8138 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8139 for (inner = region->inner, casei = 1;
8140 inner;
8141 inner = inner->next, i++, casei++)
8143 basic_block s_entry_bb, s_exit_bb;
8145 /* Skip optional reduction region. */
8146 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8148 --i;
8149 --casei;
8150 continue;
8153 s_entry_bb = inner->entry;
8154 s_exit_bb = inner->exit;
8156 t = gimple_block_label (s_entry_bb);
8157 u = build_int_cst (unsigned_type_node, casei);
8158 u = build_case_label (u, NULL, t);
8159 label_vec.quick_push (u);
8161 si = gsi_last_bb (s_entry_bb);
8162 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8163 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8164 gsi_remove (&si, true);
8165 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8167 if (s_exit_bb == NULL)
8168 continue;
8170 si = gsi_last_bb (s_exit_bb);
8171 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8172 gsi_remove (&si, true);
8174 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8177 /* Error handling code goes in DEFAULT_BB. */
8178 t = gimple_block_label (default_bb);
8179 u = build_case_label (NULL, NULL, t);
8180 make_edge (l0_bb, default_bb, 0);
8181 add_bb_to_loop (default_bb, current_loops->tree_root);
8183 stmt = gimple_build_switch (vmain, u, label_vec);
8184 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8185 gsi_remove (&switch_si, true);
8187 si = gsi_start_bb (default_bb);
8188 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8189 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8191 if (exit_reachable)
8193 tree bfn_decl;
8195 /* Code to get the next section goes in L1_BB. */
8196 si = gsi_last_bb (l1_bb);
8197 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8199 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8200 stmt = gimple_build_call (bfn_decl, 0);
8201 gimple_call_set_lhs (stmt, vnext);
8202 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8203 gsi_remove (&si, true);
8205 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8208 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8209 si = gsi_last_bb (l2_bb);
8210 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8211 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8212 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8213 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8214 else
8215 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8216 stmt = gimple_build_call (t, 0);
8217 if (gimple_omp_return_lhs (gsi_stmt (si)))
8218 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8219 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8220 gsi_remove (&si, true);
8222 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8226 /* Expand code for an OpenMP single directive. We've already expanded
8227 much of the code, here we simply place the GOMP_barrier call. */
8229 static void
8230 expand_omp_single (struct omp_region *region)
8232 basic_block entry_bb, exit_bb;
8233 gimple_stmt_iterator si;
8235 entry_bb = region->entry;
8236 exit_bb = region->exit;
8238 si = gsi_last_bb (entry_bb);
8239 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8240 gsi_remove (&si, true);
8241 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8243 si = gsi_last_bb (exit_bb);
8244 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8246 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8247 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8249 gsi_remove (&si, true);
8250 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8254 /* Generic expansion for OpenMP synchronization directives: master,
8255 ordered and critical. All we need to do here is remove the entry
8256 and exit markers for REGION. */
8258 static void
8259 expand_omp_synch (struct omp_region *region)
8261 basic_block entry_bb, exit_bb;
8262 gimple_stmt_iterator si;
8264 entry_bb = region->entry;
8265 exit_bb = region->exit;
8267 si = gsi_last_bb (entry_bb);
8268 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8269 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8270 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8271 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8272 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8273 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8274 gsi_remove (&si, true);
8275 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8277 if (exit_bb)
8279 si = gsi_last_bb (exit_bb);
8280 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8281 gsi_remove (&si, true);
8282 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8286 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8287 operation as a normal volatile load. */
8289 static bool
8290 expand_omp_atomic_load (basic_block load_bb, tree addr,
8291 tree loaded_val, int index)
8293 enum built_in_function tmpbase;
8294 gimple_stmt_iterator gsi;
8295 basic_block store_bb;
8296 location_t loc;
8297 gimple *stmt;
8298 tree decl, call, type, itype;
8300 gsi = gsi_last_bb (load_bb);
8301 stmt = gsi_stmt (gsi);
8302 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8303 loc = gimple_location (stmt);
8305 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8306 is smaller than word size, then expand_atomic_load assumes that the load
8307 is atomic. We could avoid the builtin entirely in this case. */
8309 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8310 decl = builtin_decl_explicit (tmpbase);
8311 if (decl == NULL_TREE)
8312 return false;
8314 type = TREE_TYPE (loaded_val);
8315 itype = TREE_TYPE (TREE_TYPE (decl));
8317 call = build_call_expr_loc (loc, decl, 2, addr,
8318 build_int_cst (NULL,
8319 gimple_omp_atomic_seq_cst_p (stmt)
8320 ? MEMMODEL_SEQ_CST
8321 : MEMMODEL_RELAXED));
8322 if (!useless_type_conversion_p (type, itype))
8323 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8324 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8326 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8327 gsi_remove (&gsi, true);
8329 store_bb = single_succ (load_bb);
8330 gsi = gsi_last_bb (store_bb);
8331 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8332 gsi_remove (&gsi, true);
8334 if (gimple_in_ssa_p (cfun))
8335 update_ssa (TODO_update_ssa_no_phi);
8337 return true;
8340 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8341 operation as a normal volatile store. */
8343 static bool
8344 expand_omp_atomic_store (basic_block load_bb, tree addr,
8345 tree loaded_val, tree stored_val, int index)
8347 enum built_in_function tmpbase;
8348 gimple_stmt_iterator gsi;
8349 basic_block store_bb = single_succ (load_bb);
8350 location_t loc;
8351 gimple *stmt;
8352 tree decl, call, type, itype;
8353 machine_mode imode;
8354 bool exchange;
8356 gsi = gsi_last_bb (load_bb);
8357 stmt = gsi_stmt (gsi);
8358 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8360 /* If the load value is needed, then this isn't a store but an exchange. */
8361 exchange = gimple_omp_atomic_need_value_p (stmt);
8363 gsi = gsi_last_bb (store_bb);
8364 stmt = gsi_stmt (gsi);
8365 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8366 loc = gimple_location (stmt);
8368 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8369 is smaller than word size, then expand_atomic_store assumes that the store
8370 is atomic. We could avoid the builtin entirely in this case. */
8372 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8373 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8374 decl = builtin_decl_explicit (tmpbase);
8375 if (decl == NULL_TREE)
8376 return false;
8378 type = TREE_TYPE (stored_val);
8380 /* Dig out the type of the function's second argument. */
8381 itype = TREE_TYPE (decl);
8382 itype = TYPE_ARG_TYPES (itype);
8383 itype = TREE_CHAIN (itype);
8384 itype = TREE_VALUE (itype);
8385 imode = TYPE_MODE (itype);
8387 if (exchange && !can_atomic_exchange_p (imode, true))
8388 return false;
8390 if (!useless_type_conversion_p (itype, type))
8391 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8392 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8393 build_int_cst (NULL,
8394 gimple_omp_atomic_seq_cst_p (stmt)
8395 ? MEMMODEL_SEQ_CST
8396 : MEMMODEL_RELAXED));
8397 if (exchange)
8399 if (!useless_type_conversion_p (type, itype))
8400 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8401 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8404 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8405 gsi_remove (&gsi, true);
8407 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8408 gsi = gsi_last_bb (load_bb);
8409 gsi_remove (&gsi, true);
8411 if (gimple_in_ssa_p (cfun))
8412 update_ssa (TODO_update_ssa_no_phi);
8414 return true;
8417 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8418 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8419 size of the data type, and thus usable to find the index of the builtin
8420 decl. Returns false if the expression is not of the proper form. */
8422 static bool
8423 expand_omp_atomic_fetch_op (basic_block load_bb,
8424 tree addr, tree loaded_val,
8425 tree stored_val, int index)
8427 enum built_in_function oldbase, newbase, tmpbase;
8428 tree decl, itype, call;
8429 tree lhs, rhs;
8430 basic_block store_bb = single_succ (load_bb);
8431 gimple_stmt_iterator gsi;
8432 gimple *stmt;
8433 location_t loc;
8434 enum tree_code code;
8435 bool need_old, need_new;
8436 machine_mode imode;
8437 bool seq_cst;
8439 /* We expect to find the following sequences:
8441 load_bb:
8442 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8444 store_bb:
8445 val = tmp OP something; (or: something OP tmp)
8446 GIMPLE_OMP_STORE (val)
8448 ???FIXME: Allow a more flexible sequence.
8449 Perhaps use data flow to pick the statements.
8453 gsi = gsi_after_labels (store_bb);
8454 stmt = gsi_stmt (gsi);
8455 loc = gimple_location (stmt);
8456 if (!is_gimple_assign (stmt))
8457 return false;
8458 gsi_next (&gsi);
8459 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8460 return false;
8461 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8462 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8463 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8464 gcc_checking_assert (!need_old || !need_new);
8466 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8467 return false;
8469 /* Check for one of the supported fetch-op operations. */
8470 code = gimple_assign_rhs_code (stmt);
8471 switch (code)
8473 case PLUS_EXPR:
8474 case POINTER_PLUS_EXPR:
8475 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8476 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8477 break;
8478 case MINUS_EXPR:
8479 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8480 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8481 break;
8482 case BIT_AND_EXPR:
8483 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8484 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8485 break;
8486 case BIT_IOR_EXPR:
8487 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8488 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8489 break;
8490 case BIT_XOR_EXPR:
8491 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8492 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8493 break;
8494 default:
8495 return false;
8498 /* Make sure the expression is of the proper form. */
8499 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8500 rhs = gimple_assign_rhs2 (stmt);
8501 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8502 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8503 rhs = gimple_assign_rhs1 (stmt);
8504 else
8505 return false;
8507 tmpbase = ((enum built_in_function)
8508 ((need_new ? newbase : oldbase) + index + 1));
8509 decl = builtin_decl_explicit (tmpbase);
8510 if (decl == NULL_TREE)
8511 return false;
8512 itype = TREE_TYPE (TREE_TYPE (decl));
8513 imode = TYPE_MODE (itype);
8515 /* We could test all of the various optabs involved, but the fact of the
8516 matter is that (with the exception of i486 vs i586 and xadd) all targets
8517 that support any atomic operaton optab also implements compare-and-swap.
8518 Let optabs.c take care of expanding any compare-and-swap loop. */
8519 if (!can_compare_and_swap_p (imode, true))
8520 return false;
8522 gsi = gsi_last_bb (load_bb);
8523 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8525 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8526 It only requires that the operation happen atomically. Thus we can
8527 use the RELAXED memory model. */
8528 call = build_call_expr_loc (loc, decl, 3, addr,
8529 fold_convert_loc (loc, itype, rhs),
8530 build_int_cst (NULL,
8531 seq_cst ? MEMMODEL_SEQ_CST
8532 : MEMMODEL_RELAXED));
8534 if (need_old || need_new)
8536 lhs = need_old ? loaded_val : stored_val;
8537 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8538 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8540 else
8541 call = fold_convert_loc (loc, void_type_node, call);
8542 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8543 gsi_remove (&gsi, true);
8545 gsi = gsi_last_bb (store_bb);
8546 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8547 gsi_remove (&gsi, true);
8548 gsi = gsi_last_bb (store_bb);
8549 gsi_remove (&gsi, true);
8551 if (gimple_in_ssa_p (cfun))
8552 update_ssa (TODO_update_ssa_no_phi);
8554 return true;
8557 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8559 oldval = *addr;
8560 repeat:
8561 newval = rhs; // with oldval replacing *addr in rhs
8562 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8563 if (oldval != newval)
8564 goto repeat;
8566 INDEX is log2 of the size of the data type, and thus usable to find the
8567 index of the builtin decl. */
8569 static bool
8570 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8571 tree addr, tree loaded_val, tree stored_val,
8572 int index)
8574 tree loadedi, storedi, initial, new_storedi, old_vali;
8575 tree type, itype, cmpxchg, iaddr;
8576 gimple_stmt_iterator si;
8577 basic_block loop_header = single_succ (load_bb);
8578 gimple *phi, *stmt;
8579 edge e;
8580 enum built_in_function fncode;
8582 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8583 order to use the RELAXED memory model effectively. */
8584 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8585 + index + 1);
8586 cmpxchg = builtin_decl_explicit (fncode);
8587 if (cmpxchg == NULL_TREE)
8588 return false;
8589 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8590 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8592 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8593 return false;
8595 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8596 si = gsi_last_bb (load_bb);
8597 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8599 /* For floating-point values, we'll need to view-convert them to integers
8600 so that we can perform the atomic compare and swap. Simplify the
8601 following code by always setting up the "i"ntegral variables. */
8602 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8604 tree iaddr_val;
8606 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8607 true));
8608 iaddr_val
8609 = force_gimple_operand_gsi (&si,
8610 fold_convert (TREE_TYPE (iaddr), addr),
8611 false, NULL_TREE, true, GSI_SAME_STMT);
8612 stmt = gimple_build_assign (iaddr, iaddr_val);
8613 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8614 loadedi = create_tmp_var (itype);
8615 if (gimple_in_ssa_p (cfun))
8616 loadedi = make_ssa_name (loadedi);
8618 else
8620 iaddr = addr;
8621 loadedi = loaded_val;
8624 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8625 tree loaddecl = builtin_decl_explicit (fncode);
8626 if (loaddecl)
8627 initial
8628 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8629 build_call_expr (loaddecl, 2, iaddr,
8630 build_int_cst (NULL_TREE,
8631 MEMMODEL_RELAXED)));
8632 else
8633 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8634 build_int_cst (TREE_TYPE (iaddr), 0));
8636 initial
8637 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8638 GSI_SAME_STMT);
8640 /* Move the value to the LOADEDI temporary. */
8641 if (gimple_in_ssa_p (cfun))
8643 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8644 phi = create_phi_node (loadedi, loop_header);
8645 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8646 initial);
8648 else
8649 gsi_insert_before (&si,
8650 gimple_build_assign (loadedi, initial),
8651 GSI_SAME_STMT);
8652 if (loadedi != loaded_val)
8654 gimple_stmt_iterator gsi2;
8655 tree x;
8657 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8658 gsi2 = gsi_start_bb (loop_header);
8659 if (gimple_in_ssa_p (cfun))
8661 gassign *stmt;
8662 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8663 true, GSI_SAME_STMT);
8664 stmt = gimple_build_assign (loaded_val, x);
8665 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8667 else
8669 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8670 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8671 true, GSI_SAME_STMT);
8674 gsi_remove (&si, true);
8676 si = gsi_last_bb (store_bb);
8677 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8679 if (iaddr == addr)
8680 storedi = stored_val;
8681 else
8682 storedi =
8683 force_gimple_operand_gsi (&si,
8684 build1 (VIEW_CONVERT_EXPR, itype,
8685 stored_val), true, NULL_TREE, true,
8686 GSI_SAME_STMT);
8688 /* Build the compare&swap statement. */
8689 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8690 new_storedi = force_gimple_operand_gsi (&si,
8691 fold_convert (TREE_TYPE (loadedi),
8692 new_storedi),
8693 true, NULL_TREE,
8694 true, GSI_SAME_STMT);
8696 if (gimple_in_ssa_p (cfun))
8697 old_vali = loadedi;
8698 else
8700 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8701 stmt = gimple_build_assign (old_vali, loadedi);
8702 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8704 stmt = gimple_build_assign (loadedi, new_storedi);
8705 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8708 /* Note that we always perform the comparison as an integer, even for
8709 floating point. This allows the atomic operation to properly
8710 succeed even with NaNs and -0.0. */
8711 stmt = gimple_build_cond_empty
8712 (build2 (NE_EXPR, boolean_type_node,
8713 new_storedi, old_vali));
8714 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8716 /* Update cfg. */
8717 e = single_succ_edge (store_bb);
8718 e->flags &= ~EDGE_FALLTHRU;
8719 e->flags |= EDGE_FALSE_VALUE;
8721 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8723 /* Copy the new value to loadedi (we already did that before the condition
8724 if we are not in SSA). */
8725 if (gimple_in_ssa_p (cfun))
8727 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8728 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8731 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8732 gsi_remove (&si, true);
8734 struct loop *loop = alloc_loop ();
8735 loop->header = loop_header;
8736 loop->latch = store_bb;
8737 add_loop (loop, loop_header->loop_father);
8739 if (gimple_in_ssa_p (cfun))
8740 update_ssa (TODO_update_ssa_no_phi);
8742 return true;
8745 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8747 GOMP_atomic_start ();
8748 *addr = rhs;
8749 GOMP_atomic_end ();
8751 The result is not globally atomic, but works so long as all parallel
8752 references are within #pragma omp atomic directives. According to
8753 responses received from omp@openmp.org, appears to be within spec.
8754 Which makes sense, since that's how several other compilers handle
8755 this situation as well.
8756 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8757 expanding. STORED_VAL is the operand of the matching
8758 GIMPLE_OMP_ATOMIC_STORE.
8760 We replace
8761 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8762 loaded_val = *addr;
8764 and replace
8765 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8766 *addr = stored_val;
8769 static bool
8770 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8771 tree addr, tree loaded_val, tree stored_val)
8773 gimple_stmt_iterator si;
8774 gassign *stmt;
8775 tree t;
8777 si = gsi_last_bb (load_bb);
8778 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8780 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8781 t = build_call_expr (t, 0);
8782 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8784 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8785 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8786 gsi_remove (&si, true);
8788 si = gsi_last_bb (store_bb);
8789 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8791 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8792 stored_val);
8793 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8795 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8796 t = build_call_expr (t, 0);
8797 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8798 gsi_remove (&si, true);
8800 if (gimple_in_ssa_p (cfun))
8801 update_ssa (TODO_update_ssa_no_phi);
8802 return true;
8805 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8806 using expand_omp_atomic_fetch_op. If it failed, we try to
8807 call expand_omp_atomic_pipeline, and if it fails too, the
8808 ultimate fallback is wrapping the operation in a mutex
8809 (expand_omp_atomic_mutex). REGION is the atomic region built
8810 by build_omp_regions_1(). */
8812 static void
8813 expand_omp_atomic (struct omp_region *region)
8815 basic_block load_bb = region->entry, store_bb = region->exit;
8816 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8817 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8818 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8819 tree addr = gimple_omp_atomic_load_rhs (load);
8820 tree stored_val = gimple_omp_atomic_store_val (store);
8821 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8822 HOST_WIDE_INT index;
8824 /* Make sure the type is one of the supported sizes. */
8825 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8826 index = exact_log2 (index);
8827 if (index >= 0 && index <= 4)
8829 unsigned int align = TYPE_ALIGN_UNIT (type);
8831 /* __sync builtins require strict data alignment. */
8832 if (exact_log2 (align) >= index)
8834 /* Atomic load. */
8835 if (loaded_val == stored_val
8836 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8837 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8838 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8839 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8840 return;
8842 /* Atomic store. */
8843 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8844 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8845 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8846 && store_bb == single_succ (load_bb)
8847 && first_stmt (store_bb) == store
8848 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8849 stored_val, index))
8850 return;
8852 /* When possible, use specialized atomic update functions. */
8853 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8854 && store_bb == single_succ (load_bb)
8855 && expand_omp_atomic_fetch_op (load_bb, addr,
8856 loaded_val, stored_val, index))
8857 return;
8859 /* If we don't have specialized __sync builtins, try and implement
8860 as a compare and swap loop. */
8861 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8862 loaded_val, stored_val, index))
8863 return;
8867 /* The ultimate fallback is wrapping the operation in a mutex. */
8868 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8872 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8874 static void
8875 expand_omp_target (struct omp_region *region)
8877 basic_block entry_bb, exit_bb, new_bb;
8878 struct function *child_cfun;
8879 tree child_fn, block, t;
8880 gimple_stmt_iterator gsi;
8881 gomp_target *entry_stmt;
8882 gimple *stmt;
8883 edge e;
8884 bool offloaded, data_region;
8886 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8887 new_bb = region->entry;
8889 offloaded = is_gimple_omp_offloaded (entry_stmt);
8890 switch (gimple_omp_target_kind (entry_stmt))
8892 case GF_OMP_TARGET_KIND_REGION:
8893 case GF_OMP_TARGET_KIND_UPDATE:
8894 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8895 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8896 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8897 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8898 data_region = false;
8899 break;
8900 case GF_OMP_TARGET_KIND_DATA:
8901 case GF_OMP_TARGET_KIND_OACC_DATA:
8902 data_region = true;
8903 break;
8904 default:
8905 gcc_unreachable ();
8908 child_fn = NULL_TREE;
8909 child_cfun = NULL;
8910 if (offloaded)
8912 child_fn = gimple_omp_target_child_fn (entry_stmt);
8913 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8916 /* Supported by expand_omp_taskreg, but not here. */
8917 if (child_cfun != NULL)
8918 gcc_checking_assert (!child_cfun->cfg);
8919 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8921 entry_bb = region->entry;
8922 exit_bb = region->exit;
8924 if (offloaded)
8926 unsigned srcidx, dstidx, num;
8928 /* If the offloading region needs data sent from the parent
8929 function, then the very first statement (except possible
8930 tree profile counter updates) of the offloading body
8931 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8932 &.OMP_DATA_O is passed as an argument to the child function,
8933 we need to replace it with the argument as seen by the child
8934 function.
8936 In most cases, this will end up being the identity assignment
8937 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8938 a function call that has been inlined, the original PARM_DECL
8939 .OMP_DATA_I may have been converted into a different local
8940 variable. In which case, we need to keep the assignment. */
8941 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8942 if (data_arg)
8944 basic_block entry_succ_bb = single_succ (entry_bb);
8945 gimple_stmt_iterator gsi;
8946 tree arg;
8947 gimple *tgtcopy_stmt = NULL;
8948 tree sender = TREE_VEC_ELT (data_arg, 0);
8950 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8952 gcc_assert (!gsi_end_p (gsi));
8953 stmt = gsi_stmt (gsi);
8954 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8955 continue;
8957 if (gimple_num_ops (stmt) == 2)
8959 tree arg = gimple_assign_rhs1 (stmt);
8961 /* We're ignoring the subcode because we're
8962 effectively doing a STRIP_NOPS. */
8964 if (TREE_CODE (arg) == ADDR_EXPR
8965 && TREE_OPERAND (arg, 0) == sender)
8967 tgtcopy_stmt = stmt;
8968 break;
8973 gcc_assert (tgtcopy_stmt != NULL);
8974 arg = DECL_ARGUMENTS (child_fn);
8976 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8977 gsi_remove (&gsi, true);
8980 /* Declare local variables needed in CHILD_CFUN. */
8981 block = DECL_INITIAL (child_fn);
8982 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8983 /* The gimplifier could record temporaries in the offloading block
8984 rather than in containing function's local_decls chain,
8985 which would mean cgraph missed finalizing them. Do it now. */
8986 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8987 if (TREE_CODE (t) == VAR_DECL
8988 && TREE_STATIC (t)
8989 && !DECL_EXTERNAL (t))
8990 varpool_node::finalize_decl (t);
8991 DECL_SAVED_TREE (child_fn) = NULL;
8992 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8993 gimple_set_body (child_fn, NULL);
8994 TREE_USED (block) = 1;
8996 /* Reset DECL_CONTEXT on function arguments. */
8997 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8998 DECL_CONTEXT (t) = child_fn;
9000 /* Split ENTRY_BB at GIMPLE_*,
9001 so that it can be moved to the child function. */
9002 gsi = gsi_last_bb (entry_bb);
9003 stmt = gsi_stmt (gsi);
9004 gcc_assert (stmt
9005 && gimple_code (stmt) == gimple_code (entry_stmt));
9006 e = split_block (entry_bb, stmt);
9007 gsi_remove (&gsi, true);
9008 entry_bb = e->dest;
9009 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
9011 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
9012 if (exit_bb)
9014 gsi = gsi_last_bb (exit_bb);
9015 gcc_assert (!gsi_end_p (gsi)
9016 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
9017 stmt = gimple_build_return (NULL);
9018 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
9019 gsi_remove (&gsi, true);
9022 /* Move the offloading region into CHILD_CFUN. */
9024 block = gimple_block (entry_stmt);
9026 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
9027 if (exit_bb)
9028 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
9029 /* When the OMP expansion process cannot guarantee an up-to-date
9030 loop tree arrange for the child function to fixup loops. */
9031 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
9032 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
9034 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
9035 num = vec_safe_length (child_cfun->local_decls);
9036 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
9038 t = (*child_cfun->local_decls)[srcidx];
9039 if (DECL_CONTEXT (t) == cfun->decl)
9040 continue;
9041 if (srcidx != dstidx)
9042 (*child_cfun->local_decls)[dstidx] = t;
9043 dstidx++;
9045 if (dstidx != num)
9046 vec_safe_truncate (child_cfun->local_decls, dstidx);
9048 /* Inform the callgraph about the new function. */
9049 child_cfun->curr_properties = cfun->curr_properties;
9050 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
9051 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
9052 cgraph_node *node = cgraph_node::get_create (child_fn);
9053 node->parallelized_function = 1;
9054 cgraph_node::add_new_function (child_fn, true);
9056 #ifdef ENABLE_OFFLOADING
9057 /* Add the new function to the offload table. */
9058 vec_safe_push (offload_funcs, child_fn);
9059 #endif
9061 /* Fix the callgraph edges for child_cfun. Those for cfun will be
9062 fixed in a following pass. */
9063 push_cfun (child_cfun);
9064 cgraph_edge::rebuild_edges ();
9066 #ifdef ENABLE_OFFLOADING
9067 /* Prevent IPA from removing child_fn as unreachable, since there are no
9068 refs from the parent function to child_fn in offload LTO mode. */
9069 cgraph_node::get (child_fn)->mark_force_output ();
9070 #endif
9072 /* Some EH regions might become dead, see PR34608. If
9073 pass_cleanup_cfg isn't the first pass to happen with the
9074 new child, these dead EH edges might cause problems.
9075 Clean them up now. */
9076 if (flag_exceptions)
9078 basic_block bb;
9079 bool changed = false;
9081 FOR_EACH_BB_FN (bb, cfun)
9082 changed |= gimple_purge_dead_eh_edges (bb);
9083 if (changed)
9084 cleanup_tree_cfg ();
9086 #ifdef ENABLE_CHECKING
9087 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
9088 verify_loop_structure ();
9089 #endif
9090 pop_cfun ();
9093 /* Emit a library call to launch the offloading region, or do data
9094 transfers. */
9095 tree t1, t2, t3, t4, device, cond, c, clauses;
9096 enum built_in_function start_ix;
9097 location_t clause_loc;
9099 switch (gimple_omp_target_kind (entry_stmt))
9101 case GF_OMP_TARGET_KIND_REGION:
9102 start_ix = BUILT_IN_GOMP_TARGET;
9103 break;
9104 case GF_OMP_TARGET_KIND_DATA:
9105 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9106 break;
9107 case GF_OMP_TARGET_KIND_UPDATE:
9108 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9109 break;
9110 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9111 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9112 start_ix = BUILT_IN_GOACC_PARALLEL;
9113 break;
9114 case GF_OMP_TARGET_KIND_OACC_DATA:
9115 start_ix = BUILT_IN_GOACC_DATA_START;
9116 break;
9117 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9118 start_ix = BUILT_IN_GOACC_UPDATE;
9119 break;
9120 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9121 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9122 break;
9123 default:
9124 gcc_unreachable ();
9127 clauses = gimple_omp_target_clauses (entry_stmt);
9129 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9130 library choose) and there is no conditional. */
9131 cond = NULL_TREE;
9132 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
9134 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9135 if (c)
9136 cond = OMP_CLAUSE_IF_EXPR (c);
9138 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9139 if (c)
9141 /* Even if we pass it to all library function calls, it is currently only
9142 defined/used for the OpenMP target ones. */
9143 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9144 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9145 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9147 device = OMP_CLAUSE_DEVICE_ID (c);
9148 clause_loc = OMP_CLAUSE_LOCATION (c);
9150 else
9151 clause_loc = gimple_location (entry_stmt);
9153 /* Ensure 'device' is of the correct type. */
9154 device = fold_convert_loc (clause_loc, integer_type_node, device);
9156 /* If we found the clause 'if (cond)', build
9157 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9158 if (cond)
9160 cond = gimple_boolify (cond);
9162 basic_block cond_bb, then_bb, else_bb;
9163 edge e;
9164 tree tmp_var;
9166 tmp_var = create_tmp_var (TREE_TYPE (device));
9167 if (offloaded)
9168 e = split_block_after_labels (new_bb);
9169 else
9171 gsi = gsi_last_bb (new_bb);
9172 gsi_prev (&gsi);
9173 e = split_block (new_bb, gsi_stmt (gsi));
9175 cond_bb = e->src;
9176 new_bb = e->dest;
9177 remove_edge (e);
9179 then_bb = create_empty_bb (cond_bb);
9180 else_bb = create_empty_bb (then_bb);
9181 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9182 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9184 stmt = gimple_build_cond_empty (cond);
9185 gsi = gsi_last_bb (cond_bb);
9186 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9188 gsi = gsi_start_bb (then_bb);
9189 stmt = gimple_build_assign (tmp_var, device);
9190 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9192 gsi = gsi_start_bb (else_bb);
9193 stmt = gimple_build_assign (tmp_var,
9194 build_int_cst (integer_type_node,
9195 GOMP_DEVICE_HOST_FALLBACK));
9196 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9198 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9199 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9200 add_bb_to_loop (then_bb, cond_bb->loop_father);
9201 add_bb_to_loop (else_bb, cond_bb->loop_father);
9202 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9203 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9205 device = tmp_var;
9208 gsi = gsi_last_bb (new_bb);
9209 t = gimple_omp_target_data_arg (entry_stmt);
9210 if (t == NULL)
9212 t1 = size_zero_node;
9213 t2 = build_zero_cst (ptr_type_node);
9214 t3 = t2;
9215 t4 = t2;
9217 else
9219 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9220 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9221 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9222 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9223 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9226 gimple *g;
9227 /* The maximum number used by any start_ix, without varargs. */
9228 auto_vec<tree, 11> args;
9229 args.quick_push (device);
9230 if (offloaded)
9231 args.quick_push (build_fold_addr_expr (child_fn));
9232 switch (start_ix)
9234 case BUILT_IN_GOMP_TARGET:
9235 case BUILT_IN_GOMP_TARGET_DATA:
9236 case BUILT_IN_GOMP_TARGET_UPDATE:
9237 /* This const void * is part of the current ABI, but we're not actually
9238 using it. */
9239 args.quick_push (build_zero_cst (ptr_type_node));
9240 break;
9241 case BUILT_IN_GOACC_DATA_START:
9242 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9243 case BUILT_IN_GOACC_PARALLEL:
9244 case BUILT_IN_GOACC_UPDATE:
9245 break;
9246 default:
9247 gcc_unreachable ();
9249 args.quick_push (t1);
9250 args.quick_push (t2);
9251 args.quick_push (t3);
9252 args.quick_push (t4);
9253 switch (start_ix)
9255 case BUILT_IN_GOACC_DATA_START:
9256 case BUILT_IN_GOMP_TARGET:
9257 case BUILT_IN_GOMP_TARGET_DATA:
9258 case BUILT_IN_GOMP_TARGET_UPDATE:
9259 break;
9260 case BUILT_IN_GOACC_PARALLEL:
9262 tree t_num_gangs, t_num_workers, t_vector_length;
9264 /* Default values for num_gangs, num_workers, and vector_length. */
9265 t_num_gangs = t_num_workers = t_vector_length
9266 = fold_convert_loc (gimple_location (entry_stmt),
9267 integer_type_node, integer_one_node);
9268 /* ..., but if present, use the value specified by the respective
9269 clause, making sure that are of the correct type. */
9270 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9271 if (c)
9272 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9273 integer_type_node,
9274 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9275 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9276 if (c)
9277 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9278 integer_type_node,
9279 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9280 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9281 if (c)
9282 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9283 integer_type_node,
9284 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9285 args.quick_push (t_num_gangs);
9286 args.quick_push (t_num_workers);
9287 args.quick_push (t_vector_length);
9289 /* FALLTHRU */
9290 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9291 case BUILT_IN_GOACC_UPDATE:
9293 tree t_async;
9294 int t_wait_idx;
9296 /* Default values for t_async. */
9297 t_async = fold_convert_loc (gimple_location (entry_stmt),
9298 integer_type_node,
9299 build_int_cst (integer_type_node,
9300 GOMP_ASYNC_SYNC));
9301 /* ..., but if present, use the value specified by the respective
9302 clause, making sure that is of the correct type. */
9303 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9304 if (c)
9305 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9306 integer_type_node,
9307 OMP_CLAUSE_ASYNC_EXPR (c));
9309 args.quick_push (t_async);
9310 /* Save the index, and... */
9311 t_wait_idx = args.length ();
9312 /* ... push a default value. */
9313 args.quick_push (fold_convert_loc (gimple_location (entry_stmt),
9314 integer_type_node,
9315 integer_zero_node));
9316 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9317 if (c)
9319 int n = 0;
9321 for (; c; c = OMP_CLAUSE_CHAIN (c))
9323 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9325 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9326 integer_type_node,
9327 OMP_CLAUSE_WAIT_EXPR (c)));
9328 n++;
9332 /* Now that we know the number, replace the default value. */
9333 args.ordered_remove (t_wait_idx);
9334 args.quick_insert (t_wait_idx,
9335 fold_convert_loc (gimple_location (entry_stmt),
9336 integer_type_node,
9337 build_int_cst (integer_type_node, n)));
9340 break;
9341 default:
9342 gcc_unreachable ();
9345 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
9346 gimple_set_location (g, gimple_location (entry_stmt));
9347 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9348 if (!offloaded)
9350 g = gsi_stmt (gsi);
9351 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9352 gsi_remove (&gsi, true);
9354 if (data_region
9355 && region->exit)
9357 gsi = gsi_last_bb (region->exit);
9358 g = gsi_stmt (gsi);
9359 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9360 gsi_remove (&gsi, true);
9365 /* Expand the parallel region tree rooted at REGION. Expansion
9366 proceeds in depth-first order. Innermost regions are expanded
9367 first. This way, parallel regions that require a new function to
9368 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9369 internal dependencies in their body. */
9371 static void
9372 expand_omp (struct omp_region *region)
9374 while (region)
9376 location_t saved_location;
9377 gimple *inner_stmt = NULL;
9379 /* First, determine whether this is a combined parallel+workshare
9380 region. */
9381 if (region->type == GIMPLE_OMP_PARALLEL)
9382 determine_parallel_type (region);
9384 if (region->type == GIMPLE_OMP_FOR
9385 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9386 inner_stmt = last_stmt (region->inner->entry);
9388 if (region->inner)
9389 expand_omp (region->inner);
9391 saved_location = input_location;
9392 if (gimple_has_location (last_stmt (region->entry)))
9393 input_location = gimple_location (last_stmt (region->entry));
9395 switch (region->type)
9397 case GIMPLE_OMP_PARALLEL:
9398 case GIMPLE_OMP_TASK:
9399 expand_omp_taskreg (region);
9400 break;
9402 case GIMPLE_OMP_FOR:
9403 expand_omp_for (region, inner_stmt);
9404 break;
9406 case GIMPLE_OMP_SECTIONS:
9407 expand_omp_sections (region);
9408 break;
9410 case GIMPLE_OMP_SECTION:
9411 /* Individual omp sections are handled together with their
9412 parent GIMPLE_OMP_SECTIONS region. */
9413 break;
9415 case GIMPLE_OMP_SINGLE:
9416 expand_omp_single (region);
9417 break;
9419 case GIMPLE_OMP_MASTER:
9420 case GIMPLE_OMP_TASKGROUP:
9421 case GIMPLE_OMP_ORDERED:
9422 case GIMPLE_OMP_CRITICAL:
9423 case GIMPLE_OMP_TEAMS:
9424 expand_omp_synch (region);
9425 break;
9427 case GIMPLE_OMP_ATOMIC_LOAD:
9428 expand_omp_atomic (region);
9429 break;
9431 case GIMPLE_OMP_TARGET:
9432 expand_omp_target (region);
9433 break;
9435 default:
9436 gcc_unreachable ();
9439 input_location = saved_location;
9440 region = region->next;
9445 /* Helper for build_omp_regions. Scan the dominator tree starting at
9446 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9447 true, the function ends once a single tree is built (otherwise, whole
9448 forest of OMP constructs may be built). */
9450 static void
9451 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9452 bool single_tree)
9454 gimple_stmt_iterator gsi;
9455 gimple *stmt;
9456 basic_block son;
9458 gsi = gsi_last_bb (bb);
9459 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9461 struct omp_region *region;
9462 enum gimple_code code;
9464 stmt = gsi_stmt (gsi);
9465 code = gimple_code (stmt);
9466 if (code == GIMPLE_OMP_RETURN)
9468 /* STMT is the return point out of region PARENT. Mark it
9469 as the exit point and make PARENT the immediately
9470 enclosing region. */
9471 gcc_assert (parent);
9472 region = parent;
9473 region->exit = bb;
9474 parent = parent->outer;
9476 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9478 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9479 GIMPLE_OMP_RETURN, but matches with
9480 GIMPLE_OMP_ATOMIC_LOAD. */
9481 gcc_assert (parent);
9482 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9483 region = parent;
9484 region->exit = bb;
9485 parent = parent->outer;
9487 else if (code == GIMPLE_OMP_CONTINUE)
9489 gcc_assert (parent);
9490 parent->cont = bb;
9492 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9494 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9495 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9497 else
9499 region = new_omp_region (bb, code, parent);
9500 /* Otherwise... */
9501 if (code == GIMPLE_OMP_TARGET)
9503 switch (gimple_omp_target_kind (stmt))
9505 case GF_OMP_TARGET_KIND_REGION:
9506 case GF_OMP_TARGET_KIND_DATA:
9507 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9508 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9509 case GF_OMP_TARGET_KIND_OACC_DATA:
9510 break;
9511 case GF_OMP_TARGET_KIND_UPDATE:
9512 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9513 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9514 /* ..., other than for those stand-alone directives... */
9515 region = NULL;
9516 break;
9517 default:
9518 gcc_unreachable ();
9521 /* ..., this directive becomes the parent for a new region. */
9522 if (region)
9523 parent = region;
9527 if (single_tree && !parent)
9528 return;
9530 for (son = first_dom_son (CDI_DOMINATORS, bb);
9531 son;
9532 son = next_dom_son (CDI_DOMINATORS, son))
9533 build_omp_regions_1 (son, parent, single_tree);
9536 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9537 root_omp_region. */
9539 static void
9540 build_omp_regions_root (basic_block root)
9542 gcc_assert (root_omp_region == NULL);
9543 build_omp_regions_1 (root, NULL, true);
9544 gcc_assert (root_omp_region != NULL);
9547 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9549 void
9550 omp_expand_local (basic_block head)
9552 build_omp_regions_root (head);
9553 if (dump_file && (dump_flags & TDF_DETAILS))
9555 fprintf (dump_file, "\nOMP region tree\n\n");
9556 dump_omp_region (dump_file, root_omp_region, 0);
9557 fprintf (dump_file, "\n");
9560 remove_exit_barriers (root_omp_region);
9561 expand_omp (root_omp_region);
9563 free_omp_regions ();
9566 /* Scan the CFG and build a tree of OMP regions. Return the root of
9567 the OMP region tree. */
9569 static void
9570 build_omp_regions (void)
9572 gcc_assert (root_omp_region == NULL);
9573 calculate_dominance_info (CDI_DOMINATORS);
9574 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9577 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9579 static unsigned int
9580 execute_expand_omp (void)
9582 build_omp_regions ();
9584 if (!root_omp_region)
9585 return 0;
9587 if (dump_file)
9589 fprintf (dump_file, "\nOMP region tree\n\n");
9590 dump_omp_region (dump_file, root_omp_region, 0);
9591 fprintf (dump_file, "\n");
9594 remove_exit_barriers (root_omp_region);
9596 expand_omp (root_omp_region);
9598 #ifdef ENABLE_CHECKING
9599 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
9600 verify_loop_structure ();
9601 #endif
9602 cleanup_tree_cfg ();
9604 free_omp_regions ();
9606 return 0;
9609 /* OMP expansion -- the default pass, run before creation of SSA form. */
9611 namespace {
9613 const pass_data pass_data_expand_omp =
9615 GIMPLE_PASS, /* type */
9616 "ompexp", /* name */
9617 OPTGROUP_NONE, /* optinfo_flags */
9618 TV_NONE, /* tv_id */
9619 PROP_gimple_any, /* properties_required */
9620 PROP_gimple_eomp, /* properties_provided */
9621 0, /* properties_destroyed */
9622 0, /* todo_flags_start */
9623 0, /* todo_flags_finish */
9626 class pass_expand_omp : public gimple_opt_pass
9628 public:
9629 pass_expand_omp (gcc::context *ctxt)
9630 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9633 /* opt_pass methods: */
9634 virtual unsigned int execute (function *)
9636 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9637 || flag_openmp_simd != 0)
9638 && !seen_error ());
9640 /* This pass always runs, to provide PROP_gimple_eomp.
9641 But often, there is nothing to do. */
9642 if (!gate)
9643 return 0;
9645 return execute_expand_omp ();
9648 }; // class pass_expand_omp
9650 } // anon namespace
9652 gimple_opt_pass *
9653 make_pass_expand_omp (gcc::context *ctxt)
9655 return new pass_expand_omp (ctxt);
9658 namespace {
9660 const pass_data pass_data_expand_omp_ssa =
9662 GIMPLE_PASS, /* type */
9663 "ompexpssa", /* name */
9664 OPTGROUP_NONE, /* optinfo_flags */
9665 TV_NONE, /* tv_id */
9666 PROP_cfg | PROP_ssa, /* properties_required */
9667 PROP_gimple_eomp, /* properties_provided */
9668 0, /* properties_destroyed */
9669 0, /* todo_flags_start */
9670 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9673 class pass_expand_omp_ssa : public gimple_opt_pass
9675 public:
9676 pass_expand_omp_ssa (gcc::context *ctxt)
9677 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9680 /* opt_pass methods: */
9681 virtual bool gate (function *fun)
9683 return !(fun->curr_properties & PROP_gimple_eomp);
9685 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9687 }; // class pass_expand_omp_ssa
9689 } // anon namespace
9691 gimple_opt_pass *
9692 make_pass_expand_omp_ssa (gcc::context *ctxt)
9694 return new pass_expand_omp_ssa (ctxt);
9697 /* Routines to lower OMP directives into OMP-GIMPLE. */
9699 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9700 convert it to gimple. */
9701 static void
9702 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9704 gimple *stmt;
9706 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9708 stmt = gimple_build_assign (dest, op, dest, src);
9709 gimple_seq_add_stmt (seq, stmt);
9710 return;
9713 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9714 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9715 gimplify_assign (t, rdest, seq);
9716 rdest = t;
9718 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9719 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9720 gimplify_assign (t, idest, seq);
9721 idest = t;
9723 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9724 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9725 gimplify_assign (t, rsrc, seq);
9726 rsrc = t;
9728 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9729 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9730 gimplify_assign (t, isrc, seq);
9731 isrc = t;
9733 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9734 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9735 tree result;
9737 if (op == PLUS_EXPR)
9739 stmt = gimple_build_assign (r, op, rdest, rsrc);
9740 gimple_seq_add_stmt (seq, stmt);
9742 stmt = gimple_build_assign (i, op, idest, isrc);
9743 gimple_seq_add_stmt (seq, stmt);
9745 else if (op == MULT_EXPR)
9747 /* Let x = a + ib = dest, y = c + id = src.
9748 x * y = (ac - bd) + i(ad + bc) */
9749 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9750 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9751 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9752 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9754 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9755 gimple_seq_add_stmt (seq, stmt);
9757 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9758 gimple_seq_add_stmt (seq, stmt);
9760 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9761 gimple_seq_add_stmt (seq, stmt);
9763 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9764 gimple_seq_add_stmt (seq, stmt);
9766 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9767 gimple_seq_add_stmt (seq, stmt);
9769 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9770 gimple_seq_add_stmt (seq, stmt);
9772 else
9773 gcc_unreachable ();
9775 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9776 gimplify_assign (dest, result, seq);
9779 /* Helper function to initialize local data for the reduction arrays.
9780 The reduction arrays need to be placed inside the calling function
9781 for accelerators, or else the host won't be able to preform the final
9782 reduction. */
9784 static void
9785 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9786 gimple_seq *stmt_seqp, omp_context *ctx)
9788 tree c, t, oc;
9789 gimple *stmt;
9790 omp_context *octx;
9792 /* Find the innermost OpenACC parallel context. */
9793 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9794 && (gimple_omp_target_kind (ctx->stmt)
9795 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9796 octx = ctx;
9797 else
9798 octx = ctx->outer;
9799 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9800 && (gimple_omp_target_kind (octx->stmt)
9801 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9803 /* Extract the clauses. */
9804 oc = gimple_omp_target_clauses (octx->stmt);
9806 /* Find the last outer clause. */
9807 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9810 /* Allocate arrays for each reduction variable. */
9811 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9813 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9814 continue;
9816 tree var = OMP_CLAUSE_DECL (c);
9817 tree type = get_base_type (var);
9818 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9819 ctx);
9820 tree size, call;
9822 /* Calculate size of the reduction array. */
9823 t = create_tmp_var (TREE_TYPE (nthreads));
9824 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9825 fold_convert (TREE_TYPE (nthreads),
9826 TYPE_SIZE_UNIT (type)));
9827 gimple_seq_add_stmt (stmt_seqp, stmt);
9829 size = create_tmp_var (sizetype);
9830 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9832 /* Now allocate memory for it. */
9833 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9834 stmt = gimple_build_call (call, 1, size);
9835 gimple_call_set_lhs (stmt, array);
9836 gimple_seq_add_stmt (stmt_seqp, stmt);
9838 /* Map this array into the accelerator. */
9840 /* Add the reduction array to the list of clauses. */
9841 tree x = array;
9842 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9843 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9844 OMP_CLAUSE_DECL (t) = x;
9845 OMP_CLAUSE_CHAIN (t) = NULL;
9846 if (oc)
9847 OMP_CLAUSE_CHAIN (oc) = t;
9848 else
9849 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9850 OMP_CLAUSE_SIZE (t) = size;
9851 oc = t;
9855 /* Helper function to process the array of partial reductions. Nthreads
9856 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9857 cannot be used here, because nthreads on the host may be different than
9858 on the accelerator. */
9860 static void
9861 oacc_finalize_reduction_data (tree clauses, tree nthreads,
9862 gimple_seq *stmt_seqp, omp_context *ctx)
9864 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9865 gimple *stmt;
9867 /* Create for loop.
9869 let var = the original reduction variable
9870 let array = reduction variable array
9872 for (i = 0; i < nthreads; i++)
9873 var op= array[i]
9876 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9877 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9878 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9880 /* Create and initialize an index variable. */
9881 tree ix = create_tmp_var (sizetype);
9882 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9883 stmt_seqp);
9885 /* Insert the loop header label here. */
9886 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9888 /* Exit loop if ix >= nthreads. */
9889 x = create_tmp_var (sizetype);
9890 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9891 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9892 gimple_seq_add_stmt (stmt_seqp, stmt);
9894 /* Insert the loop body label here. */
9895 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9897 /* Collapse each reduction array, one element at a time. */
9898 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9900 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9901 continue;
9903 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9905 /* reduction(-:var) sums up the partial results, so it acts
9906 identically to reduction(+:var). */
9907 if (reduction_code == MINUS_EXPR)
9908 reduction_code = PLUS_EXPR;
9910 /* Set up reduction variable var. */
9911 var = OMP_CLAUSE_DECL (c);
9912 type = get_base_type (var);
9913 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9914 (OMP_CLAUSE_DECL (c)), ctx);
9916 /* Calculate the array offset. */
9917 tree offset = create_tmp_var (sizetype);
9918 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9919 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9920 gimple_seq_add_stmt (stmt_seqp, stmt);
9922 tree ptr = create_tmp_var (TREE_TYPE (array));
9923 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9924 gimple_seq_add_stmt (stmt_seqp, stmt);
9926 /* Extract array[ix] into mem. */
9927 tree mem = create_tmp_var (type);
9928 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9930 /* Find the original reduction variable. */
9931 if (is_reference (var))
9932 var = build_simple_mem_ref (var);
9934 tree t = create_tmp_var (type);
9936 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9937 gimplify_and_add (unshare_expr(x), stmt_seqp);
9939 /* var = var op mem */
9940 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9942 case TRUTH_ANDIF_EXPR:
9943 case TRUTH_ORIF_EXPR:
9944 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9945 t, mem);
9946 gimplify_and_add (t, stmt_seqp);
9947 break;
9948 default:
9949 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9950 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9951 stmt_seqp);
9954 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9955 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9956 gimplify_and_add (unshare_expr(x), stmt_seqp);
9959 /* Increment the induction variable. */
9960 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9961 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9962 gimple_seq_add_stmt (stmt_seqp, stmt);
9964 /* Go back to the top of the loop. */
9965 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9967 /* Place the loop exit label here. */
9968 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9971 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9972 scan that for reductions. */
9974 static void
9975 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9976 gimple_seq *out_stmt_seqp, omp_context *ctx)
9978 gimple_stmt_iterator gsi;
9979 gimple_seq inner = NULL;
9981 /* A collapse clause may have inserted a new bind block. */
9982 gsi = gsi_start (*body);
9983 while (!gsi_end_p (gsi))
9985 gimple *stmt = gsi_stmt (gsi);
9986 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9988 inner = gimple_bind_body (bind_stmt);
9989 body = &inner;
9990 gsi = gsi_start (*body);
9992 else if (dyn_cast <gomp_for *> (stmt))
9993 break;
9994 else
9995 gsi_next (&gsi);
9998 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10000 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
10001 enter, exit;
10002 bool reduction_found = false;
10004 gimple *stmt = gsi_stmt (gsi);
10006 switch (gimple_code (stmt))
10008 case GIMPLE_OMP_FOR:
10009 clauses = gimple_omp_for_clauses (stmt);
10011 /* Search for a reduction clause. */
10012 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10013 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
10015 reduction_found = true;
10016 break;
10019 if (!reduction_found)
10020 break;
10022 ctx = maybe_lookup_ctx (stmt);
10023 t = NULL_TREE;
10025 /* Extract the number of threads. */
10026 nthreads = create_tmp_var (sizetype);
10027 t = oacc_max_threads (ctx);
10028 gimplify_assign (nthreads, t, in_stmt_seqp);
10030 /* Determine if this is kernel will be executed on the host. */
10031 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
10032 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
10033 stmt = gimple_build_call (call, 0);
10034 gimple_call_set_lhs (stmt, acc_device);
10035 gimple_seq_add_stmt (in_stmt_seqp, stmt);
10037 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
10038 acc_device_host = create_tmp_var (integer_type_node,
10039 ".acc_device_host");
10040 gimplify_assign (acc_device_host,
10041 build_int_cst (integer_type_node,
10042 GOMP_DEVICE_HOST),
10043 in_stmt_seqp);
10045 enter = create_artificial_label (UNKNOWN_LOCATION);
10046 exit = create_artificial_label (UNKNOWN_LOCATION);
10048 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
10049 enter, exit);
10050 gimple_seq_add_stmt (in_stmt_seqp, stmt);
10051 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
10052 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
10053 integer_one_node),
10054 in_stmt_seqp);
10055 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
10057 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
10058 ctx);
10059 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
10060 break;
10061 default:
10062 // Scan for other directives which support reduction here.
10063 break;
10068 /* If ctx is a worksharing context inside of a cancellable parallel
10069 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
10070 and conditional branch to parallel's cancel_label to handle
10071 cancellation in the implicit barrier. */
10073 static void
10074 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
10076 gimple *omp_return = gimple_seq_last_stmt (*body);
10077 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
10078 if (gimple_omp_return_nowait_p (omp_return))
10079 return;
10080 if (ctx->outer
10081 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
10082 && ctx->outer->cancellable)
10084 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
10085 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
10086 tree lhs = create_tmp_var (c_bool_type);
10087 gimple_omp_return_set_lhs (omp_return, lhs);
10088 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10089 gimple *g = gimple_build_cond (NE_EXPR, lhs,
10090 fold_convert (c_bool_type,
10091 boolean_false_node),
10092 ctx->outer->cancel_label, fallthru_label);
10093 gimple_seq_add_stmt (body, g);
10094 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10098 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10099 CTX is the enclosing OMP context for the current statement. */
10101 static void
10102 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10104 tree block, control;
10105 gimple_stmt_iterator tgsi;
10106 gomp_sections *stmt;
10107 gimple *t;
10108 gbind *new_stmt, *bind;
10109 gimple_seq ilist, dlist, olist, new_body;
10111 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
10113 push_gimplify_context ();
10115 dlist = NULL;
10116 ilist = NULL;
10117 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10118 &ilist, &dlist, ctx, NULL);
10120 new_body = gimple_omp_body (stmt);
10121 gimple_omp_set_body (stmt, NULL);
10122 tgsi = gsi_start (new_body);
10123 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10125 omp_context *sctx;
10126 gimple *sec_start;
10128 sec_start = gsi_stmt (tgsi);
10129 sctx = maybe_lookup_ctx (sec_start);
10130 gcc_assert (sctx);
10132 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10133 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10134 GSI_CONTINUE_LINKING);
10135 gimple_omp_set_body (sec_start, NULL);
10137 if (gsi_one_before_end_p (tgsi))
10139 gimple_seq l = NULL;
10140 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10141 &l, ctx);
10142 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10143 gimple_omp_section_set_last (sec_start);
10146 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10147 GSI_CONTINUE_LINKING);
10150 block = make_node (BLOCK);
10151 bind = gimple_build_bind (NULL, new_body, block);
10153 olist = NULL;
10154 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10156 block = make_node (BLOCK);
10157 new_stmt = gimple_build_bind (NULL, NULL, block);
10158 gsi_replace (gsi_p, new_stmt, true);
10160 pop_gimplify_context (new_stmt);
10161 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10162 BLOCK_VARS (block) = gimple_bind_vars (bind);
10163 if (BLOCK_VARS (block))
10164 TREE_USED (block) = 1;
10166 new_body = NULL;
10167 gimple_seq_add_seq (&new_body, ilist);
10168 gimple_seq_add_stmt (&new_body, stmt);
10169 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10170 gimple_seq_add_stmt (&new_body, bind);
10172 control = create_tmp_var (unsigned_type_node, ".section");
10173 t = gimple_build_omp_continue (control, control);
10174 gimple_omp_sections_set_control (stmt, control);
10175 gimple_seq_add_stmt (&new_body, t);
10177 gimple_seq_add_seq (&new_body, olist);
10178 if (ctx->cancellable)
10179 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10180 gimple_seq_add_seq (&new_body, dlist);
10182 new_body = maybe_catch_exception (new_body);
10184 t = gimple_build_omp_return
10185 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10186 OMP_CLAUSE_NOWAIT));
10187 gimple_seq_add_stmt (&new_body, t);
10188 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10190 gimple_bind_set_body (new_stmt, new_body);
10194 /* A subroutine of lower_omp_single. Expand the simple form of
10195 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10197 if (GOMP_single_start ())
10198 BODY;
10199 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10201 FIXME. It may be better to delay expanding the logic of this until
10202 pass_expand_omp. The expanded logic may make the job more difficult
10203 to a synchronization analysis pass. */
10205 static void
10206 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10208 location_t loc = gimple_location (single_stmt);
10209 tree tlabel = create_artificial_label (loc);
10210 tree flabel = create_artificial_label (loc);
10211 gimple *call, *cond;
10212 tree lhs, decl;
10214 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10215 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10216 call = gimple_build_call (decl, 0);
10217 gimple_call_set_lhs (call, lhs);
10218 gimple_seq_add_stmt (pre_p, call);
10220 cond = gimple_build_cond (EQ_EXPR, lhs,
10221 fold_convert_loc (loc, TREE_TYPE (lhs),
10222 boolean_true_node),
10223 tlabel, flabel);
10224 gimple_seq_add_stmt (pre_p, cond);
10225 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10226 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10227 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10231 /* A subroutine of lower_omp_single. Expand the simple form of
10232 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10234 #pragma omp single copyprivate (a, b, c)
10236 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10239 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10241 BODY;
10242 copyout.a = a;
10243 copyout.b = b;
10244 copyout.c = c;
10245 GOMP_single_copy_end (&copyout);
10247 else
10249 a = copyout_p->a;
10250 b = copyout_p->b;
10251 c = copyout_p->c;
10253 GOMP_barrier ();
10256 FIXME. It may be better to delay expanding the logic of this until
10257 pass_expand_omp. The expanded logic may make the job more difficult
10258 to a synchronization analysis pass. */
10260 static void
10261 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10262 omp_context *ctx)
10264 tree ptr_type, t, l0, l1, l2, bfn_decl;
10265 gimple_seq copyin_seq;
10266 location_t loc = gimple_location (single_stmt);
10268 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10270 ptr_type = build_pointer_type (ctx->record_type);
10271 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10273 l0 = create_artificial_label (loc);
10274 l1 = create_artificial_label (loc);
10275 l2 = create_artificial_label (loc);
10277 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10278 t = build_call_expr_loc (loc, bfn_decl, 0);
10279 t = fold_convert_loc (loc, ptr_type, t);
10280 gimplify_assign (ctx->receiver_decl, t, pre_p);
10282 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10283 build_int_cst (ptr_type, 0));
10284 t = build3 (COND_EXPR, void_type_node, t,
10285 build_and_jump (&l0), build_and_jump (&l1));
10286 gimplify_and_add (t, pre_p);
10288 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10290 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10292 copyin_seq = NULL;
10293 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10294 &copyin_seq, ctx);
10296 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10297 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10298 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10299 gimplify_and_add (t, pre_p);
10301 t = build_and_jump (&l2);
10302 gimplify_and_add (t, pre_p);
10304 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10306 gimple_seq_add_seq (pre_p, copyin_seq);
10308 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10312 /* Expand code for an OpenMP single directive. */
10314 static void
10315 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10317 tree block;
10318 gimple *t;
10319 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10320 gbind *bind;
10321 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10323 push_gimplify_context ();
10325 block = make_node (BLOCK);
10326 bind = gimple_build_bind (NULL, NULL, block);
10327 gsi_replace (gsi_p, bind, true);
10328 bind_body = NULL;
10329 dlist = NULL;
10330 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10331 &bind_body, &dlist, ctx, NULL);
10332 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10334 gimple_seq_add_stmt (&bind_body, single_stmt);
10336 if (ctx->record_type)
10337 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10338 else
10339 lower_omp_single_simple (single_stmt, &bind_body);
10341 gimple_omp_set_body (single_stmt, NULL);
10343 gimple_seq_add_seq (&bind_body, dlist);
10345 bind_body = maybe_catch_exception (bind_body);
10347 t = gimple_build_omp_return
10348 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10349 OMP_CLAUSE_NOWAIT));
10350 gimple_seq_add_stmt (&bind_body_tail, t);
10351 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10352 if (ctx->record_type)
10354 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10355 tree clobber = build_constructor (ctx->record_type, NULL);
10356 TREE_THIS_VOLATILE (clobber) = 1;
10357 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10358 clobber), GSI_SAME_STMT);
10360 gimple_seq_add_seq (&bind_body, bind_body_tail);
10361 gimple_bind_set_body (bind, bind_body);
10363 pop_gimplify_context (bind);
10365 gimple_bind_append_vars (bind, ctx->block_vars);
10366 BLOCK_VARS (block) = ctx->block_vars;
10367 if (BLOCK_VARS (block))
10368 TREE_USED (block) = 1;
10372 /* Expand code for an OpenMP master directive. */
10374 static void
10375 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10377 tree block, lab = NULL, x, bfn_decl;
10378 gimple *stmt = gsi_stmt (*gsi_p);
10379 gbind *bind;
10380 location_t loc = gimple_location (stmt);
10381 gimple_seq tseq;
10383 push_gimplify_context ();
10385 block = make_node (BLOCK);
10386 bind = gimple_build_bind (NULL, NULL, block);
10387 gsi_replace (gsi_p, bind, true);
10388 gimple_bind_add_stmt (bind, stmt);
10390 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10391 x = build_call_expr_loc (loc, bfn_decl, 0);
10392 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10393 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10394 tseq = NULL;
10395 gimplify_and_add (x, &tseq);
10396 gimple_bind_add_seq (bind, tseq);
10398 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10399 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10400 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10401 gimple_omp_set_body (stmt, NULL);
10403 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10405 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10407 pop_gimplify_context (bind);
10409 gimple_bind_append_vars (bind, ctx->block_vars);
10410 BLOCK_VARS (block) = ctx->block_vars;
10414 /* Expand code for an OpenMP taskgroup directive. */
10416 static void
10417 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10419 gimple *stmt = gsi_stmt (*gsi_p);
10420 gcall *x;
10421 gbind *bind;
10422 tree block = make_node (BLOCK);
10424 bind = gimple_build_bind (NULL, NULL, block);
10425 gsi_replace (gsi_p, bind, true);
10426 gimple_bind_add_stmt (bind, stmt);
10428 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10430 gimple_bind_add_stmt (bind, x);
10432 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10433 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10434 gimple_omp_set_body (stmt, NULL);
10436 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10438 gimple_bind_append_vars (bind, ctx->block_vars);
10439 BLOCK_VARS (block) = ctx->block_vars;
10443 /* Expand code for an OpenMP ordered directive. */
10445 static void
10446 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10448 tree block;
10449 gimple *stmt = gsi_stmt (*gsi_p);
10450 gcall *x;
10451 gbind *bind;
10453 push_gimplify_context ();
10455 block = make_node (BLOCK);
10456 bind = gimple_build_bind (NULL, NULL, block);
10457 gsi_replace (gsi_p, bind, true);
10458 gimple_bind_add_stmt (bind, stmt);
10460 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10462 gimple_bind_add_stmt (bind, x);
10464 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10465 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10466 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10467 gimple_omp_set_body (stmt, NULL);
10469 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10470 gimple_bind_add_stmt (bind, x);
10472 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10474 pop_gimplify_context (bind);
10476 gimple_bind_append_vars (bind, ctx->block_vars);
10477 BLOCK_VARS (block) = gimple_bind_vars (bind);
10481 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10482 substitution of a couple of function calls. But in the NAMED case,
10483 requires that languages coordinate a symbol name. It is therefore
10484 best put here in common code. */
10486 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10488 static void
10489 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10491 tree block;
10492 tree name, lock, unlock;
10493 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10494 gbind *bind;
10495 location_t loc = gimple_location (stmt);
10496 gimple_seq tbody;
10498 name = gimple_omp_critical_name (stmt);
10499 if (name)
10501 tree decl;
10503 if (!critical_name_mutexes)
10504 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10506 tree *n = critical_name_mutexes->get (name);
10507 if (n == NULL)
10509 char *new_str;
10511 decl = create_tmp_var_raw (ptr_type_node);
10513 new_str = ACONCAT ((".gomp_critical_user_",
10514 IDENTIFIER_POINTER (name), NULL));
10515 DECL_NAME (decl) = get_identifier (new_str);
10516 TREE_PUBLIC (decl) = 1;
10517 TREE_STATIC (decl) = 1;
10518 DECL_COMMON (decl) = 1;
10519 DECL_ARTIFICIAL (decl) = 1;
10520 DECL_IGNORED_P (decl) = 1;
10522 varpool_node::finalize_decl (decl);
10524 critical_name_mutexes->put (name, decl);
10526 else
10527 decl = *n;
10529 /* If '#pragma omp critical' is inside offloaded region or
10530 inside function marked as offloadable, the symbol must be
10531 marked as offloadable too. */
10532 omp_context *octx;
10533 if (cgraph_node::get (current_function_decl)->offloadable)
10534 varpool_node::get_create (decl)->offloadable = 1;
10535 else
10536 for (octx = ctx->outer; octx; octx = octx->outer)
10537 if (is_gimple_omp_offloaded (octx->stmt))
10539 varpool_node::get_create (decl)->offloadable = 1;
10540 break;
10543 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10544 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10546 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10547 unlock = build_call_expr_loc (loc, unlock, 1,
10548 build_fold_addr_expr_loc (loc, decl));
10550 else
10552 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10553 lock = build_call_expr_loc (loc, lock, 0);
10555 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10556 unlock = build_call_expr_loc (loc, unlock, 0);
10559 push_gimplify_context ();
10561 block = make_node (BLOCK);
10562 bind = gimple_build_bind (NULL, NULL, block);
10563 gsi_replace (gsi_p, bind, true);
10564 gimple_bind_add_stmt (bind, stmt);
10566 tbody = gimple_bind_body (bind);
10567 gimplify_and_add (lock, &tbody);
10568 gimple_bind_set_body (bind, tbody);
10570 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10571 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10572 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10573 gimple_omp_set_body (stmt, NULL);
10575 tbody = gimple_bind_body (bind);
10576 gimplify_and_add (unlock, &tbody);
10577 gimple_bind_set_body (bind, tbody);
10579 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10581 pop_gimplify_context (bind);
10582 gimple_bind_append_vars (bind, ctx->block_vars);
10583 BLOCK_VARS (block) = gimple_bind_vars (bind);
10587 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10588 for a lastprivate clause. Given a loop control predicate of (V
10589 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10590 is appended to *DLIST, iterator initialization is appended to
10591 *BODY_P. */
10593 static void
10594 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10595 gimple_seq *dlist, struct omp_context *ctx)
10597 tree clauses, cond, vinit;
10598 enum tree_code cond_code;
10599 gimple_seq stmts;
10601 cond_code = fd->loop.cond_code;
10602 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10604 /* When possible, use a strict equality expression. This can let VRP
10605 type optimizations deduce the value and remove a copy. */
10606 if (tree_fits_shwi_p (fd->loop.step))
10608 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10609 if (step == 1 || step == -1)
10610 cond_code = EQ_EXPR;
10613 tree n2 = fd->loop.n2;
10614 if (fd->collapse > 1
10615 && TREE_CODE (n2) != INTEGER_CST
10616 && gimple_omp_for_combined_into_p (fd->for_stmt)
10617 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10619 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10620 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
10622 struct omp_for_data outer_fd;
10623 extract_omp_for_data (gfor, &outer_fd, NULL);
10624 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10627 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
10629 clauses = gimple_omp_for_clauses (fd->for_stmt);
10630 stmts = NULL;
10631 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10632 if (!gimple_seq_empty_p (stmts))
10634 gimple_seq_add_seq (&stmts, *dlist);
10635 *dlist = stmts;
10637 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10638 vinit = fd->loop.n1;
10639 if (cond_code == EQ_EXPR
10640 && tree_fits_shwi_p (fd->loop.n2)
10641 && ! integer_zerop (fd->loop.n2))
10642 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10643 else
10644 vinit = unshare_expr (vinit);
10646 /* Initialize the iterator variable, so that threads that don't execute
10647 any iterations don't execute the lastprivate clauses by accident. */
10648 gimplify_assign (fd->loop.v, vinit, body_p);
10653 /* Lower code for an OMP loop directive. */
10655 static void
10656 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10658 tree *rhs_p, block;
10659 struct omp_for_data fd, *fdp = NULL;
10660 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10661 gbind *new_stmt;
10662 gimple_seq omp_for_body, body, dlist;
10663 size_t i;
10665 push_gimplify_context ();
10667 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10669 block = make_node (BLOCK);
10670 new_stmt = gimple_build_bind (NULL, NULL, block);
10671 /* Replace at gsi right away, so that 'stmt' is no member
10672 of a sequence anymore as we're going to add to a different
10673 one below. */
10674 gsi_replace (gsi_p, new_stmt, true);
10676 /* Move declaration of temporaries in the loop body before we make
10677 it go away. */
10678 omp_for_body = gimple_omp_body (stmt);
10679 if (!gimple_seq_empty_p (omp_for_body)
10680 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10682 gbind *inner_bind
10683 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10684 tree vars = gimple_bind_vars (inner_bind);
10685 gimple_bind_append_vars (new_stmt, vars);
10686 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10687 keep them on the inner_bind and it's block. */
10688 gimple_bind_set_vars (inner_bind, NULL_TREE);
10689 if (gimple_bind_block (inner_bind))
10690 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10693 if (gimple_omp_for_combined_into_p (stmt))
10695 extract_omp_for_data (stmt, &fd, NULL);
10696 fdp = &fd;
10698 /* We need two temporaries with fd.loop.v type (istart/iend)
10699 and then (fd.collapse - 1) temporaries with the same
10700 type for count2 ... countN-1 vars if not constant. */
10701 size_t count = 2;
10702 tree type = fd.iter_type;
10703 if (fd.collapse > 1
10704 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10705 count += fd.collapse - 1;
10706 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10707 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10708 tree clauses = *pc;
10709 if (parallel_for)
10710 outerc
10711 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10712 OMP_CLAUSE__LOOPTEMP_);
10713 for (i = 0; i < count; i++)
10715 tree temp;
10716 if (parallel_for)
10718 gcc_assert (outerc);
10719 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10720 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10721 OMP_CLAUSE__LOOPTEMP_);
10723 else
10725 temp = create_tmp_var (type);
10726 insert_decl_map (&ctx->outer->cb, temp, temp);
10728 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10729 OMP_CLAUSE_DECL (*pc) = temp;
10730 pc = &OMP_CLAUSE_CHAIN (*pc);
10732 *pc = clauses;
10735 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10736 dlist = NULL;
10737 body = NULL;
10738 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10739 fdp);
10740 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10742 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10744 /* Lower the header expressions. At this point, we can assume that
10745 the header is of the form:
10747 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10749 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10750 using the .omp_data_s mapping, if needed. */
10751 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10753 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10754 if (!is_gimple_min_invariant (*rhs_p))
10755 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10757 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10758 if (!is_gimple_min_invariant (*rhs_p))
10759 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10761 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10762 if (!is_gimple_min_invariant (*rhs_p))
10763 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10766 /* Once lowered, extract the bounds and clauses. */
10767 extract_omp_for_data (stmt, &fd, NULL);
10769 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10771 gimple_seq_add_stmt (&body, stmt);
10772 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10774 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10775 fd.loop.v));
10777 /* After the loop, add exit clauses. */
10778 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10780 if (ctx->cancellable)
10781 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10783 gimple_seq_add_seq (&body, dlist);
10785 body = maybe_catch_exception (body);
10787 /* Region exit marker goes at the end of the loop body. */
10788 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10789 maybe_add_implicit_barrier_cancel (ctx, &body);
10790 pop_gimplify_context (new_stmt);
10792 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10793 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10794 if (BLOCK_VARS (block))
10795 TREE_USED (block) = 1;
10797 gimple_bind_set_body (new_stmt, body);
10798 gimple_omp_set_body (stmt, NULL);
10799 gimple_omp_for_set_pre_body (stmt, NULL);
10802 /* Callback for walk_stmts. Check if the current statement only contains
10803 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10805 static tree
10806 check_combined_parallel (gimple_stmt_iterator *gsi_p,
10807 bool *handled_ops_p,
10808 struct walk_stmt_info *wi)
10810 int *info = (int *) wi->info;
10811 gimple *stmt = gsi_stmt (*gsi_p);
10813 *handled_ops_p = true;
10814 switch (gimple_code (stmt))
10816 WALK_SUBSTMTS;
10818 case GIMPLE_OMP_FOR:
10819 case GIMPLE_OMP_SECTIONS:
10820 *info = *info == 0 ? 1 : -1;
10821 break;
10822 default:
10823 *info = -1;
10824 break;
10826 return NULL;
10829 struct omp_taskcopy_context
10831 /* This field must be at the beginning, as we do "inheritance": Some
10832 callback functions for tree-inline.c (e.g., omp_copy_decl)
10833 receive a copy_body_data pointer that is up-casted to an
10834 omp_context pointer. */
10835 copy_body_data cb;
10836 omp_context *ctx;
10839 static tree
10840 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10842 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10844 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10845 return create_tmp_var (TREE_TYPE (var));
10847 return var;
10850 static tree
10851 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10853 tree name, new_fields = NULL, type, f;
10855 type = lang_hooks.types.make_type (RECORD_TYPE);
10856 name = DECL_NAME (TYPE_NAME (orig_type));
10857 name = build_decl (gimple_location (tcctx->ctx->stmt),
10858 TYPE_DECL, name, type);
10859 TYPE_NAME (type) = name;
10861 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10863 tree new_f = copy_node (f);
10864 DECL_CONTEXT (new_f) = type;
10865 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10866 TREE_CHAIN (new_f) = new_fields;
10867 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10868 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10869 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10870 &tcctx->cb, NULL);
10871 new_fields = new_f;
10872 tcctx->cb.decl_map->put (f, new_f);
10874 TYPE_FIELDS (type) = nreverse (new_fields);
10875 layout_type (type);
10876 return type;
10879 /* Create task copyfn. */
10881 static void
10882 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
10884 struct function *child_cfun;
10885 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10886 tree record_type, srecord_type, bind, list;
10887 bool record_needs_remap = false, srecord_needs_remap = false;
10888 splay_tree_node n;
10889 struct omp_taskcopy_context tcctx;
10890 location_t loc = gimple_location (task_stmt);
10892 child_fn = gimple_omp_task_copy_fn (task_stmt);
10893 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10894 gcc_assert (child_cfun->cfg == NULL);
10895 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10897 /* Reset DECL_CONTEXT on function arguments. */
10898 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10899 DECL_CONTEXT (t) = child_fn;
10901 /* Populate the function. */
10902 push_gimplify_context ();
10903 push_cfun (child_cfun);
10905 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10906 TREE_SIDE_EFFECTS (bind) = 1;
10907 list = NULL;
10908 DECL_SAVED_TREE (child_fn) = bind;
10909 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10911 /* Remap src and dst argument types if needed. */
10912 record_type = ctx->record_type;
10913 srecord_type = ctx->srecord_type;
10914 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10915 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10917 record_needs_remap = true;
10918 break;
10920 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10921 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10923 srecord_needs_remap = true;
10924 break;
10927 if (record_needs_remap || srecord_needs_remap)
10929 memset (&tcctx, '\0', sizeof (tcctx));
10930 tcctx.cb.src_fn = ctx->cb.src_fn;
10931 tcctx.cb.dst_fn = child_fn;
10932 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
10933 gcc_checking_assert (tcctx.cb.src_node);
10934 tcctx.cb.dst_node = tcctx.cb.src_node;
10935 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10936 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10937 tcctx.cb.eh_lp_nr = 0;
10938 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10939 tcctx.cb.decl_map = new hash_map<tree, tree>;
10940 tcctx.ctx = ctx;
10942 if (record_needs_remap)
10943 record_type = task_copyfn_remap_type (&tcctx, record_type);
10944 if (srecord_needs_remap)
10945 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10947 else
10948 tcctx.cb.decl_map = NULL;
10950 arg = DECL_ARGUMENTS (child_fn);
10951 TREE_TYPE (arg) = build_pointer_type (record_type);
10952 sarg = DECL_CHAIN (arg);
10953 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10955 /* First pass: initialize temporaries used in record_type and srecord_type
10956 sizes and field offsets. */
10957 if (tcctx.cb.decl_map)
10958 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10959 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10961 tree *p;
10963 decl = OMP_CLAUSE_DECL (c);
10964 p = tcctx.cb.decl_map->get (decl);
10965 if (p == NULL)
10966 continue;
10967 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10968 sf = (tree) n->value;
10969 sf = *tcctx.cb.decl_map->get (sf);
10970 src = build_simple_mem_ref_loc (loc, sarg);
10971 src = omp_build_component_ref (src, sf);
10972 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10973 append_to_statement_list (t, &list);
10976 /* Second pass: copy shared var pointers and copy construct non-VLA
10977 firstprivate vars. */
10978 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10979 switch (OMP_CLAUSE_CODE (c))
10981 case OMP_CLAUSE_SHARED:
10982 decl = OMP_CLAUSE_DECL (c);
10983 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10984 if (n == NULL)
10985 break;
10986 f = (tree) n->value;
10987 if (tcctx.cb.decl_map)
10988 f = *tcctx.cb.decl_map->get (f);
10989 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10990 sf = (tree) n->value;
10991 if (tcctx.cb.decl_map)
10992 sf = *tcctx.cb.decl_map->get (sf);
10993 src = build_simple_mem_ref_loc (loc, sarg);
10994 src = omp_build_component_ref (src, sf);
10995 dst = build_simple_mem_ref_loc (loc, arg);
10996 dst = omp_build_component_ref (dst, f);
10997 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10998 append_to_statement_list (t, &list);
10999 break;
11000 case OMP_CLAUSE_FIRSTPRIVATE:
11001 decl = OMP_CLAUSE_DECL (c);
11002 if (is_variable_sized (decl))
11003 break;
11004 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11005 if (n == NULL)
11006 break;
11007 f = (tree) n->value;
11008 if (tcctx.cb.decl_map)
11009 f = *tcctx.cb.decl_map->get (f);
11010 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11011 if (n != NULL)
11013 sf = (tree) n->value;
11014 if (tcctx.cb.decl_map)
11015 sf = *tcctx.cb.decl_map->get (sf);
11016 src = build_simple_mem_ref_loc (loc, sarg);
11017 src = omp_build_component_ref (src, sf);
11018 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
11019 src = build_simple_mem_ref_loc (loc, src);
11021 else
11022 src = decl;
11023 dst = build_simple_mem_ref_loc (loc, arg);
11024 dst = omp_build_component_ref (dst, f);
11025 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11026 append_to_statement_list (t, &list);
11027 break;
11028 case OMP_CLAUSE_PRIVATE:
11029 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
11030 break;
11031 decl = OMP_CLAUSE_DECL (c);
11032 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11033 f = (tree) n->value;
11034 if (tcctx.cb.decl_map)
11035 f = *tcctx.cb.decl_map->get (f);
11036 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11037 if (n != NULL)
11039 sf = (tree) n->value;
11040 if (tcctx.cb.decl_map)
11041 sf = *tcctx.cb.decl_map->get (sf);
11042 src = build_simple_mem_ref_loc (loc, sarg);
11043 src = omp_build_component_ref (src, sf);
11044 if (use_pointer_for_field (decl, NULL))
11045 src = build_simple_mem_ref_loc (loc, src);
11047 else
11048 src = decl;
11049 dst = build_simple_mem_ref_loc (loc, arg);
11050 dst = omp_build_component_ref (dst, f);
11051 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
11052 append_to_statement_list (t, &list);
11053 break;
11054 default:
11055 break;
11058 /* Last pass: handle VLA firstprivates. */
11059 if (tcctx.cb.decl_map)
11060 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
11061 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
11063 tree ind, ptr, df;
11065 decl = OMP_CLAUSE_DECL (c);
11066 if (!is_variable_sized (decl))
11067 continue;
11068 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11069 if (n == NULL)
11070 continue;
11071 f = (tree) n->value;
11072 f = *tcctx.cb.decl_map->get (f);
11073 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
11074 ind = DECL_VALUE_EXPR (decl);
11075 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
11076 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
11077 n = splay_tree_lookup (ctx->sfield_map,
11078 (splay_tree_key) TREE_OPERAND (ind, 0));
11079 sf = (tree) n->value;
11080 sf = *tcctx.cb.decl_map->get (sf);
11081 src = build_simple_mem_ref_loc (loc, sarg);
11082 src = omp_build_component_ref (src, sf);
11083 src = build_simple_mem_ref_loc (loc, src);
11084 dst = build_simple_mem_ref_loc (loc, arg);
11085 dst = omp_build_component_ref (dst, f);
11086 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11087 append_to_statement_list (t, &list);
11088 n = splay_tree_lookup (ctx->field_map,
11089 (splay_tree_key) TREE_OPERAND (ind, 0));
11090 df = (tree) n->value;
11091 df = *tcctx.cb.decl_map->get (df);
11092 ptr = build_simple_mem_ref_loc (loc, arg);
11093 ptr = omp_build_component_ref (ptr, df);
11094 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
11095 build_fold_addr_expr_loc (loc, dst));
11096 append_to_statement_list (t, &list);
11099 t = build1 (RETURN_EXPR, void_type_node, NULL);
11100 append_to_statement_list (t, &list);
11102 if (tcctx.cb.decl_map)
11103 delete tcctx.cb.decl_map;
11104 pop_gimplify_context (NULL);
11105 BIND_EXPR_BODY (bind) = list;
11106 pop_cfun ();
11109 static void
11110 lower_depend_clauses (gimple *stmt, gimple_seq *iseq, gimple_seq *oseq)
11112 tree c, clauses;
11113 gimple *g;
11114 size_t n_in = 0, n_out = 0, idx = 2, i;
11116 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11117 OMP_CLAUSE_DEPEND);
11118 gcc_assert (clauses);
11119 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11120 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11121 switch (OMP_CLAUSE_DEPEND_KIND (c))
11123 case OMP_CLAUSE_DEPEND_IN:
11124 n_in++;
11125 break;
11126 case OMP_CLAUSE_DEPEND_OUT:
11127 case OMP_CLAUSE_DEPEND_INOUT:
11128 n_out++;
11129 break;
11130 default:
11131 gcc_unreachable ();
11133 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11134 tree array = create_tmp_var (type);
11135 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11136 NULL_TREE);
11137 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11138 gimple_seq_add_stmt (iseq, g);
11139 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11140 NULL_TREE);
11141 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11142 gimple_seq_add_stmt (iseq, g);
11143 for (i = 0; i < 2; i++)
11145 if ((i ? n_in : n_out) == 0)
11146 continue;
11147 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11148 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11149 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11151 tree t = OMP_CLAUSE_DECL (c);
11152 t = fold_convert (ptr_type_node, t);
11153 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11154 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11155 NULL_TREE, NULL_TREE);
11156 g = gimple_build_assign (r, t);
11157 gimple_seq_add_stmt (iseq, g);
11160 tree *p = gimple_omp_task_clauses_ptr (stmt);
11161 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11162 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11163 OMP_CLAUSE_CHAIN (c) = *p;
11164 *p = c;
11165 tree clobber = build_constructor (type, NULL);
11166 TREE_THIS_VOLATILE (clobber) = 1;
11167 g = gimple_build_assign (array, clobber);
11168 gimple_seq_add_stmt (oseq, g);
11171 /* Lower the OpenMP parallel or task directive in the current statement
11172 in GSI_P. CTX holds context information for the directive. */
11174 static void
11175 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11177 tree clauses;
11178 tree child_fn, t;
11179 gimple *stmt = gsi_stmt (*gsi_p);
11180 gbind *par_bind, *bind, *dep_bind = NULL;
11181 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11182 location_t loc = gimple_location (stmt);
11184 clauses = gimple_omp_taskreg_clauses (stmt);
11185 par_bind
11186 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11187 par_body = gimple_bind_body (par_bind);
11188 child_fn = ctx->cb.dst_fn;
11189 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11190 && !gimple_omp_parallel_combined_p (stmt))
11192 struct walk_stmt_info wi;
11193 int ws_num = 0;
11195 memset (&wi, 0, sizeof (wi));
11196 wi.info = &ws_num;
11197 wi.val_only = true;
11198 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11199 if (ws_num == 1)
11200 gimple_omp_parallel_set_combined_p (stmt, true);
11202 gimple_seq dep_ilist = NULL;
11203 gimple_seq dep_olist = NULL;
11204 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11205 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11207 push_gimplify_context ();
11208 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11209 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11212 if (ctx->srecord_type)
11213 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11215 push_gimplify_context ();
11217 par_olist = NULL;
11218 par_ilist = NULL;
11219 par_rlist = NULL;
11220 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11221 lower_omp (&par_body, ctx);
11222 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11223 lower_reduction_clauses (clauses, &par_rlist, ctx);
11225 /* Declare all the variables created by mapping and the variables
11226 declared in the scope of the parallel body. */
11227 record_vars_into (ctx->block_vars, child_fn);
11228 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11230 if (ctx->record_type)
11232 ctx->sender_decl
11233 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11234 : ctx->record_type, ".omp_data_o");
11235 DECL_NAMELESS (ctx->sender_decl) = 1;
11236 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11237 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11240 olist = NULL;
11241 ilist = NULL;
11242 lower_send_clauses (clauses, &ilist, &olist, ctx);
11243 lower_send_shared_vars (&ilist, &olist, ctx);
11245 if (ctx->record_type)
11247 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11248 TREE_THIS_VOLATILE (clobber) = 1;
11249 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11250 clobber));
11253 /* Once all the expansions are done, sequence all the different
11254 fragments inside gimple_omp_body. */
11256 new_body = NULL;
11258 if (ctx->record_type)
11260 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11261 /* fixup_child_record_type might have changed receiver_decl's type. */
11262 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11263 gimple_seq_add_stmt (&new_body,
11264 gimple_build_assign (ctx->receiver_decl, t));
11267 gimple_seq_add_seq (&new_body, par_ilist);
11268 gimple_seq_add_seq (&new_body, par_body);
11269 gimple_seq_add_seq (&new_body, par_rlist);
11270 if (ctx->cancellable)
11271 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11272 gimple_seq_add_seq (&new_body, par_olist);
11273 new_body = maybe_catch_exception (new_body);
11274 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
11275 gimple_seq_add_stmt (&new_body,
11276 gimple_build_omp_continue (integer_zero_node,
11277 integer_zero_node));
11278 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11279 gimple_omp_set_body (stmt, new_body);
11281 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11282 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11283 gimple_bind_add_seq (bind, ilist);
11284 gimple_bind_add_stmt (bind, stmt);
11285 gimple_bind_add_seq (bind, olist);
11287 pop_gimplify_context (NULL);
11289 if (dep_bind)
11291 gimple_bind_add_seq (dep_bind, dep_ilist);
11292 gimple_bind_add_stmt (dep_bind, bind);
11293 gimple_bind_add_seq (dep_bind, dep_olist);
11294 pop_gimplify_context (dep_bind);
11298 /* Lower the GIMPLE_OMP_TARGET in the current statement
11299 in GSI_P. CTX holds context information for the directive. */
11301 static void
11302 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11304 tree clauses;
11305 tree child_fn, t, c;
11306 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11307 gbind *tgt_bind, *bind;
11308 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11309 location_t loc = gimple_location (stmt);
11310 bool offloaded, data_region;
11311 unsigned int map_cnt = 0;
11313 offloaded = is_gimple_omp_offloaded (stmt);
11314 switch (gimple_omp_target_kind (stmt))
11316 case GF_OMP_TARGET_KIND_REGION:
11317 case GF_OMP_TARGET_KIND_UPDATE:
11318 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11319 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11320 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11321 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11322 data_region = false;
11323 break;
11324 case GF_OMP_TARGET_KIND_DATA:
11325 case GF_OMP_TARGET_KIND_OACC_DATA:
11326 data_region = true;
11327 break;
11328 default:
11329 gcc_unreachable ();
11332 clauses = gimple_omp_target_clauses (stmt);
11334 tgt_bind = NULL;
11335 tgt_body = NULL;
11336 if (offloaded)
11338 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11339 tgt_body = gimple_bind_body (tgt_bind);
11341 else if (data_region)
11342 tgt_body = gimple_omp_body (stmt);
11343 child_fn = ctx->cb.dst_fn;
11345 push_gimplify_context ();
11347 irlist = NULL;
11348 orlist = NULL;
11349 if (offloaded
11350 && is_gimple_omp_oacc (stmt))
11351 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11353 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11354 switch (OMP_CLAUSE_CODE (c))
11356 tree var, x;
11358 default:
11359 break;
11360 case OMP_CLAUSE_MAP:
11361 #ifdef ENABLE_CHECKING
11362 /* First check what we're prepared to handle in the following. */
11363 switch (OMP_CLAUSE_MAP_KIND (c))
11365 case GOMP_MAP_ALLOC:
11366 case GOMP_MAP_TO:
11367 case GOMP_MAP_FROM:
11368 case GOMP_MAP_TOFROM:
11369 case GOMP_MAP_POINTER:
11370 case GOMP_MAP_TO_PSET:
11371 break;
11372 case GOMP_MAP_FORCE_ALLOC:
11373 case GOMP_MAP_FORCE_TO:
11374 case GOMP_MAP_FORCE_FROM:
11375 case GOMP_MAP_FORCE_TOFROM:
11376 case GOMP_MAP_FORCE_PRESENT:
11377 case GOMP_MAP_FORCE_DEALLOC:
11378 case GOMP_MAP_FORCE_DEVICEPTR:
11379 gcc_assert (is_gimple_omp_oacc (stmt));
11380 break;
11381 default:
11382 gcc_unreachable ();
11384 #endif
11385 /* FALLTHRU */
11386 case OMP_CLAUSE_TO:
11387 case OMP_CLAUSE_FROM:
11388 var = OMP_CLAUSE_DECL (c);
11389 if (!DECL_P (var))
11391 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11392 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11393 map_cnt++;
11394 continue;
11397 if (DECL_SIZE (var)
11398 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11400 tree var2 = DECL_VALUE_EXPR (var);
11401 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11402 var2 = TREE_OPERAND (var2, 0);
11403 gcc_assert (DECL_P (var2));
11404 var = var2;
11407 if (!maybe_lookup_field (var, ctx))
11408 continue;
11410 if (offloaded)
11412 x = build_receiver_ref (var, true, ctx);
11413 tree new_var = lookup_decl (var, ctx);
11414 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11415 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11416 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11417 x = build_simple_mem_ref (x);
11418 SET_DECL_VALUE_EXPR (new_var, x);
11419 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11421 map_cnt++;
11424 if (offloaded)
11426 target_nesting_level++;
11427 lower_omp (&tgt_body, ctx);
11428 target_nesting_level--;
11430 else if (data_region)
11431 lower_omp (&tgt_body, ctx);
11433 if (offloaded)
11435 /* Declare all the variables created by mapping and the variables
11436 declared in the scope of the target body. */
11437 record_vars_into (ctx->block_vars, child_fn);
11438 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11441 olist = NULL;
11442 ilist = NULL;
11443 if (ctx->record_type)
11445 ctx->sender_decl
11446 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11447 DECL_NAMELESS (ctx->sender_decl) = 1;
11448 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11449 t = make_tree_vec (3);
11450 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11451 TREE_VEC_ELT (t, 1)
11452 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11453 ".omp_data_sizes");
11454 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11455 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11456 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11457 tree tkind_type;
11458 int talign_shift;
11459 if (is_gimple_omp_oacc (stmt))
11461 tkind_type = short_unsigned_type_node;
11462 talign_shift = 8;
11464 else
11466 tkind_type = unsigned_char_type_node;
11467 talign_shift = 3;
11469 TREE_VEC_ELT (t, 2)
11470 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11471 ".omp_data_kinds");
11472 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11473 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11474 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11475 gimple_omp_target_set_data_arg (stmt, t);
11477 vec<constructor_elt, va_gc> *vsize;
11478 vec<constructor_elt, va_gc> *vkind;
11479 vec_alloc (vsize, map_cnt);
11480 vec_alloc (vkind, map_cnt);
11481 unsigned int map_idx = 0;
11483 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11484 switch (OMP_CLAUSE_CODE (c))
11486 tree ovar, nc;
11488 default:
11489 break;
11490 case OMP_CLAUSE_MAP:
11491 case OMP_CLAUSE_TO:
11492 case OMP_CLAUSE_FROM:
11493 nc = c;
11494 ovar = OMP_CLAUSE_DECL (c);
11495 if (!DECL_P (ovar))
11497 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11498 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11500 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11501 == get_base_address (ovar));
11502 nc = OMP_CLAUSE_CHAIN (c);
11503 ovar = OMP_CLAUSE_DECL (nc);
11505 else
11507 tree x = build_sender_ref (ovar, ctx);
11508 tree v
11509 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11510 gimplify_assign (x, v, &ilist);
11511 nc = NULL_TREE;
11514 else
11516 if (DECL_SIZE (ovar)
11517 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11519 tree ovar2 = DECL_VALUE_EXPR (ovar);
11520 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11521 ovar2 = TREE_OPERAND (ovar2, 0);
11522 gcc_assert (DECL_P (ovar2));
11523 ovar = ovar2;
11525 if (!maybe_lookup_field (ovar, ctx))
11526 continue;
11529 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11530 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11531 talign = DECL_ALIGN_UNIT (ovar);
11532 if (nc)
11534 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11535 tree x = build_sender_ref (ovar, ctx);
11536 if (maybe_lookup_oacc_reduction (var, ctx))
11538 gcc_checking_assert (offloaded
11539 && is_gimple_omp_oacc (stmt));
11540 gimplify_assign (x, var, &ilist);
11542 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11543 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11544 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11545 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11547 gcc_assert (offloaded);
11548 tree avar
11549 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11550 mark_addressable (avar);
11551 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11552 talign = DECL_ALIGN_UNIT (avar);
11553 avar = build_fold_addr_expr (avar);
11554 gimplify_assign (x, avar, &ilist);
11556 else if (is_gimple_reg (var))
11558 gcc_assert (offloaded);
11559 tree avar = create_tmp_var (TREE_TYPE (var));
11560 mark_addressable (avar);
11561 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11562 if (GOMP_MAP_COPY_TO_P (map_kind)
11563 || map_kind == GOMP_MAP_POINTER
11564 || map_kind == GOMP_MAP_TO_PSET
11565 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11566 gimplify_assign (avar, var, &ilist);
11567 avar = build_fold_addr_expr (avar);
11568 gimplify_assign (x, avar, &ilist);
11569 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11570 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11571 && !TYPE_READONLY (TREE_TYPE (var)))
11573 x = build_sender_ref (ovar, ctx);
11574 x = build_simple_mem_ref (x);
11575 gimplify_assign (var, x, &olist);
11578 else
11580 var = build_fold_addr_expr (var);
11581 gimplify_assign (x, var, &ilist);
11584 tree s = OMP_CLAUSE_SIZE (c);
11585 if (s == NULL_TREE)
11586 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11587 s = fold_convert (size_type_node, s);
11588 tree purpose = size_int (map_idx++);
11589 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11590 if (TREE_CODE (s) != INTEGER_CST)
11591 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11593 unsigned HOST_WIDE_INT tkind;
11594 switch (OMP_CLAUSE_CODE (c))
11596 case OMP_CLAUSE_MAP:
11597 tkind = OMP_CLAUSE_MAP_KIND (c);
11598 break;
11599 case OMP_CLAUSE_TO:
11600 tkind = GOMP_MAP_TO;
11601 break;
11602 case OMP_CLAUSE_FROM:
11603 tkind = GOMP_MAP_FROM;
11604 break;
11605 default:
11606 gcc_unreachable ();
11608 gcc_checking_assert (tkind
11609 < (HOST_WIDE_INT_C (1U) << talign_shift));
11610 talign = ceil_log2 (talign);
11611 tkind |= talign << talign_shift;
11612 gcc_checking_assert (tkind
11613 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11614 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11615 build_int_cstu (tkind_type, tkind));
11616 if (nc && nc != c)
11617 c = nc;
11620 gcc_assert (map_idx == map_cnt);
11622 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11623 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11624 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11625 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11626 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11628 gimple_seq initlist = NULL;
11629 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11630 TREE_VEC_ELT (t, 1)),
11631 &initlist, true, NULL_TREE);
11632 gimple_seq_add_seq (&ilist, initlist);
11634 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11635 NULL);
11636 TREE_THIS_VOLATILE (clobber) = 1;
11637 gimple_seq_add_stmt (&olist,
11638 gimple_build_assign (TREE_VEC_ELT (t, 1),
11639 clobber));
11642 tree clobber = build_constructor (ctx->record_type, NULL);
11643 TREE_THIS_VOLATILE (clobber) = 1;
11644 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11645 clobber));
11648 /* Once all the expansions are done, sequence all the different
11649 fragments inside gimple_omp_body. */
11651 new_body = NULL;
11653 if (offloaded
11654 && ctx->record_type)
11656 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11657 /* fixup_child_record_type might have changed receiver_decl's type. */
11658 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11659 gimple_seq_add_stmt (&new_body,
11660 gimple_build_assign (ctx->receiver_decl, t));
11663 if (offloaded)
11665 gimple_seq_add_seq (&new_body, tgt_body);
11666 new_body = maybe_catch_exception (new_body);
11668 else if (data_region)
11669 new_body = tgt_body;
11670 if (offloaded || data_region)
11672 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11673 gimple_omp_set_body (stmt, new_body);
11676 bind = gimple_build_bind (NULL, NULL,
11677 tgt_bind ? gimple_bind_block (tgt_bind)
11678 : NULL_TREE);
11679 gsi_replace (gsi_p, bind, true);
11680 gimple_bind_add_seq (bind, irlist);
11681 gimple_bind_add_seq (bind, ilist);
11682 gimple_bind_add_stmt (bind, stmt);
11683 gimple_bind_add_seq (bind, olist);
11684 gimple_bind_add_seq (bind, orlist);
11686 pop_gimplify_context (NULL);
11689 /* Expand code for an OpenMP teams directive. */
11691 static void
11692 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11694 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11695 push_gimplify_context ();
11697 tree block = make_node (BLOCK);
11698 gbind *bind = gimple_build_bind (NULL, NULL, block);
11699 gsi_replace (gsi_p, bind, true);
11700 gimple_seq bind_body = NULL;
11701 gimple_seq dlist = NULL;
11702 gimple_seq olist = NULL;
11704 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11705 OMP_CLAUSE_NUM_TEAMS);
11706 if (num_teams == NULL_TREE)
11707 num_teams = build_int_cst (unsigned_type_node, 0);
11708 else
11710 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11711 num_teams = fold_convert (unsigned_type_node, num_teams);
11712 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11714 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11715 OMP_CLAUSE_THREAD_LIMIT);
11716 if (thread_limit == NULL_TREE)
11717 thread_limit = build_int_cst (unsigned_type_node, 0);
11718 else
11720 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11721 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11722 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11723 fb_rvalue);
11726 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11727 &bind_body, &dlist, ctx, NULL);
11728 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11729 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11730 gimple_seq_add_stmt (&bind_body, teams_stmt);
11732 location_t loc = gimple_location (teams_stmt);
11733 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11734 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
11735 gimple_set_location (call, loc);
11736 gimple_seq_add_stmt (&bind_body, call);
11738 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11739 gimple_omp_set_body (teams_stmt, NULL);
11740 gimple_seq_add_seq (&bind_body, olist);
11741 gimple_seq_add_seq (&bind_body, dlist);
11742 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11743 gimple_bind_set_body (bind, bind_body);
11745 pop_gimplify_context (bind);
11747 gimple_bind_append_vars (bind, ctx->block_vars);
11748 BLOCK_VARS (block) = ctx->block_vars;
11749 if (BLOCK_VARS (block))
11750 TREE_USED (block) = 1;
11754 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11755 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11756 of OMP context, but with task_shared_vars set. */
11758 static tree
11759 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11760 void *data)
11762 tree t = *tp;
11764 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11765 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11766 return t;
11768 if (task_shared_vars
11769 && DECL_P (t)
11770 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11771 return t;
11773 /* If a global variable has been privatized, TREE_CONSTANT on
11774 ADDR_EXPR might be wrong. */
11775 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11776 recompute_tree_invariant_for_addr_expr (t);
11778 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11779 return NULL_TREE;
11782 static void
11783 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11785 gimple *stmt = gsi_stmt (*gsi_p);
11786 struct walk_stmt_info wi;
11787 gcall *call_stmt;
11789 if (gimple_has_location (stmt))
11790 input_location = gimple_location (stmt);
11792 if (task_shared_vars)
11793 memset (&wi, '\0', sizeof (wi));
11795 /* If we have issued syntax errors, avoid doing any heavy lifting.
11796 Just replace the OMP directives with a NOP to avoid
11797 confusing RTL expansion. */
11798 if (seen_error () && is_gimple_omp (stmt))
11800 gsi_replace (gsi_p, gimple_build_nop (), true);
11801 return;
11804 switch (gimple_code (stmt))
11806 case GIMPLE_COND:
11808 gcond *cond_stmt = as_a <gcond *> (stmt);
11809 if ((ctx || task_shared_vars)
11810 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11811 lower_omp_regimplify_p,
11812 ctx ? NULL : &wi, NULL)
11813 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11814 lower_omp_regimplify_p,
11815 ctx ? NULL : &wi, NULL)))
11816 gimple_regimplify_operands (cond_stmt, gsi_p);
11818 break;
11819 case GIMPLE_CATCH:
11820 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
11821 break;
11822 case GIMPLE_EH_FILTER:
11823 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
11824 break;
11825 case GIMPLE_TRY:
11826 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11827 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
11828 break;
11829 case GIMPLE_TRANSACTION:
11830 lower_omp (gimple_transaction_body_ptr (
11831 as_a <gtransaction *> (stmt)),
11832 ctx);
11833 break;
11834 case GIMPLE_BIND:
11835 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
11836 break;
11837 case GIMPLE_OMP_PARALLEL:
11838 case GIMPLE_OMP_TASK:
11839 ctx = maybe_lookup_ctx (stmt);
11840 gcc_assert (ctx);
11841 if (ctx->cancellable)
11842 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11843 lower_omp_taskreg (gsi_p, ctx);
11844 break;
11845 case GIMPLE_OMP_FOR:
11846 ctx = maybe_lookup_ctx (stmt);
11847 gcc_assert (ctx);
11848 if (ctx->cancellable)
11849 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11850 lower_omp_for (gsi_p, ctx);
11851 break;
11852 case GIMPLE_OMP_SECTIONS:
11853 ctx = maybe_lookup_ctx (stmt);
11854 gcc_assert (ctx);
11855 if (ctx->cancellable)
11856 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11857 lower_omp_sections (gsi_p, ctx);
11858 break;
11859 case GIMPLE_OMP_SINGLE:
11860 ctx = maybe_lookup_ctx (stmt);
11861 gcc_assert (ctx);
11862 lower_omp_single (gsi_p, ctx);
11863 break;
11864 case GIMPLE_OMP_MASTER:
11865 ctx = maybe_lookup_ctx (stmt);
11866 gcc_assert (ctx);
11867 lower_omp_master (gsi_p, ctx);
11868 break;
11869 case GIMPLE_OMP_TASKGROUP:
11870 ctx = maybe_lookup_ctx (stmt);
11871 gcc_assert (ctx);
11872 lower_omp_taskgroup (gsi_p, ctx);
11873 break;
11874 case GIMPLE_OMP_ORDERED:
11875 ctx = maybe_lookup_ctx (stmt);
11876 gcc_assert (ctx);
11877 lower_omp_ordered (gsi_p, ctx);
11878 break;
11879 case GIMPLE_OMP_CRITICAL:
11880 ctx = maybe_lookup_ctx (stmt);
11881 gcc_assert (ctx);
11882 lower_omp_critical (gsi_p, ctx);
11883 break;
11884 case GIMPLE_OMP_ATOMIC_LOAD:
11885 if ((ctx || task_shared_vars)
11886 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11887 as_a <gomp_atomic_load *> (stmt)),
11888 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11889 gimple_regimplify_operands (stmt, gsi_p);
11890 break;
11891 case GIMPLE_OMP_TARGET:
11892 ctx = maybe_lookup_ctx (stmt);
11893 gcc_assert (ctx);
11894 lower_omp_target (gsi_p, ctx);
11895 break;
11896 case GIMPLE_OMP_TEAMS:
11897 ctx = maybe_lookup_ctx (stmt);
11898 gcc_assert (ctx);
11899 lower_omp_teams (gsi_p, ctx);
11900 break;
11901 case GIMPLE_CALL:
11902 tree fndecl;
11903 call_stmt = as_a <gcall *> (stmt);
11904 fndecl = gimple_call_fndecl (call_stmt);
11905 if (fndecl
11906 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11907 switch (DECL_FUNCTION_CODE (fndecl))
11909 case BUILT_IN_GOMP_BARRIER:
11910 if (ctx == NULL)
11911 break;
11912 /* FALLTHRU */
11913 case BUILT_IN_GOMP_CANCEL:
11914 case BUILT_IN_GOMP_CANCELLATION_POINT:
11915 omp_context *cctx;
11916 cctx = ctx;
11917 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11918 cctx = cctx->outer;
11919 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
11920 if (!cctx->cancellable)
11922 if (DECL_FUNCTION_CODE (fndecl)
11923 == BUILT_IN_GOMP_CANCELLATION_POINT)
11925 stmt = gimple_build_nop ();
11926 gsi_replace (gsi_p, stmt, false);
11928 break;
11930 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11932 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
11933 gimple_call_set_fndecl (call_stmt, fndecl);
11934 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
11936 tree lhs;
11937 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
11938 gimple_call_set_lhs (call_stmt, lhs);
11939 tree fallthru_label;
11940 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11941 gimple *g;
11942 g = gimple_build_label (fallthru_label);
11943 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11944 g = gimple_build_cond (NE_EXPR, lhs,
11945 fold_convert (TREE_TYPE (lhs),
11946 boolean_false_node),
11947 cctx->cancel_label, fallthru_label);
11948 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11949 break;
11950 default:
11951 break;
11953 /* FALLTHRU */
11954 default:
11955 if ((ctx || task_shared_vars)
11956 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11957 ctx ? NULL : &wi))
11959 /* Just remove clobbers, this should happen only if we have
11960 "privatized" local addressable variables in SIMD regions,
11961 the clobber isn't needed in that case and gimplifying address
11962 of the ARRAY_REF into a pointer and creating MEM_REF based
11963 clobber would create worse code than we get with the clobber
11964 dropped. */
11965 if (gimple_clobber_p (stmt))
11967 gsi_replace (gsi_p, gimple_build_nop (), true);
11968 break;
11970 gimple_regimplify_operands (stmt, gsi_p);
11972 break;
11976 static void
11977 lower_omp (gimple_seq *body, omp_context *ctx)
11979 location_t saved_location = input_location;
11980 gimple_stmt_iterator gsi;
11981 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11982 lower_omp_1 (&gsi, ctx);
11983 /* During gimplification, we haven't folded statments inside offloading
11984 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
11985 if (target_nesting_level || taskreg_nesting_level)
11986 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11987 fold_stmt (&gsi);
11988 input_location = saved_location;
11991 /* Main entry point. */
11993 static unsigned int
11994 execute_lower_omp (void)
11996 gimple_seq body;
11997 int i;
11998 omp_context *ctx;
12000 /* This pass always runs, to provide PROP_gimple_lomp.
12001 But often, there is nothing to do. */
12002 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
12003 && flag_openmp_simd == 0)
12004 return 0;
12006 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
12007 delete_omp_context);
12009 body = gimple_body (current_function_decl);
12010 scan_omp (&body, NULL);
12011 gcc_assert (taskreg_nesting_level == 0);
12012 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
12013 finish_taskreg_scan (ctx);
12014 taskreg_contexts.release ();
12016 if (all_contexts->root)
12018 if (task_shared_vars)
12019 push_gimplify_context ();
12020 lower_omp (&body, NULL);
12021 if (task_shared_vars)
12022 pop_gimplify_context (NULL);
12025 if (all_contexts)
12027 splay_tree_delete (all_contexts);
12028 all_contexts = NULL;
12030 BITMAP_FREE (task_shared_vars);
12031 return 0;
12034 namespace {
12036 const pass_data pass_data_lower_omp =
12038 GIMPLE_PASS, /* type */
12039 "omplower", /* name */
12040 OPTGROUP_NONE, /* optinfo_flags */
12041 TV_NONE, /* tv_id */
12042 PROP_gimple_any, /* properties_required */
12043 PROP_gimple_lomp, /* properties_provided */
12044 0, /* properties_destroyed */
12045 0, /* todo_flags_start */
12046 0, /* todo_flags_finish */
12049 class pass_lower_omp : public gimple_opt_pass
12051 public:
12052 pass_lower_omp (gcc::context *ctxt)
12053 : gimple_opt_pass (pass_data_lower_omp, ctxt)
12056 /* opt_pass methods: */
12057 virtual unsigned int execute (function *) { return execute_lower_omp (); }
12059 }; // class pass_lower_omp
12061 } // anon namespace
12063 gimple_opt_pass *
12064 make_pass_lower_omp (gcc::context *ctxt)
12066 return new pass_lower_omp (ctxt);
12069 /* The following is a utility to diagnose structured block violations.
12070 It is not part of the "omplower" pass, as that's invoked too late. It
12071 should be invoked by the respective front ends after gimplification. */
12073 static splay_tree all_labels;
12075 /* Check for mismatched contexts and generate an error if needed. Return
12076 true if an error is detected. */
12078 static bool
12079 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
12080 gimple *branch_ctx, gimple *label_ctx)
12082 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
12083 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
12085 if (label_ctx == branch_ctx)
12086 return false;
12088 const char* kind = NULL;
12090 if (flag_cilkplus)
12092 if ((branch_ctx
12093 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12094 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12095 || (label_ctx
12096 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12097 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12098 kind = "Cilk Plus";
12100 if (flag_openacc)
12102 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
12103 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
12105 gcc_checking_assert (kind == NULL);
12106 kind = "OpenACC";
12109 if (kind == NULL)
12111 gcc_checking_assert (flag_openmp);
12112 kind = "OpenMP";
12116 Previously we kept track of the label's entire context in diagnose_sb_[12]
12117 so we could traverse it and issue a correct "exit" or "enter" error
12118 message upon a structured block violation.
12120 We built the context by building a list with tree_cons'ing, but there is
12121 no easy counterpart in gimple tuples. It seems like far too much work
12122 for issuing exit/enter error messages. If someone really misses the
12123 distinct error message... patches welcome.
12126 #if 0
12127 /* Try to avoid confusing the user by producing and error message
12128 with correct "exit" or "enter" verbiage. We prefer "exit"
12129 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12130 if (branch_ctx == NULL)
12131 exit_p = false;
12132 else
12134 while (label_ctx)
12136 if (TREE_VALUE (label_ctx) == branch_ctx)
12138 exit_p = false;
12139 break;
12141 label_ctx = TREE_CHAIN (label_ctx);
12145 if (exit_p)
12146 error ("invalid exit from %s structured block", kind);
12147 else
12148 error ("invalid entry to %s structured block", kind);
12149 #endif
12151 /* If it's obvious we have an invalid entry, be specific about the error. */
12152 if (branch_ctx == NULL)
12153 error ("invalid entry to %s structured block", kind);
12154 else
12156 /* Otherwise, be vague and lazy, but efficient. */
12157 error ("invalid branch to/from %s structured block", kind);
12160 gsi_replace (gsi_p, gimple_build_nop (), false);
12161 return true;
12164 /* Pass 1: Create a minimal tree of structured blocks, and record
12165 where each label is found. */
12167 static tree
12168 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12169 struct walk_stmt_info *wi)
12171 gimple *context = (gimple *) wi->info;
12172 gimple *inner_context;
12173 gimple *stmt = gsi_stmt (*gsi_p);
12175 *handled_ops_p = true;
12177 switch (gimple_code (stmt))
12179 WALK_SUBSTMTS;
12181 case GIMPLE_OMP_PARALLEL:
12182 case GIMPLE_OMP_TASK:
12183 case GIMPLE_OMP_SECTIONS:
12184 case GIMPLE_OMP_SINGLE:
12185 case GIMPLE_OMP_SECTION:
12186 case GIMPLE_OMP_MASTER:
12187 case GIMPLE_OMP_ORDERED:
12188 case GIMPLE_OMP_CRITICAL:
12189 case GIMPLE_OMP_TARGET:
12190 case GIMPLE_OMP_TEAMS:
12191 case GIMPLE_OMP_TASKGROUP:
12192 /* The minimal context here is just the current OMP construct. */
12193 inner_context = stmt;
12194 wi->info = inner_context;
12195 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12196 wi->info = context;
12197 break;
12199 case GIMPLE_OMP_FOR:
12200 inner_context = stmt;
12201 wi->info = inner_context;
12202 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12203 walk them. */
12204 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12205 diagnose_sb_1, NULL, wi);
12206 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12207 wi->info = context;
12208 break;
12210 case GIMPLE_LABEL:
12211 splay_tree_insert (all_labels,
12212 (splay_tree_key) gimple_label_label (
12213 as_a <glabel *> (stmt)),
12214 (splay_tree_value) context);
12215 break;
12217 default:
12218 break;
12221 return NULL_TREE;
12224 /* Pass 2: Check each branch and see if its context differs from that of
12225 the destination label's context. */
12227 static tree
12228 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12229 struct walk_stmt_info *wi)
12231 gimple *context = (gimple *) wi->info;
12232 splay_tree_node n;
12233 gimple *stmt = gsi_stmt (*gsi_p);
12235 *handled_ops_p = true;
12237 switch (gimple_code (stmt))
12239 WALK_SUBSTMTS;
12241 case GIMPLE_OMP_PARALLEL:
12242 case GIMPLE_OMP_TASK:
12243 case GIMPLE_OMP_SECTIONS:
12244 case GIMPLE_OMP_SINGLE:
12245 case GIMPLE_OMP_SECTION:
12246 case GIMPLE_OMP_MASTER:
12247 case GIMPLE_OMP_ORDERED:
12248 case GIMPLE_OMP_CRITICAL:
12249 case GIMPLE_OMP_TARGET:
12250 case GIMPLE_OMP_TEAMS:
12251 case GIMPLE_OMP_TASKGROUP:
12252 wi->info = stmt;
12253 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12254 wi->info = context;
12255 break;
12257 case GIMPLE_OMP_FOR:
12258 wi->info = stmt;
12259 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12260 walk them. */
12261 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12262 diagnose_sb_2, NULL, wi);
12263 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12264 wi->info = context;
12265 break;
12267 case GIMPLE_COND:
12269 gcond *cond_stmt = as_a <gcond *> (stmt);
12270 tree lab = gimple_cond_true_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);
12278 lab = gimple_cond_false_label (cond_stmt);
12279 if (lab)
12281 n = splay_tree_lookup (all_labels,
12282 (splay_tree_key) lab);
12283 diagnose_sb_0 (gsi_p, context,
12284 n ? (gimple *) n->value : NULL);
12287 break;
12289 case GIMPLE_GOTO:
12291 tree lab = gimple_goto_dest (stmt);
12292 if (TREE_CODE (lab) != LABEL_DECL)
12293 break;
12295 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12296 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
12298 break;
12300 case GIMPLE_SWITCH:
12302 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12303 unsigned int i;
12304 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12306 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12307 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12308 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
12309 break;
12312 break;
12314 case GIMPLE_RETURN:
12315 diagnose_sb_0 (gsi_p, context, NULL);
12316 break;
12318 default:
12319 break;
12322 return NULL_TREE;
12325 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12326 GIMPLE_* codes. */
12327 bool
12328 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12329 int *region_idx)
12331 gimple *last = last_stmt (bb);
12332 enum gimple_code code = gimple_code (last);
12333 struct omp_region *cur_region = *region;
12334 bool fallthru = false;
12336 switch (code)
12338 case GIMPLE_OMP_PARALLEL:
12339 case GIMPLE_OMP_TASK:
12340 case GIMPLE_OMP_FOR:
12341 case GIMPLE_OMP_SINGLE:
12342 case GIMPLE_OMP_TEAMS:
12343 case GIMPLE_OMP_MASTER:
12344 case GIMPLE_OMP_TASKGROUP:
12345 case GIMPLE_OMP_ORDERED:
12346 case GIMPLE_OMP_CRITICAL:
12347 case GIMPLE_OMP_SECTION:
12348 cur_region = new_omp_region (bb, code, cur_region);
12349 fallthru = true;
12350 break;
12352 case GIMPLE_OMP_TARGET:
12353 cur_region = new_omp_region (bb, code, cur_region);
12354 fallthru = true;
12355 switch (gimple_omp_target_kind (last))
12357 case GF_OMP_TARGET_KIND_REGION:
12358 case GF_OMP_TARGET_KIND_DATA:
12359 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12360 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12361 case GF_OMP_TARGET_KIND_OACC_DATA:
12362 break;
12363 case GF_OMP_TARGET_KIND_UPDATE:
12364 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12365 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12366 cur_region = cur_region->outer;
12367 break;
12368 default:
12369 gcc_unreachable ();
12371 break;
12373 case GIMPLE_OMP_SECTIONS:
12374 cur_region = new_omp_region (bb, code, cur_region);
12375 fallthru = true;
12376 break;
12378 case GIMPLE_OMP_SECTIONS_SWITCH:
12379 fallthru = false;
12380 break;
12382 case GIMPLE_OMP_ATOMIC_LOAD:
12383 case GIMPLE_OMP_ATOMIC_STORE:
12384 fallthru = true;
12385 break;
12387 case GIMPLE_OMP_RETURN:
12388 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12389 somewhere other than the next block. This will be
12390 created later. */
12391 cur_region->exit = bb;
12392 if (cur_region->type == GIMPLE_OMP_TASK)
12393 /* Add an edge corresponding to not scheduling the task
12394 immediately. */
12395 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
12396 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12397 cur_region = cur_region->outer;
12398 break;
12400 case GIMPLE_OMP_CONTINUE:
12401 cur_region->cont = bb;
12402 switch (cur_region->type)
12404 case GIMPLE_OMP_FOR:
12405 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12406 succs edges as abnormal to prevent splitting
12407 them. */
12408 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12409 /* Make the loopback edge. */
12410 make_edge (bb, single_succ (cur_region->entry),
12411 EDGE_ABNORMAL);
12413 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12414 corresponds to the case that the body of the loop
12415 is not executed at all. */
12416 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12417 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12418 fallthru = false;
12419 break;
12421 case GIMPLE_OMP_SECTIONS:
12422 /* Wire up the edges into and out of the nested sections. */
12424 basic_block switch_bb = single_succ (cur_region->entry);
12426 struct omp_region *i;
12427 for (i = cur_region->inner; i ; i = i->next)
12429 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12430 make_edge (switch_bb, i->entry, 0);
12431 make_edge (i->exit, bb, EDGE_FALLTHRU);
12434 /* Make the loopback edge to the block with
12435 GIMPLE_OMP_SECTIONS_SWITCH. */
12436 make_edge (bb, switch_bb, 0);
12438 /* Make the edge from the switch to exit. */
12439 make_edge (switch_bb, bb->next_bb, 0);
12440 fallthru = false;
12442 break;
12444 case GIMPLE_OMP_TASK:
12445 fallthru = true;
12446 break;
12448 default:
12449 gcc_unreachable ();
12451 break;
12453 default:
12454 gcc_unreachable ();
12457 if (*region != cur_region)
12459 *region = cur_region;
12460 if (cur_region)
12461 *region_idx = cur_region->entry->index;
12462 else
12463 *region_idx = 0;
12466 return fallthru;
12469 static unsigned int
12470 diagnose_omp_structured_block_errors (void)
12472 struct walk_stmt_info wi;
12473 gimple_seq body = gimple_body (current_function_decl);
12475 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12477 memset (&wi, 0, sizeof (wi));
12478 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12480 memset (&wi, 0, sizeof (wi));
12481 wi.want_locations = true;
12482 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12484 gimple_set_body (current_function_decl, body);
12486 splay_tree_delete (all_labels);
12487 all_labels = NULL;
12489 return 0;
12492 namespace {
12494 const pass_data pass_data_diagnose_omp_blocks =
12496 GIMPLE_PASS, /* type */
12497 "*diagnose_omp_blocks", /* name */
12498 OPTGROUP_NONE, /* optinfo_flags */
12499 TV_NONE, /* tv_id */
12500 PROP_gimple_any, /* properties_required */
12501 0, /* properties_provided */
12502 0, /* properties_destroyed */
12503 0, /* todo_flags_start */
12504 0, /* todo_flags_finish */
12507 class pass_diagnose_omp_blocks : public gimple_opt_pass
12509 public:
12510 pass_diagnose_omp_blocks (gcc::context *ctxt)
12511 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12514 /* opt_pass methods: */
12515 virtual bool gate (function *)
12517 return flag_cilkplus || flag_openacc || flag_openmp;
12519 virtual unsigned int execute (function *)
12521 return diagnose_omp_structured_block_errors ();
12524 }; // class pass_diagnose_omp_blocks
12526 } // anon namespace
12528 gimple_opt_pass *
12529 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12531 return new pass_diagnose_omp_blocks (ctxt);
12534 /* SIMD clone supporting code. */
12536 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12537 of arguments to reserve space for. */
12539 static struct cgraph_simd_clone *
12540 simd_clone_struct_alloc (int nargs)
12542 struct cgraph_simd_clone *clone_info;
12543 size_t len = (sizeof (struct cgraph_simd_clone)
12544 + nargs * sizeof (struct cgraph_simd_clone_arg));
12545 clone_info = (struct cgraph_simd_clone *)
12546 ggc_internal_cleared_alloc (len);
12547 return clone_info;
12550 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12552 static inline void
12553 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12554 struct cgraph_simd_clone *from)
12556 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12557 + ((from->nargs - from->inbranch)
12558 * sizeof (struct cgraph_simd_clone_arg))));
12561 /* Return vector of parameter types of function FNDECL. This uses
12562 TYPE_ARG_TYPES if available, otherwise falls back to types of
12563 DECL_ARGUMENTS types. */
12565 vec<tree>
12566 simd_clone_vector_of_formal_parm_types (tree fndecl)
12568 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12569 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12570 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12571 unsigned int i;
12572 tree arg;
12573 FOR_EACH_VEC_ELT (args, i, arg)
12574 args[i] = TREE_TYPE (args[i]);
12575 return args;
12578 /* Given a simd function in NODE, extract the simd specific
12579 information from the OMP clauses passed in CLAUSES, and return
12580 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12581 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12582 otherwise set to FALSE. */
12584 static struct cgraph_simd_clone *
12585 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12586 bool *inbranch_specified)
12588 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12589 tree t;
12590 int n;
12591 *inbranch_specified = false;
12593 n = args.length ();
12594 if (n > 0 && args.last () == void_type_node)
12595 n--;
12597 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12598 be cloned have a distinctive artificial label in addition to "omp
12599 declare simd". */
12600 bool cilk_clone
12601 = (flag_cilkplus
12602 && lookup_attribute ("cilk simd function",
12603 DECL_ATTRIBUTES (node->decl)));
12605 /* Allocate one more than needed just in case this is an in-branch
12606 clone which will require a mask argument. */
12607 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12608 clone_info->nargs = n;
12609 clone_info->cilk_elemental = cilk_clone;
12611 if (!clauses)
12613 args.release ();
12614 return clone_info;
12616 clauses = TREE_VALUE (clauses);
12617 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12618 return clone_info;
12620 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12622 switch (OMP_CLAUSE_CODE (t))
12624 case OMP_CLAUSE_INBRANCH:
12625 clone_info->inbranch = 1;
12626 *inbranch_specified = true;
12627 break;
12628 case OMP_CLAUSE_NOTINBRANCH:
12629 clone_info->inbranch = 0;
12630 *inbranch_specified = true;
12631 break;
12632 case OMP_CLAUSE_SIMDLEN:
12633 clone_info->simdlen
12634 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12635 break;
12636 case OMP_CLAUSE_LINEAR:
12638 tree decl = OMP_CLAUSE_DECL (t);
12639 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12640 int argno = TREE_INT_CST_LOW (decl);
12641 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12643 clone_info->args[argno].arg_type
12644 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12645 clone_info->args[argno].linear_step = tree_to_shwi (step);
12646 gcc_assert (clone_info->args[argno].linear_step >= 0
12647 && clone_info->args[argno].linear_step < n);
12649 else
12651 if (POINTER_TYPE_P (args[argno]))
12652 step = fold_convert (ssizetype, step);
12653 if (!tree_fits_shwi_p (step))
12655 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12656 "ignoring large linear step");
12657 args.release ();
12658 return NULL;
12660 else if (integer_zerop (step))
12662 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12663 "ignoring zero linear step");
12664 args.release ();
12665 return NULL;
12667 else
12669 clone_info->args[argno].arg_type
12670 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12671 clone_info->args[argno].linear_step = tree_to_shwi (step);
12674 break;
12676 case OMP_CLAUSE_UNIFORM:
12678 tree decl = OMP_CLAUSE_DECL (t);
12679 int argno = tree_to_uhwi (decl);
12680 clone_info->args[argno].arg_type
12681 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12682 break;
12684 case OMP_CLAUSE_ALIGNED:
12686 tree decl = OMP_CLAUSE_DECL (t);
12687 int argno = tree_to_uhwi (decl);
12688 clone_info->args[argno].alignment
12689 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12690 break;
12692 default:
12693 break;
12696 args.release ();
12697 return clone_info;
12700 /* Given a SIMD clone in NODE, calculate the characteristic data
12701 type and return the coresponding type. The characteristic data
12702 type is computed as described in the Intel Vector ABI. */
12704 static tree
12705 simd_clone_compute_base_data_type (struct cgraph_node *node,
12706 struct cgraph_simd_clone *clone_info)
12708 tree type = integer_type_node;
12709 tree fndecl = node->decl;
12711 /* a) For non-void function, the characteristic data type is the
12712 return type. */
12713 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12714 type = TREE_TYPE (TREE_TYPE (fndecl));
12716 /* b) If the function has any non-uniform, non-linear parameters,
12717 then the characteristic data type is the type of the first
12718 such parameter. */
12719 else
12721 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12722 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12723 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12725 type = map[i];
12726 break;
12728 map.release ();
12731 /* c) If the characteristic data type determined by a) or b) above
12732 is struct, union, or class type which is pass-by-value (except
12733 for the type that maps to the built-in complex data type), the
12734 characteristic data type is int. */
12735 if (RECORD_OR_UNION_TYPE_P (type)
12736 && !aggregate_value_p (type, NULL)
12737 && TREE_CODE (type) != COMPLEX_TYPE)
12738 return integer_type_node;
12740 /* d) If none of the above three classes is applicable, the
12741 characteristic data type is int. */
12743 return type;
12745 /* e) For Intel Xeon Phi native and offload compilation, if the
12746 resulting characteristic data type is 8-bit or 16-bit integer
12747 data type, the characteristic data type is int. */
12748 /* Well, we don't handle Xeon Phi yet. */
12751 static tree
12752 simd_clone_mangle (struct cgraph_node *node,
12753 struct cgraph_simd_clone *clone_info)
12755 char vecsize_mangle = clone_info->vecsize_mangle;
12756 char mask = clone_info->inbranch ? 'M' : 'N';
12757 unsigned int simdlen = clone_info->simdlen;
12758 unsigned int n;
12759 pretty_printer pp;
12761 gcc_assert (vecsize_mangle && simdlen);
12763 pp_string (&pp, "_ZGV");
12764 pp_character (&pp, vecsize_mangle);
12765 pp_character (&pp, mask);
12766 pp_decimal_int (&pp, simdlen);
12768 for (n = 0; n < clone_info->nargs; ++n)
12770 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12772 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12773 pp_character (&pp, 'u');
12774 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12776 gcc_assert (arg.linear_step != 0);
12777 pp_character (&pp, 'l');
12778 if (arg.linear_step > 1)
12779 pp_unsigned_wide_integer (&pp, arg.linear_step);
12780 else if (arg.linear_step < 0)
12782 pp_character (&pp, 'n');
12783 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12784 arg.linear_step));
12787 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12789 pp_character (&pp, 's');
12790 pp_unsigned_wide_integer (&pp, arg.linear_step);
12792 else
12793 pp_character (&pp, 'v');
12794 if (arg.alignment)
12796 pp_character (&pp, 'a');
12797 pp_decimal_int (&pp, arg.alignment);
12801 pp_underscore (&pp);
12802 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12803 if (*str == '*')
12804 ++str;
12805 pp_string (&pp, str);
12806 str = pp_formatted_text (&pp);
12808 /* If there already is a SIMD clone with the same mangled name, don't
12809 add another one. This can happen e.g. for
12810 #pragma omp declare simd
12811 #pragma omp declare simd simdlen(8)
12812 int foo (int, int);
12813 if the simdlen is assumed to be 8 for the first one, etc. */
12814 for (struct cgraph_node *clone = node->simd_clones; clone;
12815 clone = clone->simdclone->next_clone)
12816 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12817 str) == 0)
12818 return NULL_TREE;
12820 return get_identifier (str);
12823 /* Create a simd clone of OLD_NODE and return it. */
12825 static struct cgraph_node *
12826 simd_clone_create (struct cgraph_node *old_node)
12828 struct cgraph_node *new_node;
12829 if (old_node->definition)
12831 if (!old_node->has_gimple_body_p ())
12832 return NULL;
12833 old_node->get_body ();
12834 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12835 false, NULL, NULL,
12836 "simdclone");
12838 else
12840 tree old_decl = old_node->decl;
12841 tree new_decl = copy_node (old_node->decl);
12842 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12843 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12844 SET_DECL_RTL (new_decl, NULL);
12845 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12846 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
12847 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
12848 symtab->call_cgraph_insertion_hooks (new_node);
12850 if (new_node == NULL)
12851 return new_node;
12853 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12855 /* The function cgraph_function_versioning () will force the new
12856 symbol local. Undo this, and inherit external visability from
12857 the old node. */
12858 new_node->local.local = old_node->local.local;
12859 new_node->externally_visible = old_node->externally_visible;
12861 return new_node;
12864 /* Adjust the return type of the given function to its appropriate
12865 vector counterpart. Returns a simd array to be used throughout the
12866 function as a return value. */
12868 static tree
12869 simd_clone_adjust_return_type (struct cgraph_node *node)
12871 tree fndecl = node->decl;
12872 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12873 unsigned int veclen;
12874 tree t;
12876 /* Adjust the function return type. */
12877 if (orig_rettype == void_type_node)
12878 return NULL_TREE;
12879 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
12880 t = TREE_TYPE (TREE_TYPE (fndecl));
12881 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
12882 veclen = node->simdclone->vecsize_int;
12883 else
12884 veclen = node->simdclone->vecsize_float;
12885 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
12886 if (veclen > node->simdclone->simdlen)
12887 veclen = node->simdclone->simdlen;
12888 if (POINTER_TYPE_P (t))
12889 t = pointer_sized_int_node;
12890 if (veclen == node->simdclone->simdlen)
12891 t = build_vector_type (t, node->simdclone->simdlen);
12892 else
12894 t = build_vector_type (t, veclen);
12895 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
12897 TREE_TYPE (TREE_TYPE (fndecl)) = t;
12898 if (!node->definition)
12899 return NULL_TREE;
12901 t = DECL_RESULT (fndecl);
12902 /* Adjust the DECL_RESULT. */
12903 gcc_assert (TREE_TYPE (t) != void_type_node);
12904 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12905 relayout_decl (t);
12907 tree atype = build_array_type_nelts (orig_rettype,
12908 node->simdclone->simdlen);
12909 if (veclen != node->simdclone->simdlen)
12910 return build1 (VIEW_CONVERT_EXPR, atype, t);
12912 /* Set up a SIMD array to use as the return value. */
12913 tree retval = create_tmp_var_raw (atype, "retval");
12914 gimple_add_tmp_var (retval);
12915 return retval;
12918 /* Each vector argument has a corresponding array to be used locally
12919 as part of the eventual loop. Create such temporary array and
12920 return it.
12922 PREFIX is the prefix to be used for the temporary.
12924 TYPE is the inner element type.
12926 SIMDLEN is the number of elements. */
12928 static tree
12929 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12931 tree atype = build_array_type_nelts (type, simdlen);
12932 tree avar = create_tmp_var_raw (atype, prefix);
12933 gimple_add_tmp_var (avar);
12934 return avar;
12937 /* Modify the function argument types to their corresponding vector
12938 counterparts if appropriate. Also, create one array for each simd
12939 argument to be used locally when using the function arguments as
12940 part of the loop.
12942 NODE is the function whose arguments are to be adjusted.
12944 Returns an adjustment vector that will be filled describing how the
12945 argument types will be adjusted. */
12947 static ipa_parm_adjustment_vec
12948 simd_clone_adjust_argument_types (struct cgraph_node *node)
12950 vec<tree> args;
12951 ipa_parm_adjustment_vec adjustments;
12953 if (node->definition)
12954 args = ipa_get_vector_of_formal_parms (node->decl);
12955 else
12956 args = simd_clone_vector_of_formal_parm_types (node->decl);
12957 adjustments.create (args.length ());
12958 unsigned i, j, veclen;
12959 struct ipa_parm_adjustment adj;
12960 for (i = 0; i < node->simdclone->nargs; ++i)
12962 memset (&adj, 0, sizeof (adj));
12963 tree parm = args[i];
12964 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12965 adj.base_index = i;
12966 adj.base = parm;
12968 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12969 node->simdclone->args[i].orig_type = parm_type;
12971 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12973 /* No adjustment necessary for scalar arguments. */
12974 adj.op = IPA_PARM_OP_COPY;
12976 else
12978 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12979 veclen = node->simdclone->vecsize_int;
12980 else
12981 veclen = node->simdclone->vecsize_float;
12982 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12983 if (veclen > node->simdclone->simdlen)
12984 veclen = node->simdclone->simdlen;
12985 adj.arg_prefix = "simd";
12986 if (POINTER_TYPE_P (parm_type))
12987 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12988 else
12989 adj.type = build_vector_type (parm_type, veclen);
12990 node->simdclone->args[i].vector_type = adj.type;
12991 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12993 adjustments.safe_push (adj);
12994 if (j == veclen)
12996 memset (&adj, 0, sizeof (adj));
12997 adj.op = IPA_PARM_OP_NEW;
12998 adj.arg_prefix = "simd";
12999 adj.base_index = i;
13000 adj.type = node->simdclone->args[i].vector_type;
13004 if (node->definition)
13005 node->simdclone->args[i].simd_array
13006 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
13007 parm_type, node->simdclone->simdlen);
13009 adjustments.safe_push (adj);
13012 if (node->simdclone->inbranch)
13014 tree base_type
13015 = simd_clone_compute_base_data_type (node->simdclone->origin,
13016 node->simdclone);
13018 memset (&adj, 0, sizeof (adj));
13019 adj.op = IPA_PARM_OP_NEW;
13020 adj.arg_prefix = "mask";
13022 adj.base_index = i;
13023 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
13024 veclen = node->simdclone->vecsize_int;
13025 else
13026 veclen = node->simdclone->vecsize_float;
13027 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
13028 if (veclen > node->simdclone->simdlen)
13029 veclen = node->simdclone->simdlen;
13030 if (POINTER_TYPE_P (base_type))
13031 adj.type = build_vector_type (pointer_sized_int_node, veclen);
13032 else
13033 adj.type = build_vector_type (base_type, veclen);
13034 adjustments.safe_push (adj);
13036 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
13037 adjustments.safe_push (adj);
13039 /* We have previously allocated one extra entry for the mask. Use
13040 it and fill it. */
13041 struct cgraph_simd_clone *sc = node->simdclone;
13042 sc->nargs++;
13043 if (node->definition)
13045 sc->args[i].orig_arg
13046 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
13047 sc->args[i].simd_array
13048 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
13050 sc->args[i].orig_type = base_type;
13051 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
13054 if (node->definition)
13055 ipa_modify_formal_parameters (node->decl, adjustments);
13056 else
13058 tree new_arg_types = NULL_TREE, new_reversed;
13059 bool last_parm_void = false;
13060 if (args.length () > 0 && args.last () == void_type_node)
13061 last_parm_void = true;
13063 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
13064 j = adjustments.length ();
13065 for (i = 0; i < j; i++)
13067 struct ipa_parm_adjustment *adj = &adjustments[i];
13068 tree ptype;
13069 if (adj->op == IPA_PARM_OP_COPY)
13070 ptype = args[adj->base_index];
13071 else
13072 ptype = adj->type;
13073 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
13075 new_reversed = nreverse (new_arg_types);
13076 if (last_parm_void)
13078 if (new_reversed)
13079 TREE_CHAIN (new_arg_types) = void_list_node;
13080 else
13081 new_reversed = void_list_node;
13084 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
13085 TYPE_ARG_TYPES (new_type) = new_reversed;
13086 TREE_TYPE (node->decl) = new_type;
13088 adjustments.release ();
13090 args.release ();
13091 return adjustments;
13094 /* Initialize and copy the function arguments in NODE to their
13095 corresponding local simd arrays. Returns a fresh gimple_seq with
13096 the instruction sequence generated. */
13098 static gimple_seq
13099 simd_clone_init_simd_arrays (struct cgraph_node *node,
13100 ipa_parm_adjustment_vec adjustments)
13102 gimple_seq seq = NULL;
13103 unsigned i = 0, j = 0, k;
13105 for (tree arg = DECL_ARGUMENTS (node->decl);
13106 arg;
13107 arg = DECL_CHAIN (arg), i++, j++)
13109 if (adjustments[j].op == IPA_PARM_OP_COPY)
13110 continue;
13112 node->simdclone->args[i].vector_arg = arg;
13114 tree array = node->simdclone->args[i].simd_array;
13115 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13117 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13118 tree ptr = build_fold_addr_expr (array);
13119 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13120 build_int_cst (ptype, 0));
13121 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13122 gimplify_and_add (t, &seq);
13124 else
13126 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13127 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13128 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13130 tree ptr = build_fold_addr_expr (array);
13131 int elemsize;
13132 if (k)
13134 arg = DECL_CHAIN (arg);
13135 j++;
13137 elemsize
13138 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13139 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13140 build_int_cst (ptype, k * elemsize));
13141 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13142 gimplify_and_add (t, &seq);
13146 return seq;
13149 /* Callback info for ipa_simd_modify_stmt_ops below. */
13151 struct modify_stmt_info {
13152 ipa_parm_adjustment_vec adjustments;
13153 gimple *stmt;
13154 /* True if the parent statement was modified by
13155 ipa_simd_modify_stmt_ops. */
13156 bool modified;
13159 /* Callback for walk_gimple_op.
13161 Adjust operands from a given statement as specified in the
13162 adjustments vector in the callback data. */
13164 static tree
13165 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13167 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13168 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13169 tree *orig_tp = tp;
13170 if (TREE_CODE (*tp) == ADDR_EXPR)
13171 tp = &TREE_OPERAND (*tp, 0);
13172 struct ipa_parm_adjustment *cand = NULL;
13173 if (TREE_CODE (*tp) == PARM_DECL)
13174 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13175 else
13177 if (TYPE_P (*tp))
13178 *walk_subtrees = 0;
13181 tree repl = NULL_TREE;
13182 if (cand)
13183 repl = unshare_expr (cand->new_decl);
13184 else
13186 if (tp != orig_tp)
13188 *walk_subtrees = 0;
13189 bool modified = info->modified;
13190 info->modified = false;
13191 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13192 if (!info->modified)
13194 info->modified = modified;
13195 return NULL_TREE;
13197 info->modified = modified;
13198 repl = *tp;
13200 else
13201 return NULL_TREE;
13204 if (tp != orig_tp)
13206 repl = build_fold_addr_expr (repl);
13207 gimple *stmt;
13208 if (is_gimple_debug (info->stmt))
13210 tree vexpr = make_node (DEBUG_EXPR_DECL);
13211 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13212 DECL_ARTIFICIAL (vexpr) = 1;
13213 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13214 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13215 repl = vexpr;
13217 else
13219 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13220 repl = gimple_assign_lhs (stmt);
13222 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13223 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13224 *orig_tp = repl;
13226 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13228 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13229 *tp = vce;
13231 else
13232 *tp = repl;
13234 info->modified = true;
13235 return NULL_TREE;
13238 /* Traverse the function body and perform all modifications as
13239 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13240 modified such that the replacement/reduction value will now be an
13241 offset into the corresponding simd_array.
13243 This function will replace all function argument uses with their
13244 corresponding simd array elements, and ajust the return values
13245 accordingly. */
13247 static void
13248 ipa_simd_modify_function_body (struct cgraph_node *node,
13249 ipa_parm_adjustment_vec adjustments,
13250 tree retval_array, tree iter)
13252 basic_block bb;
13253 unsigned int i, j, l;
13255 /* Re-use the adjustments array, but this time use it to replace
13256 every function argument use to an offset into the corresponding
13257 simd_array. */
13258 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13260 if (!node->simdclone->args[i].vector_arg)
13261 continue;
13263 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13264 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13265 adjustments[j].new_decl
13266 = build4 (ARRAY_REF,
13267 basetype,
13268 node->simdclone->args[i].simd_array,
13269 iter,
13270 NULL_TREE, NULL_TREE);
13271 if (adjustments[j].op == IPA_PARM_OP_NONE
13272 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13273 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13276 l = adjustments.length ();
13277 for (i = 1; i < num_ssa_names; i++)
13279 tree name = ssa_name (i);
13280 if (name
13281 && SSA_NAME_VAR (name)
13282 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13284 for (j = 0; j < l; j++)
13285 if (SSA_NAME_VAR (name) == adjustments[j].base
13286 && adjustments[j].new_decl)
13288 tree base_var;
13289 if (adjustments[j].new_ssa_base == NULL_TREE)
13291 base_var
13292 = copy_var_decl (adjustments[j].base,
13293 DECL_NAME (adjustments[j].base),
13294 TREE_TYPE (adjustments[j].base));
13295 adjustments[j].new_ssa_base = base_var;
13297 else
13298 base_var = adjustments[j].new_ssa_base;
13299 if (SSA_NAME_IS_DEFAULT_DEF (name))
13301 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13302 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13303 tree new_decl = unshare_expr (adjustments[j].new_decl);
13304 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13305 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13306 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13307 gimple *stmt = gimple_build_assign (name, new_decl);
13308 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13310 else
13311 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13316 struct modify_stmt_info info;
13317 info.adjustments = adjustments;
13319 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13321 gimple_stmt_iterator gsi;
13323 gsi = gsi_start_bb (bb);
13324 while (!gsi_end_p (gsi))
13326 gimple *stmt = gsi_stmt (gsi);
13327 info.stmt = stmt;
13328 struct walk_stmt_info wi;
13330 memset (&wi, 0, sizeof (wi));
13331 info.modified = false;
13332 wi.info = &info;
13333 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13335 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13337 tree retval = gimple_return_retval (return_stmt);
13338 if (!retval)
13340 gsi_remove (&gsi, true);
13341 continue;
13344 /* Replace `return foo' with `retval_array[iter] = foo'. */
13345 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13346 retval_array, iter, NULL, NULL);
13347 stmt = gimple_build_assign (ref, retval);
13348 gsi_replace (&gsi, stmt, true);
13349 info.modified = true;
13352 if (info.modified)
13354 update_stmt (stmt);
13355 if (maybe_clean_eh_stmt (stmt))
13356 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13358 gsi_next (&gsi);
13363 /* Adjust the argument types in NODE to their appropriate vector
13364 counterparts. */
13366 static void
13367 simd_clone_adjust (struct cgraph_node *node)
13369 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13371 targetm.simd_clone.adjust (node);
13373 tree retval = simd_clone_adjust_return_type (node);
13374 ipa_parm_adjustment_vec adjustments
13375 = simd_clone_adjust_argument_types (node);
13377 push_gimplify_context ();
13379 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13381 /* Adjust all uses of vector arguments accordingly. Adjust all
13382 return values accordingly. */
13383 tree iter = create_tmp_var (unsigned_type_node, "iter");
13384 tree iter1 = make_ssa_name (iter);
13385 tree iter2 = make_ssa_name (iter);
13386 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13388 /* Initialize the iteration variable. */
13389 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13390 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13391 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13392 /* Insert the SIMD array and iv initialization at function
13393 entry. */
13394 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13396 pop_gimplify_context (NULL);
13398 /* Create a new BB right before the original exit BB, to hold the
13399 iteration increment and the condition/branch. */
13400 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13401 basic_block incr_bb = create_empty_bb (orig_exit);
13402 add_bb_to_loop (incr_bb, body_bb->loop_father);
13403 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13404 flag. Set it now to be a FALLTHRU_EDGE. */
13405 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13406 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13407 for (unsigned i = 0;
13408 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13410 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13411 redirect_edge_succ (e, incr_bb);
13413 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13414 e->probability = REG_BR_PROB_BASE;
13415 gsi = gsi_last_bb (incr_bb);
13416 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13417 build_int_cst (unsigned_type_node, 1));
13418 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13420 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13421 struct loop *loop = alloc_loop ();
13422 cfun->has_force_vectorize_loops = true;
13423 loop->safelen = node->simdclone->simdlen;
13424 loop->force_vectorize = true;
13425 loop->header = body_bb;
13427 /* Branch around the body if the mask applies. */
13428 if (node->simdclone->inbranch)
13430 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13431 tree mask_array
13432 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13433 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13434 tree aref = build4 (ARRAY_REF,
13435 TREE_TYPE (TREE_TYPE (mask_array)),
13436 mask_array, iter1,
13437 NULL, NULL);
13438 g = gimple_build_assign (mask, aref);
13439 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13440 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13441 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13443 aref = build1 (VIEW_CONVERT_EXPR,
13444 build_nonstandard_integer_type (bitsize, 0), mask);
13445 mask = make_ssa_name (TREE_TYPE (aref));
13446 g = gimple_build_assign (mask, aref);
13447 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13450 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13451 NULL, NULL);
13452 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13453 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13454 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13457 /* Generate the condition. */
13458 g = gimple_build_cond (LT_EXPR,
13459 iter2,
13460 build_int_cst (unsigned_type_node,
13461 node->simdclone->simdlen),
13462 NULL, NULL);
13463 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13464 e = split_block (incr_bb, gsi_stmt (gsi));
13465 basic_block latch_bb = e->dest;
13466 basic_block new_exit_bb;
13467 new_exit_bb = split_block_after_labels (latch_bb)->dest;
13468 loop->latch = latch_bb;
13470 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13472 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13473 /* The successor of incr_bb is already pointing to latch_bb; just
13474 change the flags.
13475 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13476 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13478 gphi *phi = create_phi_node (iter1, body_bb);
13479 edge preheader_edge = find_edge (entry_bb, body_bb);
13480 edge latch_edge = single_succ_edge (latch_bb);
13481 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13482 UNKNOWN_LOCATION);
13483 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13485 /* Generate the new return. */
13486 gsi = gsi_last_bb (new_exit_bb);
13487 if (retval
13488 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13489 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13490 retval = TREE_OPERAND (retval, 0);
13491 else if (retval)
13493 retval = build1 (VIEW_CONVERT_EXPR,
13494 TREE_TYPE (TREE_TYPE (node->decl)),
13495 retval);
13496 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13497 false, GSI_CONTINUE_LINKING);
13499 g = gimple_build_return (retval);
13500 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13502 /* Handle aligned clauses by replacing default defs of the aligned
13503 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13504 lhs. Handle linear by adding PHIs. */
13505 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13506 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13507 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
13508 || !is_gimple_reg_type
13509 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
13511 tree orig_arg = node->simdclone->args[i].orig_arg;
13512 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
13513 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
13514 else
13516 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
13517 gimple_add_tmp_var (iter1);
13519 gsi = gsi_after_labels (entry_bb);
13520 g = gimple_build_assign (iter1, orig_arg);
13521 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13522 gsi = gsi_after_labels (body_bb);
13523 g = gimple_build_assign (orig_arg, iter1);
13524 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13526 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13527 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
13528 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13529 == REFERENCE_TYPE
13530 && TREE_ADDRESSABLE
13531 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
13533 tree orig_arg = node->simdclone->args[i].orig_arg;
13534 tree def = ssa_default_def (cfun, orig_arg);
13535 if (def && !has_zero_uses (def))
13537 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
13538 gimple_add_tmp_var (iter1);
13539 gsi = gsi_after_labels (entry_bb);
13540 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
13541 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13542 gsi = gsi_after_labels (body_bb);
13543 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
13544 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13547 else if (node->simdclone->args[i].alignment
13548 && node->simdclone->args[i].arg_type
13549 == SIMD_CLONE_ARG_TYPE_UNIFORM
13550 && (node->simdclone->args[i].alignment
13551 & (node->simdclone->args[i].alignment - 1)) == 0
13552 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13553 == POINTER_TYPE)
13555 unsigned int alignment = node->simdclone->args[i].alignment;
13556 tree orig_arg = node->simdclone->args[i].orig_arg;
13557 tree def = ssa_default_def (cfun, orig_arg);
13558 if (def && !has_zero_uses (def))
13560 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13561 gimple_seq seq = NULL;
13562 bool need_cvt = false;
13563 gcall *call
13564 = gimple_build_call (fn, 2, def, size_int (alignment));
13565 g = call;
13566 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13567 ptr_type_node))
13568 need_cvt = true;
13569 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13570 gimple_call_set_lhs (g, t);
13571 gimple_seq_add_stmt_without_update (&seq, g);
13572 if (need_cvt)
13574 t = make_ssa_name (orig_arg);
13575 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13576 gimple_seq_add_stmt_without_update (&seq, g);
13578 gsi_insert_seq_on_edge_immediate
13579 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13581 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13582 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13583 entry_bb);
13584 node->create_edge (cgraph_node::get_create (fn),
13585 call, entry_bb->count, freq);
13587 imm_use_iterator iter;
13588 use_operand_p use_p;
13589 gimple *use_stmt;
13590 tree repl = gimple_get_lhs (g);
13591 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13592 if (is_gimple_debug (use_stmt) || use_stmt == call)
13593 continue;
13594 else
13595 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13596 SET_USE (use_p, repl);
13599 else if (node->simdclone->args[i].arg_type
13600 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13602 tree orig_arg = node->simdclone->args[i].orig_arg;
13603 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13604 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13605 tree def = NULL_TREE;
13606 if (TREE_ADDRESSABLE (orig_arg))
13608 def = make_ssa_name (TREE_TYPE (orig_arg));
13609 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
13610 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
13611 gsi = gsi_after_labels (entry_bb);
13612 g = gimple_build_assign (def, orig_arg);
13613 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13615 else
13617 def = ssa_default_def (cfun, orig_arg);
13618 if (!def || has_zero_uses (def))
13619 def = NULL_TREE;
13620 else
13622 iter1 = make_ssa_name (orig_arg);
13623 iter2 = make_ssa_name (orig_arg);
13626 if (def)
13628 phi = create_phi_node (iter1, body_bb);
13629 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13630 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13631 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13632 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13633 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13634 ? TREE_TYPE (orig_arg) : sizetype;
13635 tree addcst
13636 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13637 g = gimple_build_assign (iter2, code, iter1, addcst);
13638 gsi = gsi_last_bb (incr_bb);
13639 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13641 imm_use_iterator iter;
13642 use_operand_p use_p;
13643 gimple *use_stmt;
13644 if (TREE_ADDRESSABLE (orig_arg))
13646 gsi = gsi_after_labels (body_bb);
13647 g = gimple_build_assign (orig_arg, iter1);
13648 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13650 else
13651 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13652 if (use_stmt == phi)
13653 continue;
13654 else
13655 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13656 SET_USE (use_p, iter1);
13660 calculate_dominance_info (CDI_DOMINATORS);
13661 add_loop (loop, loop->header->loop_father);
13662 update_ssa (TODO_update_ssa);
13664 pop_cfun ();
13667 /* If the function in NODE is tagged as an elemental SIMD function,
13668 create the appropriate SIMD clones. */
13670 static void
13671 expand_simd_clones (struct cgraph_node *node)
13673 tree attr = lookup_attribute ("omp declare simd",
13674 DECL_ATTRIBUTES (node->decl));
13675 if (attr == NULL_TREE
13676 || node->global.inlined_to
13677 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13678 return;
13680 /* Ignore
13681 #pragma omp declare simd
13682 extern int foo ();
13683 in C, there we don't know the argument types at all. */
13684 if (!node->definition
13685 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13686 return;
13690 /* Start with parsing the "omp declare simd" attribute(s). */
13691 bool inbranch_clause_specified;
13692 struct cgraph_simd_clone *clone_info
13693 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13694 &inbranch_clause_specified);
13695 if (clone_info == NULL)
13696 continue;
13698 int orig_simdlen = clone_info->simdlen;
13699 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13700 /* The target can return 0 (no simd clones should be created),
13701 1 (just one ISA of simd clones should be created) or higher
13702 count of ISA variants. In that case, clone_info is initialized
13703 for the first ISA variant. */
13704 int count
13705 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13706 base_type, 0);
13707 if (count == 0)
13708 continue;
13710 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13711 also create one inbranch and one !inbranch clone of it. */
13712 for (int i = 0; i < count * 2; i++)
13714 struct cgraph_simd_clone *clone = clone_info;
13715 if (inbranch_clause_specified && (i & 1) != 0)
13716 continue;
13718 if (i != 0)
13720 clone = simd_clone_struct_alloc (clone_info->nargs
13721 + ((i & 1) != 0));
13722 simd_clone_struct_copy (clone, clone_info);
13723 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13724 and simd_clone_adjust_argument_types did to the first
13725 clone's info. */
13726 clone->nargs -= clone_info->inbranch;
13727 clone->simdlen = orig_simdlen;
13728 /* And call the target hook again to get the right ISA. */
13729 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13730 base_type,
13731 i / 2);
13732 if ((i & 1) != 0)
13733 clone->inbranch = 1;
13736 /* simd_clone_mangle might fail if such a clone has been created
13737 already. */
13738 tree id = simd_clone_mangle (node, clone);
13739 if (id == NULL_TREE)
13740 continue;
13742 /* Only when we are sure we want to create the clone actually
13743 clone the function (or definitions) or create another
13744 extern FUNCTION_DECL (for prototypes without definitions). */
13745 struct cgraph_node *n = simd_clone_create (node);
13746 if (n == NULL)
13747 continue;
13749 n->simdclone = clone;
13750 clone->origin = node;
13751 clone->next_clone = NULL;
13752 if (node->simd_clones == NULL)
13754 clone->prev_clone = n;
13755 node->simd_clones = n;
13757 else
13759 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13760 clone->prev_clone->simdclone->next_clone = n;
13761 node->simd_clones->simdclone->prev_clone = n;
13763 symtab->change_decl_assembler_name (n->decl, id);
13764 /* And finally adjust the return type, parameters and for
13765 definitions also function body. */
13766 if (node->definition)
13767 simd_clone_adjust (n);
13768 else
13770 simd_clone_adjust_return_type (n);
13771 simd_clone_adjust_argument_types (n);
13775 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13778 /* Entry point for IPA simd clone creation pass. */
13780 static unsigned int
13781 ipa_omp_simd_clone (void)
13783 struct cgraph_node *node;
13784 FOR_EACH_FUNCTION (node)
13785 expand_simd_clones (node);
13786 return 0;
13789 namespace {
13791 const pass_data pass_data_omp_simd_clone =
13793 SIMPLE_IPA_PASS, /* type */
13794 "simdclone", /* name */
13795 OPTGROUP_NONE, /* optinfo_flags */
13796 TV_NONE, /* tv_id */
13797 ( PROP_ssa | PROP_cfg ), /* properties_required */
13798 0, /* properties_provided */
13799 0, /* properties_destroyed */
13800 0, /* todo_flags_start */
13801 0, /* todo_flags_finish */
13804 class pass_omp_simd_clone : public simple_ipa_opt_pass
13806 public:
13807 pass_omp_simd_clone(gcc::context *ctxt)
13808 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13811 /* opt_pass methods: */
13812 virtual bool gate (function *);
13813 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
13816 bool
13817 pass_omp_simd_clone::gate (function *)
13819 return ((flag_openmp || flag_openmp_simd
13820 || flag_cilkplus
13821 || (in_lto_p && !flag_wpa))
13822 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13825 } // anon namespace
13827 simple_ipa_opt_pass *
13828 make_pass_omp_simd_clone (gcc::context *ctxt)
13830 return new pass_omp_simd_clone (ctxt);
13833 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13834 adds their addresses and sizes to constructor-vector V_CTOR. */
13835 static void
13836 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13837 vec<constructor_elt, va_gc> *v_ctor)
13839 unsigned len = vec_safe_length (v_decls);
13840 for (unsigned i = 0; i < len; i++)
13842 tree it = (*v_decls)[i];
13843 bool is_function = TREE_CODE (it) != VAR_DECL;
13845 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13846 if (!is_function)
13847 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13848 fold_convert (const_ptr_type_node,
13849 DECL_SIZE_UNIT (it)));
13853 /* Create new symbols containing (address, size) pairs for global variables,
13854 marked with "omp declare target" attribute, as well as addresses for the
13855 functions, which are outlined offloading regions. */
13856 void
13857 omp_finish_file (void)
13859 unsigned num_funcs = vec_safe_length (offload_funcs);
13860 unsigned num_vars = vec_safe_length (offload_vars);
13862 if (num_funcs == 0 && num_vars == 0)
13863 return;
13865 if (targetm_common.have_named_sections)
13867 vec<constructor_elt, va_gc> *v_f, *v_v;
13868 vec_alloc (v_f, num_funcs);
13869 vec_alloc (v_v, num_vars * 2);
13871 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13872 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13874 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13875 num_vars * 2);
13876 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13877 num_funcs);
13878 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13879 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13880 tree ctor_v = build_constructor (vars_decl_type, v_v);
13881 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13882 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13883 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13884 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13885 get_identifier (".offload_func_table"),
13886 funcs_decl_type);
13887 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13888 get_identifier (".offload_var_table"),
13889 vars_decl_type);
13890 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13891 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13892 otherwise a joint table in a binary will contain padding between
13893 tables from multiple object files. */
13894 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13895 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13896 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13897 DECL_INITIAL (funcs_decl) = ctor_f;
13898 DECL_INITIAL (vars_decl) = ctor_v;
13899 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13900 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13902 varpool_node::finalize_decl (vars_decl);
13903 varpool_node::finalize_decl (funcs_decl);
13905 else
13907 for (unsigned i = 0; i < num_funcs; i++)
13909 tree it = (*offload_funcs)[i];
13910 targetm.record_offload_symbol (it);
13912 for (unsigned i = 0; i < num_vars; i++)
13914 tree it = (*offload_vars)[i];
13915 targetm.record_offload_symbol (it);
13920 #include "gt-omp-low.h"