/cp
[official-gcc.git] / gcc / omp-low.c
blob8218403f6803c32ea63da5c4558c920f6c313b26
1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "alias.h"
30 #include "symtab.h"
31 #include "tree.h"
32 #include "fold-const.h"
33 #include "stringpool.h"
34 #include "stor-layout.h"
35 #include "rtl.h"
36 #include "predict.h"
37 #include "hard-reg-set.h"
38 #include "function.h"
39 #include "dominance.h"
40 #include "cfg.h"
41 #include "cfganal.h"
42 #include "basic-block.h"
43 #include "tree-ssa-alias.h"
44 #include "internal-fn.h"
45 #include "gimple-fold.h"
46 #include "gimple-expr.h"
47 #include "gimple.h"
48 #include "gimplify.h"
49 #include "gimple-iterator.h"
50 #include "gimplify-me.h"
51 #include "gimple-walk.h"
52 #include "tree-iterator.h"
53 #include "tree-inline.h"
54 #include "langhooks.h"
55 #include "diagnostic-core.h"
56 #include "gimple-ssa.h"
57 #include "cgraph.h"
58 #include "tree-cfg.h"
59 #include "tree-phinodes.h"
60 #include "ssa-iterators.h"
61 #include "tree-ssanames.h"
62 #include "tree-into-ssa.h"
63 #include "flags.h"
64 #include "insn-config.h"
65 #include "expmed.h"
66 #include "dojump.h"
67 #include "explow.h"
68 #include "calls.h"
69 #include "emit-rtl.h"
70 #include "varasm.h"
71 #include "stmt.h"
72 #include "expr.h"
73 #include "tree-dfa.h"
74 #include "tree-ssa.h"
75 #include "tree-pass.h"
76 #include "except.h"
77 #include "splay-tree.h"
78 #include "insn-codes.h"
79 #include "optabs.h"
80 #include "cfgloop.h"
81 #include "target.h"
82 #include "common/common-target.h"
83 #include "omp-low.h"
84 #include "gimple-low.h"
85 #include "tree-cfgcleanup.h"
86 #include "pretty-print.h"
87 #include "alloc-pool.h"
88 #include "symbol-summary.h"
89 #include "ipa-prop.h"
90 #include "tree-nested.h"
91 #include "tree-eh.h"
92 #include "cilk.h"
93 #include "context.h"
94 #include "lto-section-names.h"
95 #include "gomp-constants.h"
98 /* Lowering of OMP parallel and workshare constructs proceeds in two
99 phases. The first phase scans the function looking for OMP statements
100 and then for variables that must be replaced to satisfy data sharing
101 clauses. The second phase expands code for the constructs, as well as
102 re-gimplifying things when variables have been replaced with complex
103 expressions.
105 Final code generation is done by pass_expand_omp. The flowgraph is
106 scanned for regions which are then moved to a new
107 function, to be invoked by the thread library, or offloaded. */
109 /* OMP region information. Every parallel and workshare
110 directive is enclosed between two markers, the OMP_* directive
111 and a corresponding OMP_RETURN statement. */
113 struct omp_region
115 /* The enclosing region. */
116 struct omp_region *outer;
118 /* First child region. */
119 struct omp_region *inner;
121 /* Next peer region. */
122 struct omp_region *next;
124 /* Block containing the omp directive as its last stmt. */
125 basic_block entry;
127 /* Block containing the OMP_RETURN as its last stmt. */
128 basic_block exit;
130 /* Block containing the OMP_CONTINUE as its last stmt. */
131 basic_block cont;
133 /* If this is a combined parallel+workshare region, this is a list
134 of additional arguments needed by the combined parallel+workshare
135 library call. */
136 vec<tree, va_gc> *ws_args;
138 /* The code for the omp directive of this region. */
139 enum gimple_code type;
141 /* Schedule kind, only used for OMP_FOR type regions. */
142 enum omp_clause_schedule_kind sched_kind;
144 /* True if this is a combined parallel+workshare region. */
145 bool is_combined_parallel;
148 /* Levels of parallelism as defined by OpenACC. Increasing numbers
149 correspond to deeper loop nesting levels. */
150 #define MASK_GANG 1
151 #define MASK_WORKER 2
152 #define MASK_VECTOR 4
154 /* Context structure. Used to store information about each parallel
155 directive in the code. */
157 typedef struct omp_context
159 /* This field must be at the beginning, as we do "inheritance": Some
160 callback functions for tree-inline.c (e.g., omp_copy_decl)
161 receive a copy_body_data pointer that is up-casted to an
162 omp_context pointer. */
163 copy_body_data cb;
165 /* The tree of contexts corresponding to the encountered constructs. */
166 struct omp_context *outer;
167 gimple stmt;
169 /* Map variables to fields in a structure that allows communication
170 between sending and receiving threads. */
171 splay_tree field_map;
172 tree record_type;
173 tree sender_decl;
174 tree receiver_decl;
176 /* These are used just by task contexts, if task firstprivate fn is
177 needed. srecord_type is used to communicate from the thread
178 that encountered the task construct to task firstprivate fn,
179 record_type is allocated by GOMP_task, initialized by task firstprivate
180 fn and passed to the task body fn. */
181 splay_tree sfield_map;
182 tree srecord_type;
184 /* A chain of variables to add to the top-level block surrounding the
185 construct. In the case of a parallel, this is in the child function. */
186 tree block_vars;
188 /* A map of reduction pointer variables. For accelerators, each
189 reduction variable is replaced with an array. Each thread, in turn,
190 is assigned to a slot on that array. */
191 splay_tree reduction_map;
193 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
194 barriers should jump to during omplower pass. */
195 tree cancel_label;
197 /* What to do with variables with implicitly determined sharing
198 attributes. */
199 enum omp_clause_default_kind default_kind;
201 /* Nesting depth of this context. Used to beautify error messages re
202 invalid gotos. The outermost ctx is depth 1, with depth 0 being
203 reserved for the main body of the function. */
204 int depth;
206 /* True if this parallel directive is nested within another. */
207 bool is_nested;
209 /* True if this construct can be cancelled. */
210 bool cancellable;
212 /* For OpenACC loops, a mask of gang, worker and vector used at
213 levels below this one. */
214 int gwv_below;
215 /* For OpenACC loops, a mask of gang, worker and vector used at
216 this level and above. For parallel and kernels clauses, a mask
217 indicating which of num_gangs/num_workers/num_vectors was used. */
218 int gwv_this;
219 } omp_context;
221 /* A structure holding the elements of:
222 for (V = N1; V cond N2; V += STEP) [...] */
224 struct omp_for_data_loop
226 tree v, n1, n2, step;
227 enum tree_code cond_code;
230 /* A structure describing the main elements of a parallel loop. */
232 struct omp_for_data
234 struct omp_for_data_loop loop;
235 tree chunk_size;
236 gomp_for *for_stmt;
237 tree pre, iter_type;
238 int collapse;
239 bool have_nowait, have_ordered;
240 enum omp_clause_schedule_kind sched_kind;
241 struct omp_for_data_loop *loops;
245 static splay_tree all_contexts;
246 static int taskreg_nesting_level;
247 static int target_nesting_level;
248 static struct omp_region *root_omp_region;
249 static bitmap task_shared_vars;
250 static vec<omp_context *> taskreg_contexts;
252 static void scan_omp (gimple_seq *, omp_context *);
253 static tree scan_omp_1_op (tree *, int *, void *);
255 #define WALK_SUBSTMTS \
256 case GIMPLE_BIND: \
257 case GIMPLE_TRY: \
258 case GIMPLE_CATCH: \
259 case GIMPLE_EH_FILTER: \
260 case GIMPLE_TRANSACTION: \
261 /* The sub-statements for these should be walked. */ \
262 *handled_ops_p = false; \
263 break;
265 /* Helper function to get the name of the array containing the partial
266 reductions for OpenACC reductions. */
267 static const char *
268 oacc_get_reduction_array_id (tree node)
270 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
271 int len = strlen ("OACC") + strlen (id);
272 char *temp_name = XALLOCAVEC (char, len + 1);
273 snprintf (temp_name, len + 1, "OACC%s", id);
274 return IDENTIFIER_POINTER (get_identifier (temp_name));
277 /* Determine the number of threads OpenACC threads used to determine the
278 size of the array of partial reductions. Currently, this is num_gangs
279 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
280 because it is independed of the device used. */
282 static tree
283 oacc_max_threads (omp_context *ctx)
285 tree nthreads, vector_length, gangs, clauses;
287 gangs = fold_convert (sizetype, integer_one_node);
288 vector_length = gangs;
290 /* The reduction clause may be nested inside a loop directive.
291 Scan for the innermost vector_length clause. */
292 for (omp_context *oc = ctx; oc; oc = oc->outer)
294 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
295 || (gimple_omp_target_kind (oc->stmt)
296 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
297 continue;
299 clauses = gimple_omp_target_clauses (oc->stmt);
301 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
302 if (vector_length)
303 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
304 sizetype,
305 OMP_CLAUSE_VECTOR_LENGTH_EXPR
306 (vector_length));
307 else
308 vector_length = fold_convert (sizetype, integer_one_node);
310 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
311 if (gangs)
312 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
313 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
314 else
315 gangs = fold_convert (sizetype, integer_one_node);
317 break;
320 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
322 return nthreads;
325 /* Holds offload tables with decls. */
326 vec<tree, va_gc> *offload_funcs, *offload_vars;
328 /* Convenience function for calling scan_omp_1_op on tree operands. */
330 static inline tree
331 scan_omp_op (tree *tp, omp_context *ctx)
333 struct walk_stmt_info wi;
335 memset (&wi, 0, sizeof (wi));
336 wi.info = ctx;
337 wi.want_locations = true;
339 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
342 static void lower_omp (gimple_seq *, omp_context *);
343 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
344 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
346 /* Find an OMP clause of type KIND within CLAUSES. */
348 tree
349 find_omp_clause (tree clauses, enum omp_clause_code kind)
351 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
352 if (OMP_CLAUSE_CODE (clauses) == kind)
353 return clauses;
355 return NULL_TREE;
358 /* Return true if CTX is for an omp parallel. */
360 static inline bool
361 is_parallel_ctx (omp_context *ctx)
363 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
367 /* Return true if CTX is for an omp task. */
369 static inline bool
370 is_task_ctx (omp_context *ctx)
372 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
376 /* Return true if CTX is for an omp parallel or omp task. */
378 static inline bool
379 is_taskreg_ctx (omp_context *ctx)
381 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
382 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
386 /* Return true if REGION is a combined parallel+workshare region. */
388 static inline bool
389 is_combined_parallel (struct omp_region *region)
391 return region->is_combined_parallel;
395 /* Extract the header elements of parallel loop FOR_STMT and store
396 them into *FD. */
398 static void
399 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
400 struct omp_for_data_loop *loops)
402 tree t, var, *collapse_iter, *collapse_count;
403 tree count = NULL_TREE, iter_type = long_integer_type_node;
404 struct omp_for_data_loop *loop;
405 int i;
406 struct omp_for_data_loop dummy_loop;
407 location_t loc = gimple_location (for_stmt);
408 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
409 bool distribute = gimple_omp_for_kind (for_stmt)
410 == GF_OMP_FOR_KIND_DISTRIBUTE;
412 fd->for_stmt = for_stmt;
413 fd->pre = NULL;
414 fd->collapse = gimple_omp_for_collapse (for_stmt);
415 if (fd->collapse > 1)
416 fd->loops = loops;
417 else
418 fd->loops = &fd->loop;
420 fd->have_nowait = distribute || simd;
421 fd->have_ordered = false;
422 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
423 fd->chunk_size = NULL_TREE;
424 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
425 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
426 collapse_iter = NULL;
427 collapse_count = NULL;
429 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
430 switch (OMP_CLAUSE_CODE (t))
432 case OMP_CLAUSE_NOWAIT:
433 fd->have_nowait = true;
434 break;
435 case OMP_CLAUSE_ORDERED:
436 fd->have_ordered = true;
437 break;
438 case OMP_CLAUSE_SCHEDULE:
439 gcc_assert (!distribute);
440 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
441 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
442 break;
443 case OMP_CLAUSE_DIST_SCHEDULE:
444 gcc_assert (distribute);
445 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
446 break;
447 case OMP_CLAUSE_COLLAPSE:
448 if (fd->collapse > 1)
450 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
451 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
453 break;
454 default:
455 break;
458 /* FIXME: for now map schedule(auto) to schedule(static).
459 There should be analysis to determine whether all iterations
460 are approximately the same amount of work (then schedule(static)
461 is best) or if it varies (then schedule(dynamic,N) is better). */
462 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
464 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
465 gcc_assert (fd->chunk_size == NULL);
467 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
468 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
469 gcc_assert (fd->chunk_size == NULL);
470 else if (fd->chunk_size == NULL)
472 /* We only need to compute a default chunk size for ordered
473 static loops and dynamic loops. */
474 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
475 || fd->have_ordered)
476 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
477 ? integer_zero_node : integer_one_node;
480 for (i = 0; i < fd->collapse; i++)
482 if (fd->collapse == 1)
483 loop = &fd->loop;
484 else if (loops != NULL)
485 loop = loops + i;
486 else
487 loop = &dummy_loop;
489 loop->v = gimple_omp_for_index (for_stmt, i);
490 gcc_assert (SSA_VAR_P (loop->v));
491 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
492 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
493 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
494 loop->n1 = gimple_omp_for_initial (for_stmt, i);
496 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
497 loop->n2 = gimple_omp_for_final (for_stmt, i);
498 switch (loop->cond_code)
500 case LT_EXPR:
501 case GT_EXPR:
502 break;
503 case NE_EXPR:
504 gcc_assert (gimple_omp_for_kind (for_stmt)
505 == GF_OMP_FOR_KIND_CILKSIMD
506 || (gimple_omp_for_kind (for_stmt)
507 == GF_OMP_FOR_KIND_CILKFOR));
508 break;
509 case LE_EXPR:
510 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
511 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
512 else
513 loop->n2 = fold_build2_loc (loc,
514 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
515 build_int_cst (TREE_TYPE (loop->n2), 1));
516 loop->cond_code = LT_EXPR;
517 break;
518 case GE_EXPR:
519 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
520 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
521 else
522 loop->n2 = fold_build2_loc (loc,
523 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
524 build_int_cst (TREE_TYPE (loop->n2), 1));
525 loop->cond_code = GT_EXPR;
526 break;
527 default:
528 gcc_unreachable ();
531 t = gimple_omp_for_incr (for_stmt, i);
532 gcc_assert (TREE_OPERAND (t, 0) == var);
533 switch (TREE_CODE (t))
535 case PLUS_EXPR:
536 loop->step = TREE_OPERAND (t, 1);
537 break;
538 case POINTER_PLUS_EXPR:
539 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
540 break;
541 case MINUS_EXPR:
542 loop->step = TREE_OPERAND (t, 1);
543 loop->step = fold_build1_loc (loc,
544 NEGATE_EXPR, TREE_TYPE (loop->step),
545 loop->step);
546 break;
547 default:
548 gcc_unreachable ();
551 if (simd
552 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
553 && !fd->have_ordered))
555 if (fd->collapse == 1)
556 iter_type = TREE_TYPE (loop->v);
557 else if (i == 0
558 || TYPE_PRECISION (iter_type)
559 < TYPE_PRECISION (TREE_TYPE (loop->v)))
560 iter_type
561 = build_nonstandard_integer_type
562 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
564 else if (iter_type != long_long_unsigned_type_node)
566 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
567 iter_type = long_long_unsigned_type_node;
568 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
569 && TYPE_PRECISION (TREE_TYPE (loop->v))
570 >= TYPE_PRECISION (iter_type))
572 tree n;
574 if (loop->cond_code == LT_EXPR)
575 n = fold_build2_loc (loc,
576 PLUS_EXPR, TREE_TYPE (loop->v),
577 loop->n2, loop->step);
578 else
579 n = loop->n1;
580 if (TREE_CODE (n) != INTEGER_CST
581 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
582 iter_type = long_long_unsigned_type_node;
584 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
585 > TYPE_PRECISION (iter_type))
587 tree n1, n2;
589 if (loop->cond_code == LT_EXPR)
591 n1 = loop->n1;
592 n2 = fold_build2_loc (loc,
593 PLUS_EXPR, TREE_TYPE (loop->v),
594 loop->n2, loop->step);
596 else
598 n1 = fold_build2_loc (loc,
599 MINUS_EXPR, TREE_TYPE (loop->v),
600 loop->n2, loop->step);
601 n2 = loop->n1;
603 if (TREE_CODE (n1) != INTEGER_CST
604 || TREE_CODE (n2) != INTEGER_CST
605 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
606 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
607 iter_type = long_long_unsigned_type_node;
611 if (collapse_count && *collapse_count == NULL)
613 t = fold_binary (loop->cond_code, boolean_type_node,
614 fold_convert (TREE_TYPE (loop->v), loop->n1),
615 fold_convert (TREE_TYPE (loop->v), loop->n2));
616 if (t && integer_zerop (t))
617 count = build_zero_cst (long_long_unsigned_type_node);
618 else if ((i == 0 || count != NULL_TREE)
619 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
620 && TREE_CONSTANT (loop->n1)
621 && TREE_CONSTANT (loop->n2)
622 && TREE_CODE (loop->step) == INTEGER_CST)
624 tree itype = TREE_TYPE (loop->v);
626 if (POINTER_TYPE_P (itype))
627 itype = signed_type_for (itype);
628 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
629 t = fold_build2_loc (loc,
630 PLUS_EXPR, itype,
631 fold_convert_loc (loc, itype, loop->step), t);
632 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
633 fold_convert_loc (loc, itype, loop->n2));
634 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
635 fold_convert_loc (loc, itype, loop->n1));
636 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
637 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
638 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
639 fold_build1_loc (loc, NEGATE_EXPR, itype,
640 fold_convert_loc (loc, itype,
641 loop->step)));
642 else
643 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
644 fold_convert_loc (loc, itype, loop->step));
645 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
646 if (count != NULL_TREE)
647 count = fold_build2_loc (loc,
648 MULT_EXPR, long_long_unsigned_type_node,
649 count, t);
650 else
651 count = t;
652 if (TREE_CODE (count) != INTEGER_CST)
653 count = NULL_TREE;
655 else if (count && !integer_zerop (count))
656 count = NULL_TREE;
660 if (count
661 && !simd
662 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
663 || fd->have_ordered))
665 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
666 iter_type = long_long_unsigned_type_node;
667 else
668 iter_type = long_integer_type_node;
670 else if (collapse_iter && *collapse_iter != NULL)
671 iter_type = TREE_TYPE (*collapse_iter);
672 fd->iter_type = iter_type;
673 if (collapse_iter && *collapse_iter == NULL)
674 *collapse_iter = create_tmp_var (iter_type, ".iter");
675 if (collapse_count && *collapse_count == NULL)
677 if (count)
678 *collapse_count = fold_convert_loc (loc, iter_type, count);
679 else
680 *collapse_count = create_tmp_var (iter_type, ".count");
683 if (fd->collapse > 1)
685 fd->loop.v = *collapse_iter;
686 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
687 fd->loop.n2 = *collapse_count;
688 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
689 fd->loop.cond_code = LT_EXPR;
692 /* For OpenACC loops, force a chunk size of one, as this avoids the default
693 scheduling where several subsequent iterations are being executed by the
694 same thread. */
695 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
697 gcc_assert (fd->chunk_size == NULL_TREE);
698 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
703 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
704 is the immediate dominator of PAR_ENTRY_BB, return true if there
705 are no data dependencies that would prevent expanding the parallel
706 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
708 When expanding a combined parallel+workshare region, the call to
709 the child function may need additional arguments in the case of
710 GIMPLE_OMP_FOR regions. In some cases, these arguments are
711 computed out of variables passed in from the parent to the child
712 via 'struct .omp_data_s'. For instance:
714 #pragma omp parallel for schedule (guided, i * 4)
715 for (j ...)
717 Is lowered into:
719 # BLOCK 2 (PAR_ENTRY_BB)
720 .omp_data_o.i = i;
721 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
723 # BLOCK 3 (WS_ENTRY_BB)
724 .omp_data_i = &.omp_data_o;
725 D.1667 = .omp_data_i->i;
726 D.1598 = D.1667 * 4;
727 #pragma omp for schedule (guided, D.1598)
729 When we outline the parallel region, the call to the child function
730 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
731 that value is computed *after* the call site. So, in principle we
732 cannot do the transformation.
734 To see whether the code in WS_ENTRY_BB blocks the combined
735 parallel+workshare call, we collect all the variables used in the
736 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
737 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
738 call.
740 FIXME. If we had the SSA form built at this point, we could merely
741 hoist the code in block 3 into block 2 and be done with it. But at
742 this point we don't have dataflow information and though we could
743 hack something up here, it is really not worth the aggravation. */
745 static bool
746 workshare_safe_to_combine_p (basic_block ws_entry_bb)
748 struct omp_for_data fd;
749 gimple ws_stmt = last_stmt (ws_entry_bb);
751 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
752 return true;
754 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
756 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
758 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
759 return false;
760 if (fd.iter_type != long_integer_type_node)
761 return false;
763 /* FIXME. We give up too easily here. If any of these arguments
764 are not constants, they will likely involve variables that have
765 been mapped into fields of .omp_data_s for sharing with the child
766 function. With appropriate data flow, it would be possible to
767 see through this. */
768 if (!is_gimple_min_invariant (fd.loop.n1)
769 || !is_gimple_min_invariant (fd.loop.n2)
770 || !is_gimple_min_invariant (fd.loop.step)
771 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
772 return false;
774 return true;
778 /* Collect additional arguments needed to emit a combined
779 parallel+workshare call. WS_STMT is the workshare directive being
780 expanded. */
782 static vec<tree, va_gc> *
783 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
785 tree t;
786 location_t loc = gimple_location (ws_stmt);
787 vec<tree, va_gc> *ws_args;
789 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
791 struct omp_for_data fd;
792 tree n1, n2;
794 extract_omp_for_data (for_stmt, &fd, NULL);
795 n1 = fd.loop.n1;
796 n2 = fd.loop.n2;
798 if (gimple_omp_for_combined_into_p (for_stmt))
800 tree innerc
801 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
802 OMP_CLAUSE__LOOPTEMP_);
803 gcc_assert (innerc);
804 n1 = OMP_CLAUSE_DECL (innerc);
805 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
806 OMP_CLAUSE__LOOPTEMP_);
807 gcc_assert (innerc);
808 n2 = OMP_CLAUSE_DECL (innerc);
811 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
813 t = fold_convert_loc (loc, long_integer_type_node, n1);
814 ws_args->quick_push (t);
816 t = fold_convert_loc (loc, long_integer_type_node, n2);
817 ws_args->quick_push (t);
819 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
820 ws_args->quick_push (t);
822 if (fd.chunk_size)
824 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
825 ws_args->quick_push (t);
828 return ws_args;
830 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
832 /* Number of sections is equal to the number of edges from the
833 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
834 the exit of the sections region. */
835 basic_block bb = single_succ (gimple_bb (ws_stmt));
836 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
837 vec_alloc (ws_args, 1);
838 ws_args->quick_push (t);
839 return ws_args;
842 gcc_unreachable ();
846 /* Discover whether REGION is a combined parallel+workshare region. */
848 static void
849 determine_parallel_type (struct omp_region *region)
851 basic_block par_entry_bb, par_exit_bb;
852 basic_block ws_entry_bb, ws_exit_bb;
854 if (region == NULL || region->inner == NULL
855 || region->exit == NULL || region->inner->exit == NULL
856 || region->inner->cont == NULL)
857 return;
859 /* We only support parallel+for and parallel+sections. */
860 if (region->type != GIMPLE_OMP_PARALLEL
861 || (region->inner->type != GIMPLE_OMP_FOR
862 && region->inner->type != GIMPLE_OMP_SECTIONS))
863 return;
865 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
866 WS_EXIT_BB -> PAR_EXIT_BB. */
867 par_entry_bb = region->entry;
868 par_exit_bb = region->exit;
869 ws_entry_bb = region->inner->entry;
870 ws_exit_bb = region->inner->exit;
872 if (single_succ (par_entry_bb) == ws_entry_bb
873 && single_succ (ws_exit_bb) == par_exit_bb
874 && workshare_safe_to_combine_p (ws_entry_bb)
875 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
876 || (last_and_only_stmt (ws_entry_bb)
877 && last_and_only_stmt (par_exit_bb))))
879 gimple par_stmt = last_stmt (par_entry_bb);
880 gimple ws_stmt = last_stmt (ws_entry_bb);
882 if (region->inner->type == GIMPLE_OMP_FOR)
884 /* If this is a combined parallel loop, we need to determine
885 whether or not to use the combined library calls. There
886 are two cases where we do not apply the transformation:
887 static loops and any kind of ordered loop. In the first
888 case, we already open code the loop so there is no need
889 to do anything else. In the latter case, the combined
890 parallel loop call would still need extra synchronization
891 to implement ordered semantics, so there would not be any
892 gain in using the combined call. */
893 tree clauses = gimple_omp_for_clauses (ws_stmt);
894 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
895 if (c == NULL
896 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
897 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
899 region->is_combined_parallel = false;
900 region->inner->is_combined_parallel = false;
901 return;
905 region->is_combined_parallel = true;
906 region->inner->is_combined_parallel = true;
907 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
912 /* Return true if EXPR is variable sized. */
914 static inline bool
915 is_variable_sized (const_tree expr)
917 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
920 /* Return true if DECL is a reference type. */
922 static inline bool
923 is_reference (tree decl)
925 return lang_hooks.decls.omp_privatize_by_reference (decl);
928 /* Return the type of a decl. If the decl is reference type,
929 return its base type. */
930 static inline tree
931 get_base_type (tree decl)
933 tree type = TREE_TYPE (decl);
934 if (is_reference (decl))
935 type = TREE_TYPE (type);
936 return type;
939 /* Lookup variables. The "maybe" form
940 allows for the variable form to not have been entered, otherwise we
941 assert that the variable must have been entered. */
943 static inline tree
944 lookup_decl (tree var, omp_context *ctx)
946 tree *n = ctx->cb.decl_map->get (var);
947 return *n;
950 static inline tree
951 maybe_lookup_decl (const_tree var, omp_context *ctx)
953 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
954 return n ? *n : NULL_TREE;
957 static inline tree
958 lookup_field (tree var, omp_context *ctx)
960 splay_tree_node n;
961 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
962 return (tree) n->value;
965 static inline tree
966 lookup_sfield (tree var, omp_context *ctx)
968 splay_tree_node n;
969 n = splay_tree_lookup (ctx->sfield_map
970 ? ctx->sfield_map : ctx->field_map,
971 (splay_tree_key) var);
972 return (tree) n->value;
975 static inline tree
976 maybe_lookup_field (tree var, omp_context *ctx)
978 splay_tree_node n;
979 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
980 return n ? (tree) n->value : NULL_TREE;
983 static inline tree
984 lookup_oacc_reduction (const char *id, omp_context *ctx)
986 splay_tree_node n;
987 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
988 return (tree) n->value;
991 static inline tree
992 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
994 splay_tree_node n = NULL;
995 if (ctx->reduction_map)
996 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
997 return n ? (tree) n->value : NULL_TREE;
1000 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1001 the parallel context if DECL is to be shared. */
1003 static bool
1004 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1006 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1007 return true;
1009 /* We can only use copy-in/copy-out semantics for shared variables
1010 when we know the value is not accessible from an outer scope. */
1011 if (shared_ctx)
1013 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1015 /* ??? Trivially accessible from anywhere. But why would we even
1016 be passing an address in this case? Should we simply assert
1017 this to be false, or should we have a cleanup pass that removes
1018 these from the list of mappings? */
1019 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1020 return true;
1022 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1023 without analyzing the expression whether or not its location
1024 is accessible to anyone else. In the case of nested parallel
1025 regions it certainly may be. */
1026 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1027 return true;
1029 /* Do not use copy-in/copy-out for variables that have their
1030 address taken. */
1031 if (TREE_ADDRESSABLE (decl))
1032 return true;
1034 /* lower_send_shared_vars only uses copy-in, but not copy-out
1035 for these. */
1036 if (TREE_READONLY (decl)
1037 || ((TREE_CODE (decl) == RESULT_DECL
1038 || TREE_CODE (decl) == PARM_DECL)
1039 && DECL_BY_REFERENCE (decl)))
1040 return false;
1042 /* Disallow copy-in/out in nested parallel if
1043 decl is shared in outer parallel, otherwise
1044 each thread could store the shared variable
1045 in its own copy-in location, making the
1046 variable no longer really shared. */
1047 if (shared_ctx->is_nested)
1049 omp_context *up;
1051 for (up = shared_ctx->outer; up; up = up->outer)
1052 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1053 break;
1055 if (up)
1057 tree c;
1059 for (c = gimple_omp_taskreg_clauses (up->stmt);
1060 c; c = OMP_CLAUSE_CHAIN (c))
1061 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1062 && OMP_CLAUSE_DECL (c) == decl)
1063 break;
1065 if (c)
1066 goto maybe_mark_addressable_and_ret;
1070 /* For tasks avoid using copy-in/out. As tasks can be
1071 deferred or executed in different thread, when GOMP_task
1072 returns, the task hasn't necessarily terminated. */
1073 if (is_task_ctx (shared_ctx))
1075 tree outer;
1076 maybe_mark_addressable_and_ret:
1077 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1078 if (is_gimple_reg (outer))
1080 /* Taking address of OUTER in lower_send_shared_vars
1081 might need regimplification of everything that uses the
1082 variable. */
1083 if (!task_shared_vars)
1084 task_shared_vars = BITMAP_ALLOC (NULL);
1085 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1086 TREE_ADDRESSABLE (outer) = 1;
1088 return true;
1092 return false;
1095 /* Construct a new automatic decl similar to VAR. */
1097 static tree
1098 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1100 tree copy = copy_var_decl (var, name, type);
1102 DECL_CONTEXT (copy) = current_function_decl;
1103 DECL_CHAIN (copy) = ctx->block_vars;
1104 ctx->block_vars = copy;
1106 return copy;
1109 static tree
1110 omp_copy_decl_1 (tree var, omp_context *ctx)
1112 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1115 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1116 as appropriate. */
1117 static tree
1118 omp_build_component_ref (tree obj, tree field)
1120 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1121 if (TREE_THIS_VOLATILE (field))
1122 TREE_THIS_VOLATILE (ret) |= 1;
1123 if (TREE_READONLY (field))
1124 TREE_READONLY (ret) |= 1;
1125 return ret;
1128 /* Build tree nodes to access the field for VAR on the receiver side. */
1130 static tree
1131 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1133 tree x, field = lookup_field (var, ctx);
1135 /* If the receiver record type was remapped in the child function,
1136 remap the field into the new record type. */
1137 x = maybe_lookup_field (field, ctx);
1138 if (x != NULL)
1139 field = x;
1141 x = build_simple_mem_ref (ctx->receiver_decl);
1142 x = omp_build_component_ref (x, field);
1143 if (by_ref)
1144 x = build_simple_mem_ref (x);
1146 return x;
1149 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1150 of a parallel, this is a component reference; for workshare constructs
1151 this is some variable. */
1153 static tree
1154 build_outer_var_ref (tree var, omp_context *ctx)
1156 tree x;
1158 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1159 x = var;
1160 else if (is_variable_sized (var))
1162 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1163 x = build_outer_var_ref (x, ctx);
1164 x = build_simple_mem_ref (x);
1166 else if (is_taskreg_ctx (ctx))
1168 bool by_ref = use_pointer_for_field (var, NULL);
1169 x = build_receiver_ref (var, by_ref, ctx);
1171 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1172 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1174 /* #pragma omp simd isn't a worksharing construct, and can reference even
1175 private vars in its linear etc. clauses. */
1176 x = NULL_TREE;
1177 if (ctx->outer && is_taskreg_ctx (ctx))
1178 x = lookup_decl (var, ctx->outer);
1179 else if (ctx->outer)
1180 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1181 if (x == NULL_TREE)
1182 x = var;
1184 else if (ctx->outer)
1185 x = lookup_decl (var, ctx->outer);
1186 else if (is_reference (var))
1187 /* This can happen with orphaned constructs. If var is reference, it is
1188 possible it is shared and as such valid. */
1189 x = var;
1190 else
1191 gcc_unreachable ();
1193 if (is_reference (var))
1194 x = build_simple_mem_ref (x);
1196 return x;
1199 /* Build tree nodes to access the field for VAR on the sender side. */
1201 static tree
1202 build_sender_ref (tree var, omp_context *ctx)
1204 tree field = lookup_sfield (var, ctx);
1205 return omp_build_component_ref (ctx->sender_decl, field);
1208 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1210 static void
1211 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1213 tree field, type, sfield = NULL_TREE;
1215 gcc_assert ((mask & 1) == 0
1216 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1217 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1218 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1219 gcc_assert ((mask & 3) == 3
1220 || !is_gimple_omp_oacc (ctx->stmt));
1222 type = TREE_TYPE (var);
1223 if (mask & 4)
1225 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1226 type = build_pointer_type (build_pointer_type (type));
1228 else if (by_ref)
1229 type = build_pointer_type (type);
1230 else if ((mask & 3) == 1 && is_reference (var))
1231 type = TREE_TYPE (type);
1233 field = build_decl (DECL_SOURCE_LOCATION (var),
1234 FIELD_DECL, DECL_NAME (var), type);
1236 /* Remember what variable this field was created for. This does have a
1237 side effect of making dwarf2out ignore this member, so for helpful
1238 debugging we clear it later in delete_omp_context. */
1239 DECL_ABSTRACT_ORIGIN (field) = var;
1240 if (type == TREE_TYPE (var))
1242 DECL_ALIGN (field) = DECL_ALIGN (var);
1243 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1244 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1246 else
1247 DECL_ALIGN (field) = TYPE_ALIGN (type);
1249 if ((mask & 3) == 3)
1251 insert_field_into_struct (ctx->record_type, field);
1252 if (ctx->srecord_type)
1254 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1255 FIELD_DECL, DECL_NAME (var), type);
1256 DECL_ABSTRACT_ORIGIN (sfield) = var;
1257 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1258 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1259 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1260 insert_field_into_struct (ctx->srecord_type, sfield);
1263 else
1265 if (ctx->srecord_type == NULL_TREE)
1267 tree t;
1269 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1270 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1271 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1273 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1274 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1275 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1276 insert_field_into_struct (ctx->srecord_type, sfield);
1277 splay_tree_insert (ctx->sfield_map,
1278 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1279 (splay_tree_value) sfield);
1282 sfield = field;
1283 insert_field_into_struct ((mask & 1) ? ctx->record_type
1284 : ctx->srecord_type, field);
1287 if (mask & 1)
1288 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1289 (splay_tree_value) field);
1290 if ((mask & 2) && ctx->sfield_map)
1291 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1292 (splay_tree_value) sfield);
1295 static tree
1296 install_var_local (tree var, omp_context *ctx)
1298 tree new_var = omp_copy_decl_1 (var, ctx);
1299 insert_decl_map (&ctx->cb, var, new_var);
1300 return new_var;
1303 /* Adjust the replacement for DECL in CTX for the new context. This means
1304 copying the DECL_VALUE_EXPR, and fixing up the type. */
1306 static void
1307 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1309 tree new_decl, size;
1311 new_decl = lookup_decl (decl, ctx);
1313 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1315 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1316 && DECL_HAS_VALUE_EXPR_P (decl))
1318 tree ve = DECL_VALUE_EXPR (decl);
1319 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1320 SET_DECL_VALUE_EXPR (new_decl, ve);
1321 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1324 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1326 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1327 if (size == error_mark_node)
1328 size = TYPE_SIZE (TREE_TYPE (new_decl));
1329 DECL_SIZE (new_decl) = size;
1331 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1332 if (size == error_mark_node)
1333 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1334 DECL_SIZE_UNIT (new_decl) = size;
1338 /* The callback for remap_decl. Search all containing contexts for a
1339 mapping of the variable; this avoids having to duplicate the splay
1340 tree ahead of time. We know a mapping doesn't already exist in the
1341 given context. Create new mappings to implement default semantics. */
1343 static tree
1344 omp_copy_decl (tree var, copy_body_data *cb)
1346 omp_context *ctx = (omp_context *) cb;
1347 tree new_var;
1349 if (TREE_CODE (var) == LABEL_DECL)
1351 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1352 DECL_CONTEXT (new_var) = current_function_decl;
1353 insert_decl_map (&ctx->cb, var, new_var);
1354 return new_var;
1357 while (!is_taskreg_ctx (ctx))
1359 ctx = ctx->outer;
1360 if (ctx == NULL)
1361 return var;
1362 new_var = maybe_lookup_decl (var, ctx);
1363 if (new_var)
1364 return new_var;
1367 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1368 return var;
1370 return error_mark_node;
1374 /* Debugging dumps for parallel regions. */
1375 void dump_omp_region (FILE *, struct omp_region *, int);
1376 void debug_omp_region (struct omp_region *);
1377 void debug_all_omp_regions (void);
1379 /* Dump the parallel region tree rooted at REGION. */
1381 void
1382 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1384 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1385 gimple_code_name[region->type]);
1387 if (region->inner)
1388 dump_omp_region (file, region->inner, indent + 4);
1390 if (region->cont)
1392 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1393 region->cont->index);
1396 if (region->exit)
1397 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1398 region->exit->index);
1399 else
1400 fprintf (file, "%*s[no exit marker]\n", indent, "");
1402 if (region->next)
1403 dump_omp_region (file, region->next, indent);
1406 DEBUG_FUNCTION void
1407 debug_omp_region (struct omp_region *region)
1409 dump_omp_region (stderr, region, 0);
1412 DEBUG_FUNCTION void
1413 debug_all_omp_regions (void)
1415 dump_omp_region (stderr, root_omp_region, 0);
1419 /* Create a new parallel region starting at STMT inside region PARENT. */
1421 static struct omp_region *
1422 new_omp_region (basic_block bb, enum gimple_code type,
1423 struct omp_region *parent)
1425 struct omp_region *region = XCNEW (struct omp_region);
1427 region->outer = parent;
1428 region->entry = bb;
1429 region->type = type;
1431 if (parent)
1433 /* This is a nested region. Add it to the list of inner
1434 regions in PARENT. */
1435 region->next = parent->inner;
1436 parent->inner = region;
1438 else
1440 /* This is a toplevel region. Add it to the list of toplevel
1441 regions in ROOT_OMP_REGION. */
1442 region->next = root_omp_region;
1443 root_omp_region = region;
1446 return region;
1449 /* Release the memory associated with the region tree rooted at REGION. */
1451 static void
1452 free_omp_region_1 (struct omp_region *region)
1454 struct omp_region *i, *n;
1456 for (i = region->inner; i ; i = n)
1458 n = i->next;
1459 free_omp_region_1 (i);
1462 free (region);
1465 /* Release the memory for the entire omp region tree. */
1467 void
1468 free_omp_regions (void)
1470 struct omp_region *r, *n;
1471 for (r = root_omp_region; r ; r = n)
1473 n = r->next;
1474 free_omp_region_1 (r);
1476 root_omp_region = NULL;
1480 /* Create a new context, with OUTER_CTX being the surrounding context. */
1482 static omp_context *
1483 new_omp_context (gimple stmt, omp_context *outer_ctx)
1485 omp_context *ctx = XCNEW (omp_context);
1487 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1488 (splay_tree_value) ctx);
1489 ctx->stmt = stmt;
1491 if (outer_ctx)
1493 ctx->outer = outer_ctx;
1494 ctx->cb = outer_ctx->cb;
1495 ctx->cb.block = NULL;
1496 ctx->depth = outer_ctx->depth + 1;
1497 ctx->reduction_map = outer_ctx->reduction_map;
1499 else
1501 ctx->cb.src_fn = current_function_decl;
1502 ctx->cb.dst_fn = current_function_decl;
1503 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1504 gcc_checking_assert (ctx->cb.src_node);
1505 ctx->cb.dst_node = ctx->cb.src_node;
1506 ctx->cb.src_cfun = cfun;
1507 ctx->cb.copy_decl = omp_copy_decl;
1508 ctx->cb.eh_lp_nr = 0;
1509 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1510 ctx->depth = 1;
1513 ctx->cb.decl_map = new hash_map<tree, tree>;
1515 return ctx;
1518 static gimple_seq maybe_catch_exception (gimple_seq);
1520 /* Finalize task copyfn. */
1522 static void
1523 finalize_task_copyfn (gomp_task *task_stmt)
1525 struct function *child_cfun;
1526 tree child_fn;
1527 gimple_seq seq = NULL, new_seq;
1528 gbind *bind;
1530 child_fn = gimple_omp_task_copy_fn (task_stmt);
1531 if (child_fn == NULL_TREE)
1532 return;
1534 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1535 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1537 push_cfun (child_cfun);
1538 bind = gimplify_body (child_fn, false);
1539 gimple_seq_add_stmt (&seq, bind);
1540 new_seq = maybe_catch_exception (seq);
1541 if (new_seq != seq)
1543 bind = gimple_build_bind (NULL, new_seq, NULL);
1544 seq = NULL;
1545 gimple_seq_add_stmt (&seq, bind);
1547 gimple_set_body (child_fn, seq);
1548 pop_cfun ();
1550 /* Inform the callgraph about the new function. */
1551 cgraph_node *node = cgraph_node::get_create (child_fn);
1552 node->parallelized_function = 1;
1553 cgraph_node::add_new_function (child_fn, false);
1556 /* Destroy a omp_context data structures. Called through the splay tree
1557 value delete callback. */
1559 static void
1560 delete_omp_context (splay_tree_value value)
1562 omp_context *ctx = (omp_context *) value;
1564 delete ctx->cb.decl_map;
1566 if (ctx->field_map)
1567 splay_tree_delete (ctx->field_map);
1568 if (ctx->sfield_map)
1569 splay_tree_delete (ctx->sfield_map);
1570 /* Reduction map is copied to nested contexts, so only delete it in the
1571 owner. */
1572 if (ctx->reduction_map
1573 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1574 && is_gimple_omp_offloaded (ctx->stmt)
1575 && is_gimple_omp_oacc (ctx->stmt))
1576 splay_tree_delete (ctx->reduction_map);
1578 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1579 it produces corrupt debug information. */
1580 if (ctx->record_type)
1582 tree t;
1583 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1584 DECL_ABSTRACT_ORIGIN (t) = NULL;
1586 if (ctx->srecord_type)
1588 tree t;
1589 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1590 DECL_ABSTRACT_ORIGIN (t) = NULL;
1593 if (is_task_ctx (ctx))
1594 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1596 XDELETE (ctx);
1599 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1600 context. */
1602 static void
1603 fixup_child_record_type (omp_context *ctx)
1605 tree f, type = ctx->record_type;
1607 /* ??? It isn't sufficient to just call remap_type here, because
1608 variably_modified_type_p doesn't work the way we expect for
1609 record types. Testing each field for whether it needs remapping
1610 and creating a new record by hand works, however. */
1611 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1612 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1613 break;
1614 if (f)
1616 tree name, new_fields = NULL;
1618 type = lang_hooks.types.make_type (RECORD_TYPE);
1619 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1620 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1621 TYPE_DECL, name, type);
1622 TYPE_NAME (type) = name;
1624 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1626 tree new_f = copy_node (f);
1627 DECL_CONTEXT (new_f) = type;
1628 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1629 DECL_CHAIN (new_f) = new_fields;
1630 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1631 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1632 &ctx->cb, NULL);
1633 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1634 &ctx->cb, NULL);
1635 new_fields = new_f;
1637 /* Arrange to be able to look up the receiver field
1638 given the sender field. */
1639 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1640 (splay_tree_value) new_f);
1642 TYPE_FIELDS (type) = nreverse (new_fields);
1643 layout_type (type);
1646 TREE_TYPE (ctx->receiver_decl)
1647 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1650 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1651 specified by CLAUSES. */
1653 static void
1654 scan_sharing_clauses (tree clauses, omp_context *ctx)
1656 tree c, decl;
1657 bool scan_array_reductions = false;
1659 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1661 bool by_ref;
1663 switch (OMP_CLAUSE_CODE (c))
1665 case OMP_CLAUSE_PRIVATE:
1666 decl = OMP_CLAUSE_DECL (c);
1667 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1668 goto do_private;
1669 else if (!is_variable_sized (decl))
1670 install_var_local (decl, ctx);
1671 break;
1673 case OMP_CLAUSE_SHARED:
1674 decl = OMP_CLAUSE_DECL (c);
1675 /* Ignore shared directives in teams construct. */
1676 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1678 /* Global variables don't need to be copied,
1679 the receiver side will use them directly. */
1680 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1681 if (is_global_var (odecl))
1682 break;
1683 insert_decl_map (&ctx->cb, decl, odecl);
1684 break;
1686 gcc_assert (is_taskreg_ctx (ctx));
1687 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1688 || !is_variable_sized (decl));
1689 /* Global variables don't need to be copied,
1690 the receiver side will use them directly. */
1691 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1692 break;
1693 by_ref = use_pointer_for_field (decl, ctx);
1694 if (! TREE_READONLY (decl)
1695 || TREE_ADDRESSABLE (decl)
1696 || by_ref
1697 || is_reference (decl))
1699 install_var_field (decl, by_ref, 3, ctx);
1700 install_var_local (decl, ctx);
1701 break;
1703 /* We don't need to copy const scalar vars back. */
1704 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1705 goto do_private;
1707 case OMP_CLAUSE_LASTPRIVATE:
1708 /* Let the corresponding firstprivate clause create
1709 the variable. */
1710 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1711 break;
1712 /* FALLTHRU */
1714 case OMP_CLAUSE_FIRSTPRIVATE:
1715 if (is_gimple_omp_oacc (ctx->stmt))
1717 sorry ("clause not supported yet");
1718 break;
1720 /* FALLTHRU */
1721 case OMP_CLAUSE_REDUCTION:
1722 case OMP_CLAUSE_LINEAR:
1723 decl = OMP_CLAUSE_DECL (c);
1724 do_private:
1725 if (is_variable_sized (decl))
1727 if (is_task_ctx (ctx))
1728 install_var_field (decl, false, 1, ctx);
1729 break;
1731 else if (is_taskreg_ctx (ctx))
1733 bool global
1734 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1735 by_ref = use_pointer_for_field (decl, NULL);
1737 if (is_task_ctx (ctx)
1738 && (global || by_ref || is_reference (decl)))
1740 install_var_field (decl, false, 1, ctx);
1741 if (!global)
1742 install_var_field (decl, by_ref, 2, ctx);
1744 else if (!global)
1745 install_var_field (decl, by_ref, 3, ctx);
1747 install_var_local (decl, ctx);
1748 if (is_gimple_omp_oacc (ctx->stmt)
1749 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1751 /* Create a decl for the reduction array. */
1752 tree var = OMP_CLAUSE_DECL (c);
1753 tree type = get_base_type (var);
1754 tree ptype = build_pointer_type (type);
1755 tree array = create_tmp_var (ptype,
1756 oacc_get_reduction_array_id (var));
1757 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1758 install_var_field (array, true, 3, c);
1759 install_var_local (array, c);
1761 /* Insert it into the current context. */
1762 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1763 oacc_get_reduction_array_id (var),
1764 (splay_tree_value) array);
1765 splay_tree_insert (ctx->reduction_map,
1766 (splay_tree_key) array,
1767 (splay_tree_value) array);
1769 break;
1771 case OMP_CLAUSE__LOOPTEMP_:
1772 gcc_assert (is_parallel_ctx (ctx));
1773 decl = OMP_CLAUSE_DECL (c);
1774 install_var_field (decl, false, 3, ctx);
1775 install_var_local (decl, ctx);
1776 break;
1778 case OMP_CLAUSE_COPYPRIVATE:
1779 case OMP_CLAUSE_COPYIN:
1780 decl = OMP_CLAUSE_DECL (c);
1781 by_ref = use_pointer_for_field (decl, NULL);
1782 install_var_field (decl, by_ref, 3, ctx);
1783 break;
1785 case OMP_CLAUSE_DEFAULT:
1786 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1787 break;
1789 case OMP_CLAUSE_FINAL:
1790 case OMP_CLAUSE_IF:
1791 case OMP_CLAUSE_NUM_THREADS:
1792 case OMP_CLAUSE_NUM_TEAMS:
1793 case OMP_CLAUSE_THREAD_LIMIT:
1794 case OMP_CLAUSE_DEVICE:
1795 case OMP_CLAUSE_SCHEDULE:
1796 case OMP_CLAUSE_DIST_SCHEDULE:
1797 case OMP_CLAUSE_DEPEND:
1798 case OMP_CLAUSE__CILK_FOR_COUNT_:
1799 case OMP_CLAUSE_NUM_GANGS:
1800 case OMP_CLAUSE_NUM_WORKERS:
1801 case OMP_CLAUSE_VECTOR_LENGTH:
1802 if (ctx->outer)
1803 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1804 break;
1806 case OMP_CLAUSE_TO:
1807 case OMP_CLAUSE_FROM:
1808 case OMP_CLAUSE_MAP:
1809 if (ctx->outer)
1810 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1811 decl = OMP_CLAUSE_DECL (c);
1812 /* Global variables with "omp declare target" attribute
1813 don't need to be copied, the receiver side will use them
1814 directly. */
1815 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1816 && DECL_P (decl)
1817 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1818 && varpool_node::get_create (decl)->offloadable)
1819 break;
1820 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1821 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
1823 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1824 not offloaded; there is nothing to map for those. */
1825 if (!is_gimple_omp_offloaded (ctx->stmt)
1826 && !POINTER_TYPE_P (TREE_TYPE (decl))
1827 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
1828 break;
1830 if (DECL_P (decl))
1832 if (DECL_SIZE (decl)
1833 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1835 tree decl2 = DECL_VALUE_EXPR (decl);
1836 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1837 decl2 = TREE_OPERAND (decl2, 0);
1838 gcc_assert (DECL_P (decl2));
1839 install_var_field (decl2, true, 3, ctx);
1840 install_var_local (decl2, ctx);
1841 install_var_local (decl, ctx);
1843 else
1845 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1846 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1847 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1848 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1849 install_var_field (decl, true, 7, ctx);
1850 else
1851 install_var_field (decl, true, 3, ctx);
1852 if (is_gimple_omp_offloaded (ctx->stmt))
1853 install_var_local (decl, ctx);
1856 else
1858 tree base = get_base_address (decl);
1859 tree nc = OMP_CLAUSE_CHAIN (c);
1860 if (DECL_P (base)
1861 && nc != NULL_TREE
1862 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1863 && OMP_CLAUSE_DECL (nc) == base
1864 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1865 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1867 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1868 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1870 else
1872 if (ctx->outer)
1874 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1875 decl = OMP_CLAUSE_DECL (c);
1877 gcc_assert (!splay_tree_lookup (ctx->field_map,
1878 (splay_tree_key) decl));
1879 tree field
1880 = build_decl (OMP_CLAUSE_LOCATION (c),
1881 FIELD_DECL, NULL_TREE, ptr_type_node);
1882 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1883 insert_field_into_struct (ctx->record_type, field);
1884 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1885 (splay_tree_value) field);
1888 break;
1890 case OMP_CLAUSE_NOWAIT:
1891 case OMP_CLAUSE_ORDERED:
1892 case OMP_CLAUSE_COLLAPSE:
1893 case OMP_CLAUSE_UNTIED:
1894 case OMP_CLAUSE_MERGEABLE:
1895 case OMP_CLAUSE_PROC_BIND:
1896 case OMP_CLAUSE_SAFELEN:
1897 case OMP_CLAUSE_ASYNC:
1898 case OMP_CLAUSE_WAIT:
1899 case OMP_CLAUSE_GANG:
1900 case OMP_CLAUSE_WORKER:
1901 case OMP_CLAUSE_VECTOR:
1902 break;
1904 case OMP_CLAUSE_ALIGNED:
1905 decl = OMP_CLAUSE_DECL (c);
1906 if (is_global_var (decl)
1907 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1908 install_var_local (decl, ctx);
1909 break;
1911 case OMP_CLAUSE_DEVICE_RESIDENT:
1912 case OMP_CLAUSE_USE_DEVICE:
1913 case OMP_CLAUSE__CACHE_:
1914 case OMP_CLAUSE_INDEPENDENT:
1915 case OMP_CLAUSE_AUTO:
1916 case OMP_CLAUSE_SEQ:
1917 sorry ("Clause not supported yet");
1918 break;
1920 default:
1921 gcc_unreachable ();
1925 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1927 switch (OMP_CLAUSE_CODE (c))
1929 case OMP_CLAUSE_LASTPRIVATE:
1930 /* Let the corresponding firstprivate clause create
1931 the variable. */
1932 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1933 scan_array_reductions = true;
1934 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1935 break;
1936 /* FALLTHRU */
1938 case OMP_CLAUSE_FIRSTPRIVATE:
1939 if (is_gimple_omp_oacc (ctx->stmt))
1941 sorry ("clause not supported yet");
1942 break;
1944 /* FALLTHRU */
1945 case OMP_CLAUSE_PRIVATE:
1946 case OMP_CLAUSE_REDUCTION:
1947 case OMP_CLAUSE_LINEAR:
1948 decl = OMP_CLAUSE_DECL (c);
1949 if (is_variable_sized (decl))
1950 install_var_local (decl, ctx);
1951 fixup_remapped_decl (decl, ctx,
1952 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1953 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1954 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1955 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1956 scan_array_reductions = true;
1957 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1958 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1959 scan_array_reductions = true;
1960 break;
1962 case OMP_CLAUSE_SHARED:
1963 /* Ignore shared directives in teams construct. */
1964 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1965 break;
1966 decl = OMP_CLAUSE_DECL (c);
1967 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1968 fixup_remapped_decl (decl, ctx, false);
1969 break;
1971 case OMP_CLAUSE_MAP:
1972 if (!is_gimple_omp_offloaded (ctx->stmt))
1973 break;
1974 decl = OMP_CLAUSE_DECL (c);
1975 if (DECL_P (decl)
1976 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1977 && varpool_node::get_create (decl)->offloadable)
1978 break;
1979 if (DECL_P (decl))
1981 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1982 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1983 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1985 tree new_decl = lookup_decl (decl, ctx);
1986 TREE_TYPE (new_decl)
1987 = remap_type (TREE_TYPE (decl), &ctx->cb);
1989 else if (DECL_SIZE (decl)
1990 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1992 tree decl2 = DECL_VALUE_EXPR (decl);
1993 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1994 decl2 = TREE_OPERAND (decl2, 0);
1995 gcc_assert (DECL_P (decl2));
1996 fixup_remapped_decl (decl2, ctx, false);
1997 fixup_remapped_decl (decl, ctx, true);
1999 else
2000 fixup_remapped_decl (decl, ctx, false);
2002 break;
2004 case OMP_CLAUSE_COPYPRIVATE:
2005 case OMP_CLAUSE_COPYIN:
2006 case OMP_CLAUSE_DEFAULT:
2007 case OMP_CLAUSE_IF:
2008 case OMP_CLAUSE_NUM_THREADS:
2009 case OMP_CLAUSE_NUM_TEAMS:
2010 case OMP_CLAUSE_THREAD_LIMIT:
2011 case OMP_CLAUSE_DEVICE:
2012 case OMP_CLAUSE_SCHEDULE:
2013 case OMP_CLAUSE_DIST_SCHEDULE:
2014 case OMP_CLAUSE_NOWAIT:
2015 case OMP_CLAUSE_ORDERED:
2016 case OMP_CLAUSE_COLLAPSE:
2017 case OMP_CLAUSE_UNTIED:
2018 case OMP_CLAUSE_FINAL:
2019 case OMP_CLAUSE_MERGEABLE:
2020 case OMP_CLAUSE_PROC_BIND:
2021 case OMP_CLAUSE_SAFELEN:
2022 case OMP_CLAUSE_ALIGNED:
2023 case OMP_CLAUSE_DEPEND:
2024 case OMP_CLAUSE__LOOPTEMP_:
2025 case OMP_CLAUSE_TO:
2026 case OMP_CLAUSE_FROM:
2027 case OMP_CLAUSE__CILK_FOR_COUNT_:
2028 case OMP_CLAUSE_ASYNC:
2029 case OMP_CLAUSE_WAIT:
2030 case OMP_CLAUSE_NUM_GANGS:
2031 case OMP_CLAUSE_NUM_WORKERS:
2032 case OMP_CLAUSE_VECTOR_LENGTH:
2033 case OMP_CLAUSE_GANG:
2034 case OMP_CLAUSE_WORKER:
2035 case OMP_CLAUSE_VECTOR:
2036 break;
2038 case OMP_CLAUSE_DEVICE_RESIDENT:
2039 case OMP_CLAUSE_USE_DEVICE:
2040 case OMP_CLAUSE__CACHE_:
2041 case OMP_CLAUSE_INDEPENDENT:
2042 case OMP_CLAUSE_AUTO:
2043 case OMP_CLAUSE_SEQ:
2044 sorry ("Clause not supported yet");
2045 break;
2047 default:
2048 gcc_unreachable ();
2052 gcc_checking_assert (!scan_array_reductions
2053 || !is_gimple_omp_oacc (ctx->stmt));
2054 if (scan_array_reductions)
2055 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2056 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2057 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2059 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2060 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2062 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2063 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2064 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2065 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2066 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2067 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2070 /* Create a new name for omp child function. Returns an identifier. If
2071 IS_CILK_FOR is true then the suffix for the child function is
2072 "_cilk_for_fn." */
2074 static tree
2075 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2077 if (is_cilk_for)
2078 return clone_function_name (current_function_decl, "_cilk_for_fn");
2079 return clone_function_name (current_function_decl,
2080 task_copy ? "_omp_cpyfn" : "_omp_fn");
2083 /* Returns the type of the induction variable for the child function for
2084 _Cilk_for and the types for _high and _low variables based on TYPE. */
2086 static tree
2087 cilk_for_check_loop_diff_type (tree type)
2089 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2091 if (TYPE_UNSIGNED (type))
2092 return uint32_type_node;
2093 else
2094 return integer_type_node;
2096 else
2098 if (TYPE_UNSIGNED (type))
2099 return uint64_type_node;
2100 else
2101 return long_long_integer_type_node;
2105 /* Build a decl for the omp child function. It'll not contain a body
2106 yet, just the bare decl. */
2108 static void
2109 create_omp_child_function (omp_context *ctx, bool task_copy)
2111 tree decl, type, name, t;
2113 tree cilk_for_count
2114 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2115 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2116 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2117 tree cilk_var_type = NULL_TREE;
2119 name = create_omp_child_function_name (task_copy,
2120 cilk_for_count != NULL_TREE);
2121 if (task_copy)
2122 type = build_function_type_list (void_type_node, ptr_type_node,
2123 ptr_type_node, NULL_TREE);
2124 else if (cilk_for_count)
2126 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2127 cilk_var_type = cilk_for_check_loop_diff_type (type);
2128 type = build_function_type_list (void_type_node, ptr_type_node,
2129 cilk_var_type, cilk_var_type, NULL_TREE);
2131 else
2132 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2134 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2136 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2137 || !task_copy);
2138 if (!task_copy)
2139 ctx->cb.dst_fn = decl;
2140 else
2141 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2143 TREE_STATIC (decl) = 1;
2144 TREE_USED (decl) = 1;
2145 DECL_ARTIFICIAL (decl) = 1;
2146 DECL_IGNORED_P (decl) = 0;
2147 TREE_PUBLIC (decl) = 0;
2148 DECL_UNINLINABLE (decl) = 1;
2149 DECL_EXTERNAL (decl) = 0;
2150 DECL_CONTEXT (decl) = NULL_TREE;
2151 DECL_INITIAL (decl) = make_node (BLOCK);
2152 if (cgraph_node::get (current_function_decl)->offloadable)
2153 cgraph_node::get_create (decl)->offloadable = 1;
2154 else
2156 omp_context *octx;
2157 for (octx = ctx; octx; octx = octx->outer)
2158 if (is_gimple_omp_offloaded (octx->stmt))
2160 cgraph_node::get_create (decl)->offloadable = 1;
2161 #ifdef ENABLE_OFFLOADING
2162 g->have_offload = true;
2163 #endif
2164 break;
2168 if (cgraph_node::get_create (decl)->offloadable
2169 && !lookup_attribute ("omp declare target",
2170 DECL_ATTRIBUTES (current_function_decl)))
2171 DECL_ATTRIBUTES (decl)
2172 = tree_cons (get_identifier ("omp target entrypoint"),
2173 NULL_TREE, DECL_ATTRIBUTES (decl));
2175 t = build_decl (DECL_SOURCE_LOCATION (decl),
2176 RESULT_DECL, NULL_TREE, void_type_node);
2177 DECL_ARTIFICIAL (t) = 1;
2178 DECL_IGNORED_P (t) = 1;
2179 DECL_CONTEXT (t) = decl;
2180 DECL_RESULT (decl) = t;
2182 /* _Cilk_for's child function requires two extra parameters called
2183 __low and __high that are set the by Cilk runtime when it calls this
2184 function. */
2185 if (cilk_for_count)
2187 t = build_decl (DECL_SOURCE_LOCATION (decl),
2188 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2189 DECL_ARTIFICIAL (t) = 1;
2190 DECL_NAMELESS (t) = 1;
2191 DECL_ARG_TYPE (t) = ptr_type_node;
2192 DECL_CONTEXT (t) = current_function_decl;
2193 TREE_USED (t) = 1;
2194 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2195 DECL_ARGUMENTS (decl) = t;
2197 t = build_decl (DECL_SOURCE_LOCATION (decl),
2198 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2199 DECL_ARTIFICIAL (t) = 1;
2200 DECL_NAMELESS (t) = 1;
2201 DECL_ARG_TYPE (t) = ptr_type_node;
2202 DECL_CONTEXT (t) = current_function_decl;
2203 TREE_USED (t) = 1;
2204 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2205 DECL_ARGUMENTS (decl) = t;
2208 tree data_name = get_identifier (".omp_data_i");
2209 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2210 ptr_type_node);
2211 DECL_ARTIFICIAL (t) = 1;
2212 DECL_NAMELESS (t) = 1;
2213 DECL_ARG_TYPE (t) = ptr_type_node;
2214 DECL_CONTEXT (t) = current_function_decl;
2215 TREE_USED (t) = 1;
2216 if (cilk_for_count)
2217 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2218 DECL_ARGUMENTS (decl) = t;
2219 if (!task_copy)
2220 ctx->receiver_decl = t;
2221 else
2223 t = build_decl (DECL_SOURCE_LOCATION (decl),
2224 PARM_DECL, get_identifier (".omp_data_o"),
2225 ptr_type_node);
2226 DECL_ARTIFICIAL (t) = 1;
2227 DECL_NAMELESS (t) = 1;
2228 DECL_ARG_TYPE (t) = ptr_type_node;
2229 DECL_CONTEXT (t) = current_function_decl;
2230 TREE_USED (t) = 1;
2231 TREE_ADDRESSABLE (t) = 1;
2232 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2233 DECL_ARGUMENTS (decl) = t;
2236 /* Allocate memory for the function structure. The call to
2237 allocate_struct_function clobbers CFUN, so we need to restore
2238 it afterward. */
2239 push_struct_function (decl);
2240 cfun->function_end_locus = gimple_location (ctx->stmt);
2241 pop_cfun ();
2244 /* Callback for walk_gimple_seq. Check if combined parallel
2245 contains gimple_omp_for_combined_into_p OMP_FOR. */
2247 static tree
2248 find_combined_for (gimple_stmt_iterator *gsi_p,
2249 bool *handled_ops_p,
2250 struct walk_stmt_info *wi)
2252 gimple stmt = gsi_stmt (*gsi_p);
2254 *handled_ops_p = true;
2255 switch (gimple_code (stmt))
2257 WALK_SUBSTMTS;
2259 case GIMPLE_OMP_FOR:
2260 if (gimple_omp_for_combined_into_p (stmt)
2261 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2263 wi->info = stmt;
2264 return integer_zero_node;
2266 break;
2267 default:
2268 break;
2270 return NULL;
2273 /* Scan an OpenMP parallel directive. */
2275 static void
2276 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2278 omp_context *ctx;
2279 tree name;
2280 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2282 /* Ignore parallel directives with empty bodies, unless there
2283 are copyin clauses. */
2284 if (optimize > 0
2285 && empty_body_p (gimple_omp_body (stmt))
2286 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2287 OMP_CLAUSE_COPYIN) == NULL)
2289 gsi_replace (gsi, gimple_build_nop (), false);
2290 return;
2293 if (gimple_omp_parallel_combined_p (stmt))
2295 struct walk_stmt_info wi;
2297 memset (&wi, 0, sizeof (wi));
2298 wi.val_only = true;
2299 walk_gimple_seq (gimple_omp_body (stmt),
2300 find_combined_for, NULL, &wi);
2301 if (wi.info)
2303 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2304 struct omp_for_data fd;
2305 extract_omp_for_data (for_stmt, &fd, NULL);
2306 /* We need two temporaries with fd.loop.v type (istart/iend)
2307 and then (fd.collapse - 1) temporaries with the same
2308 type for count2 ... countN-1 vars if not constant. */
2309 size_t count = 2, i;
2310 tree type = fd.iter_type;
2311 if (fd.collapse > 1
2312 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2313 count += fd.collapse - 1;
2314 for (i = 0; i < count; i++)
2316 tree temp = create_tmp_var (type);
2317 tree c = build_omp_clause (UNKNOWN_LOCATION,
2318 OMP_CLAUSE__LOOPTEMP_);
2319 insert_decl_map (&outer_ctx->cb, temp, temp);
2320 OMP_CLAUSE_DECL (c) = temp;
2321 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2322 gimple_omp_parallel_set_clauses (stmt, c);
2327 ctx = new_omp_context (stmt, outer_ctx);
2328 taskreg_contexts.safe_push (ctx);
2329 if (taskreg_nesting_level > 1)
2330 ctx->is_nested = true;
2331 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2332 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2333 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2334 name = create_tmp_var_name (".omp_data_s");
2335 name = build_decl (gimple_location (stmt),
2336 TYPE_DECL, name, ctx->record_type);
2337 DECL_ARTIFICIAL (name) = 1;
2338 DECL_NAMELESS (name) = 1;
2339 TYPE_NAME (ctx->record_type) = name;
2340 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2341 create_omp_child_function (ctx, false);
2342 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2344 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2345 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2347 if (TYPE_FIELDS (ctx->record_type) == NULL)
2348 ctx->record_type = ctx->receiver_decl = NULL;
2351 /* Scan an OpenMP task directive. */
2353 static void
2354 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2356 omp_context *ctx;
2357 tree name, t;
2358 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2360 /* Ignore task directives with empty bodies. */
2361 if (optimize > 0
2362 && empty_body_p (gimple_omp_body (stmt)))
2364 gsi_replace (gsi, gimple_build_nop (), false);
2365 return;
2368 ctx = new_omp_context (stmt, outer_ctx);
2369 taskreg_contexts.safe_push (ctx);
2370 if (taskreg_nesting_level > 1)
2371 ctx->is_nested = true;
2372 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2373 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2374 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2375 name = create_tmp_var_name (".omp_data_s");
2376 name = build_decl (gimple_location (stmt),
2377 TYPE_DECL, name, ctx->record_type);
2378 DECL_ARTIFICIAL (name) = 1;
2379 DECL_NAMELESS (name) = 1;
2380 TYPE_NAME (ctx->record_type) = name;
2381 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2382 create_omp_child_function (ctx, false);
2383 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2385 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2387 if (ctx->srecord_type)
2389 name = create_tmp_var_name (".omp_data_a");
2390 name = build_decl (gimple_location (stmt),
2391 TYPE_DECL, name, ctx->srecord_type);
2392 DECL_ARTIFICIAL (name) = 1;
2393 DECL_NAMELESS (name) = 1;
2394 TYPE_NAME (ctx->srecord_type) = name;
2395 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2396 create_omp_child_function (ctx, true);
2399 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2401 if (TYPE_FIELDS (ctx->record_type) == NULL)
2403 ctx->record_type = ctx->receiver_decl = NULL;
2404 t = build_int_cst (long_integer_type_node, 0);
2405 gimple_omp_task_set_arg_size (stmt, t);
2406 t = build_int_cst (long_integer_type_node, 1);
2407 gimple_omp_task_set_arg_align (stmt, t);
2412 /* If any decls have been made addressable during scan_omp,
2413 adjust their fields if needed, and layout record types
2414 of parallel/task constructs. */
2416 static void
2417 finish_taskreg_scan (omp_context *ctx)
2419 if (ctx->record_type == NULL_TREE)
2420 return;
2422 /* If any task_shared_vars were needed, verify all
2423 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2424 statements if use_pointer_for_field hasn't changed
2425 because of that. If it did, update field types now. */
2426 if (task_shared_vars)
2428 tree c;
2430 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2431 c; c = OMP_CLAUSE_CHAIN (c))
2432 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2434 tree decl = OMP_CLAUSE_DECL (c);
2436 /* Global variables don't need to be copied,
2437 the receiver side will use them directly. */
2438 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2439 continue;
2440 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2441 || !use_pointer_for_field (decl, ctx))
2442 continue;
2443 tree field = lookup_field (decl, ctx);
2444 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2445 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2446 continue;
2447 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2448 TREE_THIS_VOLATILE (field) = 0;
2449 DECL_USER_ALIGN (field) = 0;
2450 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2451 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2452 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2453 if (ctx->srecord_type)
2455 tree sfield = lookup_sfield (decl, ctx);
2456 TREE_TYPE (sfield) = TREE_TYPE (field);
2457 TREE_THIS_VOLATILE (sfield) = 0;
2458 DECL_USER_ALIGN (sfield) = 0;
2459 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2460 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2461 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2466 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2468 layout_type (ctx->record_type);
2469 fixup_child_record_type (ctx);
2471 else
2473 location_t loc = gimple_location (ctx->stmt);
2474 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2475 /* Move VLA fields to the end. */
2476 p = &TYPE_FIELDS (ctx->record_type);
2477 while (*p)
2478 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2479 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2481 *q = *p;
2482 *p = TREE_CHAIN (*p);
2483 TREE_CHAIN (*q) = NULL_TREE;
2484 q = &TREE_CHAIN (*q);
2486 else
2487 p = &DECL_CHAIN (*p);
2488 *p = vla_fields;
2489 layout_type (ctx->record_type);
2490 fixup_child_record_type (ctx);
2491 if (ctx->srecord_type)
2492 layout_type (ctx->srecord_type);
2493 tree t = fold_convert_loc (loc, long_integer_type_node,
2494 TYPE_SIZE_UNIT (ctx->record_type));
2495 gimple_omp_task_set_arg_size (ctx->stmt, t);
2496 t = build_int_cst (long_integer_type_node,
2497 TYPE_ALIGN_UNIT (ctx->record_type));
2498 gimple_omp_task_set_arg_align (ctx->stmt, t);
2503 static omp_context *
2504 enclosing_target_ctx (omp_context *ctx)
2506 while (ctx != NULL
2507 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2508 ctx = ctx->outer;
2509 gcc_assert (ctx != NULL);
2510 return ctx;
2513 static bool
2514 oacc_loop_or_target_p (gimple stmt)
2516 enum gimple_code outer_type = gimple_code (stmt);
2517 return ((outer_type == GIMPLE_OMP_TARGET
2518 && ((gimple_omp_target_kind (stmt)
2519 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2520 || (gimple_omp_target_kind (stmt)
2521 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2522 || (outer_type == GIMPLE_OMP_FOR
2523 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2526 /* Scan a GIMPLE_OMP_FOR. */
2528 static void
2529 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2531 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
2532 omp_context *ctx;
2533 size_t i;
2534 tree clauses = gimple_omp_for_clauses (stmt);
2536 if (outer_ctx)
2537 outer_type = gimple_code (outer_ctx->stmt);
2539 ctx = new_omp_context (stmt, outer_ctx);
2541 if (is_gimple_omp_oacc (stmt))
2543 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2544 ctx->gwv_this = outer_ctx->gwv_this;
2545 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2547 int val;
2548 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2549 val = MASK_GANG;
2550 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2551 val = MASK_WORKER;
2552 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2553 val = MASK_VECTOR;
2554 else
2555 continue;
2556 ctx->gwv_this |= val;
2557 if (!outer_ctx)
2559 /* Skip; not nested inside a region. */
2560 continue;
2562 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2564 /* Skip; not nested inside an OpenACC region. */
2565 continue;
2567 if (outer_type == GIMPLE_OMP_FOR)
2568 outer_ctx->gwv_below |= val;
2569 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2571 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2572 if (gimple_omp_target_kind (enclosing->stmt)
2573 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2574 error_at (gimple_location (stmt),
2575 "no arguments allowed to gang, worker and vector clauses inside parallel");
2580 scan_sharing_clauses (clauses, ctx);
2582 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2583 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2585 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2586 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2587 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2588 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2590 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2592 if (is_gimple_omp_oacc (stmt))
2594 if (ctx->gwv_this & ctx->gwv_below)
2595 error_at (gimple_location (stmt),
2596 "gang, worker and vector may occur only once in a loop nest");
2597 else if (ctx->gwv_below != 0
2598 && ctx->gwv_this > ctx->gwv_below)
2599 error_at (gimple_location (stmt),
2600 "gang, worker and vector must occur in this order in a loop nest");
2601 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2602 outer_ctx->gwv_below |= ctx->gwv_below;
2606 /* Scan an OpenMP sections directive. */
2608 static void
2609 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2611 omp_context *ctx;
2613 ctx = new_omp_context (stmt, outer_ctx);
2614 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2615 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2618 /* Scan an OpenMP single directive. */
2620 static void
2621 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2623 omp_context *ctx;
2624 tree name;
2626 ctx = new_omp_context (stmt, outer_ctx);
2627 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2628 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2629 name = create_tmp_var_name (".omp_copy_s");
2630 name = build_decl (gimple_location (stmt),
2631 TYPE_DECL, name, ctx->record_type);
2632 TYPE_NAME (ctx->record_type) = name;
2634 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2635 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2637 if (TYPE_FIELDS (ctx->record_type) == NULL)
2638 ctx->record_type = NULL;
2639 else
2640 layout_type (ctx->record_type);
2643 /* Scan a GIMPLE_OMP_TARGET. */
2645 static void
2646 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2648 omp_context *ctx;
2649 tree name;
2650 bool offloaded = is_gimple_omp_offloaded (stmt);
2651 tree clauses = gimple_omp_target_clauses (stmt);
2653 ctx = new_omp_context (stmt, outer_ctx);
2654 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2655 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2656 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2657 name = create_tmp_var_name (".omp_data_t");
2658 name = build_decl (gimple_location (stmt),
2659 TYPE_DECL, name, ctx->record_type);
2660 DECL_ARTIFICIAL (name) = 1;
2661 DECL_NAMELESS (name) = 1;
2662 TYPE_NAME (ctx->record_type) = name;
2663 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2664 if (offloaded)
2666 if (is_gimple_omp_oacc (stmt))
2667 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2668 0, 0);
2670 create_omp_child_function (ctx, false);
2671 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2674 if (is_gimple_omp_oacc (stmt))
2676 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2678 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2679 ctx->gwv_this |= MASK_GANG;
2680 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2681 ctx->gwv_this |= MASK_WORKER;
2682 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2683 ctx->gwv_this |= MASK_VECTOR;
2687 scan_sharing_clauses (clauses, ctx);
2688 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2690 if (TYPE_FIELDS (ctx->record_type) == NULL)
2691 ctx->record_type = ctx->receiver_decl = NULL;
2692 else
2694 TYPE_FIELDS (ctx->record_type)
2695 = nreverse (TYPE_FIELDS (ctx->record_type));
2696 #ifdef ENABLE_CHECKING
2697 tree field;
2698 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2699 for (field = TYPE_FIELDS (ctx->record_type);
2700 field;
2701 field = DECL_CHAIN (field))
2702 gcc_assert (DECL_ALIGN (field) == align);
2703 #endif
2704 layout_type (ctx->record_type);
2705 if (offloaded)
2706 fixup_child_record_type (ctx);
2710 /* Scan an OpenMP teams directive. */
2712 static void
2713 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2715 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2716 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2717 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2720 /* Check nesting restrictions. */
2721 static bool
2722 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2724 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2725 inside an OpenACC CTX. */
2726 if (!(is_gimple_omp (stmt)
2727 && is_gimple_omp_oacc (stmt)))
2729 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2730 if (is_gimple_omp (ctx_->stmt)
2731 && is_gimple_omp_oacc (ctx_->stmt))
2733 error_at (gimple_location (stmt),
2734 "non-OpenACC construct inside of OpenACC region");
2735 return false;
2739 if (ctx != NULL)
2741 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2742 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2744 error_at (gimple_location (stmt),
2745 "OpenMP constructs may not be nested inside simd region");
2746 return false;
2748 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2750 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2751 || (gimple_omp_for_kind (stmt)
2752 != GF_OMP_FOR_KIND_DISTRIBUTE))
2753 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2755 error_at (gimple_location (stmt),
2756 "only distribute or parallel constructs are allowed to "
2757 "be closely nested inside teams construct");
2758 return false;
2762 switch (gimple_code (stmt))
2764 case GIMPLE_OMP_FOR:
2765 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2766 return true;
2767 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2769 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2771 error_at (gimple_location (stmt),
2772 "distribute construct must be closely nested inside "
2773 "teams construct");
2774 return false;
2776 return true;
2778 /* FALLTHRU */
2779 case GIMPLE_CALL:
2780 if (is_gimple_call (stmt)
2781 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2782 == BUILT_IN_GOMP_CANCEL
2783 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2784 == BUILT_IN_GOMP_CANCELLATION_POINT))
2786 const char *bad = NULL;
2787 const char *kind = NULL;
2788 if (ctx == NULL)
2790 error_at (gimple_location (stmt), "orphaned %qs construct",
2791 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2792 == BUILT_IN_GOMP_CANCEL
2793 ? "#pragma omp cancel"
2794 : "#pragma omp cancellation point");
2795 return false;
2797 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2798 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2799 : 0)
2801 case 1:
2802 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2803 bad = "#pragma omp parallel";
2804 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2805 == BUILT_IN_GOMP_CANCEL
2806 && !integer_zerop (gimple_call_arg (stmt, 1)))
2807 ctx->cancellable = true;
2808 kind = "parallel";
2809 break;
2810 case 2:
2811 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2812 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2813 bad = "#pragma omp for";
2814 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2815 == BUILT_IN_GOMP_CANCEL
2816 && !integer_zerop (gimple_call_arg (stmt, 1)))
2818 ctx->cancellable = true;
2819 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2820 OMP_CLAUSE_NOWAIT))
2821 warning_at (gimple_location (stmt), 0,
2822 "%<#pragma omp cancel for%> inside "
2823 "%<nowait%> for construct");
2824 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2825 OMP_CLAUSE_ORDERED))
2826 warning_at (gimple_location (stmt), 0,
2827 "%<#pragma omp cancel for%> inside "
2828 "%<ordered%> for construct");
2830 kind = "for";
2831 break;
2832 case 4:
2833 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2834 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2835 bad = "#pragma omp sections";
2836 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2837 == BUILT_IN_GOMP_CANCEL
2838 && !integer_zerop (gimple_call_arg (stmt, 1)))
2840 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2842 ctx->cancellable = true;
2843 if (find_omp_clause (gimple_omp_sections_clauses
2844 (ctx->stmt),
2845 OMP_CLAUSE_NOWAIT))
2846 warning_at (gimple_location (stmt), 0,
2847 "%<#pragma omp cancel sections%> inside "
2848 "%<nowait%> sections construct");
2850 else
2852 gcc_assert (ctx->outer
2853 && gimple_code (ctx->outer->stmt)
2854 == GIMPLE_OMP_SECTIONS);
2855 ctx->outer->cancellable = true;
2856 if (find_omp_clause (gimple_omp_sections_clauses
2857 (ctx->outer->stmt),
2858 OMP_CLAUSE_NOWAIT))
2859 warning_at (gimple_location (stmt), 0,
2860 "%<#pragma omp cancel sections%> inside "
2861 "%<nowait%> sections construct");
2864 kind = "sections";
2865 break;
2866 case 8:
2867 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2868 bad = "#pragma omp task";
2869 else
2870 ctx->cancellable = true;
2871 kind = "taskgroup";
2872 break;
2873 default:
2874 error_at (gimple_location (stmt), "invalid arguments");
2875 return false;
2877 if (bad)
2879 error_at (gimple_location (stmt),
2880 "%<%s %s%> construct not closely nested inside of %qs",
2881 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2882 == BUILT_IN_GOMP_CANCEL
2883 ? "#pragma omp cancel"
2884 : "#pragma omp cancellation point", kind, bad);
2885 return false;
2888 /* FALLTHRU */
2889 case GIMPLE_OMP_SECTIONS:
2890 case GIMPLE_OMP_SINGLE:
2891 for (; ctx != NULL; ctx = ctx->outer)
2892 switch (gimple_code (ctx->stmt))
2894 case GIMPLE_OMP_FOR:
2895 case GIMPLE_OMP_SECTIONS:
2896 case GIMPLE_OMP_SINGLE:
2897 case GIMPLE_OMP_ORDERED:
2898 case GIMPLE_OMP_MASTER:
2899 case GIMPLE_OMP_TASK:
2900 case GIMPLE_OMP_CRITICAL:
2901 if (is_gimple_call (stmt))
2903 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2904 != BUILT_IN_GOMP_BARRIER)
2905 return true;
2906 error_at (gimple_location (stmt),
2907 "barrier region may not be closely nested inside "
2908 "of work-sharing, critical, ordered, master or "
2909 "explicit task region");
2910 return false;
2912 error_at (gimple_location (stmt),
2913 "work-sharing region may not be closely nested inside "
2914 "of work-sharing, critical, ordered, master or explicit "
2915 "task region");
2916 return false;
2917 case GIMPLE_OMP_PARALLEL:
2918 return true;
2919 default:
2920 break;
2922 break;
2923 case GIMPLE_OMP_MASTER:
2924 for (; ctx != NULL; ctx = ctx->outer)
2925 switch (gimple_code (ctx->stmt))
2927 case GIMPLE_OMP_FOR:
2928 case GIMPLE_OMP_SECTIONS:
2929 case GIMPLE_OMP_SINGLE:
2930 case GIMPLE_OMP_TASK:
2931 error_at (gimple_location (stmt),
2932 "master region may not be closely nested inside "
2933 "of work-sharing or explicit task region");
2934 return false;
2935 case GIMPLE_OMP_PARALLEL:
2936 return true;
2937 default:
2938 break;
2940 break;
2941 case GIMPLE_OMP_ORDERED:
2942 for (; ctx != NULL; ctx = ctx->outer)
2943 switch (gimple_code (ctx->stmt))
2945 case GIMPLE_OMP_CRITICAL:
2946 case GIMPLE_OMP_TASK:
2947 error_at (gimple_location (stmt),
2948 "ordered region may not be closely nested inside "
2949 "of critical or explicit task region");
2950 return false;
2951 case GIMPLE_OMP_FOR:
2952 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2953 OMP_CLAUSE_ORDERED) == NULL)
2955 error_at (gimple_location (stmt),
2956 "ordered region must be closely nested inside "
2957 "a loop region with an ordered clause");
2958 return false;
2960 return true;
2961 case GIMPLE_OMP_PARALLEL:
2962 error_at (gimple_location (stmt),
2963 "ordered region must be closely nested inside "
2964 "a loop region with an ordered clause");
2965 return false;
2966 default:
2967 break;
2969 break;
2970 case GIMPLE_OMP_CRITICAL:
2972 tree this_stmt_name
2973 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2974 for (; ctx != NULL; ctx = ctx->outer)
2975 if (gomp_critical *other_crit
2976 = dyn_cast <gomp_critical *> (ctx->stmt))
2977 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2979 error_at (gimple_location (stmt),
2980 "critical region may not be nested inside a critical "
2981 "region with the same name");
2982 return false;
2985 break;
2986 case GIMPLE_OMP_TEAMS:
2987 if (ctx == NULL
2988 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2989 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2991 error_at (gimple_location (stmt),
2992 "teams construct not closely nested inside of target "
2993 "region");
2994 return false;
2996 break;
2997 case GIMPLE_OMP_TARGET:
2998 for (; ctx != NULL; ctx = ctx->outer)
3000 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3002 if (is_gimple_omp (stmt)
3003 && is_gimple_omp_oacc (stmt)
3004 && is_gimple_omp (ctx->stmt))
3006 error_at (gimple_location (stmt),
3007 "OpenACC construct inside of non-OpenACC region");
3008 return false;
3010 continue;
3013 const char *stmt_name, *ctx_stmt_name;
3014 switch (gimple_omp_target_kind (stmt))
3016 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3017 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3018 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3019 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3020 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3021 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3022 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3023 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3024 default: gcc_unreachable ();
3026 switch (gimple_omp_target_kind (ctx->stmt))
3028 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3029 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3030 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3031 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3032 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3033 default: gcc_unreachable ();
3036 /* OpenACC/OpenMP mismatch? */
3037 if (is_gimple_omp_oacc (stmt)
3038 != is_gimple_omp_oacc (ctx->stmt))
3040 error_at (gimple_location (stmt),
3041 "%s %s construct inside of %s %s region",
3042 (is_gimple_omp_oacc (stmt)
3043 ? "OpenACC" : "OpenMP"), stmt_name,
3044 (is_gimple_omp_oacc (ctx->stmt)
3045 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3046 return false;
3048 if (is_gimple_omp_offloaded (ctx->stmt))
3050 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3051 if (is_gimple_omp_oacc (ctx->stmt))
3053 error_at (gimple_location (stmt),
3054 "%s construct inside of %s region",
3055 stmt_name, ctx_stmt_name);
3056 return false;
3058 else
3060 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3061 warning_at (gimple_location (stmt), 0,
3062 "%s construct inside of %s region",
3063 stmt_name, ctx_stmt_name);
3067 break;
3068 default:
3069 break;
3071 return true;
3075 /* Helper function scan_omp.
3077 Callback for walk_tree or operators in walk_gimple_stmt used to
3078 scan for OMP directives in TP. */
3080 static tree
3081 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3083 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3084 omp_context *ctx = (omp_context *) wi->info;
3085 tree t = *tp;
3087 switch (TREE_CODE (t))
3089 case VAR_DECL:
3090 case PARM_DECL:
3091 case LABEL_DECL:
3092 case RESULT_DECL:
3093 if (ctx)
3094 *tp = remap_decl (t, &ctx->cb);
3095 break;
3097 default:
3098 if (ctx && TYPE_P (t))
3099 *tp = remap_type (t, &ctx->cb);
3100 else if (!DECL_P (t))
3102 *walk_subtrees = 1;
3103 if (ctx)
3105 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3106 if (tem != TREE_TYPE (t))
3108 if (TREE_CODE (t) == INTEGER_CST)
3109 *tp = wide_int_to_tree (tem, t);
3110 else
3111 TREE_TYPE (t) = tem;
3115 break;
3118 return NULL_TREE;
3121 /* Return true if FNDECL is a setjmp or a longjmp. */
3123 static bool
3124 setjmp_or_longjmp_p (const_tree fndecl)
3126 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3127 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3128 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3129 return true;
3131 tree declname = DECL_NAME (fndecl);
3132 if (!declname)
3133 return false;
3134 const char *name = IDENTIFIER_POINTER (declname);
3135 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3139 /* Helper function for scan_omp.
3141 Callback for walk_gimple_stmt used to scan for OMP directives in
3142 the current statement in GSI. */
3144 static tree
3145 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3146 struct walk_stmt_info *wi)
3148 gimple stmt = gsi_stmt (*gsi);
3149 omp_context *ctx = (omp_context *) wi->info;
3151 if (gimple_has_location (stmt))
3152 input_location = gimple_location (stmt);
3154 /* Check the nesting restrictions. */
3155 bool remove = false;
3156 if (is_gimple_omp (stmt))
3157 remove = !check_omp_nesting_restrictions (stmt, ctx);
3158 else if (is_gimple_call (stmt))
3160 tree fndecl = gimple_call_fndecl (stmt);
3161 if (fndecl)
3163 if (setjmp_or_longjmp_p (fndecl)
3164 && ctx
3165 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3166 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3168 remove = true;
3169 error_at (gimple_location (stmt),
3170 "setjmp/longjmp inside simd construct");
3172 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3173 switch (DECL_FUNCTION_CODE (fndecl))
3175 case BUILT_IN_GOMP_BARRIER:
3176 case BUILT_IN_GOMP_CANCEL:
3177 case BUILT_IN_GOMP_CANCELLATION_POINT:
3178 case BUILT_IN_GOMP_TASKYIELD:
3179 case BUILT_IN_GOMP_TASKWAIT:
3180 case BUILT_IN_GOMP_TASKGROUP_START:
3181 case BUILT_IN_GOMP_TASKGROUP_END:
3182 remove = !check_omp_nesting_restrictions (stmt, ctx);
3183 break;
3184 default:
3185 break;
3189 if (remove)
3191 stmt = gimple_build_nop ();
3192 gsi_replace (gsi, stmt, false);
3195 *handled_ops_p = true;
3197 switch (gimple_code (stmt))
3199 case GIMPLE_OMP_PARALLEL:
3200 taskreg_nesting_level++;
3201 scan_omp_parallel (gsi, ctx);
3202 taskreg_nesting_level--;
3203 break;
3205 case GIMPLE_OMP_TASK:
3206 taskreg_nesting_level++;
3207 scan_omp_task (gsi, ctx);
3208 taskreg_nesting_level--;
3209 break;
3211 case GIMPLE_OMP_FOR:
3212 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3213 break;
3215 case GIMPLE_OMP_SECTIONS:
3216 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3217 break;
3219 case GIMPLE_OMP_SINGLE:
3220 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3221 break;
3223 case GIMPLE_OMP_SECTION:
3224 case GIMPLE_OMP_MASTER:
3225 case GIMPLE_OMP_TASKGROUP:
3226 case GIMPLE_OMP_ORDERED:
3227 case GIMPLE_OMP_CRITICAL:
3228 ctx = new_omp_context (stmt, ctx);
3229 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3230 break;
3232 case GIMPLE_OMP_TARGET:
3233 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3234 break;
3236 case GIMPLE_OMP_TEAMS:
3237 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3238 break;
3240 case GIMPLE_BIND:
3242 tree var;
3244 *handled_ops_p = false;
3245 if (ctx)
3246 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3247 var ;
3248 var = DECL_CHAIN (var))
3249 insert_decl_map (&ctx->cb, var, var);
3251 break;
3252 default:
3253 *handled_ops_p = false;
3254 break;
3257 return NULL_TREE;
3261 /* Scan all the statements starting at the current statement. CTX
3262 contains context information about the OMP directives and
3263 clauses found during the scan. */
3265 static void
3266 scan_omp (gimple_seq *body_p, omp_context *ctx)
3268 location_t saved_location;
3269 struct walk_stmt_info wi;
3271 memset (&wi, 0, sizeof (wi));
3272 wi.info = ctx;
3273 wi.want_locations = true;
3275 saved_location = input_location;
3276 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3277 input_location = saved_location;
3280 /* Re-gimplification and code generation routines. */
3282 /* Build a call to GOMP_barrier. */
3284 static gimple
3285 build_omp_barrier (tree lhs)
3287 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3288 : BUILT_IN_GOMP_BARRIER);
3289 gcall *g = gimple_build_call (fndecl, 0);
3290 if (lhs)
3291 gimple_call_set_lhs (g, lhs);
3292 return g;
3295 /* If a context was created for STMT when it was scanned, return it. */
3297 static omp_context *
3298 maybe_lookup_ctx (gimple stmt)
3300 splay_tree_node n;
3301 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3302 return n ? (omp_context *) n->value : NULL;
3306 /* Find the mapping for DECL in CTX or the immediately enclosing
3307 context that has a mapping for DECL.
3309 If CTX is a nested parallel directive, we may have to use the decl
3310 mappings created in CTX's parent context. Suppose that we have the
3311 following parallel nesting (variable UIDs showed for clarity):
3313 iD.1562 = 0;
3314 #omp parallel shared(iD.1562) -> outer parallel
3315 iD.1562 = iD.1562 + 1;
3317 #omp parallel shared (iD.1562) -> inner parallel
3318 iD.1562 = iD.1562 - 1;
3320 Each parallel structure will create a distinct .omp_data_s structure
3321 for copying iD.1562 in/out of the directive:
3323 outer parallel .omp_data_s.1.i -> iD.1562
3324 inner parallel .omp_data_s.2.i -> iD.1562
3326 A shared variable mapping will produce a copy-out operation before
3327 the parallel directive and a copy-in operation after it. So, in
3328 this case we would have:
3330 iD.1562 = 0;
3331 .omp_data_o.1.i = iD.1562;
3332 #omp parallel shared(iD.1562) -> outer parallel
3333 .omp_data_i.1 = &.omp_data_o.1
3334 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3336 .omp_data_o.2.i = iD.1562; -> **
3337 #omp parallel shared(iD.1562) -> inner parallel
3338 .omp_data_i.2 = &.omp_data_o.2
3339 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3342 ** This is a problem. The symbol iD.1562 cannot be referenced
3343 inside the body of the outer parallel region. But since we are
3344 emitting this copy operation while expanding the inner parallel
3345 directive, we need to access the CTX structure of the outer
3346 parallel directive to get the correct mapping:
3348 .omp_data_o.2.i = .omp_data_i.1->i
3350 Since there may be other workshare or parallel directives enclosing
3351 the parallel directive, it may be necessary to walk up the context
3352 parent chain. This is not a problem in general because nested
3353 parallelism happens only rarely. */
3355 static tree
3356 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3358 tree t;
3359 omp_context *up;
3361 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3362 t = maybe_lookup_decl (decl, up);
3364 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3366 return t ? t : decl;
3370 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3371 in outer contexts. */
3373 static tree
3374 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3376 tree t = NULL;
3377 omp_context *up;
3379 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3380 t = maybe_lookup_decl (decl, up);
3382 return t ? t : decl;
3386 /* Construct the initialization value for reduction CLAUSE. */
3388 tree
3389 omp_reduction_init (tree clause, tree type)
3391 location_t loc = OMP_CLAUSE_LOCATION (clause);
3392 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3394 case PLUS_EXPR:
3395 case MINUS_EXPR:
3396 case BIT_IOR_EXPR:
3397 case BIT_XOR_EXPR:
3398 case TRUTH_OR_EXPR:
3399 case TRUTH_ORIF_EXPR:
3400 case TRUTH_XOR_EXPR:
3401 case NE_EXPR:
3402 return build_zero_cst (type);
3404 case MULT_EXPR:
3405 case TRUTH_AND_EXPR:
3406 case TRUTH_ANDIF_EXPR:
3407 case EQ_EXPR:
3408 return fold_convert_loc (loc, type, integer_one_node);
3410 case BIT_AND_EXPR:
3411 return fold_convert_loc (loc, type, integer_minus_one_node);
3413 case MAX_EXPR:
3414 if (SCALAR_FLOAT_TYPE_P (type))
3416 REAL_VALUE_TYPE max, min;
3417 if (HONOR_INFINITIES (type))
3419 real_inf (&max);
3420 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3422 else
3423 real_maxval (&min, 1, TYPE_MODE (type));
3424 return build_real (type, min);
3426 else
3428 gcc_assert (INTEGRAL_TYPE_P (type));
3429 return TYPE_MIN_VALUE (type);
3432 case MIN_EXPR:
3433 if (SCALAR_FLOAT_TYPE_P (type))
3435 REAL_VALUE_TYPE max;
3436 if (HONOR_INFINITIES (type))
3437 real_inf (&max);
3438 else
3439 real_maxval (&max, 0, TYPE_MODE (type));
3440 return build_real (type, max);
3442 else
3444 gcc_assert (INTEGRAL_TYPE_P (type));
3445 return TYPE_MAX_VALUE (type);
3448 default:
3449 gcc_unreachable ();
3453 /* Return alignment to be assumed for var in CLAUSE, which should be
3454 OMP_CLAUSE_ALIGNED. */
3456 static tree
3457 omp_clause_aligned_alignment (tree clause)
3459 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3460 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3462 /* Otherwise return implementation defined alignment. */
3463 unsigned int al = 1;
3464 machine_mode mode, vmode;
3465 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3466 if (vs)
3467 vs = 1 << floor_log2 (vs);
3468 static enum mode_class classes[]
3469 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3470 for (int i = 0; i < 4; i += 2)
3471 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3472 mode != VOIDmode;
3473 mode = GET_MODE_WIDER_MODE (mode))
3475 vmode = targetm.vectorize.preferred_simd_mode (mode);
3476 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3477 continue;
3478 while (vs
3479 && GET_MODE_SIZE (vmode) < vs
3480 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3481 vmode = GET_MODE_2XWIDER_MODE (vmode);
3483 tree type = lang_hooks.types.type_for_mode (mode, 1);
3484 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3485 continue;
3486 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3487 / GET_MODE_SIZE (mode));
3488 if (TYPE_MODE (type) != vmode)
3489 continue;
3490 if (TYPE_ALIGN_UNIT (type) > al)
3491 al = TYPE_ALIGN_UNIT (type);
3493 return build_int_cst (integer_type_node, al);
3496 /* Return maximum possible vectorization factor for the target. */
3498 static int
3499 omp_max_vf (void)
3501 if (!optimize
3502 || optimize_debug
3503 || !flag_tree_loop_optimize
3504 || (!flag_tree_loop_vectorize
3505 && (global_options_set.x_flag_tree_loop_vectorize
3506 || global_options_set.x_flag_tree_vectorize)))
3507 return 1;
3509 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3510 if (vs)
3512 vs = 1 << floor_log2 (vs);
3513 return vs;
3515 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3516 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3517 return GET_MODE_NUNITS (vqimode);
3518 return 1;
3521 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3522 privatization. */
3524 static bool
3525 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3526 tree &idx, tree &lane, tree &ivar, tree &lvar)
3528 if (max_vf == 0)
3530 max_vf = omp_max_vf ();
3531 if (max_vf > 1)
3533 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3534 OMP_CLAUSE_SAFELEN);
3535 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3536 max_vf = 1;
3537 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3538 max_vf) == -1)
3539 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3541 if (max_vf > 1)
3543 idx = create_tmp_var (unsigned_type_node);
3544 lane = create_tmp_var (unsigned_type_node);
3547 if (max_vf == 1)
3548 return false;
3550 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3551 tree avar = create_tmp_var_raw (atype);
3552 if (TREE_ADDRESSABLE (new_var))
3553 TREE_ADDRESSABLE (avar) = 1;
3554 DECL_ATTRIBUTES (avar)
3555 = tree_cons (get_identifier ("omp simd array"), NULL,
3556 DECL_ATTRIBUTES (avar));
3557 gimple_add_tmp_var (avar);
3558 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3559 NULL_TREE, NULL_TREE);
3560 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3561 NULL_TREE, NULL_TREE);
3562 if (DECL_P (new_var))
3564 SET_DECL_VALUE_EXPR (new_var, lvar);
3565 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3567 return true;
3570 /* Helper function of lower_rec_input_clauses. For a reference
3571 in simd reduction, add an underlying variable it will reference. */
3573 static void
3574 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3576 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3577 if (TREE_CONSTANT (z))
3579 const char *name = NULL;
3580 if (DECL_NAME (new_vard))
3581 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3583 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3584 gimple_add_tmp_var (z);
3585 TREE_ADDRESSABLE (z) = 1;
3586 z = build_fold_addr_expr_loc (loc, z);
3587 gimplify_assign (new_vard, z, ilist);
3591 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3592 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3593 private variables. Initialization statements go in ILIST, while calls
3594 to destructors go in DLIST. */
3596 static void
3597 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3598 omp_context *ctx, struct omp_for_data *fd)
3600 tree c, dtor, copyin_seq, x, ptr;
3601 bool copyin_by_ref = false;
3602 bool lastprivate_firstprivate = false;
3603 bool reduction_omp_orig_ref = false;
3604 int pass;
3605 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3606 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3607 int max_vf = 0;
3608 tree lane = NULL_TREE, idx = NULL_TREE;
3609 tree ivar = NULL_TREE, lvar = NULL_TREE;
3610 gimple_seq llist[2] = { NULL, NULL };
3612 copyin_seq = NULL;
3614 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3615 with data sharing clauses referencing variable sized vars. That
3616 is unnecessarily hard to support and very unlikely to result in
3617 vectorized code anyway. */
3618 if (is_simd)
3619 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3620 switch (OMP_CLAUSE_CODE (c))
3622 case OMP_CLAUSE_LINEAR:
3623 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3624 max_vf = 1;
3625 /* FALLTHRU */
3626 case OMP_CLAUSE_REDUCTION:
3627 case OMP_CLAUSE_PRIVATE:
3628 case OMP_CLAUSE_FIRSTPRIVATE:
3629 case OMP_CLAUSE_LASTPRIVATE:
3630 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3631 max_vf = 1;
3632 break;
3633 default:
3634 continue;
3637 /* Do all the fixed sized types in the first pass, and the variable sized
3638 types in the second pass. This makes sure that the scalar arguments to
3639 the variable sized types are processed before we use them in the
3640 variable sized operations. */
3641 for (pass = 0; pass < 2; ++pass)
3643 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3645 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3646 tree var, new_var;
3647 bool by_ref;
3648 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3650 switch (c_kind)
3652 case OMP_CLAUSE_PRIVATE:
3653 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3654 continue;
3655 break;
3656 case OMP_CLAUSE_SHARED:
3657 /* Ignore shared directives in teams construct. */
3658 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3659 continue;
3660 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3662 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3663 continue;
3665 case OMP_CLAUSE_FIRSTPRIVATE:
3666 case OMP_CLAUSE_COPYIN:
3667 case OMP_CLAUSE_LINEAR:
3668 break;
3669 case OMP_CLAUSE_REDUCTION:
3670 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3671 reduction_omp_orig_ref = true;
3672 break;
3673 case OMP_CLAUSE__LOOPTEMP_:
3674 /* Handle _looptemp_ clauses only on parallel. */
3675 if (fd)
3676 continue;
3677 break;
3678 case OMP_CLAUSE_LASTPRIVATE:
3679 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3681 lastprivate_firstprivate = true;
3682 if (pass != 0)
3683 continue;
3685 /* Even without corresponding firstprivate, if
3686 decl is Fortran allocatable, it needs outer var
3687 reference. */
3688 else if (pass == 0
3689 && lang_hooks.decls.omp_private_outer_ref
3690 (OMP_CLAUSE_DECL (c)))
3691 lastprivate_firstprivate = true;
3692 break;
3693 case OMP_CLAUSE_ALIGNED:
3694 if (pass == 0)
3695 continue;
3696 var = OMP_CLAUSE_DECL (c);
3697 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3698 && !is_global_var (var))
3700 new_var = maybe_lookup_decl (var, ctx);
3701 if (new_var == NULL_TREE)
3702 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3703 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3704 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3705 omp_clause_aligned_alignment (c));
3706 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3707 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3708 gimplify_and_add (x, ilist);
3710 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3711 && is_global_var (var))
3713 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3714 new_var = lookup_decl (var, ctx);
3715 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3716 t = build_fold_addr_expr_loc (clause_loc, t);
3717 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3718 t = build_call_expr_loc (clause_loc, t2, 2, t,
3719 omp_clause_aligned_alignment (c));
3720 t = fold_convert_loc (clause_loc, ptype, t);
3721 x = create_tmp_var (ptype);
3722 t = build2 (MODIFY_EXPR, ptype, x, t);
3723 gimplify_and_add (t, ilist);
3724 t = build_simple_mem_ref_loc (clause_loc, x);
3725 SET_DECL_VALUE_EXPR (new_var, t);
3726 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3728 continue;
3729 default:
3730 continue;
3733 new_var = var = OMP_CLAUSE_DECL (c);
3734 if (c_kind != OMP_CLAUSE_COPYIN)
3735 new_var = lookup_decl (var, ctx);
3737 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3739 if (pass != 0)
3740 continue;
3742 else if (is_variable_sized (var))
3744 /* For variable sized types, we need to allocate the
3745 actual storage here. Call alloca and store the
3746 result in the pointer decl that we created elsewhere. */
3747 if (pass == 0)
3748 continue;
3750 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3752 gcall *stmt;
3753 tree tmp, atmp;
3755 ptr = DECL_VALUE_EXPR (new_var);
3756 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3757 ptr = TREE_OPERAND (ptr, 0);
3758 gcc_assert (DECL_P (ptr));
3759 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3761 /* void *tmp = __builtin_alloca */
3762 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3763 stmt = gimple_build_call (atmp, 1, x);
3764 tmp = create_tmp_var_raw (ptr_type_node);
3765 gimple_add_tmp_var (tmp);
3766 gimple_call_set_lhs (stmt, tmp);
3768 gimple_seq_add_stmt (ilist, stmt);
3770 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3771 gimplify_assign (ptr, x, ilist);
3774 else if (is_reference (var))
3776 /* For references that are being privatized for Fortran,
3777 allocate new backing storage for the new pointer
3778 variable. This allows us to avoid changing all the
3779 code that expects a pointer to something that expects
3780 a direct variable. */
3781 if (pass == 0)
3782 continue;
3784 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3785 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3787 x = build_receiver_ref (var, false, ctx);
3788 x = build_fold_addr_expr_loc (clause_loc, x);
3790 else if (TREE_CONSTANT (x))
3792 /* For reduction in SIMD loop, defer adding the
3793 initialization of the reference, because if we decide
3794 to use SIMD array for it, the initilization could cause
3795 expansion ICE. */
3796 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3797 x = NULL_TREE;
3798 else
3800 const char *name = NULL;
3801 if (DECL_NAME (var))
3802 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3804 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3805 name);
3806 gimple_add_tmp_var (x);
3807 TREE_ADDRESSABLE (x) = 1;
3808 x = build_fold_addr_expr_loc (clause_loc, x);
3811 else
3813 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3814 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3817 if (x)
3819 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3820 gimplify_assign (new_var, x, ilist);
3823 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3825 else if (c_kind == OMP_CLAUSE_REDUCTION
3826 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3828 if (pass == 0)
3829 continue;
3831 else if (pass != 0)
3832 continue;
3834 switch (OMP_CLAUSE_CODE (c))
3836 case OMP_CLAUSE_SHARED:
3837 /* Ignore shared directives in teams construct. */
3838 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3839 continue;
3840 /* Shared global vars are just accessed directly. */
3841 if (is_global_var (new_var))
3842 break;
3843 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3844 needs to be delayed until after fixup_child_record_type so
3845 that we get the correct type during the dereference. */
3846 by_ref = use_pointer_for_field (var, ctx);
3847 x = build_receiver_ref (var, by_ref, ctx);
3848 SET_DECL_VALUE_EXPR (new_var, x);
3849 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3851 /* ??? If VAR is not passed by reference, and the variable
3852 hasn't been initialized yet, then we'll get a warning for
3853 the store into the omp_data_s structure. Ideally, we'd be
3854 able to notice this and not store anything at all, but
3855 we're generating code too early. Suppress the warning. */
3856 if (!by_ref)
3857 TREE_NO_WARNING (var) = 1;
3858 break;
3860 case OMP_CLAUSE_LASTPRIVATE:
3861 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3862 break;
3863 /* FALLTHRU */
3865 case OMP_CLAUSE_PRIVATE:
3866 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3867 x = build_outer_var_ref (var, ctx);
3868 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3870 if (is_task_ctx (ctx))
3871 x = build_receiver_ref (var, false, ctx);
3872 else
3873 x = build_outer_var_ref (var, ctx);
3875 else
3876 x = NULL;
3877 do_private:
3878 tree nx;
3879 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3880 if (is_simd)
3882 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3883 if ((TREE_ADDRESSABLE (new_var) || nx || y
3884 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3885 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3886 idx, lane, ivar, lvar))
3888 if (nx)
3889 x = lang_hooks.decls.omp_clause_default_ctor
3890 (c, unshare_expr (ivar), x);
3891 if (nx && x)
3892 gimplify_and_add (x, &llist[0]);
3893 if (y)
3895 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3896 if (y)
3898 gimple_seq tseq = NULL;
3900 dtor = y;
3901 gimplify_stmt (&dtor, &tseq);
3902 gimple_seq_add_seq (&llist[1], tseq);
3905 break;
3908 if (nx)
3909 gimplify_and_add (nx, ilist);
3910 /* FALLTHRU */
3912 do_dtor:
3913 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3914 if (x)
3916 gimple_seq tseq = NULL;
3918 dtor = x;
3919 gimplify_stmt (&dtor, &tseq);
3920 gimple_seq_add_seq (dlist, tseq);
3922 break;
3924 case OMP_CLAUSE_LINEAR:
3925 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3926 goto do_firstprivate;
3927 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3928 x = NULL;
3929 else
3930 x = build_outer_var_ref (var, ctx);
3931 goto do_private;
3933 case OMP_CLAUSE_FIRSTPRIVATE:
3934 if (is_task_ctx (ctx))
3936 if (is_reference (var) || is_variable_sized (var))
3937 goto do_dtor;
3938 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3939 ctx))
3940 || use_pointer_for_field (var, NULL))
3942 x = build_receiver_ref (var, false, ctx);
3943 SET_DECL_VALUE_EXPR (new_var, x);
3944 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3945 goto do_dtor;
3948 do_firstprivate:
3949 x = build_outer_var_ref (var, ctx);
3950 if (is_simd)
3952 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3953 && gimple_omp_for_combined_into_p (ctx->stmt))
3955 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3956 tree stept = TREE_TYPE (t);
3957 tree ct = find_omp_clause (clauses,
3958 OMP_CLAUSE__LOOPTEMP_);
3959 gcc_assert (ct);
3960 tree l = OMP_CLAUSE_DECL (ct);
3961 tree n1 = fd->loop.n1;
3962 tree step = fd->loop.step;
3963 tree itype = TREE_TYPE (l);
3964 if (POINTER_TYPE_P (itype))
3965 itype = signed_type_for (itype);
3966 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3967 if (TYPE_UNSIGNED (itype)
3968 && fd->loop.cond_code == GT_EXPR)
3969 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3970 fold_build1 (NEGATE_EXPR, itype, l),
3971 fold_build1 (NEGATE_EXPR,
3972 itype, step));
3973 else
3974 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3975 t = fold_build2 (MULT_EXPR, stept,
3976 fold_convert (stept, l), t);
3978 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3980 x = lang_hooks.decls.omp_clause_linear_ctor
3981 (c, new_var, x, t);
3982 gimplify_and_add (x, ilist);
3983 goto do_dtor;
3986 if (POINTER_TYPE_P (TREE_TYPE (x)))
3987 x = fold_build2 (POINTER_PLUS_EXPR,
3988 TREE_TYPE (x), x, t);
3989 else
3990 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3993 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3994 || TREE_ADDRESSABLE (new_var))
3995 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3996 idx, lane, ivar, lvar))
3998 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4000 tree iv = create_tmp_var (TREE_TYPE (new_var));
4001 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4002 gimplify_and_add (x, ilist);
4003 gimple_stmt_iterator gsi
4004 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4005 gassign *g
4006 = gimple_build_assign (unshare_expr (lvar), iv);
4007 gsi_insert_before_without_update (&gsi, g,
4008 GSI_SAME_STMT);
4009 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4010 enum tree_code code = PLUS_EXPR;
4011 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4012 code = POINTER_PLUS_EXPR;
4013 g = gimple_build_assign (iv, code, iv, t);
4014 gsi_insert_before_without_update (&gsi, g,
4015 GSI_SAME_STMT);
4016 break;
4018 x = lang_hooks.decls.omp_clause_copy_ctor
4019 (c, unshare_expr (ivar), x);
4020 gimplify_and_add (x, &llist[0]);
4021 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4022 if (x)
4024 gimple_seq tseq = NULL;
4026 dtor = x;
4027 gimplify_stmt (&dtor, &tseq);
4028 gimple_seq_add_seq (&llist[1], tseq);
4030 break;
4033 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4034 gimplify_and_add (x, ilist);
4035 goto do_dtor;
4037 case OMP_CLAUSE__LOOPTEMP_:
4038 gcc_assert (is_parallel_ctx (ctx));
4039 x = build_outer_var_ref (var, ctx);
4040 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4041 gimplify_and_add (x, ilist);
4042 break;
4044 case OMP_CLAUSE_COPYIN:
4045 by_ref = use_pointer_for_field (var, NULL);
4046 x = build_receiver_ref (var, by_ref, ctx);
4047 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4048 append_to_statement_list (x, &copyin_seq);
4049 copyin_by_ref |= by_ref;
4050 break;
4052 case OMP_CLAUSE_REDUCTION:
4053 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4055 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4056 gimple tseq;
4057 x = build_outer_var_ref (var, ctx);
4059 if (is_reference (var)
4060 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4061 TREE_TYPE (x)))
4062 x = build_fold_addr_expr_loc (clause_loc, x);
4063 SET_DECL_VALUE_EXPR (placeholder, x);
4064 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4065 tree new_vard = new_var;
4066 if (is_reference (var))
4068 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4069 new_vard = TREE_OPERAND (new_var, 0);
4070 gcc_assert (DECL_P (new_vard));
4072 if (is_simd
4073 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4074 idx, lane, ivar, lvar))
4076 if (new_vard == new_var)
4078 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4079 SET_DECL_VALUE_EXPR (new_var, ivar);
4081 else
4083 SET_DECL_VALUE_EXPR (new_vard,
4084 build_fold_addr_expr (ivar));
4085 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4087 x = lang_hooks.decls.omp_clause_default_ctor
4088 (c, unshare_expr (ivar),
4089 build_outer_var_ref (var, ctx));
4090 if (x)
4091 gimplify_and_add (x, &llist[0]);
4092 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4094 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4095 lower_omp (&tseq, ctx);
4096 gimple_seq_add_seq (&llist[0], tseq);
4098 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4099 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4100 lower_omp (&tseq, ctx);
4101 gimple_seq_add_seq (&llist[1], tseq);
4102 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4103 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4104 if (new_vard == new_var)
4105 SET_DECL_VALUE_EXPR (new_var, lvar);
4106 else
4107 SET_DECL_VALUE_EXPR (new_vard,
4108 build_fold_addr_expr (lvar));
4109 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4110 if (x)
4112 tseq = NULL;
4113 dtor = x;
4114 gimplify_stmt (&dtor, &tseq);
4115 gimple_seq_add_seq (&llist[1], tseq);
4117 break;
4119 /* If this is a reference to constant size reduction var
4120 with placeholder, we haven't emitted the initializer
4121 for it because it is undesirable if SIMD arrays are used.
4122 But if they aren't used, we need to emit the deferred
4123 initialization now. */
4124 else if (is_reference (var) && is_simd)
4125 handle_simd_reference (clause_loc, new_vard, ilist);
4126 x = lang_hooks.decls.omp_clause_default_ctor
4127 (c, unshare_expr (new_var),
4128 build_outer_var_ref (var, ctx));
4129 if (x)
4130 gimplify_and_add (x, ilist);
4131 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4133 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4134 lower_omp (&tseq, ctx);
4135 gimple_seq_add_seq (ilist, tseq);
4137 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4138 if (is_simd)
4140 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4141 lower_omp (&tseq, ctx);
4142 gimple_seq_add_seq (dlist, tseq);
4143 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4145 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4146 goto do_dtor;
4148 else
4150 x = omp_reduction_init (c, TREE_TYPE (new_var));
4151 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4152 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4154 /* reduction(-:var) sums up the partial results, so it
4155 acts identically to reduction(+:var). */
4156 if (code == MINUS_EXPR)
4157 code = PLUS_EXPR;
4159 tree new_vard = new_var;
4160 if (is_simd && is_reference (var))
4162 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4163 new_vard = TREE_OPERAND (new_var, 0);
4164 gcc_assert (DECL_P (new_vard));
4166 if (is_simd
4167 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4168 idx, lane, ivar, lvar))
4170 tree ref = build_outer_var_ref (var, ctx);
4172 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4174 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4175 ref = build_outer_var_ref (var, ctx);
4176 gimplify_assign (ref, x, &llist[1]);
4178 if (new_vard != new_var)
4180 SET_DECL_VALUE_EXPR (new_vard,
4181 build_fold_addr_expr (lvar));
4182 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4185 else
4187 if (is_reference (var) && is_simd)
4188 handle_simd_reference (clause_loc, new_vard, ilist);
4189 gimplify_assign (new_var, x, ilist);
4190 if (is_simd)
4192 tree ref = build_outer_var_ref (var, ctx);
4194 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4195 ref = build_outer_var_ref (var, ctx);
4196 gimplify_assign (ref, x, dlist);
4200 break;
4202 default:
4203 gcc_unreachable ();
4208 if (lane)
4210 tree uid = create_tmp_var (ptr_type_node, "simduid");
4211 /* Don't want uninit warnings on simduid, it is always uninitialized,
4212 but we use it not for the value, but for the DECL_UID only. */
4213 TREE_NO_WARNING (uid) = 1;
4214 gimple g
4215 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4216 gimple_call_set_lhs (g, lane);
4217 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4218 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4219 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4220 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4221 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4222 gimple_omp_for_set_clauses (ctx->stmt, c);
4223 g = gimple_build_assign (lane, INTEGER_CST,
4224 build_int_cst (unsigned_type_node, 0));
4225 gimple_seq_add_stmt (ilist, g);
4226 for (int i = 0; i < 2; i++)
4227 if (llist[i])
4229 tree vf = create_tmp_var (unsigned_type_node);
4230 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4231 gimple_call_set_lhs (g, vf);
4232 gimple_seq *seq = i == 0 ? ilist : dlist;
4233 gimple_seq_add_stmt (seq, g);
4234 tree t = build_int_cst (unsigned_type_node, 0);
4235 g = gimple_build_assign (idx, INTEGER_CST, t);
4236 gimple_seq_add_stmt (seq, g);
4237 tree body = create_artificial_label (UNKNOWN_LOCATION);
4238 tree header = create_artificial_label (UNKNOWN_LOCATION);
4239 tree end = create_artificial_label (UNKNOWN_LOCATION);
4240 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4241 gimple_seq_add_stmt (seq, gimple_build_label (body));
4242 gimple_seq_add_seq (seq, llist[i]);
4243 t = build_int_cst (unsigned_type_node, 1);
4244 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4245 gimple_seq_add_stmt (seq, g);
4246 gimple_seq_add_stmt (seq, gimple_build_label (header));
4247 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4248 gimple_seq_add_stmt (seq, g);
4249 gimple_seq_add_stmt (seq, gimple_build_label (end));
4253 /* The copyin sequence is not to be executed by the main thread, since
4254 that would result in self-copies. Perhaps not visible to scalars,
4255 but it certainly is to C++ operator=. */
4256 if (copyin_seq)
4258 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4260 x = build2 (NE_EXPR, boolean_type_node, x,
4261 build_int_cst (TREE_TYPE (x), 0));
4262 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4263 gimplify_and_add (x, ilist);
4266 /* If any copyin variable is passed by reference, we must ensure the
4267 master thread doesn't modify it before it is copied over in all
4268 threads. Similarly for variables in both firstprivate and
4269 lastprivate clauses we need to ensure the lastprivate copying
4270 happens after firstprivate copying in all threads. And similarly
4271 for UDRs if initializer expression refers to omp_orig. */
4272 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4274 /* Don't add any barrier for #pragma omp simd or
4275 #pragma omp distribute. */
4276 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4277 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4278 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4281 /* If max_vf is non-zero, then we can use only a vectorization factor
4282 up to the max_vf we chose. So stick it into the safelen clause. */
4283 if (max_vf)
4285 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4286 OMP_CLAUSE_SAFELEN);
4287 if (c == NULL_TREE
4288 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4289 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4290 max_vf) == 1))
4292 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4293 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4294 max_vf);
4295 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4296 gimple_omp_for_set_clauses (ctx->stmt, c);
4302 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4303 both parallel and workshare constructs. PREDICATE may be NULL if it's
4304 always true. */
4306 static void
4307 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4308 omp_context *ctx)
4310 tree x, c, label = NULL, orig_clauses = clauses;
4311 bool par_clauses = false;
4312 tree simduid = NULL, lastlane = NULL;
4314 /* Early exit if there are no lastprivate or linear clauses. */
4315 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4316 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4317 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4318 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4319 break;
4320 if (clauses == NULL)
4322 /* If this was a workshare clause, see if it had been combined
4323 with its parallel. In that case, look for the clauses on the
4324 parallel statement itself. */
4325 if (is_parallel_ctx (ctx))
4326 return;
4328 ctx = ctx->outer;
4329 if (ctx == NULL || !is_parallel_ctx (ctx))
4330 return;
4332 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4333 OMP_CLAUSE_LASTPRIVATE);
4334 if (clauses == NULL)
4335 return;
4336 par_clauses = true;
4339 if (predicate)
4341 gcond *stmt;
4342 tree label_true, arm1, arm2;
4344 label = create_artificial_label (UNKNOWN_LOCATION);
4345 label_true = create_artificial_label (UNKNOWN_LOCATION);
4346 arm1 = TREE_OPERAND (predicate, 0);
4347 arm2 = TREE_OPERAND (predicate, 1);
4348 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4349 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4350 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4351 label_true, label);
4352 gimple_seq_add_stmt (stmt_list, stmt);
4353 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4356 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4357 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4359 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4360 if (simduid)
4361 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4364 for (c = clauses; c ;)
4366 tree var, new_var;
4367 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4369 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4370 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4371 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4373 var = OMP_CLAUSE_DECL (c);
4374 new_var = lookup_decl (var, ctx);
4376 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4378 tree val = DECL_VALUE_EXPR (new_var);
4379 if (TREE_CODE (val) == ARRAY_REF
4380 && VAR_P (TREE_OPERAND (val, 0))
4381 && lookup_attribute ("omp simd array",
4382 DECL_ATTRIBUTES (TREE_OPERAND (val,
4383 0))))
4385 if (lastlane == NULL)
4387 lastlane = create_tmp_var (unsigned_type_node);
4388 gcall *g
4389 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4390 2, simduid,
4391 TREE_OPERAND (val, 1));
4392 gimple_call_set_lhs (g, lastlane);
4393 gimple_seq_add_stmt (stmt_list, g);
4395 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4396 TREE_OPERAND (val, 0), lastlane,
4397 NULL_TREE, NULL_TREE);
4401 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4402 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4404 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4405 gimple_seq_add_seq (stmt_list,
4406 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4407 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4409 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4410 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4412 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4413 gimple_seq_add_seq (stmt_list,
4414 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4415 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4418 x = build_outer_var_ref (var, ctx);
4419 if (is_reference (var))
4420 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4421 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4422 gimplify_and_add (x, stmt_list);
4424 c = OMP_CLAUSE_CHAIN (c);
4425 if (c == NULL && !par_clauses)
4427 /* If this was a workshare clause, see if it had been combined
4428 with its parallel. In that case, continue looking for the
4429 clauses also on the parallel statement itself. */
4430 if (is_parallel_ctx (ctx))
4431 break;
4433 ctx = ctx->outer;
4434 if (ctx == NULL || !is_parallel_ctx (ctx))
4435 break;
4437 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4438 OMP_CLAUSE_LASTPRIVATE);
4439 par_clauses = true;
4443 if (label)
4444 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4447 static void
4448 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4449 tree tid, tree var, tree new_var)
4451 /* The atomic add at the end of the sum creates unnecessary
4452 write contention on accelerators. To work around this,
4453 create an array to store the partial reductions. Later, in
4454 lower_omp_for (for openacc), the values of array will be
4455 combined. */
4457 tree t = NULL_TREE, array, x;
4458 tree type = get_base_type (var);
4459 gimple stmt;
4461 /* Now insert the partial reductions into the array. */
4463 /* Find the reduction array. */
4465 tree ptype = build_pointer_type (type);
4467 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4468 t = build_receiver_ref (t, false, ctx->outer);
4470 array = create_tmp_var (ptype);
4471 gimplify_assign (array, t, stmt_seqp);
4473 tree ptr = create_tmp_var (TREE_TYPE (array));
4475 /* Find the reduction array. */
4477 /* testing a unary conversion. */
4478 tree offset = create_tmp_var (sizetype);
4479 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4480 stmt_seqp);
4481 t = create_tmp_var (sizetype);
4482 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4483 stmt_seqp);
4484 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4485 gimple_seq_add_stmt (stmt_seqp, stmt);
4487 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4488 of adding sizeof(var) to the array? */
4489 ptr = create_tmp_var (ptype);
4490 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4491 offset);
4492 gimple_seq_add_stmt (stmt_seqp, stmt);
4494 /* Move the local sum to gfc$sum[i]. */
4495 x = unshare_expr (build_simple_mem_ref (ptr));
4496 stmt = gimplify_assign (x, new_var, stmt_seqp);
4499 /* Generate code to implement the REDUCTION clauses. */
4501 static void
4502 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4504 gimple_seq sub_seq = NULL;
4505 gimple stmt;
4506 tree x, c, tid = NULL_TREE;
4507 int count = 0;
4509 /* SIMD reductions are handled in lower_rec_input_clauses. */
4510 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4511 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4512 return;
4514 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4515 update in that case, otherwise use a lock. */
4516 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4517 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4519 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4521 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4522 count = -1;
4523 break;
4525 count++;
4528 if (count == 0)
4529 return;
4531 /* Initialize thread info for OpenACC. */
4532 if (is_gimple_omp_oacc (ctx->stmt))
4534 /* Get the current thread id. */
4535 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4536 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4537 gimple stmt = gimple_build_call (call, 0);
4538 gimple_call_set_lhs (stmt, tid);
4539 gimple_seq_add_stmt (stmt_seqp, stmt);
4542 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4544 tree var, ref, new_var;
4545 enum tree_code code;
4546 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4548 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4549 continue;
4551 var = OMP_CLAUSE_DECL (c);
4552 new_var = lookup_decl (var, ctx);
4553 if (is_reference (var))
4554 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4555 ref = build_outer_var_ref (var, ctx);
4556 code = OMP_CLAUSE_REDUCTION_CODE (c);
4558 /* reduction(-:var) sums up the partial results, so it acts
4559 identically to reduction(+:var). */
4560 if (code == MINUS_EXPR)
4561 code = PLUS_EXPR;
4563 if (is_gimple_omp_oacc (ctx->stmt))
4565 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4567 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4569 else if (count == 1)
4571 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4573 addr = save_expr (addr);
4574 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4575 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4576 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4577 gimplify_and_add (x, stmt_seqp);
4578 return;
4580 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4582 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4584 if (is_reference (var)
4585 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4586 TREE_TYPE (ref)))
4587 ref = build_fold_addr_expr_loc (clause_loc, ref);
4588 SET_DECL_VALUE_EXPR (placeholder, ref);
4589 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4590 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4591 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4592 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4593 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4595 else
4597 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4598 ref = build_outer_var_ref (var, ctx);
4599 gimplify_assign (ref, x, &sub_seq);
4603 if (is_gimple_omp_oacc (ctx->stmt))
4604 return;
4606 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4608 gimple_seq_add_stmt (stmt_seqp, stmt);
4610 gimple_seq_add_seq (stmt_seqp, sub_seq);
4612 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4614 gimple_seq_add_stmt (stmt_seqp, stmt);
4618 /* Generate code to implement the COPYPRIVATE clauses. */
4620 static void
4621 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4622 omp_context *ctx)
4624 tree c;
4626 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4628 tree var, new_var, ref, x;
4629 bool by_ref;
4630 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4632 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4633 continue;
4635 var = OMP_CLAUSE_DECL (c);
4636 by_ref = use_pointer_for_field (var, NULL);
4638 ref = build_sender_ref (var, ctx);
4639 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4640 if (by_ref)
4642 x = build_fold_addr_expr_loc (clause_loc, new_var);
4643 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4645 gimplify_assign (ref, x, slist);
4647 ref = build_receiver_ref (var, false, ctx);
4648 if (by_ref)
4650 ref = fold_convert_loc (clause_loc,
4651 build_pointer_type (TREE_TYPE (new_var)),
4652 ref);
4653 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4655 if (is_reference (var))
4657 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4658 ref = build_simple_mem_ref_loc (clause_loc, ref);
4659 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4661 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4662 gimplify_and_add (x, rlist);
4667 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4668 and REDUCTION from the sender (aka parent) side. */
4670 static void
4671 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4672 omp_context *ctx)
4674 tree c;
4676 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4678 tree val, ref, x, var;
4679 bool by_ref, do_in = false, do_out = false;
4680 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4682 switch (OMP_CLAUSE_CODE (c))
4684 case OMP_CLAUSE_PRIVATE:
4685 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4686 break;
4687 continue;
4688 case OMP_CLAUSE_FIRSTPRIVATE:
4689 case OMP_CLAUSE_COPYIN:
4690 case OMP_CLAUSE_LASTPRIVATE:
4691 case OMP_CLAUSE_REDUCTION:
4692 case OMP_CLAUSE__LOOPTEMP_:
4693 break;
4694 default:
4695 continue;
4698 val = OMP_CLAUSE_DECL (c);
4699 var = lookup_decl_in_outer_ctx (val, ctx);
4701 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4702 && is_global_var (var))
4703 continue;
4704 if (is_variable_sized (val))
4705 continue;
4706 by_ref = use_pointer_for_field (val, NULL);
4708 switch (OMP_CLAUSE_CODE (c))
4710 case OMP_CLAUSE_PRIVATE:
4711 case OMP_CLAUSE_FIRSTPRIVATE:
4712 case OMP_CLAUSE_COPYIN:
4713 case OMP_CLAUSE__LOOPTEMP_:
4714 do_in = true;
4715 break;
4717 case OMP_CLAUSE_LASTPRIVATE:
4718 if (by_ref || is_reference (val))
4720 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4721 continue;
4722 do_in = true;
4724 else
4726 do_out = true;
4727 if (lang_hooks.decls.omp_private_outer_ref (val))
4728 do_in = true;
4730 break;
4732 case OMP_CLAUSE_REDUCTION:
4733 do_in = true;
4734 do_out = !(by_ref || is_reference (val));
4735 break;
4737 default:
4738 gcc_unreachable ();
4741 if (do_in)
4743 ref = build_sender_ref (val, ctx);
4744 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4745 gimplify_assign (ref, x, ilist);
4746 if (is_task_ctx (ctx))
4747 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4750 if (do_out)
4752 ref = build_sender_ref (val, ctx);
4753 gimplify_assign (var, ref, olist);
4758 /* Generate code to implement SHARED from the sender (aka parent)
4759 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4760 list things that got automatically shared. */
4762 static void
4763 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4765 tree var, ovar, nvar, f, x, record_type;
4767 if (ctx->record_type == NULL)
4768 return;
4770 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4771 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4773 ovar = DECL_ABSTRACT_ORIGIN (f);
4774 nvar = maybe_lookup_decl (ovar, ctx);
4775 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4776 continue;
4778 /* If CTX is a nested parallel directive. Find the immediately
4779 enclosing parallel or workshare construct that contains a
4780 mapping for OVAR. */
4781 var = lookup_decl_in_outer_ctx (ovar, ctx);
4783 if (use_pointer_for_field (ovar, ctx))
4785 x = build_sender_ref (ovar, ctx);
4786 var = build_fold_addr_expr (var);
4787 gimplify_assign (x, var, ilist);
4789 else
4791 x = build_sender_ref (ovar, ctx);
4792 gimplify_assign (x, var, ilist);
4794 if (!TREE_READONLY (var)
4795 /* We don't need to receive a new reference to a result
4796 or parm decl. In fact we may not store to it as we will
4797 invalidate any pending RSO and generate wrong gimple
4798 during inlining. */
4799 && !((TREE_CODE (var) == RESULT_DECL
4800 || TREE_CODE (var) == PARM_DECL)
4801 && DECL_BY_REFERENCE (var)))
4803 x = build_sender_ref (ovar, ctx);
4804 gimplify_assign (var, x, olist);
4811 /* A convenience function to build an empty GIMPLE_COND with just the
4812 condition. */
4814 static gcond *
4815 gimple_build_cond_empty (tree cond)
4817 enum tree_code pred_code;
4818 tree lhs, rhs;
4820 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4821 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4825 /* Build the function calls to GOMP_parallel_start etc to actually
4826 generate the parallel operation. REGION is the parallel region
4827 being expanded. BB is the block where to insert the code. WS_ARGS
4828 will be set if this is a call to a combined parallel+workshare
4829 construct, it contains the list of additional arguments needed by
4830 the workshare construct. */
4832 static void
4833 expand_parallel_call (struct omp_region *region, basic_block bb,
4834 gomp_parallel *entry_stmt,
4835 vec<tree, va_gc> *ws_args)
4837 tree t, t1, t2, val, cond, c, clauses, flags;
4838 gimple_stmt_iterator gsi;
4839 gimple stmt;
4840 enum built_in_function start_ix;
4841 int start_ix2;
4842 location_t clause_loc;
4843 vec<tree, va_gc> *args;
4845 clauses = gimple_omp_parallel_clauses (entry_stmt);
4847 /* Determine what flavor of GOMP_parallel we will be
4848 emitting. */
4849 start_ix = BUILT_IN_GOMP_PARALLEL;
4850 if (is_combined_parallel (region))
4852 switch (region->inner->type)
4854 case GIMPLE_OMP_FOR:
4855 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4856 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4857 + (region->inner->sched_kind
4858 == OMP_CLAUSE_SCHEDULE_RUNTIME
4859 ? 3 : region->inner->sched_kind));
4860 start_ix = (enum built_in_function)start_ix2;
4861 break;
4862 case GIMPLE_OMP_SECTIONS:
4863 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4864 break;
4865 default:
4866 gcc_unreachable ();
4870 /* By default, the value of NUM_THREADS is zero (selected at run time)
4871 and there is no conditional. */
4872 cond = NULL_TREE;
4873 val = build_int_cst (unsigned_type_node, 0);
4874 flags = build_int_cst (unsigned_type_node, 0);
4876 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4877 if (c)
4878 cond = OMP_CLAUSE_IF_EXPR (c);
4880 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4881 if (c)
4883 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4884 clause_loc = OMP_CLAUSE_LOCATION (c);
4886 else
4887 clause_loc = gimple_location (entry_stmt);
4889 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4890 if (c)
4891 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4893 /* Ensure 'val' is of the correct type. */
4894 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4896 /* If we found the clause 'if (cond)', build either
4897 (cond != 0) or (cond ? val : 1u). */
4898 if (cond)
4900 cond = gimple_boolify (cond);
4902 if (integer_zerop (val))
4903 val = fold_build2_loc (clause_loc,
4904 EQ_EXPR, unsigned_type_node, cond,
4905 build_int_cst (TREE_TYPE (cond), 0));
4906 else
4908 basic_block cond_bb, then_bb, else_bb;
4909 edge e, e_then, e_else;
4910 tree tmp_then, tmp_else, tmp_join, tmp_var;
4912 tmp_var = create_tmp_var (TREE_TYPE (val));
4913 if (gimple_in_ssa_p (cfun))
4915 tmp_then = make_ssa_name (tmp_var);
4916 tmp_else = make_ssa_name (tmp_var);
4917 tmp_join = make_ssa_name (tmp_var);
4919 else
4921 tmp_then = tmp_var;
4922 tmp_else = tmp_var;
4923 tmp_join = tmp_var;
4926 e = split_block_after_labels (bb);
4927 cond_bb = e->src;
4928 bb = e->dest;
4929 remove_edge (e);
4931 then_bb = create_empty_bb (cond_bb);
4932 else_bb = create_empty_bb (then_bb);
4933 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4934 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4936 stmt = gimple_build_cond_empty (cond);
4937 gsi = gsi_start_bb (cond_bb);
4938 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4940 gsi = gsi_start_bb (then_bb);
4941 stmt = gimple_build_assign (tmp_then, val);
4942 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4944 gsi = gsi_start_bb (else_bb);
4945 stmt = gimple_build_assign
4946 (tmp_else, build_int_cst (unsigned_type_node, 1));
4947 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4949 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4950 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4951 add_bb_to_loop (then_bb, cond_bb->loop_father);
4952 add_bb_to_loop (else_bb, cond_bb->loop_father);
4953 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4954 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4956 if (gimple_in_ssa_p (cfun))
4958 gphi *phi = create_phi_node (tmp_join, bb);
4959 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4960 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4963 val = tmp_join;
4966 gsi = gsi_start_bb (bb);
4967 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4968 false, GSI_CONTINUE_LINKING);
4971 gsi = gsi_last_bb (bb);
4972 t = gimple_omp_parallel_data_arg (entry_stmt);
4973 if (t == NULL)
4974 t1 = null_pointer_node;
4975 else
4976 t1 = build_fold_addr_expr (t);
4977 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4979 vec_alloc (args, 4 + vec_safe_length (ws_args));
4980 args->quick_push (t2);
4981 args->quick_push (t1);
4982 args->quick_push (val);
4983 if (ws_args)
4984 args->splice (*ws_args);
4985 args->quick_push (flags);
4987 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4988 builtin_decl_explicit (start_ix), args);
4990 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4991 false, GSI_CONTINUE_LINKING);
4994 /* Insert a function call whose name is FUNC_NAME with the information from
4995 ENTRY_STMT into the basic_block BB. */
4997 static void
4998 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
4999 vec <tree, va_gc> *ws_args)
5001 tree t, t1, t2;
5002 gimple_stmt_iterator gsi;
5003 vec <tree, va_gc> *args;
5005 gcc_assert (vec_safe_length (ws_args) == 2);
5006 tree func_name = (*ws_args)[0];
5007 tree grain = (*ws_args)[1];
5009 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5010 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5011 gcc_assert (count != NULL_TREE);
5012 count = OMP_CLAUSE_OPERAND (count, 0);
5014 gsi = gsi_last_bb (bb);
5015 t = gimple_omp_parallel_data_arg (entry_stmt);
5016 if (t == NULL)
5017 t1 = null_pointer_node;
5018 else
5019 t1 = build_fold_addr_expr (t);
5020 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5022 vec_alloc (args, 4);
5023 args->quick_push (t2);
5024 args->quick_push (t1);
5025 args->quick_push (count);
5026 args->quick_push (grain);
5027 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5029 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5030 GSI_CONTINUE_LINKING);
5033 /* Build the function call to GOMP_task to actually
5034 generate the task operation. BB is the block where to insert the code. */
5036 static void
5037 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5039 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5040 gimple_stmt_iterator gsi;
5041 location_t loc = gimple_location (entry_stmt);
5043 clauses = gimple_omp_task_clauses (entry_stmt);
5045 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5046 if (c)
5047 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5048 else
5049 cond = boolean_true_node;
5051 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5052 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5053 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5054 flags = build_int_cst (unsigned_type_node,
5055 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5057 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5058 if (c)
5060 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5061 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5062 build_int_cst (unsigned_type_node, 2),
5063 build_int_cst (unsigned_type_node, 0));
5064 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5066 if (depend)
5067 depend = OMP_CLAUSE_DECL (depend);
5068 else
5069 depend = build_int_cst (ptr_type_node, 0);
5071 gsi = gsi_last_bb (bb);
5072 t = gimple_omp_task_data_arg (entry_stmt);
5073 if (t == NULL)
5074 t2 = null_pointer_node;
5075 else
5076 t2 = build_fold_addr_expr_loc (loc, t);
5077 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5078 t = gimple_omp_task_copy_fn (entry_stmt);
5079 if (t == NULL)
5080 t3 = null_pointer_node;
5081 else
5082 t3 = build_fold_addr_expr_loc (loc, t);
5084 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5085 8, t1, t2, t3,
5086 gimple_omp_task_arg_size (entry_stmt),
5087 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5088 depend);
5090 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5091 false, GSI_CONTINUE_LINKING);
5095 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5096 catch handler and return it. This prevents programs from violating the
5097 structured block semantics with throws. */
5099 static gimple_seq
5100 maybe_catch_exception (gimple_seq body)
5102 gimple g;
5103 tree decl;
5105 if (!flag_exceptions)
5106 return body;
5108 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5109 decl = lang_hooks.eh_protect_cleanup_actions ();
5110 else
5111 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5113 g = gimple_build_eh_must_not_throw (decl);
5114 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5115 GIMPLE_TRY_CATCH);
5117 return gimple_seq_alloc_with_stmt (g);
5120 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5122 static tree
5123 vec2chain (vec<tree, va_gc> *v)
5125 tree chain = NULL_TREE, t;
5126 unsigned ix;
5128 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5130 DECL_CHAIN (t) = chain;
5131 chain = t;
5134 return chain;
5138 /* Remove barriers in REGION->EXIT's block. Note that this is only
5139 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5140 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5141 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5142 removed. */
5144 static void
5145 remove_exit_barrier (struct omp_region *region)
5147 gimple_stmt_iterator gsi;
5148 basic_block exit_bb;
5149 edge_iterator ei;
5150 edge e;
5151 gimple stmt;
5152 int any_addressable_vars = -1;
5154 exit_bb = region->exit;
5156 /* If the parallel region doesn't return, we don't have REGION->EXIT
5157 block at all. */
5158 if (! exit_bb)
5159 return;
5161 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5162 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5163 statements that can appear in between are extremely limited -- no
5164 memory operations at all. Here, we allow nothing at all, so the
5165 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5166 gsi = gsi_last_bb (exit_bb);
5167 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5168 gsi_prev (&gsi);
5169 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5170 return;
5172 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5174 gsi = gsi_last_bb (e->src);
5175 if (gsi_end_p (gsi))
5176 continue;
5177 stmt = gsi_stmt (gsi);
5178 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5179 && !gimple_omp_return_nowait_p (stmt))
5181 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5182 in many cases. If there could be tasks queued, the barrier
5183 might be needed to let the tasks run before some local
5184 variable of the parallel that the task uses as shared
5185 runs out of scope. The task can be spawned either
5186 from within current function (this would be easy to check)
5187 or from some function it calls and gets passed an address
5188 of such a variable. */
5189 if (any_addressable_vars < 0)
5191 gomp_parallel *parallel_stmt
5192 = as_a <gomp_parallel *> (last_stmt (region->entry));
5193 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5194 tree local_decls, block, decl;
5195 unsigned ix;
5197 any_addressable_vars = 0;
5198 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5199 if (TREE_ADDRESSABLE (decl))
5201 any_addressable_vars = 1;
5202 break;
5204 for (block = gimple_block (stmt);
5205 !any_addressable_vars
5206 && block
5207 && TREE_CODE (block) == BLOCK;
5208 block = BLOCK_SUPERCONTEXT (block))
5210 for (local_decls = BLOCK_VARS (block);
5211 local_decls;
5212 local_decls = DECL_CHAIN (local_decls))
5213 if (TREE_ADDRESSABLE (local_decls))
5215 any_addressable_vars = 1;
5216 break;
5218 if (block == gimple_block (parallel_stmt))
5219 break;
5222 if (!any_addressable_vars)
5223 gimple_omp_return_set_nowait (stmt);
5228 static void
5229 remove_exit_barriers (struct omp_region *region)
5231 if (region->type == GIMPLE_OMP_PARALLEL)
5232 remove_exit_barrier (region);
5234 if (region->inner)
5236 region = region->inner;
5237 remove_exit_barriers (region);
5238 while (region->next)
5240 region = region->next;
5241 remove_exit_barriers (region);
5246 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5247 calls. These can't be declared as const functions, but
5248 within one parallel body they are constant, so they can be
5249 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5250 which are declared const. Similarly for task body, except
5251 that in untied task omp_get_thread_num () can change at any task
5252 scheduling point. */
5254 static void
5255 optimize_omp_library_calls (gimple entry_stmt)
5257 basic_block bb;
5258 gimple_stmt_iterator gsi;
5259 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5260 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5261 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5262 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5263 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5264 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5265 OMP_CLAUSE_UNTIED) != NULL);
5267 FOR_EACH_BB_FN (bb, cfun)
5268 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5270 gimple call = gsi_stmt (gsi);
5271 tree decl;
5273 if (is_gimple_call (call)
5274 && (decl = gimple_call_fndecl (call))
5275 && DECL_EXTERNAL (decl)
5276 && TREE_PUBLIC (decl)
5277 && DECL_INITIAL (decl) == NULL)
5279 tree built_in;
5281 if (DECL_NAME (decl) == thr_num_id)
5283 /* In #pragma omp task untied omp_get_thread_num () can change
5284 during the execution of the task region. */
5285 if (untied_task)
5286 continue;
5287 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5289 else if (DECL_NAME (decl) == num_thr_id)
5290 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5291 else
5292 continue;
5294 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5295 || gimple_call_num_args (call) != 0)
5296 continue;
5298 if (flag_exceptions && !TREE_NOTHROW (decl))
5299 continue;
5301 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5302 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5303 TREE_TYPE (TREE_TYPE (built_in))))
5304 continue;
5306 gimple_call_set_fndecl (call, built_in);
5311 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5312 regimplified. */
5314 static tree
5315 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5317 tree t = *tp;
5319 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5320 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5321 return t;
5323 if (TREE_CODE (t) == ADDR_EXPR)
5324 recompute_tree_invariant_for_addr_expr (t);
5326 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5327 return NULL_TREE;
5330 /* Prepend TO = FROM assignment before *GSI_P. */
5332 static void
5333 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5335 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5336 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5337 true, GSI_SAME_STMT);
5338 gimple stmt = gimple_build_assign (to, from);
5339 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5340 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5341 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5343 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5344 gimple_regimplify_operands (stmt, &gsi);
5348 /* Expand the OpenMP parallel or task directive starting at REGION. */
5350 static void
5351 expand_omp_taskreg (struct omp_region *region)
5353 basic_block entry_bb, exit_bb, new_bb;
5354 struct function *child_cfun;
5355 tree child_fn, block, t;
5356 gimple_stmt_iterator gsi;
5357 gimple entry_stmt, stmt;
5358 edge e;
5359 vec<tree, va_gc> *ws_args;
5361 entry_stmt = last_stmt (region->entry);
5362 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5363 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5365 entry_bb = region->entry;
5366 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
5367 exit_bb = region->cont;
5368 else
5369 exit_bb = region->exit;
5371 bool is_cilk_for
5372 = (flag_cilkplus
5373 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5374 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5375 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5377 if (is_cilk_for)
5378 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5379 and the inner statement contains the name of the built-in function
5380 and grain. */
5381 ws_args = region->inner->ws_args;
5382 else if (is_combined_parallel (region))
5383 ws_args = region->ws_args;
5384 else
5385 ws_args = NULL;
5387 if (child_cfun->cfg)
5389 /* Due to inlining, it may happen that we have already outlined
5390 the region, in which case all we need to do is make the
5391 sub-graph unreachable and emit the parallel call. */
5392 edge entry_succ_e, exit_succ_e;
5394 entry_succ_e = single_succ_edge (entry_bb);
5396 gsi = gsi_last_bb (entry_bb);
5397 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5398 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5399 gsi_remove (&gsi, true);
5401 new_bb = entry_bb;
5402 if (exit_bb)
5404 exit_succ_e = single_succ_edge (exit_bb);
5405 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5407 remove_edge_and_dominated_blocks (entry_succ_e);
5409 else
5411 unsigned srcidx, dstidx, num;
5413 /* If the parallel region needs data sent from the parent
5414 function, then the very first statement (except possible
5415 tree profile counter updates) of the parallel body
5416 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5417 &.OMP_DATA_O is passed as an argument to the child function,
5418 we need to replace it with the argument as seen by the child
5419 function.
5421 In most cases, this will end up being the identity assignment
5422 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5423 a function call that has been inlined, the original PARM_DECL
5424 .OMP_DATA_I may have been converted into a different local
5425 variable. In which case, we need to keep the assignment. */
5426 if (gimple_omp_taskreg_data_arg (entry_stmt))
5428 basic_block entry_succ_bb
5429 = single_succ_p (entry_bb) ? single_succ (entry_bb)
5430 : FALLTHRU_EDGE (entry_bb)->dest;
5431 tree arg, narg;
5432 gimple parcopy_stmt = NULL;
5434 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5436 gimple stmt;
5438 gcc_assert (!gsi_end_p (gsi));
5439 stmt = gsi_stmt (gsi);
5440 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5441 continue;
5443 if (gimple_num_ops (stmt) == 2)
5445 tree arg = gimple_assign_rhs1 (stmt);
5447 /* We're ignore the subcode because we're
5448 effectively doing a STRIP_NOPS. */
5450 if (TREE_CODE (arg) == ADDR_EXPR
5451 && TREE_OPERAND (arg, 0)
5452 == gimple_omp_taskreg_data_arg (entry_stmt))
5454 parcopy_stmt = stmt;
5455 break;
5460 gcc_assert (parcopy_stmt != NULL);
5461 arg = DECL_ARGUMENTS (child_fn);
5463 if (!gimple_in_ssa_p (cfun))
5465 if (gimple_assign_lhs (parcopy_stmt) == arg)
5466 gsi_remove (&gsi, true);
5467 else
5469 /* ?? Is setting the subcode really necessary ?? */
5470 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5471 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5474 else
5476 /* If we are in ssa form, we must load the value from the default
5477 definition of the argument. That should not be defined now,
5478 since the argument is not used uninitialized. */
5479 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5480 narg = make_ssa_name (arg, gimple_build_nop ());
5481 set_ssa_default_def (cfun, arg, narg);
5482 /* ?? Is setting the subcode really necessary ?? */
5483 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5484 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5485 update_stmt (parcopy_stmt);
5489 /* Declare local variables needed in CHILD_CFUN. */
5490 block = DECL_INITIAL (child_fn);
5491 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5492 /* The gimplifier could record temporaries in parallel/task block
5493 rather than in containing function's local_decls chain,
5494 which would mean cgraph missed finalizing them. Do it now. */
5495 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5496 if (TREE_CODE (t) == VAR_DECL
5497 && TREE_STATIC (t)
5498 && !DECL_EXTERNAL (t))
5499 varpool_node::finalize_decl (t);
5500 DECL_SAVED_TREE (child_fn) = NULL;
5501 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5502 gimple_set_body (child_fn, NULL);
5503 TREE_USED (block) = 1;
5505 /* Reset DECL_CONTEXT on function arguments. */
5506 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5507 DECL_CONTEXT (t) = child_fn;
5509 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5510 so that it can be moved to the child function. */
5511 gsi = gsi_last_bb (entry_bb);
5512 stmt = gsi_stmt (gsi);
5513 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5514 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5515 e = split_block (entry_bb, stmt);
5516 gsi_remove (&gsi, true);
5517 entry_bb = e->dest;
5518 edge e2 = NULL;
5519 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5520 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5521 else
5523 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
5524 gcc_assert (e2->dest == region->exit);
5525 remove_edge (BRANCH_EDGE (entry_bb));
5526 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
5527 gsi = gsi_last_bb (region->exit);
5528 gcc_assert (!gsi_end_p (gsi)
5529 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5530 gsi_remove (&gsi, true);
5533 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5534 if (exit_bb)
5536 gsi = gsi_last_bb (exit_bb);
5537 gcc_assert (!gsi_end_p (gsi)
5538 && (gimple_code (gsi_stmt (gsi))
5539 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
5540 stmt = gimple_build_return (NULL);
5541 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5542 gsi_remove (&gsi, true);
5545 /* Move the parallel region into CHILD_CFUN. */
5547 if (gimple_in_ssa_p (cfun))
5549 init_tree_ssa (child_cfun);
5550 init_ssa_operands (child_cfun);
5551 child_cfun->gimple_df->in_ssa_p = true;
5552 block = NULL_TREE;
5554 else
5555 block = gimple_block (entry_stmt);
5557 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5558 if (exit_bb)
5559 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5560 if (e2)
5562 basic_block dest_bb = e2->dest;
5563 if (!exit_bb)
5564 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
5565 remove_edge (e2);
5566 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
5568 /* When the OMP expansion process cannot guarantee an up-to-date
5569 loop tree arrange for the child function to fixup loops. */
5570 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5571 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5573 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5574 num = vec_safe_length (child_cfun->local_decls);
5575 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5577 t = (*child_cfun->local_decls)[srcidx];
5578 if (DECL_CONTEXT (t) == cfun->decl)
5579 continue;
5580 if (srcidx != dstidx)
5581 (*child_cfun->local_decls)[dstidx] = t;
5582 dstidx++;
5584 if (dstidx != num)
5585 vec_safe_truncate (child_cfun->local_decls, dstidx);
5587 /* Inform the callgraph about the new function. */
5588 child_cfun->curr_properties = cfun->curr_properties;
5589 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
5590 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
5591 cgraph_node *node = cgraph_node::get_create (child_fn);
5592 node->parallelized_function = 1;
5593 cgraph_node::add_new_function (child_fn, true);
5595 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5596 fixed in a following pass. */
5597 push_cfun (child_cfun);
5598 if (optimize)
5599 optimize_omp_library_calls (entry_stmt);
5600 cgraph_edge::rebuild_edges ();
5602 /* Some EH regions might become dead, see PR34608. If
5603 pass_cleanup_cfg isn't the first pass to happen with the
5604 new child, these dead EH edges might cause problems.
5605 Clean them up now. */
5606 if (flag_exceptions)
5608 basic_block bb;
5609 bool changed = false;
5611 FOR_EACH_BB_FN (bb, cfun)
5612 changed |= gimple_purge_dead_eh_edges (bb);
5613 if (changed)
5614 cleanup_tree_cfg ();
5616 if (gimple_in_ssa_p (cfun))
5617 update_ssa (TODO_update_ssa);
5618 pop_cfun ();
5621 /* Emit a library call to launch the children threads. */
5622 if (is_cilk_for)
5623 expand_cilk_for_call (new_bb,
5624 as_a <gomp_parallel *> (entry_stmt), ws_args);
5625 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5626 expand_parallel_call (region, new_bb,
5627 as_a <gomp_parallel *> (entry_stmt), ws_args);
5628 else
5629 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5630 if (gimple_in_ssa_p (cfun))
5631 update_ssa (TODO_update_ssa_only_virtuals);
5635 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5636 of the combined collapse > 1 loop constructs, generate code like:
5637 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5638 if (cond3 is <)
5639 adj = STEP3 - 1;
5640 else
5641 adj = STEP3 + 1;
5642 count3 = (adj + N32 - N31) / STEP3;
5643 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5644 if (cond2 is <)
5645 adj = STEP2 - 1;
5646 else
5647 adj = STEP2 + 1;
5648 count2 = (adj + N22 - N21) / STEP2;
5649 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5650 if (cond1 is <)
5651 adj = STEP1 - 1;
5652 else
5653 adj = STEP1 + 1;
5654 count1 = (adj + N12 - N11) / STEP1;
5655 count = count1 * count2 * count3;
5656 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5657 count = 0;
5658 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5659 of the combined loop constructs, just initialize COUNTS array
5660 from the _looptemp_ clauses. */
5662 /* NOTE: It *could* be better to moosh all of the BBs together,
5663 creating one larger BB with all the computation and the unexpected
5664 jump at the end. I.e.
5666 bool zero3, zero2, zero1, zero;
5668 zero3 = N32 c3 N31;
5669 count3 = (N32 - N31) /[cl] STEP3;
5670 zero2 = N22 c2 N21;
5671 count2 = (N22 - N21) /[cl] STEP2;
5672 zero1 = N12 c1 N11;
5673 count1 = (N12 - N11) /[cl] STEP1;
5674 zero = zero3 || zero2 || zero1;
5675 count = count1 * count2 * count3;
5676 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5678 After all, we expect the zero=false, and thus we expect to have to
5679 evaluate all of the comparison expressions, so short-circuiting
5680 oughtn't be a win. Since the condition isn't protecting a
5681 denominator, we're not concerned about divide-by-zero, so we can
5682 fully evaluate count even if a numerator turned out to be wrong.
5684 It seems like putting this all together would create much better
5685 scheduling opportunities, and less pressure on the chip's branch
5686 predictor. */
5688 static void
5689 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5690 basic_block &entry_bb, tree *counts,
5691 basic_block &zero_iter_bb, int &first_zero_iter,
5692 basic_block &l2_dom_bb)
5694 tree t, type = TREE_TYPE (fd->loop.v);
5695 edge e, ne;
5696 int i;
5698 /* Collapsed loops need work for expansion into SSA form. */
5699 gcc_assert (!gimple_in_ssa_p (cfun));
5701 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5702 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5704 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5705 isn't supposed to be handled, as the inner loop doesn't
5706 use it. */
5707 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5708 OMP_CLAUSE__LOOPTEMP_);
5709 gcc_assert (innerc);
5710 for (i = 0; i < fd->collapse; i++)
5712 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5713 OMP_CLAUSE__LOOPTEMP_);
5714 gcc_assert (innerc);
5715 if (i)
5716 counts[i] = OMP_CLAUSE_DECL (innerc);
5717 else
5718 counts[0] = NULL_TREE;
5720 return;
5723 for (i = 0; i < fd->collapse; i++)
5725 tree itype = TREE_TYPE (fd->loops[i].v);
5727 if (SSA_VAR_P (fd->loop.n2)
5728 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5729 fold_convert (itype, fd->loops[i].n1),
5730 fold_convert (itype, fd->loops[i].n2)))
5731 == NULL_TREE || !integer_onep (t)))
5733 gcond *cond_stmt;
5734 tree n1, n2;
5735 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5736 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5737 true, GSI_SAME_STMT);
5738 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5739 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5740 true, GSI_SAME_STMT);
5741 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5742 NULL_TREE, NULL_TREE);
5743 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5744 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5745 expand_omp_regimplify_p, NULL, NULL)
5746 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5747 expand_omp_regimplify_p, NULL, NULL))
5749 *gsi = gsi_for_stmt (cond_stmt);
5750 gimple_regimplify_operands (cond_stmt, gsi);
5752 e = split_block (entry_bb, cond_stmt);
5753 if (zero_iter_bb == NULL)
5755 gassign *assign_stmt;
5756 first_zero_iter = i;
5757 zero_iter_bb = create_empty_bb (entry_bb);
5758 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5759 *gsi = gsi_after_labels (zero_iter_bb);
5760 assign_stmt = gimple_build_assign (fd->loop.n2,
5761 build_zero_cst (type));
5762 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5763 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5764 entry_bb);
5766 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5767 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5768 e->flags = EDGE_TRUE_VALUE;
5769 e->probability = REG_BR_PROB_BASE - ne->probability;
5770 if (l2_dom_bb == NULL)
5771 l2_dom_bb = entry_bb;
5772 entry_bb = e->dest;
5773 *gsi = gsi_last_bb (entry_bb);
5776 if (POINTER_TYPE_P (itype))
5777 itype = signed_type_for (itype);
5778 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5779 ? -1 : 1));
5780 t = fold_build2 (PLUS_EXPR, itype,
5781 fold_convert (itype, fd->loops[i].step), t);
5782 t = fold_build2 (PLUS_EXPR, itype, t,
5783 fold_convert (itype, fd->loops[i].n2));
5784 t = fold_build2 (MINUS_EXPR, itype, t,
5785 fold_convert (itype, fd->loops[i].n1));
5786 /* ?? We could probably use CEIL_DIV_EXPR instead of
5787 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5788 generate the same code in the end because generically we
5789 don't know that the values involved must be negative for
5790 GT?? */
5791 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5792 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5793 fold_build1 (NEGATE_EXPR, itype, t),
5794 fold_build1 (NEGATE_EXPR, itype,
5795 fold_convert (itype,
5796 fd->loops[i].step)));
5797 else
5798 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5799 fold_convert (itype, fd->loops[i].step));
5800 t = fold_convert (type, t);
5801 if (TREE_CODE (t) == INTEGER_CST)
5802 counts[i] = t;
5803 else
5805 counts[i] = create_tmp_reg (type, ".count");
5806 expand_omp_build_assign (gsi, counts[i], t);
5808 if (SSA_VAR_P (fd->loop.n2))
5810 if (i == 0)
5811 t = counts[0];
5812 else
5813 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5814 expand_omp_build_assign (gsi, fd->loop.n2, t);
5820 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5821 T = V;
5822 V3 = N31 + (T % count3) * STEP3;
5823 T = T / count3;
5824 V2 = N21 + (T % count2) * STEP2;
5825 T = T / count2;
5826 V1 = N11 + T * STEP1;
5827 if this loop doesn't have an inner loop construct combined with it.
5828 If it does have an inner loop construct combined with it and the
5829 iteration count isn't known constant, store values from counts array
5830 into its _looptemp_ temporaries instead. */
5832 static void
5833 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5834 tree *counts, gimple inner_stmt, tree startvar)
5836 int i;
5837 if (gimple_omp_for_combined_p (fd->for_stmt))
5839 /* If fd->loop.n2 is constant, then no propagation of the counts
5840 is needed, they are constant. */
5841 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5842 return;
5844 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5845 ? gimple_omp_parallel_clauses (inner_stmt)
5846 : gimple_omp_for_clauses (inner_stmt);
5847 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5848 isn't supposed to be handled, as the inner loop doesn't
5849 use it. */
5850 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5851 gcc_assert (innerc);
5852 for (i = 0; i < fd->collapse; i++)
5854 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5855 OMP_CLAUSE__LOOPTEMP_);
5856 gcc_assert (innerc);
5857 if (i)
5859 tree tem = OMP_CLAUSE_DECL (innerc);
5860 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5861 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5862 false, GSI_CONTINUE_LINKING);
5863 gassign *stmt = gimple_build_assign (tem, t);
5864 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5867 return;
5870 tree type = TREE_TYPE (fd->loop.v);
5871 tree tem = create_tmp_reg (type, ".tem");
5872 gassign *stmt = gimple_build_assign (tem, startvar);
5873 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5875 for (i = fd->collapse - 1; i >= 0; i--)
5877 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5878 itype = vtype;
5879 if (POINTER_TYPE_P (vtype))
5880 itype = signed_type_for (vtype);
5881 if (i != 0)
5882 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5883 else
5884 t = tem;
5885 t = fold_convert (itype, t);
5886 t = fold_build2 (MULT_EXPR, itype, t,
5887 fold_convert (itype, fd->loops[i].step));
5888 if (POINTER_TYPE_P (vtype))
5889 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5890 else
5891 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5892 t = force_gimple_operand_gsi (gsi, t,
5893 DECL_P (fd->loops[i].v)
5894 && TREE_ADDRESSABLE (fd->loops[i].v),
5895 NULL_TREE, false,
5896 GSI_CONTINUE_LINKING);
5897 stmt = gimple_build_assign (fd->loops[i].v, t);
5898 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5899 if (i != 0)
5901 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5902 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5903 false, GSI_CONTINUE_LINKING);
5904 stmt = gimple_build_assign (tem, t);
5905 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5911 /* Helper function for expand_omp_for_*. Generate code like:
5912 L10:
5913 V3 += STEP3;
5914 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5915 L11:
5916 V3 = N31;
5917 V2 += STEP2;
5918 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5919 L12:
5920 V2 = N21;
5921 V1 += STEP1;
5922 goto BODY_BB; */
5924 static basic_block
5925 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5926 basic_block body_bb)
5928 basic_block last_bb, bb, collapse_bb = NULL;
5929 int i;
5930 gimple_stmt_iterator gsi;
5931 edge e;
5932 tree t;
5933 gimple stmt;
5935 last_bb = cont_bb;
5936 for (i = fd->collapse - 1; i >= 0; i--)
5938 tree vtype = TREE_TYPE (fd->loops[i].v);
5940 bb = create_empty_bb (last_bb);
5941 add_bb_to_loop (bb, last_bb->loop_father);
5942 gsi = gsi_start_bb (bb);
5944 if (i < fd->collapse - 1)
5946 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5947 e->probability = REG_BR_PROB_BASE / 8;
5949 t = fd->loops[i + 1].n1;
5950 t = force_gimple_operand_gsi (&gsi, t,
5951 DECL_P (fd->loops[i + 1].v)
5952 && TREE_ADDRESSABLE (fd->loops[i
5953 + 1].v),
5954 NULL_TREE, false,
5955 GSI_CONTINUE_LINKING);
5956 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5957 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5959 else
5960 collapse_bb = bb;
5962 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5964 if (POINTER_TYPE_P (vtype))
5965 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5966 else
5967 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5968 t = force_gimple_operand_gsi (&gsi, t,
5969 DECL_P (fd->loops[i].v)
5970 && TREE_ADDRESSABLE (fd->loops[i].v),
5971 NULL_TREE, false, GSI_CONTINUE_LINKING);
5972 stmt = gimple_build_assign (fd->loops[i].v, t);
5973 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5975 if (i > 0)
5977 t = fd->loops[i].n2;
5978 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5979 false, GSI_CONTINUE_LINKING);
5980 tree v = fd->loops[i].v;
5981 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5982 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5983 false, GSI_CONTINUE_LINKING);
5984 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5985 stmt = gimple_build_cond_empty (t);
5986 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5987 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5988 e->probability = REG_BR_PROB_BASE * 7 / 8;
5990 else
5991 make_edge (bb, body_bb, EDGE_FALLTHRU);
5992 last_bb = bb;
5995 return collapse_bb;
5999 /* A subroutine of expand_omp_for. Generate code for a parallel
6000 loop with any schedule. Given parameters:
6002 for (V = N1; V cond N2; V += STEP) BODY;
6004 where COND is "<" or ">", we generate pseudocode
6006 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
6007 if (more) goto L0; else goto L3;
6009 V = istart0;
6010 iend = iend0;
6012 BODY;
6013 V += STEP;
6014 if (V cond iend) goto L1; else goto L2;
6016 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6019 If this is a combined omp parallel loop, instead of the call to
6020 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6021 If this is gimple_omp_for_combined_p loop, then instead of assigning
6022 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6023 inner GIMPLE_OMP_FOR and V += STEP; and
6024 if (V cond iend) goto L1; else goto L2; are removed.
6026 For collapsed loops, given parameters:
6027 collapse(3)
6028 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6029 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6030 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6031 BODY;
6033 we generate pseudocode
6035 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6036 if (cond3 is <)
6037 adj = STEP3 - 1;
6038 else
6039 adj = STEP3 + 1;
6040 count3 = (adj + N32 - N31) / STEP3;
6041 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6042 if (cond2 is <)
6043 adj = STEP2 - 1;
6044 else
6045 adj = STEP2 + 1;
6046 count2 = (adj + N22 - N21) / STEP2;
6047 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6048 if (cond1 is <)
6049 adj = STEP1 - 1;
6050 else
6051 adj = STEP1 + 1;
6052 count1 = (adj + N12 - N11) / STEP1;
6053 count = count1 * count2 * count3;
6054 goto Z1;
6056 count = 0;
6058 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6059 if (more) goto L0; else goto L3;
6061 V = istart0;
6062 T = V;
6063 V3 = N31 + (T % count3) * STEP3;
6064 T = T / count3;
6065 V2 = N21 + (T % count2) * STEP2;
6066 T = T / count2;
6067 V1 = N11 + T * STEP1;
6068 iend = iend0;
6070 BODY;
6071 V += 1;
6072 if (V < iend) goto L10; else goto L2;
6073 L10:
6074 V3 += STEP3;
6075 if (V3 cond3 N32) goto L1; else goto L11;
6076 L11:
6077 V3 = N31;
6078 V2 += STEP2;
6079 if (V2 cond2 N22) goto L1; else goto L12;
6080 L12:
6081 V2 = N21;
6082 V1 += STEP1;
6083 goto L1;
6085 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6090 static void
6091 expand_omp_for_generic (struct omp_region *region,
6092 struct omp_for_data *fd,
6093 enum built_in_function start_fn,
6094 enum built_in_function next_fn,
6095 gimple inner_stmt)
6097 tree type, istart0, iend0, iend;
6098 tree t, vmain, vback, bias = NULL_TREE;
6099 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6100 basic_block l2_bb = NULL, l3_bb = NULL;
6101 gimple_stmt_iterator gsi;
6102 gassign *assign_stmt;
6103 bool in_combined_parallel = is_combined_parallel (region);
6104 bool broken_loop = region->cont == NULL;
6105 edge e, ne;
6106 tree *counts = NULL;
6107 int i;
6109 gcc_assert (!broken_loop || !in_combined_parallel);
6110 gcc_assert (fd->iter_type == long_integer_type_node
6111 || !in_combined_parallel);
6113 type = TREE_TYPE (fd->loop.v);
6114 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6115 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6116 TREE_ADDRESSABLE (istart0) = 1;
6117 TREE_ADDRESSABLE (iend0) = 1;
6119 /* See if we need to bias by LLONG_MIN. */
6120 if (fd->iter_type == long_long_unsigned_type_node
6121 && TREE_CODE (type) == INTEGER_TYPE
6122 && !TYPE_UNSIGNED (type))
6124 tree n1, n2;
6126 if (fd->loop.cond_code == LT_EXPR)
6128 n1 = fd->loop.n1;
6129 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6131 else
6133 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6134 n2 = fd->loop.n1;
6136 if (TREE_CODE (n1) != INTEGER_CST
6137 || TREE_CODE (n2) != INTEGER_CST
6138 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6139 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6142 entry_bb = region->entry;
6143 cont_bb = region->cont;
6144 collapse_bb = NULL;
6145 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6146 gcc_assert (broken_loop
6147 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6148 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6149 l1_bb = single_succ (l0_bb);
6150 if (!broken_loop)
6152 l2_bb = create_empty_bb (cont_bb);
6153 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6154 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6156 else
6157 l2_bb = NULL;
6158 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6159 exit_bb = region->exit;
6161 gsi = gsi_last_bb (entry_bb);
6163 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6164 if (fd->collapse > 1)
6166 int first_zero_iter = -1;
6167 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6169 counts = XALLOCAVEC (tree, fd->collapse);
6170 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6171 zero_iter_bb, first_zero_iter,
6172 l2_dom_bb);
6174 if (zero_iter_bb)
6176 /* Some counts[i] vars might be uninitialized if
6177 some loop has zero iterations. But the body shouldn't
6178 be executed in that case, so just avoid uninit warnings. */
6179 for (i = first_zero_iter; i < fd->collapse; i++)
6180 if (SSA_VAR_P (counts[i]))
6181 TREE_NO_WARNING (counts[i]) = 1;
6182 gsi_prev (&gsi);
6183 e = split_block (entry_bb, gsi_stmt (gsi));
6184 entry_bb = e->dest;
6185 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6186 gsi = gsi_last_bb (entry_bb);
6187 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6188 get_immediate_dominator (CDI_DOMINATORS,
6189 zero_iter_bb));
6192 if (in_combined_parallel)
6194 /* In a combined parallel loop, emit a call to
6195 GOMP_loop_foo_next. */
6196 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6197 build_fold_addr_expr (istart0),
6198 build_fold_addr_expr (iend0));
6200 else
6202 tree t0, t1, t2, t3, t4;
6203 /* If this is not a combined parallel loop, emit a call to
6204 GOMP_loop_foo_start in ENTRY_BB. */
6205 t4 = build_fold_addr_expr (iend0);
6206 t3 = build_fold_addr_expr (istart0);
6207 t2 = fold_convert (fd->iter_type, fd->loop.step);
6208 t1 = fd->loop.n2;
6209 t0 = fd->loop.n1;
6210 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6212 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6213 OMP_CLAUSE__LOOPTEMP_);
6214 gcc_assert (innerc);
6215 t0 = OMP_CLAUSE_DECL (innerc);
6216 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6217 OMP_CLAUSE__LOOPTEMP_);
6218 gcc_assert (innerc);
6219 t1 = OMP_CLAUSE_DECL (innerc);
6221 if (POINTER_TYPE_P (TREE_TYPE (t0))
6222 && TYPE_PRECISION (TREE_TYPE (t0))
6223 != TYPE_PRECISION (fd->iter_type))
6225 /* Avoid casting pointers to integer of a different size. */
6226 tree itype = signed_type_for (type);
6227 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6228 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6230 else
6232 t1 = fold_convert (fd->iter_type, t1);
6233 t0 = fold_convert (fd->iter_type, t0);
6235 if (bias)
6237 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6238 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6240 if (fd->iter_type == long_integer_type_node)
6242 if (fd->chunk_size)
6244 t = fold_convert (fd->iter_type, fd->chunk_size);
6245 t = build_call_expr (builtin_decl_explicit (start_fn),
6246 6, t0, t1, t2, t, t3, t4);
6248 else
6249 t = build_call_expr (builtin_decl_explicit (start_fn),
6250 5, t0, t1, t2, t3, t4);
6252 else
6254 tree t5;
6255 tree c_bool_type;
6256 tree bfn_decl;
6258 /* The GOMP_loop_ull_*start functions have additional boolean
6259 argument, true for < loops and false for > loops.
6260 In Fortran, the C bool type can be different from
6261 boolean_type_node. */
6262 bfn_decl = builtin_decl_explicit (start_fn);
6263 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6264 t5 = build_int_cst (c_bool_type,
6265 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6266 if (fd->chunk_size)
6268 tree bfn_decl = builtin_decl_explicit (start_fn);
6269 t = fold_convert (fd->iter_type, fd->chunk_size);
6270 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6272 else
6273 t = build_call_expr (builtin_decl_explicit (start_fn),
6274 6, t5, t0, t1, t2, t3, t4);
6277 if (TREE_TYPE (t) != boolean_type_node)
6278 t = fold_build2 (NE_EXPR, boolean_type_node,
6279 t, build_int_cst (TREE_TYPE (t), 0));
6280 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6281 true, GSI_SAME_STMT);
6282 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6284 /* Remove the GIMPLE_OMP_FOR statement. */
6285 gsi_remove (&gsi, true);
6287 /* Iteration setup for sequential loop goes in L0_BB. */
6288 tree startvar = fd->loop.v;
6289 tree endvar = NULL_TREE;
6291 if (gimple_omp_for_combined_p (fd->for_stmt))
6293 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6294 && gimple_omp_for_kind (inner_stmt)
6295 == GF_OMP_FOR_KIND_SIMD);
6296 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6297 OMP_CLAUSE__LOOPTEMP_);
6298 gcc_assert (innerc);
6299 startvar = OMP_CLAUSE_DECL (innerc);
6300 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6301 OMP_CLAUSE__LOOPTEMP_);
6302 gcc_assert (innerc);
6303 endvar = OMP_CLAUSE_DECL (innerc);
6306 gsi = gsi_start_bb (l0_bb);
6307 t = istart0;
6308 if (bias)
6309 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6310 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6311 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6312 t = fold_convert (TREE_TYPE (startvar), t);
6313 t = force_gimple_operand_gsi (&gsi, t,
6314 DECL_P (startvar)
6315 && TREE_ADDRESSABLE (startvar),
6316 NULL_TREE, false, GSI_CONTINUE_LINKING);
6317 assign_stmt = gimple_build_assign (startvar, t);
6318 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6320 t = iend0;
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 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6327 false, GSI_CONTINUE_LINKING);
6328 if (endvar)
6330 assign_stmt = gimple_build_assign (endvar, iend);
6331 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6332 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6333 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6334 else
6335 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6336 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6338 if (fd->collapse > 1)
6339 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6341 if (!broken_loop)
6343 /* Code to control the increment and predicate for the sequential
6344 loop goes in the CONT_BB. */
6345 gsi = gsi_last_bb (cont_bb);
6346 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6347 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6348 vmain = gimple_omp_continue_control_use (cont_stmt);
6349 vback = gimple_omp_continue_control_def (cont_stmt);
6351 if (!gimple_omp_for_combined_p (fd->for_stmt))
6353 if (POINTER_TYPE_P (type))
6354 t = fold_build_pointer_plus (vmain, fd->loop.step);
6355 else
6356 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6357 t = force_gimple_operand_gsi (&gsi, t,
6358 DECL_P (vback)
6359 && TREE_ADDRESSABLE (vback),
6360 NULL_TREE, true, GSI_SAME_STMT);
6361 assign_stmt = gimple_build_assign (vback, t);
6362 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6364 t = build2 (fd->loop.cond_code, boolean_type_node,
6365 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6366 iend);
6367 gcond *cond_stmt = gimple_build_cond_empty (t);
6368 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6371 /* Remove GIMPLE_OMP_CONTINUE. */
6372 gsi_remove (&gsi, true);
6374 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6375 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6377 /* Emit code to get the next parallel iteration in L2_BB. */
6378 gsi = gsi_start_bb (l2_bb);
6380 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6381 build_fold_addr_expr (istart0),
6382 build_fold_addr_expr (iend0));
6383 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6384 false, GSI_CONTINUE_LINKING);
6385 if (TREE_TYPE (t) != boolean_type_node)
6386 t = fold_build2 (NE_EXPR, boolean_type_node,
6387 t, build_int_cst (TREE_TYPE (t), 0));
6388 gcond *cond_stmt = gimple_build_cond_empty (t);
6389 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6392 /* Add the loop cleanup function. */
6393 gsi = gsi_last_bb (exit_bb);
6394 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6395 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6396 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6397 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6398 else
6399 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6400 gcall *call_stmt = gimple_build_call (t, 0);
6401 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6402 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6403 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6404 gsi_remove (&gsi, true);
6406 /* Connect the new blocks. */
6407 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6408 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6410 if (!broken_loop)
6412 gimple_seq phis;
6414 e = find_edge (cont_bb, l3_bb);
6415 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6417 phis = phi_nodes (l3_bb);
6418 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6420 gimple phi = gsi_stmt (gsi);
6421 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6422 PHI_ARG_DEF_FROM_EDGE (phi, e));
6424 remove_edge (e);
6426 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6427 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6428 e = find_edge (cont_bb, l1_bb);
6429 if (gimple_omp_for_combined_p (fd->for_stmt))
6431 remove_edge (e);
6432 e = NULL;
6434 else if (fd->collapse > 1)
6436 remove_edge (e);
6437 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6439 else
6440 e->flags = EDGE_TRUE_VALUE;
6441 if (e)
6443 e->probability = REG_BR_PROB_BASE * 7 / 8;
6444 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6446 else
6448 e = find_edge (cont_bb, l2_bb);
6449 e->flags = EDGE_FALLTHRU;
6451 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6453 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6454 recompute_dominator (CDI_DOMINATORS, l2_bb));
6455 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6456 recompute_dominator (CDI_DOMINATORS, l3_bb));
6457 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6458 recompute_dominator (CDI_DOMINATORS, l0_bb));
6459 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6460 recompute_dominator (CDI_DOMINATORS, l1_bb));
6462 struct loop *outer_loop = alloc_loop ();
6463 outer_loop->header = l0_bb;
6464 outer_loop->latch = l2_bb;
6465 add_loop (outer_loop, l0_bb->loop_father);
6467 if (!gimple_omp_for_combined_p (fd->for_stmt))
6469 struct loop *loop = alloc_loop ();
6470 loop->header = l1_bb;
6471 /* The loop may have multiple latches. */
6472 add_loop (loop, outer_loop);
6478 /* A subroutine of expand_omp_for. Generate code for a parallel
6479 loop with static schedule and no specified chunk size. Given
6480 parameters:
6482 for (V = N1; V cond N2; V += STEP) BODY;
6484 where COND is "<" or ">", we generate pseudocode
6486 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6487 if (cond is <)
6488 adj = STEP - 1;
6489 else
6490 adj = STEP + 1;
6491 if ((__typeof (V)) -1 > 0 && cond is >)
6492 n = -(adj + N2 - N1) / -STEP;
6493 else
6494 n = (adj + N2 - N1) / STEP;
6495 q = n / nthreads;
6496 tt = n % nthreads;
6497 if (threadid < tt) goto L3; else goto L4;
6499 tt = 0;
6500 q = q + 1;
6502 s0 = q * threadid + tt;
6503 e0 = s0 + q;
6504 V = s0 * STEP + N1;
6505 if (s0 >= e0) goto L2; else goto L0;
6507 e = e0 * STEP + N1;
6509 BODY;
6510 V += STEP;
6511 if (V cond e) goto L1;
6515 static void
6516 expand_omp_for_static_nochunk (struct omp_region *region,
6517 struct omp_for_data *fd,
6518 gimple inner_stmt)
6520 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6521 tree type, itype, vmain, vback;
6522 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6523 basic_block body_bb, cont_bb, collapse_bb = NULL;
6524 basic_block fin_bb;
6525 gimple_stmt_iterator gsi;
6526 edge ep;
6527 bool broken_loop = region->cont == NULL;
6528 tree *counts = NULL;
6529 tree n1, n2, step;
6531 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6532 != GF_OMP_FOR_KIND_OACC_LOOP)
6533 || !inner_stmt);
6535 itype = type = TREE_TYPE (fd->loop.v);
6536 if (POINTER_TYPE_P (type))
6537 itype = signed_type_for (type);
6539 entry_bb = region->entry;
6540 cont_bb = region->cont;
6541 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6542 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6543 gcc_assert (broken_loop
6544 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6545 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6546 body_bb = single_succ (seq_start_bb);
6547 if (!broken_loop)
6549 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6550 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6552 exit_bb = region->exit;
6554 /* Iteration space partitioning goes in ENTRY_BB. */
6555 gsi = gsi_last_bb (entry_bb);
6556 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6558 if (fd->collapse > 1)
6560 int first_zero_iter = -1;
6561 basic_block l2_dom_bb = NULL;
6563 counts = XALLOCAVEC (tree, fd->collapse);
6564 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6565 fin_bb, first_zero_iter,
6566 l2_dom_bb);
6567 t = NULL_TREE;
6569 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6570 t = integer_one_node;
6571 else
6572 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6573 fold_convert (type, fd->loop.n1),
6574 fold_convert (type, fd->loop.n2));
6575 if (fd->collapse == 1
6576 && TYPE_UNSIGNED (type)
6577 && (t == NULL_TREE || !integer_onep (t)))
6579 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6580 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6581 true, GSI_SAME_STMT);
6582 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6583 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6584 true, GSI_SAME_STMT);
6585 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6586 NULL_TREE, NULL_TREE);
6587 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6588 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6589 expand_omp_regimplify_p, NULL, NULL)
6590 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6591 expand_omp_regimplify_p, NULL, NULL))
6593 gsi = gsi_for_stmt (cond_stmt);
6594 gimple_regimplify_operands (cond_stmt, &gsi);
6596 ep = split_block (entry_bb, cond_stmt);
6597 ep->flags = EDGE_TRUE_VALUE;
6598 entry_bb = ep->dest;
6599 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6600 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6601 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6602 if (gimple_in_ssa_p (cfun))
6604 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6605 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6606 !gsi_end_p (gpi); gsi_next (&gpi))
6608 gphi *phi = gpi.phi ();
6609 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6610 ep, UNKNOWN_LOCATION);
6613 gsi = gsi_last_bb (entry_bb);
6616 switch (gimple_omp_for_kind (fd->for_stmt))
6618 case GF_OMP_FOR_KIND_FOR:
6619 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6620 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6621 break;
6622 case GF_OMP_FOR_KIND_DISTRIBUTE:
6623 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6624 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6625 break;
6626 case GF_OMP_FOR_KIND_OACC_LOOP:
6627 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6628 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6629 break;
6630 default:
6631 gcc_unreachable ();
6633 nthreads = build_call_expr (nthreads, 0);
6634 nthreads = fold_convert (itype, nthreads);
6635 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6636 true, GSI_SAME_STMT);
6637 threadid = build_call_expr (threadid, 0);
6638 threadid = fold_convert (itype, threadid);
6639 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6640 true, GSI_SAME_STMT);
6642 n1 = fd->loop.n1;
6643 n2 = fd->loop.n2;
6644 step = fd->loop.step;
6645 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6647 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6648 OMP_CLAUSE__LOOPTEMP_);
6649 gcc_assert (innerc);
6650 n1 = OMP_CLAUSE_DECL (innerc);
6651 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6652 OMP_CLAUSE__LOOPTEMP_);
6653 gcc_assert (innerc);
6654 n2 = OMP_CLAUSE_DECL (innerc);
6656 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6657 true, NULL_TREE, true, GSI_SAME_STMT);
6658 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6659 true, NULL_TREE, true, GSI_SAME_STMT);
6660 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6661 true, NULL_TREE, true, GSI_SAME_STMT);
6663 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6664 t = fold_build2 (PLUS_EXPR, itype, step, t);
6665 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6666 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6667 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6668 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6669 fold_build1 (NEGATE_EXPR, itype, t),
6670 fold_build1 (NEGATE_EXPR, itype, step));
6671 else
6672 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6673 t = fold_convert (itype, t);
6674 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6676 q = create_tmp_reg (itype, "q");
6677 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6678 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6679 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6681 tt = create_tmp_reg (itype, "tt");
6682 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6683 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6684 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6686 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6687 gcond *cond_stmt = gimple_build_cond_empty (t);
6688 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6690 second_bb = split_block (entry_bb, cond_stmt)->dest;
6691 gsi = gsi_last_bb (second_bb);
6692 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6694 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6695 GSI_SAME_STMT);
6696 gassign *assign_stmt
6697 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6698 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6700 third_bb = split_block (second_bb, assign_stmt)->dest;
6701 gsi = gsi_last_bb (third_bb);
6702 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6704 t = build2 (MULT_EXPR, itype, q, threadid);
6705 t = build2 (PLUS_EXPR, itype, t, tt);
6706 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6708 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6709 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6711 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6712 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6714 /* Remove the GIMPLE_OMP_FOR statement. */
6715 gsi_remove (&gsi, true);
6717 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6718 gsi = gsi_start_bb (seq_start_bb);
6720 tree startvar = fd->loop.v;
6721 tree endvar = NULL_TREE;
6723 if (gimple_omp_for_combined_p (fd->for_stmt))
6725 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6726 ? gimple_omp_parallel_clauses (inner_stmt)
6727 : gimple_omp_for_clauses (inner_stmt);
6728 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6729 gcc_assert (innerc);
6730 startvar = OMP_CLAUSE_DECL (innerc);
6731 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6732 OMP_CLAUSE__LOOPTEMP_);
6733 gcc_assert (innerc);
6734 endvar = OMP_CLAUSE_DECL (innerc);
6736 t = fold_convert (itype, s0);
6737 t = fold_build2 (MULT_EXPR, itype, t, step);
6738 if (POINTER_TYPE_P (type))
6739 t = fold_build_pointer_plus (n1, t);
6740 else
6741 t = fold_build2 (PLUS_EXPR, type, t, n1);
6742 t = fold_convert (TREE_TYPE (startvar), t);
6743 t = force_gimple_operand_gsi (&gsi, t,
6744 DECL_P (startvar)
6745 && TREE_ADDRESSABLE (startvar),
6746 NULL_TREE, false, GSI_CONTINUE_LINKING);
6747 assign_stmt = gimple_build_assign (startvar, t);
6748 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6750 t = fold_convert (itype, e0);
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 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6758 false, GSI_CONTINUE_LINKING);
6759 if (endvar)
6761 assign_stmt = gimple_build_assign (endvar, e);
6762 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6763 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6764 assign_stmt = gimple_build_assign (fd->loop.v, e);
6765 else
6766 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6767 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6769 if (fd->collapse > 1)
6770 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6772 if (!broken_loop)
6774 /* The code controlling the sequential loop replaces the
6775 GIMPLE_OMP_CONTINUE. */
6776 gsi = gsi_last_bb (cont_bb);
6777 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6778 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6779 vmain = gimple_omp_continue_control_use (cont_stmt);
6780 vback = gimple_omp_continue_control_def (cont_stmt);
6782 if (!gimple_omp_for_combined_p (fd->for_stmt))
6784 if (POINTER_TYPE_P (type))
6785 t = fold_build_pointer_plus (vmain, step);
6786 else
6787 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6788 t = force_gimple_operand_gsi (&gsi, t,
6789 DECL_P (vback)
6790 && TREE_ADDRESSABLE (vback),
6791 NULL_TREE, true, GSI_SAME_STMT);
6792 assign_stmt = gimple_build_assign (vback, t);
6793 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6795 t = build2 (fd->loop.cond_code, boolean_type_node,
6796 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6797 ? t : vback, e);
6798 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6801 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6802 gsi_remove (&gsi, true);
6804 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6805 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6808 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6809 gsi = gsi_last_bb (exit_bb);
6810 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6812 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6813 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6814 gcc_checking_assert (t == NULL_TREE);
6815 else
6816 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6818 gsi_remove (&gsi, true);
6820 /* Connect all the blocks. */
6821 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6822 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6823 ep = find_edge (entry_bb, second_bb);
6824 ep->flags = EDGE_TRUE_VALUE;
6825 ep->probability = REG_BR_PROB_BASE / 4;
6826 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6827 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6829 if (!broken_loop)
6831 ep = find_edge (cont_bb, body_bb);
6832 if (gimple_omp_for_combined_p (fd->for_stmt))
6834 remove_edge (ep);
6835 ep = NULL;
6837 else if (fd->collapse > 1)
6839 remove_edge (ep);
6840 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6842 else
6843 ep->flags = EDGE_TRUE_VALUE;
6844 find_edge (cont_bb, fin_bb)->flags
6845 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6848 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6849 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6850 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6852 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6853 recompute_dominator (CDI_DOMINATORS, body_bb));
6854 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6855 recompute_dominator (CDI_DOMINATORS, fin_bb));
6857 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6859 struct loop *loop = alloc_loop ();
6860 loop->header = body_bb;
6861 if (collapse_bb == NULL)
6862 loop->latch = cont_bb;
6863 add_loop (loop, body_bb->loop_father);
6868 /* A subroutine of expand_omp_for. Generate code for a parallel
6869 loop with static schedule and a specified chunk size. Given
6870 parameters:
6872 for (V = N1; V cond N2; V += STEP) BODY;
6874 where COND is "<" or ">", we generate pseudocode
6876 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6877 if (cond is <)
6878 adj = STEP - 1;
6879 else
6880 adj = STEP + 1;
6881 if ((__typeof (V)) -1 > 0 && cond is >)
6882 n = -(adj + N2 - N1) / -STEP;
6883 else
6884 n = (adj + N2 - N1) / STEP;
6885 trip = 0;
6886 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6887 here so that V is defined
6888 if the loop is not entered
6890 s0 = (trip * nthreads + threadid) * CHUNK;
6891 e0 = min(s0 + CHUNK, n);
6892 if (s0 < n) goto L1; else goto L4;
6894 V = s0 * STEP + N1;
6895 e = e0 * STEP + N1;
6897 BODY;
6898 V += STEP;
6899 if (V cond e) goto L2; else goto L3;
6901 trip += 1;
6902 goto L0;
6906 static void
6907 expand_omp_for_static_chunk (struct omp_region *region,
6908 struct omp_for_data *fd, gimple inner_stmt)
6910 tree n, s0, e0, e, t;
6911 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6912 tree type, itype, vmain, vback, vextra;
6913 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6914 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6915 gimple_stmt_iterator gsi;
6916 edge se;
6917 bool broken_loop = region->cont == NULL;
6918 tree *counts = NULL;
6919 tree n1, n2, step;
6921 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6922 != GF_OMP_FOR_KIND_OACC_LOOP)
6923 || !inner_stmt);
6925 itype = type = TREE_TYPE (fd->loop.v);
6926 if (POINTER_TYPE_P (type))
6927 itype = signed_type_for (type);
6929 entry_bb = region->entry;
6930 se = split_block (entry_bb, last_stmt (entry_bb));
6931 entry_bb = se->src;
6932 iter_part_bb = se->dest;
6933 cont_bb = region->cont;
6934 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6935 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6936 gcc_assert (broken_loop
6937 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6938 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6939 body_bb = single_succ (seq_start_bb);
6940 if (!broken_loop)
6942 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6943 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6944 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6946 exit_bb = region->exit;
6948 /* Trip and adjustment setup goes in ENTRY_BB. */
6949 gsi = gsi_last_bb (entry_bb);
6950 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6952 if (fd->collapse > 1)
6954 int first_zero_iter = -1;
6955 basic_block l2_dom_bb = NULL;
6957 counts = XALLOCAVEC (tree, fd->collapse);
6958 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6959 fin_bb, first_zero_iter,
6960 l2_dom_bb);
6961 t = NULL_TREE;
6963 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6964 t = integer_one_node;
6965 else
6966 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6967 fold_convert (type, fd->loop.n1),
6968 fold_convert (type, fd->loop.n2));
6969 if (fd->collapse == 1
6970 && TYPE_UNSIGNED (type)
6971 && (t == NULL_TREE || !integer_onep (t)))
6973 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6974 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6975 true, GSI_SAME_STMT);
6976 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6977 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6978 true, GSI_SAME_STMT);
6979 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6980 NULL_TREE, NULL_TREE);
6981 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6982 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6983 expand_omp_regimplify_p, NULL, NULL)
6984 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6985 expand_omp_regimplify_p, NULL, NULL))
6987 gsi = gsi_for_stmt (cond_stmt);
6988 gimple_regimplify_operands (cond_stmt, &gsi);
6990 se = split_block (entry_bb, cond_stmt);
6991 se->flags = EDGE_TRUE_VALUE;
6992 entry_bb = se->dest;
6993 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6994 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6995 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6996 if (gimple_in_ssa_p (cfun))
6998 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6999 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
7000 !gsi_end_p (gpi); gsi_next (&gpi))
7002 gphi *phi = gpi.phi ();
7003 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
7004 se, UNKNOWN_LOCATION);
7007 gsi = gsi_last_bb (entry_bb);
7010 switch (gimple_omp_for_kind (fd->for_stmt))
7012 case GF_OMP_FOR_KIND_FOR:
7013 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7014 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7015 break;
7016 case GF_OMP_FOR_KIND_DISTRIBUTE:
7017 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7018 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7019 break;
7020 case GF_OMP_FOR_KIND_OACC_LOOP:
7021 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7022 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7023 break;
7024 default:
7025 gcc_unreachable ();
7027 nthreads = build_call_expr (nthreads, 0);
7028 nthreads = fold_convert (itype, nthreads);
7029 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7030 true, GSI_SAME_STMT);
7031 threadid = build_call_expr (threadid, 0);
7032 threadid = fold_convert (itype, threadid);
7033 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7034 true, GSI_SAME_STMT);
7036 n1 = fd->loop.n1;
7037 n2 = fd->loop.n2;
7038 step = fd->loop.step;
7039 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7041 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7042 OMP_CLAUSE__LOOPTEMP_);
7043 gcc_assert (innerc);
7044 n1 = OMP_CLAUSE_DECL (innerc);
7045 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7046 OMP_CLAUSE__LOOPTEMP_);
7047 gcc_assert (innerc);
7048 n2 = OMP_CLAUSE_DECL (innerc);
7050 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7051 true, NULL_TREE, true, GSI_SAME_STMT);
7052 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7053 true, NULL_TREE, true, GSI_SAME_STMT);
7054 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7055 true, NULL_TREE, true, GSI_SAME_STMT);
7056 fd->chunk_size
7057 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7058 true, NULL_TREE, true, GSI_SAME_STMT);
7060 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7061 t = fold_build2 (PLUS_EXPR, itype, step, t);
7062 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7063 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7064 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7065 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7066 fold_build1 (NEGATE_EXPR, itype, t),
7067 fold_build1 (NEGATE_EXPR, itype, step));
7068 else
7069 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7070 t = fold_convert (itype, t);
7071 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7072 true, GSI_SAME_STMT);
7074 trip_var = create_tmp_reg (itype, ".trip");
7075 if (gimple_in_ssa_p (cfun))
7077 trip_init = make_ssa_name (trip_var);
7078 trip_main = make_ssa_name (trip_var);
7079 trip_back = make_ssa_name (trip_var);
7081 else
7083 trip_init = trip_var;
7084 trip_main = trip_var;
7085 trip_back = trip_var;
7088 gassign *assign_stmt
7089 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7090 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7092 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7093 t = fold_build2 (MULT_EXPR, itype, t, step);
7094 if (POINTER_TYPE_P (type))
7095 t = fold_build_pointer_plus (n1, t);
7096 else
7097 t = fold_build2 (PLUS_EXPR, type, t, n1);
7098 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7099 true, GSI_SAME_STMT);
7101 /* Remove the GIMPLE_OMP_FOR. */
7102 gsi_remove (&gsi, true);
7104 /* Iteration space partitioning goes in ITER_PART_BB. */
7105 gsi = gsi_last_bb (iter_part_bb);
7107 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7108 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7109 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7110 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7111 false, GSI_CONTINUE_LINKING);
7113 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7114 t = fold_build2 (MIN_EXPR, itype, t, n);
7115 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7116 false, GSI_CONTINUE_LINKING);
7118 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7119 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7121 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7122 gsi = gsi_start_bb (seq_start_bb);
7124 tree startvar = fd->loop.v;
7125 tree endvar = NULL_TREE;
7127 if (gimple_omp_for_combined_p (fd->for_stmt))
7129 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7130 ? gimple_omp_parallel_clauses (inner_stmt)
7131 : gimple_omp_for_clauses (inner_stmt);
7132 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7133 gcc_assert (innerc);
7134 startvar = OMP_CLAUSE_DECL (innerc);
7135 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7136 OMP_CLAUSE__LOOPTEMP_);
7137 gcc_assert (innerc);
7138 endvar = OMP_CLAUSE_DECL (innerc);
7141 t = fold_convert (itype, s0);
7142 t = fold_build2 (MULT_EXPR, itype, t, step);
7143 if (POINTER_TYPE_P (type))
7144 t = fold_build_pointer_plus (n1, t);
7145 else
7146 t = fold_build2 (PLUS_EXPR, type, t, n1);
7147 t = fold_convert (TREE_TYPE (startvar), t);
7148 t = force_gimple_operand_gsi (&gsi, t,
7149 DECL_P (startvar)
7150 && TREE_ADDRESSABLE (startvar),
7151 NULL_TREE, false, GSI_CONTINUE_LINKING);
7152 assign_stmt = gimple_build_assign (startvar, t);
7153 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7155 t = fold_convert (itype, e0);
7156 t = fold_build2 (MULT_EXPR, itype, t, step);
7157 if (POINTER_TYPE_P (type))
7158 t = fold_build_pointer_plus (n1, t);
7159 else
7160 t = fold_build2 (PLUS_EXPR, type, t, n1);
7161 t = fold_convert (TREE_TYPE (startvar), t);
7162 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7163 false, GSI_CONTINUE_LINKING);
7164 if (endvar)
7166 assign_stmt = gimple_build_assign (endvar, e);
7167 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7168 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7169 assign_stmt = gimple_build_assign (fd->loop.v, e);
7170 else
7171 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7172 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7174 if (fd->collapse > 1)
7175 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7177 if (!broken_loop)
7179 /* The code controlling the sequential loop goes in CONT_BB,
7180 replacing the GIMPLE_OMP_CONTINUE. */
7181 gsi = gsi_last_bb (cont_bb);
7182 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7183 vmain = gimple_omp_continue_control_use (cont_stmt);
7184 vback = gimple_omp_continue_control_def (cont_stmt);
7186 if (!gimple_omp_for_combined_p (fd->for_stmt))
7188 if (POINTER_TYPE_P (type))
7189 t = fold_build_pointer_plus (vmain, step);
7190 else
7191 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7192 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7193 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7194 true, GSI_SAME_STMT);
7195 assign_stmt = gimple_build_assign (vback, t);
7196 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7198 t = build2 (fd->loop.cond_code, boolean_type_node,
7199 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7200 ? t : vback, e);
7201 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7204 /* Remove GIMPLE_OMP_CONTINUE. */
7205 gsi_remove (&gsi, true);
7207 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7208 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7210 /* Trip update code goes into TRIP_UPDATE_BB. */
7211 gsi = gsi_start_bb (trip_update_bb);
7213 t = build_int_cst (itype, 1);
7214 t = build2 (PLUS_EXPR, itype, trip_main, t);
7215 assign_stmt = gimple_build_assign (trip_back, t);
7216 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7219 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7220 gsi = gsi_last_bb (exit_bb);
7221 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7223 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7224 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7225 gcc_checking_assert (t == NULL_TREE);
7226 else
7227 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7229 gsi_remove (&gsi, true);
7231 /* Connect the new blocks. */
7232 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7233 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7235 if (!broken_loop)
7237 se = find_edge (cont_bb, body_bb);
7238 if (gimple_omp_for_combined_p (fd->for_stmt))
7240 remove_edge (se);
7241 se = NULL;
7243 else if (fd->collapse > 1)
7245 remove_edge (se);
7246 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7248 else
7249 se->flags = EDGE_TRUE_VALUE;
7250 find_edge (cont_bb, trip_update_bb)->flags
7251 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7253 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7256 if (gimple_in_ssa_p (cfun))
7258 gphi_iterator psi;
7259 gphi *phi;
7260 edge re, ene;
7261 edge_var_map *vm;
7262 size_t i;
7264 gcc_assert (fd->collapse == 1 && !broken_loop);
7266 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7267 remove arguments of the phi nodes in fin_bb. We need to create
7268 appropriate phi nodes in iter_part_bb instead. */
7269 se = single_pred_edge (fin_bb);
7270 re = single_succ_edge (trip_update_bb);
7271 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7272 ene = single_succ_edge (entry_bb);
7274 psi = gsi_start_phis (fin_bb);
7275 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7276 gsi_next (&psi), ++i)
7278 gphi *nphi;
7279 source_location locus;
7281 phi = psi.phi ();
7282 t = gimple_phi_result (phi);
7283 gcc_assert (t == redirect_edge_var_map_result (vm));
7284 nphi = create_phi_node (t, iter_part_bb);
7286 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7287 locus = gimple_phi_arg_location_from_edge (phi, se);
7289 /* A special case -- fd->loop.v is not yet computed in
7290 iter_part_bb, we need to use vextra instead. */
7291 if (t == fd->loop.v)
7292 t = vextra;
7293 add_phi_arg (nphi, t, ene, locus);
7294 locus = redirect_edge_var_map_location (vm);
7295 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7297 gcc_assert (gsi_end_p (psi) && i == head->length ());
7298 redirect_edge_var_map_clear (re);
7299 while (1)
7301 psi = gsi_start_phis (fin_bb);
7302 if (gsi_end_p (psi))
7303 break;
7304 remove_phi_node (&psi, false);
7307 /* Make phi node for trip. */
7308 phi = create_phi_node (trip_main, iter_part_bb);
7309 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7310 UNKNOWN_LOCATION);
7311 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7312 UNKNOWN_LOCATION);
7315 if (!broken_loop)
7316 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7317 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7318 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7319 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7320 recompute_dominator (CDI_DOMINATORS, fin_bb));
7321 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7322 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7323 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7324 recompute_dominator (CDI_DOMINATORS, body_bb));
7326 if (!broken_loop)
7328 struct loop *trip_loop = alloc_loop ();
7329 trip_loop->header = iter_part_bb;
7330 trip_loop->latch = trip_update_bb;
7331 add_loop (trip_loop, iter_part_bb->loop_father);
7333 if (!gimple_omp_for_combined_p (fd->for_stmt))
7335 struct loop *loop = alloc_loop ();
7336 loop->header = body_bb;
7337 if (collapse_bb == NULL)
7338 loop->latch = cont_bb;
7339 add_loop (loop, trip_loop);
7344 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7345 Given parameters:
7346 for (V = N1; V cond N2; V += STEP) BODY;
7348 where COND is "<" or ">" or "!=", we generate pseudocode
7350 for (ind_var = low; ind_var < high; ind_var++)
7352 V = n1 + (ind_var * STEP)
7354 <BODY>
7357 In the above pseudocode, low and high are function parameters of the
7358 child function. In the function below, we are inserting a temp.
7359 variable that will be making a call to two OMP functions that will not be
7360 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7361 with _Cilk_for). These functions are replaced with low and high
7362 by the function that handles taskreg. */
7365 static void
7366 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7368 bool broken_loop = region->cont == NULL;
7369 basic_block entry_bb = region->entry;
7370 basic_block cont_bb = region->cont;
7372 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7373 gcc_assert (broken_loop
7374 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7375 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7376 basic_block l1_bb, l2_bb;
7378 if (!broken_loop)
7380 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7381 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7382 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7383 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7385 else
7387 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7388 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7389 l2_bb = single_succ (l1_bb);
7391 basic_block exit_bb = region->exit;
7392 basic_block l2_dom_bb = NULL;
7394 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7396 /* Below statements until the "tree high_val = ..." are pseudo statements
7397 used to pass information to be used by expand_omp_taskreg.
7398 low_val and high_val will be replaced by the __low and __high
7399 parameter from the child function.
7401 The call_exprs part is a place-holder, it is mainly used
7402 to distinctly identify to the top-level part that this is
7403 where we should put low and high (reasoning given in header
7404 comment). */
7406 tree child_fndecl
7407 = gimple_omp_parallel_child_fn (
7408 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7409 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7410 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7412 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7413 high_val = t;
7414 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7415 low_val = t;
7417 gcc_assert (low_val && high_val);
7419 tree type = TREE_TYPE (low_val);
7420 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7421 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7423 /* Not needed in SSA form right now. */
7424 gcc_assert (!gimple_in_ssa_p (cfun));
7425 if (l2_dom_bb == NULL)
7426 l2_dom_bb = l1_bb;
7428 tree n1 = low_val;
7429 tree n2 = high_val;
7431 gimple stmt = gimple_build_assign (ind_var, n1);
7433 /* Replace the GIMPLE_OMP_FOR statement. */
7434 gsi_replace (&gsi, stmt, true);
7436 if (!broken_loop)
7438 /* Code to control the increment goes in the CONT_BB. */
7439 gsi = gsi_last_bb (cont_bb);
7440 stmt = gsi_stmt (gsi);
7441 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7442 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7443 build_one_cst (type));
7445 /* Replace GIMPLE_OMP_CONTINUE. */
7446 gsi_replace (&gsi, stmt, true);
7449 /* Emit the condition in L1_BB. */
7450 gsi = gsi_after_labels (l1_bb);
7451 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7452 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7453 fd->loop.step);
7454 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7455 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7456 fd->loop.n1, fold_convert (sizetype, t));
7457 else
7458 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7459 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7460 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7461 expand_omp_build_assign (&gsi, fd->loop.v, t);
7463 /* The condition is always '<' since the runtime will fill in the low
7464 and high values. */
7465 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7466 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7468 /* Remove GIMPLE_OMP_RETURN. */
7469 gsi = gsi_last_bb (exit_bb);
7470 gsi_remove (&gsi, true);
7472 /* Connect the new blocks. */
7473 remove_edge (FALLTHRU_EDGE (entry_bb));
7475 edge e, ne;
7476 if (!broken_loop)
7478 remove_edge (BRANCH_EDGE (entry_bb));
7479 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7481 e = BRANCH_EDGE (l1_bb);
7482 ne = FALLTHRU_EDGE (l1_bb);
7483 e->flags = EDGE_TRUE_VALUE;
7485 else
7487 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7489 ne = single_succ_edge (l1_bb);
7490 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7493 ne->flags = EDGE_FALSE_VALUE;
7494 e->probability = REG_BR_PROB_BASE * 7 / 8;
7495 ne->probability = REG_BR_PROB_BASE / 8;
7497 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7498 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7499 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7501 if (!broken_loop)
7503 struct loop *loop = alloc_loop ();
7504 loop->header = l1_bb;
7505 loop->latch = cont_bb;
7506 add_loop (loop, l1_bb->loop_father);
7507 loop->safelen = INT_MAX;
7510 /* Pick the correct library function based on the precision of the
7511 induction variable type. */
7512 tree lib_fun = NULL_TREE;
7513 if (TYPE_PRECISION (type) == 32)
7514 lib_fun = cilk_for_32_fndecl;
7515 else if (TYPE_PRECISION (type) == 64)
7516 lib_fun = cilk_for_64_fndecl;
7517 else
7518 gcc_unreachable ();
7520 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7522 /* WS_ARGS contains the library function flavor to call:
7523 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7524 user-defined grain value. If the user does not define one, then zero
7525 is passed in by the parser. */
7526 vec_alloc (region->ws_args, 2);
7527 region->ws_args->quick_push (lib_fun);
7528 region->ws_args->quick_push (fd->chunk_size);
7531 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7532 loop. Given parameters:
7534 for (V = N1; V cond N2; V += STEP) BODY;
7536 where COND is "<" or ">", we generate pseudocode
7538 V = N1;
7539 goto L1;
7541 BODY;
7542 V += STEP;
7544 if (V cond N2) goto L0; else goto L2;
7547 For collapsed loops, given parameters:
7548 collapse(3)
7549 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7550 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7551 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7552 BODY;
7554 we generate pseudocode
7556 if (cond3 is <)
7557 adj = STEP3 - 1;
7558 else
7559 adj = STEP3 + 1;
7560 count3 = (adj + N32 - N31) / STEP3;
7561 if (cond2 is <)
7562 adj = STEP2 - 1;
7563 else
7564 adj = STEP2 + 1;
7565 count2 = (adj + N22 - N21) / STEP2;
7566 if (cond1 is <)
7567 adj = STEP1 - 1;
7568 else
7569 adj = STEP1 + 1;
7570 count1 = (adj + N12 - N11) / STEP1;
7571 count = count1 * count2 * count3;
7572 V = 0;
7573 V1 = N11;
7574 V2 = N21;
7575 V3 = N31;
7576 goto L1;
7578 BODY;
7579 V += 1;
7580 V3 += STEP3;
7581 V2 += (V3 cond3 N32) ? 0 : STEP2;
7582 V3 = (V3 cond3 N32) ? V3 : N31;
7583 V1 += (V2 cond2 N22) ? 0 : STEP1;
7584 V2 = (V2 cond2 N22) ? V2 : N21;
7586 if (V < count) goto L0; else goto L2;
7591 static void
7592 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7594 tree type, t;
7595 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7596 gimple_stmt_iterator gsi;
7597 gimple stmt;
7598 gcond *cond_stmt;
7599 bool broken_loop = region->cont == NULL;
7600 edge e, ne;
7601 tree *counts = NULL;
7602 int i;
7603 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7604 OMP_CLAUSE_SAFELEN);
7605 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7606 OMP_CLAUSE__SIMDUID_);
7607 tree n1, n2;
7609 type = TREE_TYPE (fd->loop.v);
7610 entry_bb = region->entry;
7611 cont_bb = region->cont;
7612 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7613 gcc_assert (broken_loop
7614 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7615 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7616 if (!broken_loop)
7618 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7619 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7620 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7621 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7623 else
7625 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7626 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7627 l2_bb = single_succ (l1_bb);
7629 exit_bb = region->exit;
7630 l2_dom_bb = NULL;
7632 gsi = gsi_last_bb (entry_bb);
7634 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7635 /* Not needed in SSA form right now. */
7636 gcc_assert (!gimple_in_ssa_p (cfun));
7637 if (fd->collapse > 1)
7639 int first_zero_iter = -1;
7640 basic_block zero_iter_bb = l2_bb;
7642 counts = XALLOCAVEC (tree, fd->collapse);
7643 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7644 zero_iter_bb, first_zero_iter,
7645 l2_dom_bb);
7647 if (l2_dom_bb == NULL)
7648 l2_dom_bb = l1_bb;
7650 n1 = fd->loop.n1;
7651 n2 = fd->loop.n2;
7652 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7654 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7655 OMP_CLAUSE__LOOPTEMP_);
7656 gcc_assert (innerc);
7657 n1 = OMP_CLAUSE_DECL (innerc);
7658 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7659 OMP_CLAUSE__LOOPTEMP_);
7660 gcc_assert (innerc);
7661 n2 = OMP_CLAUSE_DECL (innerc);
7662 expand_omp_build_assign (&gsi, fd->loop.v,
7663 fold_convert (type, n1));
7664 if (fd->collapse > 1)
7666 gsi_prev (&gsi);
7667 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7668 gsi_next (&gsi);
7671 else
7673 expand_omp_build_assign (&gsi, fd->loop.v,
7674 fold_convert (type, fd->loop.n1));
7675 if (fd->collapse > 1)
7676 for (i = 0; i < fd->collapse; i++)
7678 tree itype = TREE_TYPE (fd->loops[i].v);
7679 if (POINTER_TYPE_P (itype))
7680 itype = signed_type_for (itype);
7681 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7682 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7686 /* Remove the GIMPLE_OMP_FOR statement. */
7687 gsi_remove (&gsi, true);
7689 if (!broken_loop)
7691 /* Code to control the increment goes in the CONT_BB. */
7692 gsi = gsi_last_bb (cont_bb);
7693 stmt = gsi_stmt (gsi);
7694 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7696 if (POINTER_TYPE_P (type))
7697 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7698 else
7699 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7700 expand_omp_build_assign (&gsi, fd->loop.v, t);
7702 if (fd->collapse > 1)
7704 i = fd->collapse - 1;
7705 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7707 t = fold_convert (sizetype, fd->loops[i].step);
7708 t = fold_build_pointer_plus (fd->loops[i].v, t);
7710 else
7712 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7713 fd->loops[i].step);
7714 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7715 fd->loops[i].v, t);
7717 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7719 for (i = fd->collapse - 1; i > 0; i--)
7721 tree itype = TREE_TYPE (fd->loops[i].v);
7722 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7723 if (POINTER_TYPE_P (itype2))
7724 itype2 = signed_type_for (itype2);
7725 t = build3 (COND_EXPR, itype2,
7726 build2 (fd->loops[i].cond_code, boolean_type_node,
7727 fd->loops[i].v,
7728 fold_convert (itype, fd->loops[i].n2)),
7729 build_int_cst (itype2, 0),
7730 fold_convert (itype2, fd->loops[i - 1].step));
7731 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7732 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7733 else
7734 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7735 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7737 t = build3 (COND_EXPR, itype,
7738 build2 (fd->loops[i].cond_code, boolean_type_node,
7739 fd->loops[i].v,
7740 fold_convert (itype, fd->loops[i].n2)),
7741 fd->loops[i].v,
7742 fold_convert (itype, fd->loops[i].n1));
7743 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7747 /* Remove GIMPLE_OMP_CONTINUE. */
7748 gsi_remove (&gsi, true);
7751 /* Emit the condition in L1_BB. */
7752 gsi = gsi_start_bb (l1_bb);
7754 t = fold_convert (type, n2);
7755 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7756 false, GSI_CONTINUE_LINKING);
7757 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7758 cond_stmt = gimple_build_cond_empty (t);
7759 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7760 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7761 NULL, NULL)
7762 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7763 NULL, NULL))
7765 gsi = gsi_for_stmt (cond_stmt);
7766 gimple_regimplify_operands (cond_stmt, &gsi);
7769 /* Remove GIMPLE_OMP_RETURN. */
7770 gsi = gsi_last_bb (exit_bb);
7771 gsi_remove (&gsi, true);
7773 /* Connect the new blocks. */
7774 remove_edge (FALLTHRU_EDGE (entry_bb));
7776 if (!broken_loop)
7778 remove_edge (BRANCH_EDGE (entry_bb));
7779 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7781 e = BRANCH_EDGE (l1_bb);
7782 ne = FALLTHRU_EDGE (l1_bb);
7783 e->flags = EDGE_TRUE_VALUE;
7785 else
7787 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7789 ne = single_succ_edge (l1_bb);
7790 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7793 ne->flags = EDGE_FALSE_VALUE;
7794 e->probability = REG_BR_PROB_BASE * 7 / 8;
7795 ne->probability = REG_BR_PROB_BASE / 8;
7797 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7798 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7799 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7801 if (!broken_loop)
7803 struct loop *loop = alloc_loop ();
7804 loop->header = l1_bb;
7805 loop->latch = cont_bb;
7806 add_loop (loop, l1_bb->loop_father);
7807 if (safelen == NULL_TREE)
7808 loop->safelen = INT_MAX;
7809 else
7811 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7812 if (TREE_CODE (safelen) != INTEGER_CST)
7813 loop->safelen = 0;
7814 else if (!tree_fits_uhwi_p (safelen)
7815 || tree_to_uhwi (safelen) > INT_MAX)
7816 loop->safelen = INT_MAX;
7817 else
7818 loop->safelen = tree_to_uhwi (safelen);
7819 if (loop->safelen == 1)
7820 loop->safelen = 0;
7822 if (simduid)
7824 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7825 cfun->has_simduid_loops = true;
7827 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7828 the loop. */
7829 if ((flag_tree_loop_vectorize
7830 || (!global_options_set.x_flag_tree_loop_vectorize
7831 && !global_options_set.x_flag_tree_vectorize))
7832 && flag_tree_loop_optimize
7833 && loop->safelen > 1)
7835 loop->force_vectorize = true;
7836 cfun->has_force_vectorize_loops = true;
7839 else if (simduid)
7840 cfun->has_simduid_loops = true;
7844 /* Expand the OMP loop defined by REGION. */
7846 static void
7847 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7849 struct omp_for_data fd;
7850 struct omp_for_data_loop *loops;
7852 loops
7853 = (struct omp_for_data_loop *)
7854 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7855 * sizeof (struct omp_for_data_loop));
7856 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7857 &fd, loops);
7858 region->sched_kind = fd.sched_kind;
7860 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7861 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7862 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7863 if (region->cont)
7865 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7866 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7867 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7869 else
7870 /* If there isn't a continue then this is a degerate case where
7871 the introduction of abnormal edges during lowering will prevent
7872 original loops from being detected. Fix that up. */
7873 loops_state_set (LOOPS_NEED_FIXUP);
7875 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7876 expand_omp_simd (region, &fd);
7877 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7878 expand_cilk_for (region, &fd);
7879 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7880 && !fd.have_ordered)
7882 if (fd.chunk_size == NULL)
7883 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7884 else
7885 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7887 else
7889 int fn_index, start_ix, next_ix;
7891 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7892 == GF_OMP_FOR_KIND_FOR);
7893 if (fd.chunk_size == NULL
7894 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7895 fd.chunk_size = integer_zero_node;
7896 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7897 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7898 ? 3 : fd.sched_kind;
7899 fn_index += fd.have_ordered * 4;
7900 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7901 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7902 if (fd.iter_type == long_long_unsigned_type_node)
7904 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7905 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7906 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7907 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7909 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7910 (enum built_in_function) next_ix, inner_stmt);
7913 if (gimple_in_ssa_p (cfun))
7914 update_ssa (TODO_update_ssa_only_virtuals);
7918 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7920 v = GOMP_sections_start (n);
7922 switch (v)
7924 case 0:
7925 goto L2;
7926 case 1:
7927 section 1;
7928 goto L1;
7929 case 2:
7931 case n:
7933 default:
7934 abort ();
7937 v = GOMP_sections_next ();
7938 goto L0;
7940 reduction;
7942 If this is a combined parallel sections, replace the call to
7943 GOMP_sections_start with call to GOMP_sections_next. */
7945 static void
7946 expand_omp_sections (struct omp_region *region)
7948 tree t, u, vin = NULL, vmain, vnext, l2;
7949 unsigned len;
7950 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7951 gimple_stmt_iterator si, switch_si;
7952 gomp_sections *sections_stmt;
7953 gimple stmt;
7954 gomp_continue *cont;
7955 edge_iterator ei;
7956 edge e;
7957 struct omp_region *inner;
7958 unsigned i, casei;
7959 bool exit_reachable = region->cont != NULL;
7961 gcc_assert (region->exit != NULL);
7962 entry_bb = region->entry;
7963 l0_bb = single_succ (entry_bb);
7964 l1_bb = region->cont;
7965 l2_bb = region->exit;
7966 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7967 l2 = gimple_block_label (l2_bb);
7968 else
7970 /* This can happen if there are reductions. */
7971 len = EDGE_COUNT (l0_bb->succs);
7972 gcc_assert (len > 0);
7973 e = EDGE_SUCC (l0_bb, len - 1);
7974 si = gsi_last_bb (e->dest);
7975 l2 = NULL_TREE;
7976 if (gsi_end_p (si)
7977 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7978 l2 = gimple_block_label (e->dest);
7979 else
7980 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7982 si = gsi_last_bb (e->dest);
7983 if (gsi_end_p (si)
7984 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7986 l2 = gimple_block_label (e->dest);
7987 break;
7991 if (exit_reachable)
7992 default_bb = create_empty_bb (l1_bb->prev_bb);
7993 else
7994 default_bb = create_empty_bb (l0_bb);
7996 /* We will build a switch() with enough cases for all the
7997 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7998 and a default case to abort if something goes wrong. */
7999 len = EDGE_COUNT (l0_bb->succs);
8001 /* Use vec::quick_push on label_vec throughout, since we know the size
8002 in advance. */
8003 auto_vec<tree> label_vec (len);
8005 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
8006 GIMPLE_OMP_SECTIONS statement. */
8007 si = gsi_last_bb (entry_bb);
8008 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
8009 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8010 vin = gimple_omp_sections_control (sections_stmt);
8011 if (!is_combined_parallel (region))
8013 /* If we are not inside a combined parallel+sections region,
8014 call GOMP_sections_start. */
8015 t = build_int_cst (unsigned_type_node, len - 1);
8016 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
8017 stmt = gimple_build_call (u, 1, t);
8019 else
8021 /* Otherwise, call GOMP_sections_next. */
8022 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8023 stmt = gimple_build_call (u, 0);
8025 gimple_call_set_lhs (stmt, vin);
8026 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8027 gsi_remove (&si, true);
8029 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8030 L0_BB. */
8031 switch_si = gsi_last_bb (l0_bb);
8032 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8033 if (exit_reachable)
8035 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8036 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8037 vmain = gimple_omp_continue_control_use (cont);
8038 vnext = gimple_omp_continue_control_def (cont);
8040 else
8042 vmain = vin;
8043 vnext = NULL_TREE;
8046 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8047 label_vec.quick_push (t);
8048 i = 1;
8050 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8051 for (inner = region->inner, casei = 1;
8052 inner;
8053 inner = inner->next, i++, casei++)
8055 basic_block s_entry_bb, s_exit_bb;
8057 /* Skip optional reduction region. */
8058 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8060 --i;
8061 --casei;
8062 continue;
8065 s_entry_bb = inner->entry;
8066 s_exit_bb = inner->exit;
8068 t = gimple_block_label (s_entry_bb);
8069 u = build_int_cst (unsigned_type_node, casei);
8070 u = build_case_label (u, NULL, t);
8071 label_vec.quick_push (u);
8073 si = gsi_last_bb (s_entry_bb);
8074 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8075 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8076 gsi_remove (&si, true);
8077 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8079 if (s_exit_bb == NULL)
8080 continue;
8082 si = gsi_last_bb (s_exit_bb);
8083 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8084 gsi_remove (&si, true);
8086 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8089 /* Error handling code goes in DEFAULT_BB. */
8090 t = gimple_block_label (default_bb);
8091 u = build_case_label (NULL, NULL, t);
8092 make_edge (l0_bb, default_bb, 0);
8093 add_bb_to_loop (default_bb, current_loops->tree_root);
8095 stmt = gimple_build_switch (vmain, u, label_vec);
8096 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8097 gsi_remove (&switch_si, true);
8099 si = gsi_start_bb (default_bb);
8100 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8101 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8103 if (exit_reachable)
8105 tree bfn_decl;
8107 /* Code to get the next section goes in L1_BB. */
8108 si = gsi_last_bb (l1_bb);
8109 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8111 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8112 stmt = gimple_build_call (bfn_decl, 0);
8113 gimple_call_set_lhs (stmt, vnext);
8114 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8115 gsi_remove (&si, true);
8117 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8120 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8121 si = gsi_last_bb (l2_bb);
8122 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8123 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8124 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8125 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8126 else
8127 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8128 stmt = gimple_build_call (t, 0);
8129 if (gimple_omp_return_lhs (gsi_stmt (si)))
8130 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8131 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8132 gsi_remove (&si, true);
8134 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8138 /* Expand code for an OpenMP single directive. We've already expanded
8139 much of the code, here we simply place the GOMP_barrier call. */
8141 static void
8142 expand_omp_single (struct omp_region *region)
8144 basic_block entry_bb, exit_bb;
8145 gimple_stmt_iterator si;
8147 entry_bb = region->entry;
8148 exit_bb = region->exit;
8150 si = gsi_last_bb (entry_bb);
8151 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8152 gsi_remove (&si, true);
8153 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8155 si = gsi_last_bb (exit_bb);
8156 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8158 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8159 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8161 gsi_remove (&si, true);
8162 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8166 /* Generic expansion for OpenMP synchronization directives: master,
8167 ordered and critical. All we need to do here is remove the entry
8168 and exit markers for REGION. */
8170 static void
8171 expand_omp_synch (struct omp_region *region)
8173 basic_block entry_bb, exit_bb;
8174 gimple_stmt_iterator si;
8176 entry_bb = region->entry;
8177 exit_bb = region->exit;
8179 si = gsi_last_bb (entry_bb);
8180 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8181 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8182 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8183 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8184 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8185 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8186 gsi_remove (&si, true);
8187 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8189 if (exit_bb)
8191 si = gsi_last_bb (exit_bb);
8192 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8193 gsi_remove (&si, true);
8194 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8198 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8199 operation as a normal volatile load. */
8201 static bool
8202 expand_omp_atomic_load (basic_block load_bb, tree addr,
8203 tree loaded_val, int index)
8205 enum built_in_function tmpbase;
8206 gimple_stmt_iterator gsi;
8207 basic_block store_bb;
8208 location_t loc;
8209 gimple stmt;
8210 tree decl, call, type, itype;
8212 gsi = gsi_last_bb (load_bb);
8213 stmt = gsi_stmt (gsi);
8214 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8215 loc = gimple_location (stmt);
8217 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8218 is smaller than word size, then expand_atomic_load assumes that the load
8219 is atomic. We could avoid the builtin entirely in this case. */
8221 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8222 decl = builtin_decl_explicit (tmpbase);
8223 if (decl == NULL_TREE)
8224 return false;
8226 type = TREE_TYPE (loaded_val);
8227 itype = TREE_TYPE (TREE_TYPE (decl));
8229 call = build_call_expr_loc (loc, decl, 2, addr,
8230 build_int_cst (NULL,
8231 gimple_omp_atomic_seq_cst_p (stmt)
8232 ? MEMMODEL_SEQ_CST
8233 : MEMMODEL_RELAXED));
8234 if (!useless_type_conversion_p (type, itype))
8235 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8236 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8238 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8239 gsi_remove (&gsi, true);
8241 store_bb = single_succ (load_bb);
8242 gsi = gsi_last_bb (store_bb);
8243 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8244 gsi_remove (&gsi, true);
8246 if (gimple_in_ssa_p (cfun))
8247 update_ssa (TODO_update_ssa_no_phi);
8249 return true;
8252 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8253 operation as a normal volatile store. */
8255 static bool
8256 expand_omp_atomic_store (basic_block load_bb, tree addr,
8257 tree loaded_val, tree stored_val, int index)
8259 enum built_in_function tmpbase;
8260 gimple_stmt_iterator gsi;
8261 basic_block store_bb = single_succ (load_bb);
8262 location_t loc;
8263 gimple stmt;
8264 tree decl, call, type, itype;
8265 machine_mode imode;
8266 bool exchange;
8268 gsi = gsi_last_bb (load_bb);
8269 stmt = gsi_stmt (gsi);
8270 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8272 /* If the load value is needed, then this isn't a store but an exchange. */
8273 exchange = gimple_omp_atomic_need_value_p (stmt);
8275 gsi = gsi_last_bb (store_bb);
8276 stmt = gsi_stmt (gsi);
8277 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8278 loc = gimple_location (stmt);
8280 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8281 is smaller than word size, then expand_atomic_store assumes that the store
8282 is atomic. We could avoid the builtin entirely in this case. */
8284 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8285 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8286 decl = builtin_decl_explicit (tmpbase);
8287 if (decl == NULL_TREE)
8288 return false;
8290 type = TREE_TYPE (stored_val);
8292 /* Dig out the type of the function's second argument. */
8293 itype = TREE_TYPE (decl);
8294 itype = TYPE_ARG_TYPES (itype);
8295 itype = TREE_CHAIN (itype);
8296 itype = TREE_VALUE (itype);
8297 imode = TYPE_MODE (itype);
8299 if (exchange && !can_atomic_exchange_p (imode, true))
8300 return false;
8302 if (!useless_type_conversion_p (itype, type))
8303 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8304 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8305 build_int_cst (NULL,
8306 gimple_omp_atomic_seq_cst_p (stmt)
8307 ? MEMMODEL_SEQ_CST
8308 : MEMMODEL_RELAXED));
8309 if (exchange)
8311 if (!useless_type_conversion_p (type, itype))
8312 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8313 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8316 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8317 gsi_remove (&gsi, true);
8319 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8320 gsi = gsi_last_bb (load_bb);
8321 gsi_remove (&gsi, true);
8323 if (gimple_in_ssa_p (cfun))
8324 update_ssa (TODO_update_ssa_no_phi);
8326 return true;
8329 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8330 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8331 size of the data type, and thus usable to find the index of the builtin
8332 decl. Returns false if the expression is not of the proper form. */
8334 static bool
8335 expand_omp_atomic_fetch_op (basic_block load_bb,
8336 tree addr, tree loaded_val,
8337 tree stored_val, int index)
8339 enum built_in_function oldbase, newbase, tmpbase;
8340 tree decl, itype, call;
8341 tree lhs, rhs;
8342 basic_block store_bb = single_succ (load_bb);
8343 gimple_stmt_iterator gsi;
8344 gimple stmt;
8345 location_t loc;
8346 enum tree_code code;
8347 bool need_old, need_new;
8348 machine_mode imode;
8349 bool seq_cst;
8351 /* We expect to find the following sequences:
8353 load_bb:
8354 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8356 store_bb:
8357 val = tmp OP something; (or: something OP tmp)
8358 GIMPLE_OMP_STORE (val)
8360 ???FIXME: Allow a more flexible sequence.
8361 Perhaps use data flow to pick the statements.
8365 gsi = gsi_after_labels (store_bb);
8366 stmt = gsi_stmt (gsi);
8367 loc = gimple_location (stmt);
8368 if (!is_gimple_assign (stmt))
8369 return false;
8370 gsi_next (&gsi);
8371 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8372 return false;
8373 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8374 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8375 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8376 gcc_checking_assert (!need_old || !need_new);
8378 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8379 return false;
8381 /* Check for one of the supported fetch-op operations. */
8382 code = gimple_assign_rhs_code (stmt);
8383 switch (code)
8385 case PLUS_EXPR:
8386 case POINTER_PLUS_EXPR:
8387 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8388 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8389 break;
8390 case MINUS_EXPR:
8391 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8392 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8393 break;
8394 case BIT_AND_EXPR:
8395 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8396 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8397 break;
8398 case BIT_IOR_EXPR:
8399 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8400 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8401 break;
8402 case BIT_XOR_EXPR:
8403 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8404 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8405 break;
8406 default:
8407 return false;
8410 /* Make sure the expression is of the proper form. */
8411 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8412 rhs = gimple_assign_rhs2 (stmt);
8413 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8414 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8415 rhs = gimple_assign_rhs1 (stmt);
8416 else
8417 return false;
8419 tmpbase = ((enum built_in_function)
8420 ((need_new ? newbase : oldbase) + index + 1));
8421 decl = builtin_decl_explicit (tmpbase);
8422 if (decl == NULL_TREE)
8423 return false;
8424 itype = TREE_TYPE (TREE_TYPE (decl));
8425 imode = TYPE_MODE (itype);
8427 /* We could test all of the various optabs involved, but the fact of the
8428 matter is that (with the exception of i486 vs i586 and xadd) all targets
8429 that support any atomic operaton optab also implements compare-and-swap.
8430 Let optabs.c take care of expanding any compare-and-swap loop. */
8431 if (!can_compare_and_swap_p (imode, true))
8432 return false;
8434 gsi = gsi_last_bb (load_bb);
8435 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8437 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8438 It only requires that the operation happen atomically. Thus we can
8439 use the RELAXED memory model. */
8440 call = build_call_expr_loc (loc, decl, 3, addr,
8441 fold_convert_loc (loc, itype, rhs),
8442 build_int_cst (NULL,
8443 seq_cst ? MEMMODEL_SEQ_CST
8444 : MEMMODEL_RELAXED));
8446 if (need_old || need_new)
8448 lhs = need_old ? loaded_val : stored_val;
8449 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8450 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8452 else
8453 call = fold_convert_loc (loc, void_type_node, call);
8454 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8455 gsi_remove (&gsi, true);
8457 gsi = gsi_last_bb (store_bb);
8458 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8459 gsi_remove (&gsi, true);
8460 gsi = gsi_last_bb (store_bb);
8461 gsi_remove (&gsi, true);
8463 if (gimple_in_ssa_p (cfun))
8464 update_ssa (TODO_update_ssa_no_phi);
8466 return true;
8469 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8471 oldval = *addr;
8472 repeat:
8473 newval = rhs; // with oldval replacing *addr in rhs
8474 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8475 if (oldval != newval)
8476 goto repeat;
8478 INDEX is log2 of the size of the data type, and thus usable to find the
8479 index of the builtin decl. */
8481 static bool
8482 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8483 tree addr, tree loaded_val, tree stored_val,
8484 int index)
8486 tree loadedi, storedi, initial, new_storedi, old_vali;
8487 tree type, itype, cmpxchg, iaddr;
8488 gimple_stmt_iterator si;
8489 basic_block loop_header = single_succ (load_bb);
8490 gimple phi, stmt;
8491 edge e;
8492 enum built_in_function fncode;
8494 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8495 order to use the RELAXED memory model effectively. */
8496 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8497 + index + 1);
8498 cmpxchg = builtin_decl_explicit (fncode);
8499 if (cmpxchg == NULL_TREE)
8500 return false;
8501 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8502 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8504 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8505 return false;
8507 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8508 si = gsi_last_bb (load_bb);
8509 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8511 /* For floating-point values, we'll need to view-convert them to integers
8512 so that we can perform the atomic compare and swap. Simplify the
8513 following code by always setting up the "i"ntegral variables. */
8514 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8516 tree iaddr_val;
8518 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8519 true));
8520 iaddr_val
8521 = force_gimple_operand_gsi (&si,
8522 fold_convert (TREE_TYPE (iaddr), addr),
8523 false, NULL_TREE, true, GSI_SAME_STMT);
8524 stmt = gimple_build_assign (iaddr, iaddr_val);
8525 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8526 loadedi = create_tmp_var (itype);
8527 if (gimple_in_ssa_p (cfun))
8528 loadedi = make_ssa_name (loadedi);
8530 else
8532 iaddr = addr;
8533 loadedi = loaded_val;
8536 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8537 tree loaddecl = builtin_decl_explicit (fncode);
8538 if (loaddecl)
8539 initial
8540 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8541 build_call_expr (loaddecl, 2, iaddr,
8542 build_int_cst (NULL_TREE,
8543 MEMMODEL_RELAXED)));
8544 else
8545 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8546 build_int_cst (TREE_TYPE (iaddr), 0));
8548 initial
8549 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8550 GSI_SAME_STMT);
8552 /* Move the value to the LOADEDI temporary. */
8553 if (gimple_in_ssa_p (cfun))
8555 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8556 phi = create_phi_node (loadedi, loop_header);
8557 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8558 initial);
8560 else
8561 gsi_insert_before (&si,
8562 gimple_build_assign (loadedi, initial),
8563 GSI_SAME_STMT);
8564 if (loadedi != loaded_val)
8566 gimple_stmt_iterator gsi2;
8567 tree x;
8569 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8570 gsi2 = gsi_start_bb (loop_header);
8571 if (gimple_in_ssa_p (cfun))
8573 gassign *stmt;
8574 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8575 true, GSI_SAME_STMT);
8576 stmt = gimple_build_assign (loaded_val, x);
8577 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8579 else
8581 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8582 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8583 true, GSI_SAME_STMT);
8586 gsi_remove (&si, true);
8588 si = gsi_last_bb (store_bb);
8589 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8591 if (iaddr == addr)
8592 storedi = stored_val;
8593 else
8594 storedi =
8595 force_gimple_operand_gsi (&si,
8596 build1 (VIEW_CONVERT_EXPR, itype,
8597 stored_val), true, NULL_TREE, true,
8598 GSI_SAME_STMT);
8600 /* Build the compare&swap statement. */
8601 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8602 new_storedi = force_gimple_operand_gsi (&si,
8603 fold_convert (TREE_TYPE (loadedi),
8604 new_storedi),
8605 true, NULL_TREE,
8606 true, GSI_SAME_STMT);
8608 if (gimple_in_ssa_p (cfun))
8609 old_vali = loadedi;
8610 else
8612 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8613 stmt = gimple_build_assign (old_vali, loadedi);
8614 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8616 stmt = gimple_build_assign (loadedi, new_storedi);
8617 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8620 /* Note that we always perform the comparison as an integer, even for
8621 floating point. This allows the atomic operation to properly
8622 succeed even with NaNs and -0.0. */
8623 stmt = gimple_build_cond_empty
8624 (build2 (NE_EXPR, boolean_type_node,
8625 new_storedi, old_vali));
8626 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8628 /* Update cfg. */
8629 e = single_succ_edge (store_bb);
8630 e->flags &= ~EDGE_FALLTHRU;
8631 e->flags |= EDGE_FALSE_VALUE;
8633 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8635 /* Copy the new value to loadedi (we already did that before the condition
8636 if we are not in SSA). */
8637 if (gimple_in_ssa_p (cfun))
8639 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8640 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8643 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8644 gsi_remove (&si, true);
8646 struct loop *loop = alloc_loop ();
8647 loop->header = loop_header;
8648 loop->latch = store_bb;
8649 add_loop (loop, loop_header->loop_father);
8651 if (gimple_in_ssa_p (cfun))
8652 update_ssa (TODO_update_ssa_no_phi);
8654 return true;
8657 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8659 GOMP_atomic_start ();
8660 *addr = rhs;
8661 GOMP_atomic_end ();
8663 The result is not globally atomic, but works so long as all parallel
8664 references are within #pragma omp atomic directives. According to
8665 responses received from omp@openmp.org, appears to be within spec.
8666 Which makes sense, since that's how several other compilers handle
8667 this situation as well.
8668 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8669 expanding. STORED_VAL is the operand of the matching
8670 GIMPLE_OMP_ATOMIC_STORE.
8672 We replace
8673 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8674 loaded_val = *addr;
8676 and replace
8677 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8678 *addr = stored_val;
8681 static bool
8682 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8683 tree addr, tree loaded_val, tree stored_val)
8685 gimple_stmt_iterator si;
8686 gassign *stmt;
8687 tree t;
8689 si = gsi_last_bb (load_bb);
8690 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8692 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8693 t = build_call_expr (t, 0);
8694 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8696 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8697 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8698 gsi_remove (&si, true);
8700 si = gsi_last_bb (store_bb);
8701 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8703 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8704 stored_val);
8705 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8707 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8708 t = build_call_expr (t, 0);
8709 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8710 gsi_remove (&si, true);
8712 if (gimple_in_ssa_p (cfun))
8713 update_ssa (TODO_update_ssa_no_phi);
8714 return true;
8717 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8718 using expand_omp_atomic_fetch_op. If it failed, we try to
8719 call expand_omp_atomic_pipeline, and if it fails too, the
8720 ultimate fallback is wrapping the operation in a mutex
8721 (expand_omp_atomic_mutex). REGION is the atomic region built
8722 by build_omp_regions_1(). */
8724 static void
8725 expand_omp_atomic (struct omp_region *region)
8727 basic_block load_bb = region->entry, store_bb = region->exit;
8728 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8729 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8730 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8731 tree addr = gimple_omp_atomic_load_rhs (load);
8732 tree stored_val = gimple_omp_atomic_store_val (store);
8733 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8734 HOST_WIDE_INT index;
8736 /* Make sure the type is one of the supported sizes. */
8737 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8738 index = exact_log2 (index);
8739 if (index >= 0 && index <= 4)
8741 unsigned int align = TYPE_ALIGN_UNIT (type);
8743 /* __sync builtins require strict data alignment. */
8744 if (exact_log2 (align) >= index)
8746 /* Atomic load. */
8747 if (loaded_val == stored_val
8748 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8749 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8750 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8751 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8752 return;
8754 /* Atomic store. */
8755 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8756 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8757 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8758 && store_bb == single_succ (load_bb)
8759 && first_stmt (store_bb) == store
8760 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8761 stored_val, index))
8762 return;
8764 /* When possible, use specialized atomic update functions. */
8765 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8766 && store_bb == single_succ (load_bb)
8767 && expand_omp_atomic_fetch_op (load_bb, addr,
8768 loaded_val, stored_val, index))
8769 return;
8771 /* If we don't have specialized __sync builtins, try and implement
8772 as a compare and swap loop. */
8773 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8774 loaded_val, stored_val, index))
8775 return;
8779 /* The ultimate fallback is wrapping the operation in a mutex. */
8780 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8784 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8786 static void
8787 expand_omp_target (struct omp_region *region)
8789 basic_block entry_bb, exit_bb, new_bb;
8790 struct function *child_cfun;
8791 tree child_fn, block, t;
8792 gimple_stmt_iterator gsi;
8793 gomp_target *entry_stmt;
8794 gimple stmt;
8795 edge e;
8796 bool offloaded, data_region;
8798 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8799 new_bb = region->entry;
8801 offloaded = is_gimple_omp_offloaded (entry_stmt);
8802 switch (gimple_omp_target_kind (entry_stmt))
8804 case GF_OMP_TARGET_KIND_REGION:
8805 case GF_OMP_TARGET_KIND_UPDATE:
8806 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8807 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8808 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8809 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8810 data_region = false;
8811 break;
8812 case GF_OMP_TARGET_KIND_DATA:
8813 case GF_OMP_TARGET_KIND_OACC_DATA:
8814 data_region = true;
8815 break;
8816 default:
8817 gcc_unreachable ();
8820 child_fn = NULL_TREE;
8821 child_cfun = NULL;
8822 if (offloaded)
8824 child_fn = gimple_omp_target_child_fn (entry_stmt);
8825 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8828 /* Supported by expand_omp_taskreg, but not here. */
8829 if (child_cfun != NULL)
8830 gcc_checking_assert (!child_cfun->cfg);
8831 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8833 entry_bb = region->entry;
8834 exit_bb = region->exit;
8836 if (offloaded)
8838 unsigned srcidx, dstidx, num;
8840 /* If the offloading region needs data sent from the parent
8841 function, then the very first statement (except possible
8842 tree profile counter updates) of the offloading body
8843 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8844 &.OMP_DATA_O is passed as an argument to the child function,
8845 we need to replace it with the argument as seen by the child
8846 function.
8848 In most cases, this will end up being the identity assignment
8849 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8850 a function call that has been inlined, the original PARM_DECL
8851 .OMP_DATA_I may have been converted into a different local
8852 variable. In which case, we need to keep the assignment. */
8853 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8854 if (data_arg)
8856 basic_block entry_succ_bb = single_succ (entry_bb);
8857 gimple_stmt_iterator gsi;
8858 tree arg;
8859 gimple tgtcopy_stmt = NULL;
8860 tree sender = TREE_VEC_ELT (data_arg, 0);
8862 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8864 gcc_assert (!gsi_end_p (gsi));
8865 stmt = gsi_stmt (gsi);
8866 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8867 continue;
8869 if (gimple_num_ops (stmt) == 2)
8871 tree arg = gimple_assign_rhs1 (stmt);
8873 /* We're ignoring the subcode because we're
8874 effectively doing a STRIP_NOPS. */
8876 if (TREE_CODE (arg) == ADDR_EXPR
8877 && TREE_OPERAND (arg, 0) == sender)
8879 tgtcopy_stmt = stmt;
8880 break;
8885 gcc_assert (tgtcopy_stmt != NULL);
8886 arg = DECL_ARGUMENTS (child_fn);
8888 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8889 gsi_remove (&gsi, true);
8892 /* Declare local variables needed in CHILD_CFUN. */
8893 block = DECL_INITIAL (child_fn);
8894 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8895 /* The gimplifier could record temporaries in the offloading block
8896 rather than in containing function's local_decls chain,
8897 which would mean cgraph missed finalizing them. Do it now. */
8898 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8899 if (TREE_CODE (t) == VAR_DECL
8900 && TREE_STATIC (t)
8901 && !DECL_EXTERNAL (t))
8902 varpool_node::finalize_decl (t);
8903 DECL_SAVED_TREE (child_fn) = NULL;
8904 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8905 gimple_set_body (child_fn, NULL);
8906 TREE_USED (block) = 1;
8908 /* Reset DECL_CONTEXT on function arguments. */
8909 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8910 DECL_CONTEXT (t) = child_fn;
8912 /* Split ENTRY_BB at GIMPLE_*,
8913 so that it can be moved to the child function. */
8914 gsi = gsi_last_bb (entry_bb);
8915 stmt = gsi_stmt (gsi);
8916 gcc_assert (stmt
8917 && gimple_code (stmt) == gimple_code (entry_stmt));
8918 e = split_block (entry_bb, stmt);
8919 gsi_remove (&gsi, true);
8920 entry_bb = e->dest;
8921 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8923 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8924 if (exit_bb)
8926 gsi = gsi_last_bb (exit_bb);
8927 gcc_assert (!gsi_end_p (gsi)
8928 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8929 stmt = gimple_build_return (NULL);
8930 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8931 gsi_remove (&gsi, true);
8934 /* Move the offloading region into CHILD_CFUN. */
8936 block = gimple_block (entry_stmt);
8938 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8939 if (exit_bb)
8940 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8941 /* When the OMP expansion process cannot guarantee an up-to-date
8942 loop tree arrange for the child function to fixup loops. */
8943 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8944 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8946 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8947 num = vec_safe_length (child_cfun->local_decls);
8948 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8950 t = (*child_cfun->local_decls)[srcidx];
8951 if (DECL_CONTEXT (t) == cfun->decl)
8952 continue;
8953 if (srcidx != dstidx)
8954 (*child_cfun->local_decls)[dstidx] = t;
8955 dstidx++;
8957 if (dstidx != num)
8958 vec_safe_truncate (child_cfun->local_decls, dstidx);
8960 /* Inform the callgraph about the new function. */
8961 child_cfun->curr_properties = cfun->curr_properties;
8962 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
8963 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
8964 cgraph_node *node = cgraph_node::get_create (child_fn);
8965 node->parallelized_function = 1;
8966 cgraph_node::add_new_function (child_fn, true);
8968 #ifdef ENABLE_OFFLOADING
8969 /* Add the new function to the offload table. */
8970 vec_safe_push (offload_funcs, child_fn);
8971 #endif
8973 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8974 fixed in a following pass. */
8975 push_cfun (child_cfun);
8976 cgraph_edge::rebuild_edges ();
8978 #ifdef ENABLE_OFFLOADING
8979 /* Prevent IPA from removing child_fn as unreachable, since there are no
8980 refs from the parent function to child_fn in offload LTO mode. */
8981 cgraph_node::get (child_fn)->mark_force_output ();
8982 #endif
8984 /* Some EH regions might become dead, see PR34608. If
8985 pass_cleanup_cfg isn't the first pass to happen with the
8986 new child, these dead EH edges might cause problems.
8987 Clean them up now. */
8988 if (flag_exceptions)
8990 basic_block bb;
8991 bool changed = false;
8993 FOR_EACH_BB_FN (bb, cfun)
8994 changed |= gimple_purge_dead_eh_edges (bb);
8995 if (changed)
8996 cleanup_tree_cfg ();
8998 pop_cfun ();
9001 /* Emit a library call to launch the offloading region, or do data
9002 transfers. */
9003 tree t1, t2, t3, t4, device, cond, c, clauses;
9004 enum built_in_function start_ix;
9005 location_t clause_loc;
9007 switch (gimple_omp_target_kind (entry_stmt))
9009 case GF_OMP_TARGET_KIND_REGION:
9010 start_ix = BUILT_IN_GOMP_TARGET;
9011 break;
9012 case GF_OMP_TARGET_KIND_DATA:
9013 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9014 break;
9015 case GF_OMP_TARGET_KIND_UPDATE:
9016 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9017 break;
9018 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9019 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9020 start_ix = BUILT_IN_GOACC_PARALLEL;
9021 break;
9022 case GF_OMP_TARGET_KIND_OACC_DATA:
9023 start_ix = BUILT_IN_GOACC_DATA_START;
9024 break;
9025 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9026 start_ix = BUILT_IN_GOACC_UPDATE;
9027 break;
9028 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9029 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9030 break;
9031 default:
9032 gcc_unreachable ();
9035 clauses = gimple_omp_target_clauses (entry_stmt);
9037 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9038 library choose) and there is no conditional. */
9039 cond = NULL_TREE;
9040 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
9042 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9043 if (c)
9044 cond = OMP_CLAUSE_IF_EXPR (c);
9046 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9047 if (c)
9049 /* Even if we pass it to all library function calls, it is currently only
9050 defined/used for the OpenMP target ones. */
9051 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9052 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9053 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9055 device = OMP_CLAUSE_DEVICE_ID (c);
9056 clause_loc = OMP_CLAUSE_LOCATION (c);
9058 else
9059 clause_loc = gimple_location (entry_stmt);
9061 /* Ensure 'device' is of the correct type. */
9062 device = fold_convert_loc (clause_loc, integer_type_node, device);
9064 /* If we found the clause 'if (cond)', build
9065 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9066 if (cond)
9068 cond = gimple_boolify (cond);
9070 basic_block cond_bb, then_bb, else_bb;
9071 edge e;
9072 tree tmp_var;
9074 tmp_var = create_tmp_var (TREE_TYPE (device));
9075 if (offloaded)
9076 e = split_block_after_labels (new_bb);
9077 else
9079 gsi = gsi_last_bb (new_bb);
9080 gsi_prev (&gsi);
9081 e = split_block (new_bb, gsi_stmt (gsi));
9083 cond_bb = e->src;
9084 new_bb = e->dest;
9085 remove_edge (e);
9087 then_bb = create_empty_bb (cond_bb);
9088 else_bb = create_empty_bb (then_bb);
9089 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9090 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9092 stmt = gimple_build_cond_empty (cond);
9093 gsi = gsi_last_bb (cond_bb);
9094 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9096 gsi = gsi_start_bb (then_bb);
9097 stmt = gimple_build_assign (tmp_var, device);
9098 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9100 gsi = gsi_start_bb (else_bb);
9101 stmt = gimple_build_assign (tmp_var,
9102 build_int_cst (integer_type_node,
9103 GOMP_DEVICE_HOST_FALLBACK));
9104 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9106 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9107 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9108 add_bb_to_loop (then_bb, cond_bb->loop_father);
9109 add_bb_to_loop (else_bb, cond_bb->loop_father);
9110 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9111 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9113 device = tmp_var;
9116 gsi = gsi_last_bb (new_bb);
9117 t = gimple_omp_target_data_arg (entry_stmt);
9118 if (t == NULL)
9120 t1 = size_zero_node;
9121 t2 = build_zero_cst (ptr_type_node);
9122 t3 = t2;
9123 t4 = t2;
9125 else
9127 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9128 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9129 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9130 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9131 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9134 gimple g;
9135 /* The maximum number used by any start_ix, without varargs. */
9136 auto_vec<tree, 11> args;
9137 args.quick_push (device);
9138 if (offloaded)
9139 args.quick_push (build_fold_addr_expr (child_fn));
9140 switch (start_ix)
9142 case BUILT_IN_GOMP_TARGET:
9143 case BUILT_IN_GOMP_TARGET_DATA:
9144 case BUILT_IN_GOMP_TARGET_UPDATE:
9145 /* This const void * is part of the current ABI, but we're not actually
9146 using it. */
9147 args.quick_push (build_zero_cst (ptr_type_node));
9148 break;
9149 case BUILT_IN_GOACC_DATA_START:
9150 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9151 case BUILT_IN_GOACC_PARALLEL:
9152 case BUILT_IN_GOACC_UPDATE:
9153 break;
9154 default:
9155 gcc_unreachable ();
9157 args.quick_push (t1);
9158 args.quick_push (t2);
9159 args.quick_push (t3);
9160 args.quick_push (t4);
9161 switch (start_ix)
9163 case BUILT_IN_GOACC_DATA_START:
9164 case BUILT_IN_GOMP_TARGET:
9165 case BUILT_IN_GOMP_TARGET_DATA:
9166 case BUILT_IN_GOMP_TARGET_UPDATE:
9167 break;
9168 case BUILT_IN_GOACC_PARALLEL:
9170 tree t_num_gangs, t_num_workers, t_vector_length;
9172 /* Default values for num_gangs, num_workers, and vector_length. */
9173 t_num_gangs = t_num_workers = t_vector_length
9174 = fold_convert_loc (gimple_location (entry_stmt),
9175 integer_type_node, integer_one_node);
9176 /* ..., but if present, use the value specified by the respective
9177 clause, making sure that are of the correct type. */
9178 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9179 if (c)
9180 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9181 integer_type_node,
9182 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9183 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9184 if (c)
9185 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9186 integer_type_node,
9187 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9188 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9189 if (c)
9190 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9191 integer_type_node,
9192 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9193 args.quick_push (t_num_gangs);
9194 args.quick_push (t_num_workers);
9195 args.quick_push (t_vector_length);
9197 /* FALLTHRU */
9198 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9199 case BUILT_IN_GOACC_UPDATE:
9201 tree t_async;
9202 int t_wait_idx;
9204 /* Default values for t_async. */
9205 t_async = fold_convert_loc (gimple_location (entry_stmt),
9206 integer_type_node,
9207 build_int_cst (integer_type_node,
9208 GOMP_ASYNC_SYNC));
9209 /* ..., but if present, use the value specified by the respective
9210 clause, making sure that is of the correct type. */
9211 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9212 if (c)
9213 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9214 integer_type_node,
9215 OMP_CLAUSE_ASYNC_EXPR (c));
9217 args.quick_push (t_async);
9218 /* Save the index, and... */
9219 t_wait_idx = args.length ();
9220 /* ... push a default value. */
9221 args.quick_push (fold_convert_loc (gimple_location (entry_stmt),
9222 integer_type_node,
9223 integer_zero_node));
9224 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9225 if (c)
9227 int n = 0;
9229 for (; c; c = OMP_CLAUSE_CHAIN (c))
9231 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9233 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9234 integer_type_node,
9235 OMP_CLAUSE_WAIT_EXPR (c)));
9236 n++;
9240 /* Now that we know the number, replace the default value. */
9241 args.ordered_remove (t_wait_idx);
9242 args.quick_insert (t_wait_idx,
9243 fold_convert_loc (gimple_location (entry_stmt),
9244 integer_type_node,
9245 build_int_cst (integer_type_node, n)));
9248 break;
9249 default:
9250 gcc_unreachable ();
9253 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
9254 gimple_set_location (g, gimple_location (entry_stmt));
9255 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9256 if (!offloaded)
9258 g = gsi_stmt (gsi);
9259 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9260 gsi_remove (&gsi, true);
9262 if (data_region
9263 && region->exit)
9265 gsi = gsi_last_bb (region->exit);
9266 g = gsi_stmt (gsi);
9267 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9268 gsi_remove (&gsi, true);
9273 /* Expand the parallel region tree rooted at REGION. Expansion
9274 proceeds in depth-first order. Innermost regions are expanded
9275 first. This way, parallel regions that require a new function to
9276 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9277 internal dependencies in their body. */
9279 static void
9280 expand_omp (struct omp_region *region)
9282 while (region)
9284 location_t saved_location;
9285 gimple inner_stmt = NULL;
9287 /* First, determine whether this is a combined parallel+workshare
9288 region. */
9289 if (region->type == GIMPLE_OMP_PARALLEL)
9290 determine_parallel_type (region);
9292 if (region->type == GIMPLE_OMP_FOR
9293 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9294 inner_stmt = last_stmt (region->inner->entry);
9296 if (region->inner)
9297 expand_omp (region->inner);
9299 saved_location = input_location;
9300 if (gimple_has_location (last_stmt (region->entry)))
9301 input_location = gimple_location (last_stmt (region->entry));
9303 switch (region->type)
9305 case GIMPLE_OMP_PARALLEL:
9306 case GIMPLE_OMP_TASK:
9307 expand_omp_taskreg (region);
9308 break;
9310 case GIMPLE_OMP_FOR:
9311 expand_omp_for (region, inner_stmt);
9312 break;
9314 case GIMPLE_OMP_SECTIONS:
9315 expand_omp_sections (region);
9316 break;
9318 case GIMPLE_OMP_SECTION:
9319 /* Individual omp sections are handled together with their
9320 parent GIMPLE_OMP_SECTIONS region. */
9321 break;
9323 case GIMPLE_OMP_SINGLE:
9324 expand_omp_single (region);
9325 break;
9327 case GIMPLE_OMP_MASTER:
9328 case GIMPLE_OMP_TASKGROUP:
9329 case GIMPLE_OMP_ORDERED:
9330 case GIMPLE_OMP_CRITICAL:
9331 case GIMPLE_OMP_TEAMS:
9332 expand_omp_synch (region);
9333 break;
9335 case GIMPLE_OMP_ATOMIC_LOAD:
9336 expand_omp_atomic (region);
9337 break;
9339 case GIMPLE_OMP_TARGET:
9340 expand_omp_target (region);
9341 break;
9343 default:
9344 gcc_unreachable ();
9347 input_location = saved_location;
9348 region = region->next;
9353 /* Helper for build_omp_regions. Scan the dominator tree starting at
9354 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9355 true, the function ends once a single tree is built (otherwise, whole
9356 forest of OMP constructs may be built). */
9358 static void
9359 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9360 bool single_tree)
9362 gimple_stmt_iterator gsi;
9363 gimple stmt;
9364 basic_block son;
9366 gsi = gsi_last_bb (bb);
9367 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9369 struct omp_region *region;
9370 enum gimple_code code;
9372 stmt = gsi_stmt (gsi);
9373 code = gimple_code (stmt);
9374 if (code == GIMPLE_OMP_RETURN)
9376 /* STMT is the return point out of region PARENT. Mark it
9377 as the exit point and make PARENT the immediately
9378 enclosing region. */
9379 gcc_assert (parent);
9380 region = parent;
9381 region->exit = bb;
9382 parent = parent->outer;
9384 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9386 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9387 GIMPLE_OMP_RETURN, but matches with
9388 GIMPLE_OMP_ATOMIC_LOAD. */
9389 gcc_assert (parent);
9390 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9391 region = parent;
9392 region->exit = bb;
9393 parent = parent->outer;
9395 else if (code == GIMPLE_OMP_CONTINUE)
9397 gcc_assert (parent);
9398 parent->cont = bb;
9400 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9402 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9403 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9405 else
9407 region = new_omp_region (bb, code, parent);
9408 /* Otherwise... */
9409 if (code == GIMPLE_OMP_TARGET)
9411 switch (gimple_omp_target_kind (stmt))
9413 case GF_OMP_TARGET_KIND_REGION:
9414 case GF_OMP_TARGET_KIND_DATA:
9415 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9416 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9417 case GF_OMP_TARGET_KIND_OACC_DATA:
9418 break;
9419 case GF_OMP_TARGET_KIND_UPDATE:
9420 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9421 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9422 /* ..., other than for those stand-alone directives... */
9423 region = NULL;
9424 break;
9425 default:
9426 gcc_unreachable ();
9429 /* ..., this directive becomes the parent for a new region. */
9430 if (region)
9431 parent = region;
9435 if (single_tree && !parent)
9436 return;
9438 for (son = first_dom_son (CDI_DOMINATORS, bb);
9439 son;
9440 son = next_dom_son (CDI_DOMINATORS, son))
9441 build_omp_regions_1 (son, parent, single_tree);
9444 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9445 root_omp_region. */
9447 static void
9448 build_omp_regions_root (basic_block root)
9450 gcc_assert (root_omp_region == NULL);
9451 build_omp_regions_1 (root, NULL, true);
9452 gcc_assert (root_omp_region != NULL);
9455 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9457 void
9458 omp_expand_local (basic_block head)
9460 build_omp_regions_root (head);
9461 if (dump_file && (dump_flags & TDF_DETAILS))
9463 fprintf (dump_file, "\nOMP region tree\n\n");
9464 dump_omp_region (dump_file, root_omp_region, 0);
9465 fprintf (dump_file, "\n");
9468 remove_exit_barriers (root_omp_region);
9469 expand_omp (root_omp_region);
9471 free_omp_regions ();
9474 /* Scan the CFG and build a tree of OMP regions. Return the root of
9475 the OMP region tree. */
9477 static void
9478 build_omp_regions (void)
9480 gcc_assert (root_omp_region == NULL);
9481 calculate_dominance_info (CDI_DOMINATORS);
9482 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9485 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9487 static unsigned int
9488 execute_expand_omp (void)
9490 build_omp_regions ();
9492 if (!root_omp_region)
9493 return 0;
9495 if (dump_file)
9497 fprintf (dump_file, "\nOMP region tree\n\n");
9498 dump_omp_region (dump_file, root_omp_region, 0);
9499 fprintf (dump_file, "\n");
9502 remove_exit_barriers (root_omp_region);
9504 expand_omp (root_omp_region);
9506 cleanup_tree_cfg ();
9508 free_omp_regions ();
9510 return 0;
9513 /* OMP expansion -- the default pass, run before creation of SSA form. */
9515 namespace {
9517 const pass_data pass_data_expand_omp =
9519 GIMPLE_PASS, /* type */
9520 "ompexp", /* name */
9521 OPTGROUP_NONE, /* optinfo_flags */
9522 TV_NONE, /* tv_id */
9523 PROP_gimple_any, /* properties_required */
9524 PROP_gimple_eomp, /* properties_provided */
9525 0, /* properties_destroyed */
9526 0, /* todo_flags_start */
9527 0, /* todo_flags_finish */
9530 class pass_expand_omp : public gimple_opt_pass
9532 public:
9533 pass_expand_omp (gcc::context *ctxt)
9534 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9537 /* opt_pass methods: */
9538 virtual unsigned int execute (function *)
9540 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9541 || flag_openmp_simd != 0)
9542 && !seen_error ());
9544 /* This pass always runs, to provide PROP_gimple_eomp.
9545 But often, there is nothing to do. */
9546 if (!gate)
9547 return 0;
9549 return execute_expand_omp ();
9552 }; // class pass_expand_omp
9554 } // anon namespace
9556 gimple_opt_pass *
9557 make_pass_expand_omp (gcc::context *ctxt)
9559 return new pass_expand_omp (ctxt);
9562 namespace {
9564 const pass_data pass_data_expand_omp_ssa =
9566 GIMPLE_PASS, /* type */
9567 "ompexpssa", /* name */
9568 OPTGROUP_NONE, /* optinfo_flags */
9569 TV_NONE, /* tv_id */
9570 PROP_cfg | PROP_ssa, /* properties_required */
9571 PROP_gimple_eomp, /* properties_provided */
9572 0, /* properties_destroyed */
9573 0, /* todo_flags_start */
9574 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9577 class pass_expand_omp_ssa : public gimple_opt_pass
9579 public:
9580 pass_expand_omp_ssa (gcc::context *ctxt)
9581 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9584 /* opt_pass methods: */
9585 virtual bool gate (function *fun)
9587 return !(fun->curr_properties & PROP_gimple_eomp);
9589 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9591 }; // class pass_expand_omp_ssa
9593 } // anon namespace
9595 gimple_opt_pass *
9596 make_pass_expand_omp_ssa (gcc::context *ctxt)
9598 return new pass_expand_omp_ssa (ctxt);
9601 /* Routines to lower OMP directives into OMP-GIMPLE. */
9603 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9604 convert it to gimple. */
9605 static void
9606 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9608 gimple stmt;
9610 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9612 stmt = gimple_build_assign (dest, op, dest, src);
9613 gimple_seq_add_stmt (seq, stmt);
9614 return;
9617 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9618 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9619 gimplify_assign (t, rdest, seq);
9620 rdest = t;
9622 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9623 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9624 gimplify_assign (t, idest, seq);
9625 idest = t;
9627 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9628 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9629 gimplify_assign (t, rsrc, seq);
9630 rsrc = t;
9632 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9633 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9634 gimplify_assign (t, isrc, seq);
9635 isrc = t;
9637 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9638 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9639 tree result;
9641 if (op == PLUS_EXPR)
9643 stmt = gimple_build_assign (r, op, rdest, rsrc);
9644 gimple_seq_add_stmt (seq, stmt);
9646 stmt = gimple_build_assign (i, op, idest, isrc);
9647 gimple_seq_add_stmt (seq, stmt);
9649 else if (op == MULT_EXPR)
9651 /* Let x = a + ib = dest, y = c + id = src.
9652 x * y = (ac - bd) + i(ad + bc) */
9653 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9654 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9655 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9656 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9658 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9659 gimple_seq_add_stmt (seq, stmt);
9661 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9662 gimple_seq_add_stmt (seq, stmt);
9664 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9665 gimple_seq_add_stmt (seq, stmt);
9667 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9668 gimple_seq_add_stmt (seq, stmt);
9670 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9671 gimple_seq_add_stmt (seq, stmt);
9673 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9674 gimple_seq_add_stmt (seq, stmt);
9676 else
9677 gcc_unreachable ();
9679 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9680 gimplify_assign (dest, result, seq);
9683 /* Helper function to initialize local data for the reduction arrays.
9684 The reduction arrays need to be placed inside the calling function
9685 for accelerators, or else the host won't be able to preform the final
9686 reduction. */
9688 static void
9689 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9690 gimple_seq *stmt_seqp, omp_context *ctx)
9692 tree c, t, oc;
9693 gimple stmt;
9694 omp_context *octx;
9696 /* Find the innermost OpenACC parallel context. */
9697 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9698 && (gimple_omp_target_kind (ctx->stmt)
9699 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9700 octx = ctx;
9701 else
9702 octx = ctx->outer;
9703 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9704 && (gimple_omp_target_kind (octx->stmt)
9705 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9707 /* Extract the clauses. */
9708 oc = gimple_omp_target_clauses (octx->stmt);
9710 /* Find the last outer clause. */
9711 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9714 /* Allocate arrays for each reduction variable. */
9715 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9717 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9718 continue;
9720 tree var = OMP_CLAUSE_DECL (c);
9721 tree type = get_base_type (var);
9722 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9723 ctx);
9724 tree size, call;
9726 /* Calculate size of the reduction array. */
9727 t = create_tmp_var (TREE_TYPE (nthreads));
9728 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9729 fold_convert (TREE_TYPE (nthreads),
9730 TYPE_SIZE_UNIT (type)));
9731 gimple_seq_add_stmt (stmt_seqp, stmt);
9733 size = create_tmp_var (sizetype);
9734 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9736 /* Now allocate memory for it. */
9737 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9738 stmt = gimple_build_call (call, 1, size);
9739 gimple_call_set_lhs (stmt, array);
9740 gimple_seq_add_stmt (stmt_seqp, stmt);
9742 /* Map this array into the accelerator. */
9744 /* Add the reduction array to the list of clauses. */
9745 tree x = array;
9746 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9747 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9748 OMP_CLAUSE_DECL (t) = x;
9749 OMP_CLAUSE_CHAIN (t) = NULL;
9750 if (oc)
9751 OMP_CLAUSE_CHAIN (oc) = t;
9752 else
9753 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9754 OMP_CLAUSE_SIZE (t) = size;
9755 oc = t;
9759 /* Helper function to process the array of partial reductions. Nthreads
9760 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9761 cannot be used here, because nthreads on the host may be different than
9762 on the accelerator. */
9764 static void
9765 oacc_finalize_reduction_data (tree clauses, tree nthreads,
9766 gimple_seq *stmt_seqp, omp_context *ctx)
9768 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9769 gimple stmt;
9771 /* Create for loop.
9773 let var = the original reduction variable
9774 let array = reduction variable array
9776 for (i = 0; i < nthreads; i++)
9777 var op= array[i]
9780 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9781 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9782 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9784 /* Create and initialize an index variable. */
9785 tree ix = create_tmp_var (sizetype);
9786 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9787 stmt_seqp);
9789 /* Insert the loop header label here. */
9790 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9792 /* Exit loop if ix >= nthreads. */
9793 x = create_tmp_var (sizetype);
9794 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9795 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9796 gimple_seq_add_stmt (stmt_seqp, stmt);
9798 /* Insert the loop body label here. */
9799 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9801 /* Collapse each reduction array, one element at a time. */
9802 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9804 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9805 continue;
9807 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9809 /* reduction(-:var) sums up the partial results, so it acts
9810 identically to reduction(+:var). */
9811 if (reduction_code == MINUS_EXPR)
9812 reduction_code = PLUS_EXPR;
9814 /* Set up reduction variable var. */
9815 var = OMP_CLAUSE_DECL (c);
9816 type = get_base_type (var);
9817 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9818 (OMP_CLAUSE_DECL (c)), ctx);
9820 /* Calculate the array offset. */
9821 tree offset = create_tmp_var (sizetype);
9822 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9823 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9824 gimple_seq_add_stmt (stmt_seqp, stmt);
9826 tree ptr = create_tmp_var (TREE_TYPE (array));
9827 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9828 gimple_seq_add_stmt (stmt_seqp, stmt);
9830 /* Extract array[ix] into mem. */
9831 tree mem = create_tmp_var (type);
9832 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9834 /* Find the original reduction variable. */
9835 if (is_reference (var))
9836 var = build_simple_mem_ref (var);
9838 tree t = create_tmp_var (type);
9840 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9841 gimplify_and_add (unshare_expr(x), stmt_seqp);
9843 /* var = var op mem */
9844 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9846 case TRUTH_ANDIF_EXPR:
9847 case TRUTH_ORIF_EXPR:
9848 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9849 t, mem);
9850 gimplify_and_add (t, stmt_seqp);
9851 break;
9852 default:
9853 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9854 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9855 stmt_seqp);
9858 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9859 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9860 gimplify_and_add (unshare_expr(x), stmt_seqp);
9863 /* Increment the induction variable. */
9864 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9865 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9866 gimple_seq_add_stmt (stmt_seqp, stmt);
9868 /* Go back to the top of the loop. */
9869 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9871 /* Place the loop exit label here. */
9872 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9875 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9876 scan that for reductions. */
9878 static void
9879 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9880 gimple_seq *out_stmt_seqp, omp_context *ctx)
9882 gimple_stmt_iterator gsi;
9883 gimple_seq inner = NULL;
9885 /* A collapse clause may have inserted a new bind block. */
9886 gsi = gsi_start (*body);
9887 while (!gsi_end_p (gsi))
9889 gimple stmt = gsi_stmt (gsi);
9890 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9892 inner = gimple_bind_body (bind_stmt);
9893 body = &inner;
9894 gsi = gsi_start (*body);
9896 else if (dyn_cast <gomp_for *> (stmt))
9897 break;
9898 else
9899 gsi_next (&gsi);
9902 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9904 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9905 enter, exit;
9906 bool reduction_found = false;
9908 gimple stmt = gsi_stmt (gsi);
9910 switch (gimple_code (stmt))
9912 case GIMPLE_OMP_FOR:
9913 clauses = gimple_omp_for_clauses (stmt);
9915 /* Search for a reduction clause. */
9916 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9917 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9919 reduction_found = true;
9920 break;
9923 if (!reduction_found)
9924 break;
9926 ctx = maybe_lookup_ctx (stmt);
9927 t = NULL_TREE;
9929 /* Extract the number of threads. */
9930 nthreads = create_tmp_var (sizetype);
9931 t = oacc_max_threads (ctx);
9932 gimplify_assign (nthreads, t, in_stmt_seqp);
9934 /* Determine if this is kernel will be executed on the host. */
9935 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9936 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9937 stmt = gimple_build_call (call, 0);
9938 gimple_call_set_lhs (stmt, acc_device);
9939 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9941 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9942 acc_device_host = create_tmp_var (integer_type_node,
9943 ".acc_device_host");
9944 gimplify_assign (acc_device_host,
9945 build_int_cst (integer_type_node,
9946 GOMP_DEVICE_HOST),
9947 in_stmt_seqp);
9949 enter = create_artificial_label (UNKNOWN_LOCATION);
9950 exit = create_artificial_label (UNKNOWN_LOCATION);
9952 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9953 enter, exit);
9954 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9955 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9956 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9957 integer_one_node),
9958 in_stmt_seqp);
9959 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9961 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9962 gimplify_assign (acc_device_host,
9963 build_int_cst (integer_type_node,
9964 GOMP_DEVICE_HOST_NONSHM),
9965 in_stmt_seqp);
9967 enter = create_artificial_label (UNKNOWN_LOCATION);
9968 exit = create_artificial_label (UNKNOWN_LOCATION);
9970 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9971 enter, exit);
9972 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9973 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9974 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9975 integer_one_node),
9976 in_stmt_seqp);
9977 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9979 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9980 ctx);
9981 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9982 break;
9983 default:
9984 // Scan for other directives which support reduction here.
9985 break;
9990 /* If ctx is a worksharing context inside of a cancellable parallel
9991 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9992 and conditional branch to parallel's cancel_label to handle
9993 cancellation in the implicit barrier. */
9995 static void
9996 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9998 gimple omp_return = gimple_seq_last_stmt (*body);
9999 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
10000 if (gimple_omp_return_nowait_p (omp_return))
10001 return;
10002 if (ctx->outer
10003 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
10004 && ctx->outer->cancellable)
10006 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
10007 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
10008 tree lhs = create_tmp_var (c_bool_type);
10009 gimple_omp_return_set_lhs (omp_return, lhs);
10010 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10011 gimple g = gimple_build_cond (NE_EXPR, lhs,
10012 fold_convert (c_bool_type,
10013 boolean_false_node),
10014 ctx->outer->cancel_label, fallthru_label);
10015 gimple_seq_add_stmt (body, g);
10016 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10020 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10021 CTX is the enclosing OMP context for the current statement. */
10023 static void
10024 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10026 tree block, control;
10027 gimple_stmt_iterator tgsi;
10028 gomp_sections *stmt;
10029 gimple t;
10030 gbind *new_stmt, *bind;
10031 gimple_seq ilist, dlist, olist, new_body;
10033 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
10035 push_gimplify_context ();
10037 dlist = NULL;
10038 ilist = NULL;
10039 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10040 &ilist, &dlist, ctx, NULL);
10042 new_body = gimple_omp_body (stmt);
10043 gimple_omp_set_body (stmt, NULL);
10044 tgsi = gsi_start (new_body);
10045 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10047 omp_context *sctx;
10048 gimple sec_start;
10050 sec_start = gsi_stmt (tgsi);
10051 sctx = maybe_lookup_ctx (sec_start);
10052 gcc_assert (sctx);
10054 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10055 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10056 GSI_CONTINUE_LINKING);
10057 gimple_omp_set_body (sec_start, NULL);
10059 if (gsi_one_before_end_p (tgsi))
10061 gimple_seq l = NULL;
10062 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10063 &l, ctx);
10064 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10065 gimple_omp_section_set_last (sec_start);
10068 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10069 GSI_CONTINUE_LINKING);
10072 block = make_node (BLOCK);
10073 bind = gimple_build_bind (NULL, new_body, block);
10075 olist = NULL;
10076 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10078 block = make_node (BLOCK);
10079 new_stmt = gimple_build_bind (NULL, NULL, block);
10080 gsi_replace (gsi_p, new_stmt, true);
10082 pop_gimplify_context (new_stmt);
10083 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10084 BLOCK_VARS (block) = gimple_bind_vars (bind);
10085 if (BLOCK_VARS (block))
10086 TREE_USED (block) = 1;
10088 new_body = NULL;
10089 gimple_seq_add_seq (&new_body, ilist);
10090 gimple_seq_add_stmt (&new_body, stmt);
10091 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10092 gimple_seq_add_stmt (&new_body, bind);
10094 control = create_tmp_var (unsigned_type_node, ".section");
10095 t = gimple_build_omp_continue (control, control);
10096 gimple_omp_sections_set_control (stmt, control);
10097 gimple_seq_add_stmt (&new_body, t);
10099 gimple_seq_add_seq (&new_body, olist);
10100 if (ctx->cancellable)
10101 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10102 gimple_seq_add_seq (&new_body, dlist);
10104 new_body = maybe_catch_exception (new_body);
10106 t = gimple_build_omp_return
10107 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10108 OMP_CLAUSE_NOWAIT));
10109 gimple_seq_add_stmt (&new_body, t);
10110 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10112 gimple_bind_set_body (new_stmt, new_body);
10116 /* A subroutine of lower_omp_single. Expand the simple form of
10117 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10119 if (GOMP_single_start ())
10120 BODY;
10121 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10123 FIXME. It may be better to delay expanding the logic of this until
10124 pass_expand_omp. The expanded logic may make the job more difficult
10125 to a synchronization analysis pass. */
10127 static void
10128 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10130 location_t loc = gimple_location (single_stmt);
10131 tree tlabel = create_artificial_label (loc);
10132 tree flabel = create_artificial_label (loc);
10133 gimple call, cond;
10134 tree lhs, decl;
10136 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10137 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10138 call = gimple_build_call (decl, 0);
10139 gimple_call_set_lhs (call, lhs);
10140 gimple_seq_add_stmt (pre_p, call);
10142 cond = gimple_build_cond (EQ_EXPR, lhs,
10143 fold_convert_loc (loc, TREE_TYPE (lhs),
10144 boolean_true_node),
10145 tlabel, flabel);
10146 gimple_seq_add_stmt (pre_p, cond);
10147 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10148 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10149 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10153 /* A subroutine of lower_omp_single. Expand the simple form of
10154 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10156 #pragma omp single copyprivate (a, b, c)
10158 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10161 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10163 BODY;
10164 copyout.a = a;
10165 copyout.b = b;
10166 copyout.c = c;
10167 GOMP_single_copy_end (&copyout);
10169 else
10171 a = copyout_p->a;
10172 b = copyout_p->b;
10173 c = copyout_p->c;
10175 GOMP_barrier ();
10178 FIXME. It may be better to delay expanding the logic of this until
10179 pass_expand_omp. The expanded logic may make the job more difficult
10180 to a synchronization analysis pass. */
10182 static void
10183 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10184 omp_context *ctx)
10186 tree ptr_type, t, l0, l1, l2, bfn_decl;
10187 gimple_seq copyin_seq;
10188 location_t loc = gimple_location (single_stmt);
10190 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10192 ptr_type = build_pointer_type (ctx->record_type);
10193 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10195 l0 = create_artificial_label (loc);
10196 l1 = create_artificial_label (loc);
10197 l2 = create_artificial_label (loc);
10199 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10200 t = build_call_expr_loc (loc, bfn_decl, 0);
10201 t = fold_convert_loc (loc, ptr_type, t);
10202 gimplify_assign (ctx->receiver_decl, t, pre_p);
10204 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10205 build_int_cst (ptr_type, 0));
10206 t = build3 (COND_EXPR, void_type_node, t,
10207 build_and_jump (&l0), build_and_jump (&l1));
10208 gimplify_and_add (t, pre_p);
10210 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10212 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10214 copyin_seq = NULL;
10215 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10216 &copyin_seq, ctx);
10218 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10219 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10220 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10221 gimplify_and_add (t, pre_p);
10223 t = build_and_jump (&l2);
10224 gimplify_and_add (t, pre_p);
10226 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10228 gimple_seq_add_seq (pre_p, copyin_seq);
10230 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10234 /* Expand code for an OpenMP single directive. */
10236 static void
10237 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10239 tree block;
10240 gimple t;
10241 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10242 gbind *bind;
10243 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10245 push_gimplify_context ();
10247 block = make_node (BLOCK);
10248 bind = gimple_build_bind (NULL, NULL, block);
10249 gsi_replace (gsi_p, bind, true);
10250 bind_body = NULL;
10251 dlist = NULL;
10252 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10253 &bind_body, &dlist, ctx, NULL);
10254 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10256 gimple_seq_add_stmt (&bind_body, single_stmt);
10258 if (ctx->record_type)
10259 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10260 else
10261 lower_omp_single_simple (single_stmt, &bind_body);
10263 gimple_omp_set_body (single_stmt, NULL);
10265 gimple_seq_add_seq (&bind_body, dlist);
10267 bind_body = maybe_catch_exception (bind_body);
10269 t = gimple_build_omp_return
10270 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10271 OMP_CLAUSE_NOWAIT));
10272 gimple_seq_add_stmt (&bind_body_tail, t);
10273 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10274 if (ctx->record_type)
10276 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10277 tree clobber = build_constructor (ctx->record_type, NULL);
10278 TREE_THIS_VOLATILE (clobber) = 1;
10279 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10280 clobber), GSI_SAME_STMT);
10282 gimple_seq_add_seq (&bind_body, bind_body_tail);
10283 gimple_bind_set_body (bind, bind_body);
10285 pop_gimplify_context (bind);
10287 gimple_bind_append_vars (bind, ctx->block_vars);
10288 BLOCK_VARS (block) = ctx->block_vars;
10289 if (BLOCK_VARS (block))
10290 TREE_USED (block) = 1;
10294 /* Expand code for an OpenMP master directive. */
10296 static void
10297 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10299 tree block, lab = NULL, x, bfn_decl;
10300 gimple stmt = gsi_stmt (*gsi_p);
10301 gbind *bind;
10302 location_t loc = gimple_location (stmt);
10303 gimple_seq tseq;
10305 push_gimplify_context ();
10307 block = make_node (BLOCK);
10308 bind = gimple_build_bind (NULL, NULL, block);
10309 gsi_replace (gsi_p, bind, true);
10310 gimple_bind_add_stmt (bind, stmt);
10312 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10313 x = build_call_expr_loc (loc, bfn_decl, 0);
10314 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10315 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10316 tseq = NULL;
10317 gimplify_and_add (x, &tseq);
10318 gimple_bind_add_seq (bind, tseq);
10320 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10321 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10322 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10323 gimple_omp_set_body (stmt, NULL);
10325 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10327 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10329 pop_gimplify_context (bind);
10331 gimple_bind_append_vars (bind, ctx->block_vars);
10332 BLOCK_VARS (block) = ctx->block_vars;
10336 /* Expand code for an OpenMP taskgroup directive. */
10338 static void
10339 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10341 gimple stmt = gsi_stmt (*gsi_p);
10342 gcall *x;
10343 gbind *bind;
10344 tree block = make_node (BLOCK);
10346 bind = gimple_build_bind (NULL, NULL, block);
10347 gsi_replace (gsi_p, bind, true);
10348 gimple_bind_add_stmt (bind, stmt);
10350 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10352 gimple_bind_add_stmt (bind, x);
10354 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10355 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10356 gimple_omp_set_body (stmt, NULL);
10358 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10360 gimple_bind_append_vars (bind, ctx->block_vars);
10361 BLOCK_VARS (block) = ctx->block_vars;
10365 /* Expand code for an OpenMP ordered directive. */
10367 static void
10368 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10370 tree block;
10371 gimple stmt = gsi_stmt (*gsi_p);
10372 gcall *x;
10373 gbind *bind;
10375 push_gimplify_context ();
10377 block = make_node (BLOCK);
10378 bind = gimple_build_bind (NULL, NULL, block);
10379 gsi_replace (gsi_p, bind, true);
10380 gimple_bind_add_stmt (bind, stmt);
10382 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10384 gimple_bind_add_stmt (bind, x);
10386 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10387 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10388 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10389 gimple_omp_set_body (stmt, NULL);
10391 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10392 gimple_bind_add_stmt (bind, x);
10394 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10396 pop_gimplify_context (bind);
10398 gimple_bind_append_vars (bind, ctx->block_vars);
10399 BLOCK_VARS (block) = gimple_bind_vars (bind);
10403 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10404 substitution of a couple of function calls. But in the NAMED case,
10405 requires that languages coordinate a symbol name. It is therefore
10406 best put here in common code. */
10408 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10410 static void
10411 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10413 tree block;
10414 tree name, lock, unlock;
10415 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10416 gbind *bind;
10417 location_t loc = gimple_location (stmt);
10418 gimple_seq tbody;
10420 name = gimple_omp_critical_name (stmt);
10421 if (name)
10423 tree decl;
10425 if (!critical_name_mutexes)
10426 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10428 tree *n = critical_name_mutexes->get (name);
10429 if (n == NULL)
10431 char *new_str;
10433 decl = create_tmp_var_raw (ptr_type_node);
10435 new_str = ACONCAT ((".gomp_critical_user_",
10436 IDENTIFIER_POINTER (name), NULL));
10437 DECL_NAME (decl) = get_identifier (new_str);
10438 TREE_PUBLIC (decl) = 1;
10439 TREE_STATIC (decl) = 1;
10440 DECL_COMMON (decl) = 1;
10441 DECL_ARTIFICIAL (decl) = 1;
10442 DECL_IGNORED_P (decl) = 1;
10444 varpool_node::finalize_decl (decl);
10446 critical_name_mutexes->put (name, decl);
10448 else
10449 decl = *n;
10451 /* If '#pragma omp critical' is inside offloaded region or
10452 inside function marked as offloadable, the symbol must be
10453 marked as offloadable too. */
10454 omp_context *octx;
10455 if (cgraph_node::get (current_function_decl)->offloadable)
10456 varpool_node::get_create (decl)->offloadable = 1;
10457 else
10458 for (octx = ctx->outer; octx; octx = octx->outer)
10459 if (is_gimple_omp_offloaded (octx->stmt))
10461 varpool_node::get_create (decl)->offloadable = 1;
10462 break;
10465 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10466 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10468 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10469 unlock = build_call_expr_loc (loc, unlock, 1,
10470 build_fold_addr_expr_loc (loc, decl));
10472 else
10474 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10475 lock = build_call_expr_loc (loc, lock, 0);
10477 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10478 unlock = build_call_expr_loc (loc, unlock, 0);
10481 push_gimplify_context ();
10483 block = make_node (BLOCK);
10484 bind = gimple_build_bind (NULL, NULL, block);
10485 gsi_replace (gsi_p, bind, true);
10486 gimple_bind_add_stmt (bind, stmt);
10488 tbody = gimple_bind_body (bind);
10489 gimplify_and_add (lock, &tbody);
10490 gimple_bind_set_body (bind, tbody);
10492 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10493 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10494 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10495 gimple_omp_set_body (stmt, NULL);
10497 tbody = gimple_bind_body (bind);
10498 gimplify_and_add (unlock, &tbody);
10499 gimple_bind_set_body (bind, tbody);
10501 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10503 pop_gimplify_context (bind);
10504 gimple_bind_append_vars (bind, ctx->block_vars);
10505 BLOCK_VARS (block) = gimple_bind_vars (bind);
10509 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10510 for a lastprivate clause. Given a loop control predicate of (V
10511 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10512 is appended to *DLIST, iterator initialization is appended to
10513 *BODY_P. */
10515 static void
10516 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10517 gimple_seq *dlist, struct omp_context *ctx)
10519 tree clauses, cond, vinit;
10520 enum tree_code cond_code;
10521 gimple_seq stmts;
10523 cond_code = fd->loop.cond_code;
10524 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10526 /* When possible, use a strict equality expression. This can let VRP
10527 type optimizations deduce the value and remove a copy. */
10528 if (tree_fits_shwi_p (fd->loop.step))
10530 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10531 if (step == 1 || step == -1)
10532 cond_code = EQ_EXPR;
10535 tree n2 = fd->loop.n2;
10536 if (fd->collapse > 1
10537 && TREE_CODE (n2) != INTEGER_CST
10538 && gimple_omp_for_combined_into_p (fd->for_stmt)
10539 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10541 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10542 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
10544 struct omp_for_data outer_fd;
10545 extract_omp_for_data (gfor, &outer_fd, NULL);
10546 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10549 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
10551 clauses = gimple_omp_for_clauses (fd->for_stmt);
10552 stmts = NULL;
10553 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10554 if (!gimple_seq_empty_p (stmts))
10556 gimple_seq_add_seq (&stmts, *dlist);
10557 *dlist = stmts;
10559 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10560 vinit = fd->loop.n1;
10561 if (cond_code == EQ_EXPR
10562 && tree_fits_shwi_p (fd->loop.n2)
10563 && ! integer_zerop (fd->loop.n2))
10564 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10565 else
10566 vinit = unshare_expr (vinit);
10568 /* Initialize the iterator variable, so that threads that don't execute
10569 any iterations don't execute the lastprivate clauses by accident. */
10570 gimplify_assign (fd->loop.v, vinit, body_p);
10575 /* Lower code for an OMP loop directive. */
10577 static void
10578 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10580 tree *rhs_p, block;
10581 struct omp_for_data fd, *fdp = NULL;
10582 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10583 gbind *new_stmt;
10584 gimple_seq omp_for_body, body, dlist;
10585 size_t i;
10587 push_gimplify_context ();
10589 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10591 block = make_node (BLOCK);
10592 new_stmt = gimple_build_bind (NULL, NULL, block);
10593 /* Replace at gsi right away, so that 'stmt' is no member
10594 of a sequence anymore as we're going to add to to a different
10595 one below. */
10596 gsi_replace (gsi_p, new_stmt, true);
10598 /* Move declaration of temporaries in the loop body before we make
10599 it go away. */
10600 omp_for_body = gimple_omp_body (stmt);
10601 if (!gimple_seq_empty_p (omp_for_body)
10602 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10604 gbind *inner_bind
10605 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10606 tree vars = gimple_bind_vars (inner_bind);
10607 gimple_bind_append_vars (new_stmt, vars);
10608 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10609 keep them on the inner_bind and it's block. */
10610 gimple_bind_set_vars (inner_bind, NULL_TREE);
10611 if (gimple_bind_block (inner_bind))
10612 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10615 if (gimple_omp_for_combined_into_p (stmt))
10617 extract_omp_for_data (stmt, &fd, NULL);
10618 fdp = &fd;
10620 /* We need two temporaries with fd.loop.v type (istart/iend)
10621 and then (fd.collapse - 1) temporaries with the same
10622 type for count2 ... countN-1 vars if not constant. */
10623 size_t count = 2;
10624 tree type = fd.iter_type;
10625 if (fd.collapse > 1
10626 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10627 count += fd.collapse - 1;
10628 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10629 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10630 tree clauses = *pc;
10631 if (parallel_for)
10632 outerc
10633 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10634 OMP_CLAUSE__LOOPTEMP_);
10635 for (i = 0; i < count; i++)
10637 tree temp;
10638 if (parallel_for)
10640 gcc_assert (outerc);
10641 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10642 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10643 OMP_CLAUSE__LOOPTEMP_);
10645 else
10647 temp = create_tmp_var (type);
10648 insert_decl_map (&ctx->outer->cb, temp, temp);
10650 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10651 OMP_CLAUSE_DECL (*pc) = temp;
10652 pc = &OMP_CLAUSE_CHAIN (*pc);
10654 *pc = clauses;
10657 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10658 dlist = NULL;
10659 body = NULL;
10660 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10661 fdp);
10662 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10664 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10666 /* Lower the header expressions. At this point, we can assume that
10667 the header is of the form:
10669 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10671 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10672 using the .omp_data_s mapping, if needed. */
10673 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10675 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10676 if (!is_gimple_min_invariant (*rhs_p))
10677 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10679 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10680 if (!is_gimple_min_invariant (*rhs_p))
10681 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10683 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10684 if (!is_gimple_min_invariant (*rhs_p))
10685 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10688 /* Once lowered, extract the bounds and clauses. */
10689 extract_omp_for_data (stmt, &fd, NULL);
10691 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10693 gimple_seq_add_stmt (&body, stmt);
10694 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10696 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10697 fd.loop.v));
10699 /* After the loop, add exit clauses. */
10700 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10702 if (ctx->cancellable)
10703 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10705 gimple_seq_add_seq (&body, dlist);
10707 body = maybe_catch_exception (body);
10709 /* Region exit marker goes at the end of the loop body. */
10710 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10711 maybe_add_implicit_barrier_cancel (ctx, &body);
10712 pop_gimplify_context (new_stmt);
10714 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10715 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10716 if (BLOCK_VARS (block))
10717 TREE_USED (block) = 1;
10719 gimple_bind_set_body (new_stmt, body);
10720 gimple_omp_set_body (stmt, NULL);
10721 gimple_omp_for_set_pre_body (stmt, NULL);
10724 /* Callback for walk_stmts. Check if the current statement only contains
10725 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10727 static tree
10728 check_combined_parallel (gimple_stmt_iterator *gsi_p,
10729 bool *handled_ops_p,
10730 struct walk_stmt_info *wi)
10732 int *info = (int *) wi->info;
10733 gimple stmt = gsi_stmt (*gsi_p);
10735 *handled_ops_p = true;
10736 switch (gimple_code (stmt))
10738 WALK_SUBSTMTS;
10740 case GIMPLE_OMP_FOR:
10741 case GIMPLE_OMP_SECTIONS:
10742 *info = *info == 0 ? 1 : -1;
10743 break;
10744 default:
10745 *info = -1;
10746 break;
10748 return NULL;
10751 struct omp_taskcopy_context
10753 /* This field must be at the beginning, as we do "inheritance": Some
10754 callback functions for tree-inline.c (e.g., omp_copy_decl)
10755 receive a copy_body_data pointer that is up-casted to an
10756 omp_context pointer. */
10757 copy_body_data cb;
10758 omp_context *ctx;
10761 static tree
10762 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10764 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10766 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10767 return create_tmp_var (TREE_TYPE (var));
10769 return var;
10772 static tree
10773 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10775 tree name, new_fields = NULL, type, f;
10777 type = lang_hooks.types.make_type (RECORD_TYPE);
10778 name = DECL_NAME (TYPE_NAME (orig_type));
10779 name = build_decl (gimple_location (tcctx->ctx->stmt),
10780 TYPE_DECL, name, type);
10781 TYPE_NAME (type) = name;
10783 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10785 tree new_f = copy_node (f);
10786 DECL_CONTEXT (new_f) = type;
10787 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10788 TREE_CHAIN (new_f) = new_fields;
10789 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10790 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10791 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10792 &tcctx->cb, NULL);
10793 new_fields = new_f;
10794 tcctx->cb.decl_map->put (f, new_f);
10796 TYPE_FIELDS (type) = nreverse (new_fields);
10797 layout_type (type);
10798 return type;
10801 /* Create task copyfn. */
10803 static void
10804 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
10806 struct function *child_cfun;
10807 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10808 tree record_type, srecord_type, bind, list;
10809 bool record_needs_remap = false, srecord_needs_remap = false;
10810 splay_tree_node n;
10811 struct omp_taskcopy_context tcctx;
10812 location_t loc = gimple_location (task_stmt);
10814 child_fn = gimple_omp_task_copy_fn (task_stmt);
10815 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10816 gcc_assert (child_cfun->cfg == NULL);
10817 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10819 /* Reset DECL_CONTEXT on function arguments. */
10820 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10821 DECL_CONTEXT (t) = child_fn;
10823 /* Populate the function. */
10824 push_gimplify_context ();
10825 push_cfun (child_cfun);
10827 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10828 TREE_SIDE_EFFECTS (bind) = 1;
10829 list = NULL;
10830 DECL_SAVED_TREE (child_fn) = bind;
10831 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10833 /* Remap src and dst argument types if needed. */
10834 record_type = ctx->record_type;
10835 srecord_type = ctx->srecord_type;
10836 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10837 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10839 record_needs_remap = true;
10840 break;
10842 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10843 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10845 srecord_needs_remap = true;
10846 break;
10849 if (record_needs_remap || srecord_needs_remap)
10851 memset (&tcctx, '\0', sizeof (tcctx));
10852 tcctx.cb.src_fn = ctx->cb.src_fn;
10853 tcctx.cb.dst_fn = child_fn;
10854 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
10855 gcc_checking_assert (tcctx.cb.src_node);
10856 tcctx.cb.dst_node = tcctx.cb.src_node;
10857 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10858 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10859 tcctx.cb.eh_lp_nr = 0;
10860 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10861 tcctx.cb.decl_map = new hash_map<tree, tree>;
10862 tcctx.ctx = ctx;
10864 if (record_needs_remap)
10865 record_type = task_copyfn_remap_type (&tcctx, record_type);
10866 if (srecord_needs_remap)
10867 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10869 else
10870 tcctx.cb.decl_map = NULL;
10872 arg = DECL_ARGUMENTS (child_fn);
10873 TREE_TYPE (arg) = build_pointer_type (record_type);
10874 sarg = DECL_CHAIN (arg);
10875 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10877 /* First pass: initialize temporaries used in record_type and srecord_type
10878 sizes and field offsets. */
10879 if (tcctx.cb.decl_map)
10880 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10881 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10883 tree *p;
10885 decl = OMP_CLAUSE_DECL (c);
10886 p = tcctx.cb.decl_map->get (decl);
10887 if (p == NULL)
10888 continue;
10889 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10890 sf = (tree) n->value;
10891 sf = *tcctx.cb.decl_map->get (sf);
10892 src = build_simple_mem_ref_loc (loc, sarg);
10893 src = omp_build_component_ref (src, sf);
10894 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10895 append_to_statement_list (t, &list);
10898 /* Second pass: copy shared var pointers and copy construct non-VLA
10899 firstprivate vars. */
10900 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10901 switch (OMP_CLAUSE_CODE (c))
10903 case OMP_CLAUSE_SHARED:
10904 decl = OMP_CLAUSE_DECL (c);
10905 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10906 if (n == NULL)
10907 break;
10908 f = (tree) n->value;
10909 if (tcctx.cb.decl_map)
10910 f = *tcctx.cb.decl_map->get (f);
10911 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10912 sf = (tree) n->value;
10913 if (tcctx.cb.decl_map)
10914 sf = *tcctx.cb.decl_map->get (sf);
10915 src = build_simple_mem_ref_loc (loc, sarg);
10916 src = omp_build_component_ref (src, sf);
10917 dst = build_simple_mem_ref_loc (loc, arg);
10918 dst = omp_build_component_ref (dst, f);
10919 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10920 append_to_statement_list (t, &list);
10921 break;
10922 case OMP_CLAUSE_FIRSTPRIVATE:
10923 decl = OMP_CLAUSE_DECL (c);
10924 if (is_variable_sized (decl))
10925 break;
10926 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10927 if (n == NULL)
10928 break;
10929 f = (tree) n->value;
10930 if (tcctx.cb.decl_map)
10931 f = *tcctx.cb.decl_map->get (f);
10932 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10933 if (n != NULL)
10935 sf = (tree) n->value;
10936 if (tcctx.cb.decl_map)
10937 sf = *tcctx.cb.decl_map->get (sf);
10938 src = build_simple_mem_ref_loc (loc, sarg);
10939 src = omp_build_component_ref (src, sf);
10940 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
10941 src = build_simple_mem_ref_loc (loc, src);
10943 else
10944 src = decl;
10945 dst = build_simple_mem_ref_loc (loc, arg);
10946 dst = omp_build_component_ref (dst, f);
10947 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10948 append_to_statement_list (t, &list);
10949 break;
10950 case OMP_CLAUSE_PRIVATE:
10951 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10952 break;
10953 decl = OMP_CLAUSE_DECL (c);
10954 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10955 f = (tree) n->value;
10956 if (tcctx.cb.decl_map)
10957 f = *tcctx.cb.decl_map->get (f);
10958 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10959 if (n != NULL)
10961 sf = (tree) n->value;
10962 if (tcctx.cb.decl_map)
10963 sf = *tcctx.cb.decl_map->get (sf);
10964 src = build_simple_mem_ref_loc (loc, sarg);
10965 src = omp_build_component_ref (src, sf);
10966 if (use_pointer_for_field (decl, NULL))
10967 src = build_simple_mem_ref_loc (loc, src);
10969 else
10970 src = decl;
10971 dst = build_simple_mem_ref_loc (loc, arg);
10972 dst = omp_build_component_ref (dst, f);
10973 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10974 append_to_statement_list (t, &list);
10975 break;
10976 default:
10977 break;
10980 /* Last pass: handle VLA firstprivates. */
10981 if (tcctx.cb.decl_map)
10982 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10983 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10985 tree ind, ptr, df;
10987 decl = OMP_CLAUSE_DECL (c);
10988 if (!is_variable_sized (decl))
10989 continue;
10990 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10991 if (n == NULL)
10992 continue;
10993 f = (tree) n->value;
10994 f = *tcctx.cb.decl_map->get (f);
10995 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10996 ind = DECL_VALUE_EXPR (decl);
10997 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10998 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10999 n = splay_tree_lookup (ctx->sfield_map,
11000 (splay_tree_key) TREE_OPERAND (ind, 0));
11001 sf = (tree) n->value;
11002 sf = *tcctx.cb.decl_map->get (sf);
11003 src = build_simple_mem_ref_loc (loc, sarg);
11004 src = omp_build_component_ref (src, sf);
11005 src = build_simple_mem_ref_loc (loc, src);
11006 dst = build_simple_mem_ref_loc (loc, arg);
11007 dst = omp_build_component_ref (dst, f);
11008 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11009 append_to_statement_list (t, &list);
11010 n = splay_tree_lookup (ctx->field_map,
11011 (splay_tree_key) TREE_OPERAND (ind, 0));
11012 df = (tree) n->value;
11013 df = *tcctx.cb.decl_map->get (df);
11014 ptr = build_simple_mem_ref_loc (loc, arg);
11015 ptr = omp_build_component_ref (ptr, df);
11016 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
11017 build_fold_addr_expr_loc (loc, dst));
11018 append_to_statement_list (t, &list);
11021 t = build1 (RETURN_EXPR, void_type_node, NULL);
11022 append_to_statement_list (t, &list);
11024 if (tcctx.cb.decl_map)
11025 delete tcctx.cb.decl_map;
11026 pop_gimplify_context (NULL);
11027 BIND_EXPR_BODY (bind) = list;
11028 pop_cfun ();
11031 static void
11032 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
11034 tree c, clauses;
11035 gimple g;
11036 size_t n_in = 0, n_out = 0, idx = 2, i;
11038 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11039 OMP_CLAUSE_DEPEND);
11040 gcc_assert (clauses);
11041 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11042 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11043 switch (OMP_CLAUSE_DEPEND_KIND (c))
11045 case OMP_CLAUSE_DEPEND_IN:
11046 n_in++;
11047 break;
11048 case OMP_CLAUSE_DEPEND_OUT:
11049 case OMP_CLAUSE_DEPEND_INOUT:
11050 n_out++;
11051 break;
11052 default:
11053 gcc_unreachable ();
11055 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11056 tree array = create_tmp_var (type);
11057 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11058 NULL_TREE);
11059 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11060 gimple_seq_add_stmt (iseq, g);
11061 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11062 NULL_TREE);
11063 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11064 gimple_seq_add_stmt (iseq, g);
11065 for (i = 0; i < 2; i++)
11067 if ((i ? n_in : n_out) == 0)
11068 continue;
11069 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11070 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11071 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11073 tree t = OMP_CLAUSE_DECL (c);
11074 t = fold_convert (ptr_type_node, t);
11075 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11076 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11077 NULL_TREE, NULL_TREE);
11078 g = gimple_build_assign (r, t);
11079 gimple_seq_add_stmt (iseq, g);
11082 tree *p = gimple_omp_task_clauses_ptr (stmt);
11083 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11084 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11085 OMP_CLAUSE_CHAIN (c) = *p;
11086 *p = c;
11087 tree clobber = build_constructor (type, NULL);
11088 TREE_THIS_VOLATILE (clobber) = 1;
11089 g = gimple_build_assign (array, clobber);
11090 gimple_seq_add_stmt (oseq, g);
11093 /* Lower the OpenMP parallel or task directive in the current statement
11094 in GSI_P. CTX holds context information for the directive. */
11096 static void
11097 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11099 tree clauses;
11100 tree child_fn, t;
11101 gimple stmt = gsi_stmt (*gsi_p);
11102 gbind *par_bind, *bind, *dep_bind = NULL;
11103 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11104 location_t loc = gimple_location (stmt);
11106 clauses = gimple_omp_taskreg_clauses (stmt);
11107 par_bind
11108 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11109 par_body = gimple_bind_body (par_bind);
11110 child_fn = ctx->cb.dst_fn;
11111 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11112 && !gimple_omp_parallel_combined_p (stmt))
11114 struct walk_stmt_info wi;
11115 int ws_num = 0;
11117 memset (&wi, 0, sizeof (wi));
11118 wi.info = &ws_num;
11119 wi.val_only = true;
11120 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11121 if (ws_num == 1)
11122 gimple_omp_parallel_set_combined_p (stmt, true);
11124 gimple_seq dep_ilist = NULL;
11125 gimple_seq dep_olist = NULL;
11126 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11127 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11129 push_gimplify_context ();
11130 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11131 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11134 if (ctx->srecord_type)
11135 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11137 push_gimplify_context ();
11139 par_olist = NULL;
11140 par_ilist = NULL;
11141 par_rlist = NULL;
11142 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11143 lower_omp (&par_body, ctx);
11144 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11145 lower_reduction_clauses (clauses, &par_rlist, ctx);
11147 /* Declare all the variables created by mapping and the variables
11148 declared in the scope of the parallel body. */
11149 record_vars_into (ctx->block_vars, child_fn);
11150 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11152 if (ctx->record_type)
11154 ctx->sender_decl
11155 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11156 : ctx->record_type, ".omp_data_o");
11157 DECL_NAMELESS (ctx->sender_decl) = 1;
11158 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11159 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11162 olist = NULL;
11163 ilist = NULL;
11164 lower_send_clauses (clauses, &ilist, &olist, ctx);
11165 lower_send_shared_vars (&ilist, &olist, ctx);
11167 if (ctx->record_type)
11169 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11170 TREE_THIS_VOLATILE (clobber) = 1;
11171 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11172 clobber));
11175 /* Once all the expansions are done, sequence all the different
11176 fragments inside gimple_omp_body. */
11178 new_body = NULL;
11180 if (ctx->record_type)
11182 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11183 /* fixup_child_record_type might have changed receiver_decl's type. */
11184 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11185 gimple_seq_add_stmt (&new_body,
11186 gimple_build_assign (ctx->receiver_decl, t));
11189 gimple_seq_add_seq (&new_body, par_ilist);
11190 gimple_seq_add_seq (&new_body, par_body);
11191 gimple_seq_add_seq (&new_body, par_rlist);
11192 if (ctx->cancellable)
11193 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11194 gimple_seq_add_seq (&new_body, par_olist);
11195 new_body = maybe_catch_exception (new_body);
11196 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
11197 gimple_seq_add_stmt (&new_body,
11198 gimple_build_omp_continue (integer_zero_node,
11199 integer_zero_node));
11200 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11201 gimple_omp_set_body (stmt, new_body);
11203 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11204 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11205 gimple_bind_add_seq (bind, ilist);
11206 gimple_bind_add_stmt (bind, stmt);
11207 gimple_bind_add_seq (bind, olist);
11209 pop_gimplify_context (NULL);
11211 if (dep_bind)
11213 gimple_bind_add_seq (dep_bind, dep_ilist);
11214 gimple_bind_add_stmt (dep_bind, bind);
11215 gimple_bind_add_seq (dep_bind, dep_olist);
11216 pop_gimplify_context (dep_bind);
11220 /* Lower the GIMPLE_OMP_TARGET in the current statement
11221 in GSI_P. CTX holds context information for the directive. */
11223 static void
11224 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11226 tree clauses;
11227 tree child_fn, t, c;
11228 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11229 gbind *tgt_bind, *bind;
11230 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11231 location_t loc = gimple_location (stmt);
11232 bool offloaded, data_region;
11233 unsigned int map_cnt = 0;
11235 offloaded = is_gimple_omp_offloaded (stmt);
11236 switch (gimple_omp_target_kind (stmt))
11238 case GF_OMP_TARGET_KIND_REGION:
11239 case GF_OMP_TARGET_KIND_UPDATE:
11240 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11241 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11242 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11243 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11244 data_region = false;
11245 break;
11246 case GF_OMP_TARGET_KIND_DATA:
11247 case GF_OMP_TARGET_KIND_OACC_DATA:
11248 data_region = true;
11249 break;
11250 default:
11251 gcc_unreachable ();
11254 clauses = gimple_omp_target_clauses (stmt);
11256 tgt_bind = NULL;
11257 tgt_body = NULL;
11258 if (offloaded)
11260 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11261 tgt_body = gimple_bind_body (tgt_bind);
11263 else if (data_region)
11264 tgt_body = gimple_omp_body (stmt);
11265 child_fn = ctx->cb.dst_fn;
11267 push_gimplify_context ();
11269 irlist = NULL;
11270 orlist = NULL;
11271 if (offloaded
11272 && is_gimple_omp_oacc (stmt))
11273 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11275 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11276 switch (OMP_CLAUSE_CODE (c))
11278 tree var, x;
11280 default:
11281 break;
11282 case OMP_CLAUSE_MAP:
11283 #ifdef ENABLE_CHECKING
11284 /* First check what we're prepared to handle in the following. */
11285 switch (OMP_CLAUSE_MAP_KIND (c))
11287 case GOMP_MAP_ALLOC:
11288 case GOMP_MAP_TO:
11289 case GOMP_MAP_FROM:
11290 case GOMP_MAP_TOFROM:
11291 case GOMP_MAP_POINTER:
11292 case GOMP_MAP_TO_PSET:
11293 break;
11294 case GOMP_MAP_FORCE_ALLOC:
11295 case GOMP_MAP_FORCE_TO:
11296 case GOMP_MAP_FORCE_FROM:
11297 case GOMP_MAP_FORCE_TOFROM:
11298 case GOMP_MAP_FORCE_PRESENT:
11299 case GOMP_MAP_FORCE_DEALLOC:
11300 case GOMP_MAP_FORCE_DEVICEPTR:
11301 gcc_assert (is_gimple_omp_oacc (stmt));
11302 break;
11303 default:
11304 gcc_unreachable ();
11306 #endif
11307 /* FALLTHRU */
11308 case OMP_CLAUSE_TO:
11309 case OMP_CLAUSE_FROM:
11310 var = OMP_CLAUSE_DECL (c);
11311 if (!DECL_P (var))
11313 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11314 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11315 map_cnt++;
11316 continue;
11319 if (DECL_SIZE (var)
11320 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11322 tree var2 = DECL_VALUE_EXPR (var);
11323 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11324 var2 = TREE_OPERAND (var2, 0);
11325 gcc_assert (DECL_P (var2));
11326 var = var2;
11329 if (!maybe_lookup_field (var, ctx))
11330 continue;
11332 if (offloaded)
11334 x = build_receiver_ref (var, true, ctx);
11335 tree new_var = lookup_decl (var, ctx);
11336 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11337 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11338 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11339 x = build_simple_mem_ref (x);
11340 SET_DECL_VALUE_EXPR (new_var, x);
11341 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11343 map_cnt++;
11346 if (offloaded)
11348 target_nesting_level++;
11349 lower_omp (&tgt_body, ctx);
11350 target_nesting_level--;
11352 else if (data_region)
11353 lower_omp (&tgt_body, ctx);
11355 if (offloaded)
11357 /* Declare all the variables created by mapping and the variables
11358 declared in the scope of the target body. */
11359 record_vars_into (ctx->block_vars, child_fn);
11360 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11363 olist = NULL;
11364 ilist = NULL;
11365 if (ctx->record_type)
11367 ctx->sender_decl
11368 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11369 DECL_NAMELESS (ctx->sender_decl) = 1;
11370 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11371 t = make_tree_vec (3);
11372 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11373 TREE_VEC_ELT (t, 1)
11374 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11375 ".omp_data_sizes");
11376 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11377 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11378 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11379 tree tkind_type;
11380 int talign_shift;
11381 if (is_gimple_omp_oacc (stmt))
11383 tkind_type = short_unsigned_type_node;
11384 talign_shift = 8;
11386 else
11388 tkind_type = unsigned_char_type_node;
11389 talign_shift = 3;
11391 TREE_VEC_ELT (t, 2)
11392 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11393 ".omp_data_kinds");
11394 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11395 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11396 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11397 gimple_omp_target_set_data_arg (stmt, t);
11399 vec<constructor_elt, va_gc> *vsize;
11400 vec<constructor_elt, va_gc> *vkind;
11401 vec_alloc (vsize, map_cnt);
11402 vec_alloc (vkind, map_cnt);
11403 unsigned int map_idx = 0;
11405 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11406 switch (OMP_CLAUSE_CODE (c))
11408 tree ovar, nc;
11410 default:
11411 break;
11412 case OMP_CLAUSE_MAP:
11413 case OMP_CLAUSE_TO:
11414 case OMP_CLAUSE_FROM:
11415 nc = c;
11416 ovar = OMP_CLAUSE_DECL (c);
11417 if (!DECL_P (ovar))
11419 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11420 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11422 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11423 == get_base_address (ovar));
11424 nc = OMP_CLAUSE_CHAIN (c);
11425 ovar = OMP_CLAUSE_DECL (nc);
11427 else
11429 tree x = build_sender_ref (ovar, ctx);
11430 tree v
11431 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11432 gimplify_assign (x, v, &ilist);
11433 nc = NULL_TREE;
11436 else
11438 if (DECL_SIZE (ovar)
11439 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11441 tree ovar2 = DECL_VALUE_EXPR (ovar);
11442 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11443 ovar2 = TREE_OPERAND (ovar2, 0);
11444 gcc_assert (DECL_P (ovar2));
11445 ovar = ovar2;
11447 if (!maybe_lookup_field (ovar, ctx))
11448 continue;
11451 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11452 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11453 talign = DECL_ALIGN_UNIT (ovar);
11454 if (nc)
11456 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11457 tree x = build_sender_ref (ovar, ctx);
11458 if (maybe_lookup_oacc_reduction (var, ctx))
11460 gcc_checking_assert (offloaded
11461 && is_gimple_omp_oacc (stmt));
11462 gimplify_assign (x, var, &ilist);
11464 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11465 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11466 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11467 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11469 gcc_assert (offloaded);
11470 tree avar
11471 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11472 mark_addressable (avar);
11473 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11474 talign = DECL_ALIGN_UNIT (avar);
11475 avar = build_fold_addr_expr (avar);
11476 gimplify_assign (x, avar, &ilist);
11478 else if (is_gimple_reg (var))
11480 gcc_assert (offloaded);
11481 tree avar = create_tmp_var (TREE_TYPE (var));
11482 mark_addressable (avar);
11483 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11484 if (GOMP_MAP_COPY_TO_P (map_kind)
11485 || map_kind == GOMP_MAP_POINTER
11486 || map_kind == GOMP_MAP_TO_PSET
11487 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11488 gimplify_assign (avar, var, &ilist);
11489 avar = build_fold_addr_expr (avar);
11490 gimplify_assign (x, avar, &ilist);
11491 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11492 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11493 && !TYPE_READONLY (TREE_TYPE (var)))
11495 x = build_sender_ref (ovar, ctx);
11496 x = build_simple_mem_ref (x);
11497 gimplify_assign (var, x, &olist);
11500 else
11502 var = build_fold_addr_expr (var);
11503 gimplify_assign (x, var, &ilist);
11506 tree s = OMP_CLAUSE_SIZE (c);
11507 if (s == NULL_TREE)
11508 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11509 s = fold_convert (size_type_node, s);
11510 tree purpose = size_int (map_idx++);
11511 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11512 if (TREE_CODE (s) != INTEGER_CST)
11513 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11515 unsigned HOST_WIDE_INT tkind;
11516 switch (OMP_CLAUSE_CODE (c))
11518 case OMP_CLAUSE_MAP:
11519 tkind = OMP_CLAUSE_MAP_KIND (c);
11520 break;
11521 case OMP_CLAUSE_TO:
11522 tkind = GOMP_MAP_TO;
11523 break;
11524 case OMP_CLAUSE_FROM:
11525 tkind = GOMP_MAP_FROM;
11526 break;
11527 default:
11528 gcc_unreachable ();
11530 gcc_checking_assert (tkind
11531 < (HOST_WIDE_INT_C (1U) << talign_shift));
11532 talign = ceil_log2 (talign);
11533 tkind |= talign << talign_shift;
11534 gcc_checking_assert (tkind
11535 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11536 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11537 build_int_cstu (tkind_type, tkind));
11538 if (nc && nc != c)
11539 c = nc;
11542 gcc_assert (map_idx == map_cnt);
11544 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11545 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11546 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11547 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11548 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11550 gimple_seq initlist = NULL;
11551 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11552 TREE_VEC_ELT (t, 1)),
11553 &initlist, true, NULL_TREE);
11554 gimple_seq_add_seq (&ilist, initlist);
11556 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11557 NULL);
11558 TREE_THIS_VOLATILE (clobber) = 1;
11559 gimple_seq_add_stmt (&olist,
11560 gimple_build_assign (TREE_VEC_ELT (t, 1),
11561 clobber));
11564 tree clobber = build_constructor (ctx->record_type, NULL);
11565 TREE_THIS_VOLATILE (clobber) = 1;
11566 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11567 clobber));
11570 /* Once all the expansions are done, sequence all the different
11571 fragments inside gimple_omp_body. */
11573 new_body = NULL;
11575 if (offloaded
11576 && ctx->record_type)
11578 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11579 /* fixup_child_record_type might have changed receiver_decl's type. */
11580 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11581 gimple_seq_add_stmt (&new_body,
11582 gimple_build_assign (ctx->receiver_decl, t));
11585 if (offloaded)
11587 gimple_seq_add_seq (&new_body, tgt_body);
11588 new_body = maybe_catch_exception (new_body);
11590 else if (data_region)
11591 new_body = tgt_body;
11592 if (offloaded || data_region)
11594 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11595 gimple_omp_set_body (stmt, new_body);
11598 bind = gimple_build_bind (NULL, NULL,
11599 tgt_bind ? gimple_bind_block (tgt_bind)
11600 : NULL_TREE);
11601 gsi_replace (gsi_p, bind, true);
11602 gimple_bind_add_seq (bind, irlist);
11603 gimple_bind_add_seq (bind, ilist);
11604 gimple_bind_add_stmt (bind, stmt);
11605 gimple_bind_add_seq (bind, olist);
11606 gimple_bind_add_seq (bind, orlist);
11608 pop_gimplify_context (NULL);
11611 /* Expand code for an OpenMP teams directive. */
11613 static void
11614 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11616 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11617 push_gimplify_context ();
11619 tree block = make_node (BLOCK);
11620 gbind *bind = gimple_build_bind (NULL, NULL, block);
11621 gsi_replace (gsi_p, bind, true);
11622 gimple_seq bind_body = NULL;
11623 gimple_seq dlist = NULL;
11624 gimple_seq olist = NULL;
11626 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11627 OMP_CLAUSE_NUM_TEAMS);
11628 if (num_teams == NULL_TREE)
11629 num_teams = build_int_cst (unsigned_type_node, 0);
11630 else
11632 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11633 num_teams = fold_convert (unsigned_type_node, num_teams);
11634 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11636 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11637 OMP_CLAUSE_THREAD_LIMIT);
11638 if (thread_limit == NULL_TREE)
11639 thread_limit = build_int_cst (unsigned_type_node, 0);
11640 else
11642 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11643 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11644 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11645 fb_rvalue);
11648 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11649 &bind_body, &dlist, ctx, NULL);
11650 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11651 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11652 gimple_seq_add_stmt (&bind_body, teams_stmt);
11654 location_t loc = gimple_location (teams_stmt);
11655 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11656 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11657 gimple_set_location (call, loc);
11658 gimple_seq_add_stmt (&bind_body, call);
11660 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11661 gimple_omp_set_body (teams_stmt, NULL);
11662 gimple_seq_add_seq (&bind_body, olist);
11663 gimple_seq_add_seq (&bind_body, dlist);
11664 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11665 gimple_bind_set_body (bind, bind_body);
11667 pop_gimplify_context (bind);
11669 gimple_bind_append_vars (bind, ctx->block_vars);
11670 BLOCK_VARS (block) = ctx->block_vars;
11671 if (BLOCK_VARS (block))
11672 TREE_USED (block) = 1;
11676 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11677 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11678 of OMP context, but with task_shared_vars set. */
11680 static tree
11681 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11682 void *data)
11684 tree t = *tp;
11686 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11687 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11688 return t;
11690 if (task_shared_vars
11691 && DECL_P (t)
11692 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11693 return t;
11695 /* If a global variable has been privatized, TREE_CONSTANT on
11696 ADDR_EXPR might be wrong. */
11697 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11698 recompute_tree_invariant_for_addr_expr (t);
11700 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11701 return NULL_TREE;
11704 static void
11705 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11707 gimple stmt = gsi_stmt (*gsi_p);
11708 struct walk_stmt_info wi;
11709 gcall *call_stmt;
11711 if (gimple_has_location (stmt))
11712 input_location = gimple_location (stmt);
11714 if (task_shared_vars)
11715 memset (&wi, '\0', sizeof (wi));
11717 /* If we have issued syntax errors, avoid doing any heavy lifting.
11718 Just replace the OMP directives with a NOP to avoid
11719 confusing RTL expansion. */
11720 if (seen_error () && is_gimple_omp (stmt))
11722 gsi_replace (gsi_p, gimple_build_nop (), true);
11723 return;
11726 switch (gimple_code (stmt))
11728 case GIMPLE_COND:
11730 gcond *cond_stmt = as_a <gcond *> (stmt);
11731 if ((ctx || task_shared_vars)
11732 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11733 lower_omp_regimplify_p,
11734 ctx ? NULL : &wi, NULL)
11735 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11736 lower_omp_regimplify_p,
11737 ctx ? NULL : &wi, NULL)))
11738 gimple_regimplify_operands (cond_stmt, gsi_p);
11740 break;
11741 case GIMPLE_CATCH:
11742 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
11743 break;
11744 case GIMPLE_EH_FILTER:
11745 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
11746 break;
11747 case GIMPLE_TRY:
11748 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11749 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
11750 break;
11751 case GIMPLE_TRANSACTION:
11752 lower_omp (gimple_transaction_body_ptr (
11753 as_a <gtransaction *> (stmt)),
11754 ctx);
11755 break;
11756 case GIMPLE_BIND:
11757 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
11758 break;
11759 case GIMPLE_OMP_PARALLEL:
11760 case GIMPLE_OMP_TASK:
11761 ctx = maybe_lookup_ctx (stmt);
11762 gcc_assert (ctx);
11763 if (ctx->cancellable)
11764 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11765 lower_omp_taskreg (gsi_p, ctx);
11766 break;
11767 case GIMPLE_OMP_FOR:
11768 ctx = maybe_lookup_ctx (stmt);
11769 gcc_assert (ctx);
11770 if (ctx->cancellable)
11771 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11772 lower_omp_for (gsi_p, ctx);
11773 break;
11774 case GIMPLE_OMP_SECTIONS:
11775 ctx = maybe_lookup_ctx (stmt);
11776 gcc_assert (ctx);
11777 if (ctx->cancellable)
11778 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11779 lower_omp_sections (gsi_p, ctx);
11780 break;
11781 case GIMPLE_OMP_SINGLE:
11782 ctx = maybe_lookup_ctx (stmt);
11783 gcc_assert (ctx);
11784 lower_omp_single (gsi_p, ctx);
11785 break;
11786 case GIMPLE_OMP_MASTER:
11787 ctx = maybe_lookup_ctx (stmt);
11788 gcc_assert (ctx);
11789 lower_omp_master (gsi_p, ctx);
11790 break;
11791 case GIMPLE_OMP_TASKGROUP:
11792 ctx = maybe_lookup_ctx (stmt);
11793 gcc_assert (ctx);
11794 lower_omp_taskgroup (gsi_p, ctx);
11795 break;
11796 case GIMPLE_OMP_ORDERED:
11797 ctx = maybe_lookup_ctx (stmt);
11798 gcc_assert (ctx);
11799 lower_omp_ordered (gsi_p, ctx);
11800 break;
11801 case GIMPLE_OMP_CRITICAL:
11802 ctx = maybe_lookup_ctx (stmt);
11803 gcc_assert (ctx);
11804 lower_omp_critical (gsi_p, ctx);
11805 break;
11806 case GIMPLE_OMP_ATOMIC_LOAD:
11807 if ((ctx || task_shared_vars)
11808 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11809 as_a <gomp_atomic_load *> (stmt)),
11810 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11811 gimple_regimplify_operands (stmt, gsi_p);
11812 break;
11813 case GIMPLE_OMP_TARGET:
11814 ctx = maybe_lookup_ctx (stmt);
11815 gcc_assert (ctx);
11816 lower_omp_target (gsi_p, ctx);
11817 break;
11818 case GIMPLE_OMP_TEAMS:
11819 ctx = maybe_lookup_ctx (stmt);
11820 gcc_assert (ctx);
11821 lower_omp_teams (gsi_p, ctx);
11822 break;
11823 case GIMPLE_CALL:
11824 tree fndecl;
11825 call_stmt = as_a <gcall *> (stmt);
11826 fndecl = gimple_call_fndecl (call_stmt);
11827 if (fndecl
11828 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11829 switch (DECL_FUNCTION_CODE (fndecl))
11831 case BUILT_IN_GOMP_BARRIER:
11832 if (ctx == NULL)
11833 break;
11834 /* FALLTHRU */
11835 case BUILT_IN_GOMP_CANCEL:
11836 case BUILT_IN_GOMP_CANCELLATION_POINT:
11837 omp_context *cctx;
11838 cctx = ctx;
11839 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11840 cctx = cctx->outer;
11841 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
11842 if (!cctx->cancellable)
11844 if (DECL_FUNCTION_CODE (fndecl)
11845 == BUILT_IN_GOMP_CANCELLATION_POINT)
11847 stmt = gimple_build_nop ();
11848 gsi_replace (gsi_p, stmt, false);
11850 break;
11852 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11854 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
11855 gimple_call_set_fndecl (call_stmt, fndecl);
11856 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
11858 tree lhs;
11859 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
11860 gimple_call_set_lhs (call_stmt, lhs);
11861 tree fallthru_label;
11862 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11863 gimple g;
11864 g = gimple_build_label (fallthru_label);
11865 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11866 g = gimple_build_cond (NE_EXPR, lhs,
11867 fold_convert (TREE_TYPE (lhs),
11868 boolean_false_node),
11869 cctx->cancel_label, fallthru_label);
11870 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11871 break;
11872 default:
11873 break;
11875 /* FALLTHRU */
11876 default:
11877 if ((ctx || task_shared_vars)
11878 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11879 ctx ? NULL : &wi))
11881 /* Just remove clobbers, this should happen only if we have
11882 "privatized" local addressable variables in SIMD regions,
11883 the clobber isn't needed in that case and gimplifying address
11884 of the ARRAY_REF into a pointer and creating MEM_REF based
11885 clobber would create worse code than we get with the clobber
11886 dropped. */
11887 if (gimple_clobber_p (stmt))
11889 gsi_replace (gsi_p, gimple_build_nop (), true);
11890 break;
11892 gimple_regimplify_operands (stmt, gsi_p);
11894 break;
11898 static void
11899 lower_omp (gimple_seq *body, omp_context *ctx)
11901 location_t saved_location = input_location;
11902 gimple_stmt_iterator gsi;
11903 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11904 lower_omp_1 (&gsi, ctx);
11905 /* During gimplification, we haven't folded statments inside offloading
11906 regions (gimplify.c:maybe_fold_stmt); do that now. */
11907 if (target_nesting_level)
11908 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11909 fold_stmt (&gsi);
11910 input_location = saved_location;
11913 /* Main entry point. */
11915 static unsigned int
11916 execute_lower_omp (void)
11918 gimple_seq body;
11919 int i;
11920 omp_context *ctx;
11922 /* This pass always runs, to provide PROP_gimple_lomp.
11923 But often, there is nothing to do. */
11924 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11925 && flag_openmp_simd == 0)
11926 return 0;
11928 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11929 delete_omp_context);
11931 body = gimple_body (current_function_decl);
11932 scan_omp (&body, NULL);
11933 gcc_assert (taskreg_nesting_level == 0);
11934 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11935 finish_taskreg_scan (ctx);
11936 taskreg_contexts.release ();
11938 if (all_contexts->root)
11940 if (task_shared_vars)
11941 push_gimplify_context ();
11942 lower_omp (&body, NULL);
11943 if (task_shared_vars)
11944 pop_gimplify_context (NULL);
11947 if (all_contexts)
11949 splay_tree_delete (all_contexts);
11950 all_contexts = NULL;
11952 BITMAP_FREE (task_shared_vars);
11953 return 0;
11956 namespace {
11958 const pass_data pass_data_lower_omp =
11960 GIMPLE_PASS, /* type */
11961 "omplower", /* name */
11962 OPTGROUP_NONE, /* optinfo_flags */
11963 TV_NONE, /* tv_id */
11964 PROP_gimple_any, /* properties_required */
11965 PROP_gimple_lomp, /* properties_provided */
11966 0, /* properties_destroyed */
11967 0, /* todo_flags_start */
11968 0, /* todo_flags_finish */
11971 class pass_lower_omp : public gimple_opt_pass
11973 public:
11974 pass_lower_omp (gcc::context *ctxt)
11975 : gimple_opt_pass (pass_data_lower_omp, ctxt)
11978 /* opt_pass methods: */
11979 virtual unsigned int execute (function *) { return execute_lower_omp (); }
11981 }; // class pass_lower_omp
11983 } // anon namespace
11985 gimple_opt_pass *
11986 make_pass_lower_omp (gcc::context *ctxt)
11988 return new pass_lower_omp (ctxt);
11991 /* The following is a utility to diagnose structured block violations.
11992 It is not part of the "omplower" pass, as that's invoked too late. It
11993 should be invoked by the respective front ends after gimplification. */
11995 static splay_tree all_labels;
11997 /* Check for mismatched contexts and generate an error if needed. Return
11998 true if an error is detected. */
12000 static bool
12001 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
12002 gimple branch_ctx, gimple label_ctx)
12004 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
12005 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
12007 if (label_ctx == branch_ctx)
12008 return false;
12010 const char* kind = NULL;
12012 if (flag_cilkplus)
12014 if ((branch_ctx
12015 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12016 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12017 || (label_ctx
12018 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12019 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12020 kind = "Cilk Plus";
12022 if (flag_openacc)
12024 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
12025 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
12027 gcc_checking_assert (kind == NULL);
12028 kind = "OpenACC";
12031 if (kind == NULL)
12033 gcc_checking_assert (flag_openmp);
12034 kind = "OpenMP";
12038 Previously we kept track of the label's entire context in diagnose_sb_[12]
12039 so we could traverse it and issue a correct "exit" or "enter" error
12040 message upon a structured block violation.
12042 We built the context by building a list with tree_cons'ing, but there is
12043 no easy counterpart in gimple tuples. It seems like far too much work
12044 for issuing exit/enter error messages. If someone really misses the
12045 distinct error message... patches welcome.
12048 #if 0
12049 /* Try to avoid confusing the user by producing and error message
12050 with correct "exit" or "enter" verbiage. We prefer "exit"
12051 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12052 if (branch_ctx == NULL)
12053 exit_p = false;
12054 else
12056 while (label_ctx)
12058 if (TREE_VALUE (label_ctx) == branch_ctx)
12060 exit_p = false;
12061 break;
12063 label_ctx = TREE_CHAIN (label_ctx);
12067 if (exit_p)
12068 error ("invalid exit from %s structured block", kind);
12069 else
12070 error ("invalid entry to %s structured block", kind);
12071 #endif
12073 /* If it's obvious we have an invalid entry, be specific about the error. */
12074 if (branch_ctx == NULL)
12075 error ("invalid entry to %s structured block", kind);
12076 else
12078 /* Otherwise, be vague and lazy, but efficient. */
12079 error ("invalid branch to/from %s structured block", kind);
12082 gsi_replace (gsi_p, gimple_build_nop (), false);
12083 return true;
12086 /* Pass 1: Create a minimal tree of structured blocks, and record
12087 where each label is found. */
12089 static tree
12090 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12091 struct walk_stmt_info *wi)
12093 gimple context = (gimple) wi->info;
12094 gimple inner_context;
12095 gimple stmt = gsi_stmt (*gsi_p);
12097 *handled_ops_p = true;
12099 switch (gimple_code (stmt))
12101 WALK_SUBSTMTS;
12103 case GIMPLE_OMP_PARALLEL:
12104 case GIMPLE_OMP_TASK:
12105 case GIMPLE_OMP_SECTIONS:
12106 case GIMPLE_OMP_SINGLE:
12107 case GIMPLE_OMP_SECTION:
12108 case GIMPLE_OMP_MASTER:
12109 case GIMPLE_OMP_ORDERED:
12110 case GIMPLE_OMP_CRITICAL:
12111 case GIMPLE_OMP_TARGET:
12112 case GIMPLE_OMP_TEAMS:
12113 case GIMPLE_OMP_TASKGROUP:
12114 /* The minimal context here is just the current OMP construct. */
12115 inner_context = stmt;
12116 wi->info = inner_context;
12117 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12118 wi->info = context;
12119 break;
12121 case GIMPLE_OMP_FOR:
12122 inner_context = stmt;
12123 wi->info = inner_context;
12124 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12125 walk them. */
12126 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12127 diagnose_sb_1, NULL, wi);
12128 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12129 wi->info = context;
12130 break;
12132 case GIMPLE_LABEL:
12133 splay_tree_insert (all_labels,
12134 (splay_tree_key) gimple_label_label (
12135 as_a <glabel *> (stmt)),
12136 (splay_tree_value) context);
12137 break;
12139 default:
12140 break;
12143 return NULL_TREE;
12146 /* Pass 2: Check each branch and see if its context differs from that of
12147 the destination label's context. */
12149 static tree
12150 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12151 struct walk_stmt_info *wi)
12153 gimple context = (gimple) wi->info;
12154 splay_tree_node n;
12155 gimple stmt = gsi_stmt (*gsi_p);
12157 *handled_ops_p = true;
12159 switch (gimple_code (stmt))
12161 WALK_SUBSTMTS;
12163 case GIMPLE_OMP_PARALLEL:
12164 case GIMPLE_OMP_TASK:
12165 case GIMPLE_OMP_SECTIONS:
12166 case GIMPLE_OMP_SINGLE:
12167 case GIMPLE_OMP_SECTION:
12168 case GIMPLE_OMP_MASTER:
12169 case GIMPLE_OMP_ORDERED:
12170 case GIMPLE_OMP_CRITICAL:
12171 case GIMPLE_OMP_TARGET:
12172 case GIMPLE_OMP_TEAMS:
12173 case GIMPLE_OMP_TASKGROUP:
12174 wi->info = stmt;
12175 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12176 wi->info = context;
12177 break;
12179 case GIMPLE_OMP_FOR:
12180 wi->info = stmt;
12181 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12182 walk them. */
12183 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12184 diagnose_sb_2, NULL, wi);
12185 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12186 wi->info = context;
12187 break;
12189 case GIMPLE_COND:
12191 gcond *cond_stmt = as_a <gcond *> (stmt);
12192 tree lab = gimple_cond_true_label (cond_stmt);
12193 if (lab)
12195 n = splay_tree_lookup (all_labels,
12196 (splay_tree_key) lab);
12197 diagnose_sb_0 (gsi_p, context,
12198 n ? (gimple) n->value : NULL);
12200 lab = gimple_cond_false_label (cond_stmt);
12201 if (lab)
12203 n = splay_tree_lookup (all_labels,
12204 (splay_tree_key) lab);
12205 diagnose_sb_0 (gsi_p, context,
12206 n ? (gimple) n->value : NULL);
12209 break;
12211 case GIMPLE_GOTO:
12213 tree lab = gimple_goto_dest (stmt);
12214 if (TREE_CODE (lab) != LABEL_DECL)
12215 break;
12217 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12218 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
12220 break;
12222 case GIMPLE_SWITCH:
12224 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12225 unsigned int i;
12226 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12228 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12229 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12230 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
12231 break;
12234 break;
12236 case GIMPLE_RETURN:
12237 diagnose_sb_0 (gsi_p, context, NULL);
12238 break;
12240 default:
12241 break;
12244 return NULL_TREE;
12247 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12248 GIMPLE_* codes. */
12249 bool
12250 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12251 int *region_idx)
12253 gimple last = last_stmt (bb);
12254 enum gimple_code code = gimple_code (last);
12255 struct omp_region *cur_region = *region;
12256 bool fallthru = false;
12258 switch (code)
12260 case GIMPLE_OMP_PARALLEL:
12261 case GIMPLE_OMP_TASK:
12262 case GIMPLE_OMP_FOR:
12263 case GIMPLE_OMP_SINGLE:
12264 case GIMPLE_OMP_TEAMS:
12265 case GIMPLE_OMP_MASTER:
12266 case GIMPLE_OMP_TASKGROUP:
12267 case GIMPLE_OMP_ORDERED:
12268 case GIMPLE_OMP_CRITICAL:
12269 case GIMPLE_OMP_SECTION:
12270 cur_region = new_omp_region (bb, code, cur_region);
12271 fallthru = true;
12272 break;
12274 case GIMPLE_OMP_TARGET:
12275 cur_region = new_omp_region (bb, code, cur_region);
12276 fallthru = true;
12277 switch (gimple_omp_target_kind (last))
12279 case GF_OMP_TARGET_KIND_REGION:
12280 case GF_OMP_TARGET_KIND_DATA:
12281 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12282 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12283 case GF_OMP_TARGET_KIND_OACC_DATA:
12284 break;
12285 case GF_OMP_TARGET_KIND_UPDATE:
12286 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12287 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12288 cur_region = cur_region->outer;
12289 break;
12290 default:
12291 gcc_unreachable ();
12293 break;
12295 case GIMPLE_OMP_SECTIONS:
12296 cur_region = new_omp_region (bb, code, cur_region);
12297 fallthru = true;
12298 break;
12300 case GIMPLE_OMP_SECTIONS_SWITCH:
12301 fallthru = false;
12302 break;
12304 case GIMPLE_OMP_ATOMIC_LOAD:
12305 case GIMPLE_OMP_ATOMIC_STORE:
12306 fallthru = true;
12307 break;
12309 case GIMPLE_OMP_RETURN:
12310 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12311 somewhere other than the next block. This will be
12312 created later. */
12313 cur_region->exit = bb;
12314 if (cur_region->type == GIMPLE_OMP_TASK)
12315 /* Add an edge corresponding to not scheduling the task
12316 immediately. */
12317 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
12318 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12319 cur_region = cur_region->outer;
12320 break;
12322 case GIMPLE_OMP_CONTINUE:
12323 cur_region->cont = bb;
12324 switch (cur_region->type)
12326 case GIMPLE_OMP_FOR:
12327 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12328 succs edges as abnormal to prevent splitting
12329 them. */
12330 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12331 /* Make the loopback edge. */
12332 make_edge (bb, single_succ (cur_region->entry),
12333 EDGE_ABNORMAL);
12335 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12336 corresponds to the case that the body of the loop
12337 is not executed at all. */
12338 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12339 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12340 fallthru = false;
12341 break;
12343 case GIMPLE_OMP_SECTIONS:
12344 /* Wire up the edges into and out of the nested sections. */
12346 basic_block switch_bb = single_succ (cur_region->entry);
12348 struct omp_region *i;
12349 for (i = cur_region->inner; i ; i = i->next)
12351 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12352 make_edge (switch_bb, i->entry, 0);
12353 make_edge (i->exit, bb, EDGE_FALLTHRU);
12356 /* Make the loopback edge to the block with
12357 GIMPLE_OMP_SECTIONS_SWITCH. */
12358 make_edge (bb, switch_bb, 0);
12360 /* Make the edge from the switch to exit. */
12361 make_edge (switch_bb, bb->next_bb, 0);
12362 fallthru = false;
12364 break;
12366 case GIMPLE_OMP_TASK:
12367 fallthru = true;
12368 break;
12370 default:
12371 gcc_unreachable ();
12373 break;
12375 default:
12376 gcc_unreachable ();
12379 if (*region != cur_region)
12381 *region = cur_region;
12382 if (cur_region)
12383 *region_idx = cur_region->entry->index;
12384 else
12385 *region_idx = 0;
12388 return fallthru;
12391 static unsigned int
12392 diagnose_omp_structured_block_errors (void)
12394 struct walk_stmt_info wi;
12395 gimple_seq body = gimple_body (current_function_decl);
12397 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12399 memset (&wi, 0, sizeof (wi));
12400 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12402 memset (&wi, 0, sizeof (wi));
12403 wi.want_locations = true;
12404 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12406 gimple_set_body (current_function_decl, body);
12408 splay_tree_delete (all_labels);
12409 all_labels = NULL;
12411 return 0;
12414 namespace {
12416 const pass_data pass_data_diagnose_omp_blocks =
12418 GIMPLE_PASS, /* type */
12419 "*diagnose_omp_blocks", /* name */
12420 OPTGROUP_NONE, /* optinfo_flags */
12421 TV_NONE, /* tv_id */
12422 PROP_gimple_any, /* properties_required */
12423 0, /* properties_provided */
12424 0, /* properties_destroyed */
12425 0, /* todo_flags_start */
12426 0, /* todo_flags_finish */
12429 class pass_diagnose_omp_blocks : public gimple_opt_pass
12431 public:
12432 pass_diagnose_omp_blocks (gcc::context *ctxt)
12433 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12436 /* opt_pass methods: */
12437 virtual bool gate (function *)
12439 return flag_cilkplus || flag_openacc || flag_openmp;
12441 virtual unsigned int execute (function *)
12443 return diagnose_omp_structured_block_errors ();
12446 }; // class pass_diagnose_omp_blocks
12448 } // anon namespace
12450 gimple_opt_pass *
12451 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12453 return new pass_diagnose_omp_blocks (ctxt);
12456 /* SIMD clone supporting code. */
12458 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12459 of arguments to reserve space for. */
12461 static struct cgraph_simd_clone *
12462 simd_clone_struct_alloc (int nargs)
12464 struct cgraph_simd_clone *clone_info;
12465 size_t len = (sizeof (struct cgraph_simd_clone)
12466 + nargs * sizeof (struct cgraph_simd_clone_arg));
12467 clone_info = (struct cgraph_simd_clone *)
12468 ggc_internal_cleared_alloc (len);
12469 return clone_info;
12472 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12474 static inline void
12475 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12476 struct cgraph_simd_clone *from)
12478 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12479 + ((from->nargs - from->inbranch)
12480 * sizeof (struct cgraph_simd_clone_arg))));
12483 /* Return vector of parameter types of function FNDECL. This uses
12484 TYPE_ARG_TYPES if available, otherwise falls back to types of
12485 DECL_ARGUMENTS types. */
12487 vec<tree>
12488 simd_clone_vector_of_formal_parm_types (tree fndecl)
12490 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12491 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12492 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12493 unsigned int i;
12494 tree arg;
12495 FOR_EACH_VEC_ELT (args, i, arg)
12496 args[i] = TREE_TYPE (args[i]);
12497 return args;
12500 /* Given a simd function in NODE, extract the simd specific
12501 information from the OMP clauses passed in CLAUSES, and return
12502 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12503 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12504 otherwise set to FALSE. */
12506 static struct cgraph_simd_clone *
12507 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12508 bool *inbranch_specified)
12510 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12511 tree t;
12512 int n;
12513 *inbranch_specified = false;
12515 n = args.length ();
12516 if (n > 0 && args.last () == void_type_node)
12517 n--;
12519 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12520 be cloned have a distinctive artificial label in addition to "omp
12521 declare simd". */
12522 bool cilk_clone
12523 = (flag_cilkplus
12524 && lookup_attribute ("cilk simd function",
12525 DECL_ATTRIBUTES (node->decl)));
12527 /* Allocate one more than needed just in case this is an in-branch
12528 clone which will require a mask argument. */
12529 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12530 clone_info->nargs = n;
12531 clone_info->cilk_elemental = cilk_clone;
12533 if (!clauses)
12535 args.release ();
12536 return clone_info;
12538 clauses = TREE_VALUE (clauses);
12539 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12540 return clone_info;
12542 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12544 switch (OMP_CLAUSE_CODE (t))
12546 case OMP_CLAUSE_INBRANCH:
12547 clone_info->inbranch = 1;
12548 *inbranch_specified = true;
12549 break;
12550 case OMP_CLAUSE_NOTINBRANCH:
12551 clone_info->inbranch = 0;
12552 *inbranch_specified = true;
12553 break;
12554 case OMP_CLAUSE_SIMDLEN:
12555 clone_info->simdlen
12556 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12557 break;
12558 case OMP_CLAUSE_LINEAR:
12560 tree decl = OMP_CLAUSE_DECL (t);
12561 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12562 int argno = TREE_INT_CST_LOW (decl);
12563 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12565 clone_info->args[argno].arg_type
12566 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12567 clone_info->args[argno].linear_step = tree_to_shwi (step);
12568 gcc_assert (clone_info->args[argno].linear_step >= 0
12569 && clone_info->args[argno].linear_step < n);
12571 else
12573 if (POINTER_TYPE_P (args[argno]))
12574 step = fold_convert (ssizetype, step);
12575 if (!tree_fits_shwi_p (step))
12577 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12578 "ignoring large linear step");
12579 args.release ();
12580 return NULL;
12582 else if (integer_zerop (step))
12584 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12585 "ignoring zero linear step");
12586 args.release ();
12587 return NULL;
12589 else
12591 clone_info->args[argno].arg_type
12592 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12593 clone_info->args[argno].linear_step = tree_to_shwi (step);
12596 break;
12598 case OMP_CLAUSE_UNIFORM:
12600 tree decl = OMP_CLAUSE_DECL (t);
12601 int argno = tree_to_uhwi (decl);
12602 clone_info->args[argno].arg_type
12603 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12604 break;
12606 case OMP_CLAUSE_ALIGNED:
12608 tree decl = OMP_CLAUSE_DECL (t);
12609 int argno = tree_to_uhwi (decl);
12610 clone_info->args[argno].alignment
12611 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12612 break;
12614 default:
12615 break;
12618 args.release ();
12619 return clone_info;
12622 /* Given a SIMD clone in NODE, calculate the characteristic data
12623 type and return the coresponding type. The characteristic data
12624 type is computed as described in the Intel Vector ABI. */
12626 static tree
12627 simd_clone_compute_base_data_type (struct cgraph_node *node,
12628 struct cgraph_simd_clone *clone_info)
12630 tree type = integer_type_node;
12631 tree fndecl = node->decl;
12633 /* a) For non-void function, the characteristic data type is the
12634 return type. */
12635 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12636 type = TREE_TYPE (TREE_TYPE (fndecl));
12638 /* b) If the function has any non-uniform, non-linear parameters,
12639 then the characteristic data type is the type of the first
12640 such parameter. */
12641 else
12643 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12644 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12645 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12647 type = map[i];
12648 break;
12650 map.release ();
12653 /* c) If the characteristic data type determined by a) or b) above
12654 is struct, union, or class type which is pass-by-value (except
12655 for the type that maps to the built-in complex data type), the
12656 characteristic data type is int. */
12657 if (RECORD_OR_UNION_TYPE_P (type)
12658 && !aggregate_value_p (type, NULL)
12659 && TREE_CODE (type) != COMPLEX_TYPE)
12660 return integer_type_node;
12662 /* d) If none of the above three classes is applicable, the
12663 characteristic data type is int. */
12665 return type;
12667 /* e) For Intel Xeon Phi native and offload compilation, if the
12668 resulting characteristic data type is 8-bit or 16-bit integer
12669 data type, the characteristic data type is int. */
12670 /* Well, we don't handle Xeon Phi yet. */
12673 static tree
12674 simd_clone_mangle (struct cgraph_node *node,
12675 struct cgraph_simd_clone *clone_info)
12677 char vecsize_mangle = clone_info->vecsize_mangle;
12678 char mask = clone_info->inbranch ? 'M' : 'N';
12679 unsigned int simdlen = clone_info->simdlen;
12680 unsigned int n;
12681 pretty_printer pp;
12683 gcc_assert (vecsize_mangle && simdlen);
12685 pp_string (&pp, "_ZGV");
12686 pp_character (&pp, vecsize_mangle);
12687 pp_character (&pp, mask);
12688 pp_decimal_int (&pp, simdlen);
12690 for (n = 0; n < clone_info->nargs; ++n)
12692 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12694 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12695 pp_character (&pp, 'u');
12696 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12698 gcc_assert (arg.linear_step != 0);
12699 pp_character (&pp, 'l');
12700 if (arg.linear_step > 1)
12701 pp_unsigned_wide_integer (&pp, arg.linear_step);
12702 else if (arg.linear_step < 0)
12704 pp_character (&pp, 'n');
12705 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12706 arg.linear_step));
12709 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12711 pp_character (&pp, 's');
12712 pp_unsigned_wide_integer (&pp, arg.linear_step);
12714 else
12715 pp_character (&pp, 'v');
12716 if (arg.alignment)
12718 pp_character (&pp, 'a');
12719 pp_decimal_int (&pp, arg.alignment);
12723 pp_underscore (&pp);
12724 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12725 if (*str == '*')
12726 ++str;
12727 pp_string (&pp, str);
12728 str = pp_formatted_text (&pp);
12730 /* If there already is a SIMD clone with the same mangled name, don't
12731 add another one. This can happen e.g. for
12732 #pragma omp declare simd
12733 #pragma omp declare simd simdlen(8)
12734 int foo (int, int);
12735 if the simdlen is assumed to be 8 for the first one, etc. */
12736 for (struct cgraph_node *clone = node->simd_clones; clone;
12737 clone = clone->simdclone->next_clone)
12738 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12739 str) == 0)
12740 return NULL_TREE;
12742 return get_identifier (str);
12745 /* Create a simd clone of OLD_NODE and return it. */
12747 static struct cgraph_node *
12748 simd_clone_create (struct cgraph_node *old_node)
12750 struct cgraph_node *new_node;
12751 if (old_node->definition)
12753 if (!old_node->has_gimple_body_p ())
12754 return NULL;
12755 old_node->get_body ();
12756 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12757 false, NULL, NULL,
12758 "simdclone");
12760 else
12762 tree old_decl = old_node->decl;
12763 tree new_decl = copy_node (old_node->decl);
12764 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12765 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12766 SET_DECL_RTL (new_decl, NULL);
12767 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12768 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
12769 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
12770 symtab->call_cgraph_insertion_hooks (new_node);
12772 if (new_node == NULL)
12773 return new_node;
12775 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12777 /* The function cgraph_function_versioning () will force the new
12778 symbol local. Undo this, and inherit external visability from
12779 the old node. */
12780 new_node->local.local = old_node->local.local;
12781 new_node->externally_visible = old_node->externally_visible;
12783 return new_node;
12786 /* Adjust the return type of the given function to its appropriate
12787 vector counterpart. Returns a simd array to be used throughout the
12788 function as a return value. */
12790 static tree
12791 simd_clone_adjust_return_type (struct cgraph_node *node)
12793 tree fndecl = node->decl;
12794 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12795 unsigned int veclen;
12796 tree t;
12798 /* Adjust the function return type. */
12799 if (orig_rettype == void_type_node)
12800 return NULL_TREE;
12801 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
12802 t = TREE_TYPE (TREE_TYPE (fndecl));
12803 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
12804 veclen = node->simdclone->vecsize_int;
12805 else
12806 veclen = node->simdclone->vecsize_float;
12807 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
12808 if (veclen > node->simdclone->simdlen)
12809 veclen = node->simdclone->simdlen;
12810 if (POINTER_TYPE_P (t))
12811 t = pointer_sized_int_node;
12812 if (veclen == node->simdclone->simdlen)
12813 t = build_vector_type (t, node->simdclone->simdlen);
12814 else
12816 t = build_vector_type (t, veclen);
12817 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
12819 TREE_TYPE (TREE_TYPE (fndecl)) = t;
12820 if (!node->definition)
12821 return NULL_TREE;
12823 t = DECL_RESULT (fndecl);
12824 /* Adjust the DECL_RESULT. */
12825 gcc_assert (TREE_TYPE (t) != void_type_node);
12826 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12827 relayout_decl (t);
12829 tree atype = build_array_type_nelts (orig_rettype,
12830 node->simdclone->simdlen);
12831 if (veclen != node->simdclone->simdlen)
12832 return build1 (VIEW_CONVERT_EXPR, atype, t);
12834 /* Set up a SIMD array to use as the return value. */
12835 tree retval = create_tmp_var_raw (atype, "retval");
12836 gimple_add_tmp_var (retval);
12837 return retval;
12840 /* Each vector argument has a corresponding array to be used locally
12841 as part of the eventual loop. Create such temporary array and
12842 return it.
12844 PREFIX is the prefix to be used for the temporary.
12846 TYPE is the inner element type.
12848 SIMDLEN is the number of elements. */
12850 static tree
12851 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12853 tree atype = build_array_type_nelts (type, simdlen);
12854 tree avar = create_tmp_var_raw (atype, prefix);
12855 gimple_add_tmp_var (avar);
12856 return avar;
12859 /* Modify the function argument types to their corresponding vector
12860 counterparts if appropriate. Also, create one array for each simd
12861 argument to be used locally when using the function arguments as
12862 part of the loop.
12864 NODE is the function whose arguments are to be adjusted.
12866 Returns an adjustment vector that will be filled describing how the
12867 argument types will be adjusted. */
12869 static ipa_parm_adjustment_vec
12870 simd_clone_adjust_argument_types (struct cgraph_node *node)
12872 vec<tree> args;
12873 ipa_parm_adjustment_vec adjustments;
12875 if (node->definition)
12876 args = ipa_get_vector_of_formal_parms (node->decl);
12877 else
12878 args = simd_clone_vector_of_formal_parm_types (node->decl);
12879 adjustments.create (args.length ());
12880 unsigned i, j, veclen;
12881 struct ipa_parm_adjustment adj;
12882 for (i = 0; i < node->simdclone->nargs; ++i)
12884 memset (&adj, 0, sizeof (adj));
12885 tree parm = args[i];
12886 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12887 adj.base_index = i;
12888 adj.base = parm;
12890 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12891 node->simdclone->args[i].orig_type = parm_type;
12893 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12895 /* No adjustment necessary for scalar arguments. */
12896 adj.op = IPA_PARM_OP_COPY;
12898 else
12900 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12901 veclen = node->simdclone->vecsize_int;
12902 else
12903 veclen = node->simdclone->vecsize_float;
12904 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12905 if (veclen > node->simdclone->simdlen)
12906 veclen = node->simdclone->simdlen;
12907 adj.arg_prefix = "simd";
12908 if (POINTER_TYPE_P (parm_type))
12909 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12910 else
12911 adj.type = build_vector_type (parm_type, veclen);
12912 node->simdclone->args[i].vector_type = adj.type;
12913 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12915 adjustments.safe_push (adj);
12916 if (j == veclen)
12918 memset (&adj, 0, sizeof (adj));
12919 adj.op = IPA_PARM_OP_NEW;
12920 adj.arg_prefix = "simd";
12921 adj.base_index = i;
12922 adj.type = node->simdclone->args[i].vector_type;
12926 if (node->definition)
12927 node->simdclone->args[i].simd_array
12928 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12929 parm_type, node->simdclone->simdlen);
12931 adjustments.safe_push (adj);
12934 if (node->simdclone->inbranch)
12936 tree base_type
12937 = simd_clone_compute_base_data_type (node->simdclone->origin,
12938 node->simdclone);
12940 memset (&adj, 0, sizeof (adj));
12941 adj.op = IPA_PARM_OP_NEW;
12942 adj.arg_prefix = "mask";
12944 adj.base_index = i;
12945 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12946 veclen = node->simdclone->vecsize_int;
12947 else
12948 veclen = node->simdclone->vecsize_float;
12949 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12950 if (veclen > node->simdclone->simdlen)
12951 veclen = node->simdclone->simdlen;
12952 if (POINTER_TYPE_P (base_type))
12953 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12954 else
12955 adj.type = build_vector_type (base_type, veclen);
12956 adjustments.safe_push (adj);
12958 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12959 adjustments.safe_push (adj);
12961 /* We have previously allocated one extra entry for the mask. Use
12962 it and fill it. */
12963 struct cgraph_simd_clone *sc = node->simdclone;
12964 sc->nargs++;
12965 if (node->definition)
12967 sc->args[i].orig_arg
12968 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12969 sc->args[i].simd_array
12970 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12972 sc->args[i].orig_type = base_type;
12973 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12976 if (node->definition)
12977 ipa_modify_formal_parameters (node->decl, adjustments);
12978 else
12980 tree new_arg_types = NULL_TREE, new_reversed;
12981 bool last_parm_void = false;
12982 if (args.length () > 0 && args.last () == void_type_node)
12983 last_parm_void = true;
12985 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12986 j = adjustments.length ();
12987 for (i = 0; i < j; i++)
12989 struct ipa_parm_adjustment *adj = &adjustments[i];
12990 tree ptype;
12991 if (adj->op == IPA_PARM_OP_COPY)
12992 ptype = args[adj->base_index];
12993 else
12994 ptype = adj->type;
12995 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12997 new_reversed = nreverse (new_arg_types);
12998 if (last_parm_void)
13000 if (new_reversed)
13001 TREE_CHAIN (new_arg_types) = void_list_node;
13002 else
13003 new_reversed = void_list_node;
13006 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
13007 TYPE_ARG_TYPES (new_type) = new_reversed;
13008 TREE_TYPE (node->decl) = new_type;
13010 adjustments.release ();
13012 args.release ();
13013 return adjustments;
13016 /* Initialize and copy the function arguments in NODE to their
13017 corresponding local simd arrays. Returns a fresh gimple_seq with
13018 the instruction sequence generated. */
13020 static gimple_seq
13021 simd_clone_init_simd_arrays (struct cgraph_node *node,
13022 ipa_parm_adjustment_vec adjustments)
13024 gimple_seq seq = NULL;
13025 unsigned i = 0, j = 0, k;
13027 for (tree arg = DECL_ARGUMENTS (node->decl);
13028 arg;
13029 arg = DECL_CHAIN (arg), i++, j++)
13031 if (adjustments[j].op == IPA_PARM_OP_COPY)
13032 continue;
13034 node->simdclone->args[i].vector_arg = arg;
13036 tree array = node->simdclone->args[i].simd_array;
13037 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13039 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13040 tree ptr = build_fold_addr_expr (array);
13041 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13042 build_int_cst (ptype, 0));
13043 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13044 gimplify_and_add (t, &seq);
13046 else
13048 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13049 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13050 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13052 tree ptr = build_fold_addr_expr (array);
13053 int elemsize;
13054 if (k)
13056 arg = DECL_CHAIN (arg);
13057 j++;
13059 elemsize
13060 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13061 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13062 build_int_cst (ptype, k * elemsize));
13063 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13064 gimplify_and_add (t, &seq);
13068 return seq;
13071 /* Callback info for ipa_simd_modify_stmt_ops below. */
13073 struct modify_stmt_info {
13074 ipa_parm_adjustment_vec adjustments;
13075 gimple stmt;
13076 /* True if the parent statement was modified by
13077 ipa_simd_modify_stmt_ops. */
13078 bool modified;
13081 /* Callback for walk_gimple_op.
13083 Adjust operands from a given statement as specified in the
13084 adjustments vector in the callback data. */
13086 static tree
13087 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13089 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13090 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13091 tree *orig_tp = tp;
13092 if (TREE_CODE (*tp) == ADDR_EXPR)
13093 tp = &TREE_OPERAND (*tp, 0);
13094 struct ipa_parm_adjustment *cand = NULL;
13095 if (TREE_CODE (*tp) == PARM_DECL)
13096 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13097 else
13099 if (TYPE_P (*tp))
13100 *walk_subtrees = 0;
13103 tree repl = NULL_TREE;
13104 if (cand)
13105 repl = unshare_expr (cand->new_decl);
13106 else
13108 if (tp != orig_tp)
13110 *walk_subtrees = 0;
13111 bool modified = info->modified;
13112 info->modified = false;
13113 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13114 if (!info->modified)
13116 info->modified = modified;
13117 return NULL_TREE;
13119 info->modified = modified;
13120 repl = *tp;
13122 else
13123 return NULL_TREE;
13126 if (tp != orig_tp)
13128 repl = build_fold_addr_expr (repl);
13129 gimple stmt;
13130 if (is_gimple_debug (info->stmt))
13132 tree vexpr = make_node (DEBUG_EXPR_DECL);
13133 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13134 DECL_ARTIFICIAL (vexpr) = 1;
13135 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13136 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13137 repl = vexpr;
13139 else
13141 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13142 repl = gimple_assign_lhs (stmt);
13144 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13145 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13146 *orig_tp = repl;
13148 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13150 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13151 *tp = vce;
13153 else
13154 *tp = repl;
13156 info->modified = true;
13157 return NULL_TREE;
13160 /* Traverse the function body and perform all modifications as
13161 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13162 modified such that the replacement/reduction value will now be an
13163 offset into the corresponding simd_array.
13165 This function will replace all function argument uses with their
13166 corresponding simd array elements, and ajust the return values
13167 accordingly. */
13169 static void
13170 ipa_simd_modify_function_body (struct cgraph_node *node,
13171 ipa_parm_adjustment_vec adjustments,
13172 tree retval_array, tree iter)
13174 basic_block bb;
13175 unsigned int i, j, l;
13177 /* Re-use the adjustments array, but this time use it to replace
13178 every function argument use to an offset into the corresponding
13179 simd_array. */
13180 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13182 if (!node->simdclone->args[i].vector_arg)
13183 continue;
13185 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13186 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13187 adjustments[j].new_decl
13188 = build4 (ARRAY_REF,
13189 basetype,
13190 node->simdclone->args[i].simd_array,
13191 iter,
13192 NULL_TREE, NULL_TREE);
13193 if (adjustments[j].op == IPA_PARM_OP_NONE
13194 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13195 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13198 l = adjustments.length ();
13199 for (i = 1; i < num_ssa_names; i++)
13201 tree name = ssa_name (i);
13202 if (name
13203 && SSA_NAME_VAR (name)
13204 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13206 for (j = 0; j < l; j++)
13207 if (SSA_NAME_VAR (name) == adjustments[j].base
13208 && adjustments[j].new_decl)
13210 tree base_var;
13211 if (adjustments[j].new_ssa_base == NULL_TREE)
13213 base_var
13214 = copy_var_decl (adjustments[j].base,
13215 DECL_NAME (adjustments[j].base),
13216 TREE_TYPE (adjustments[j].base));
13217 adjustments[j].new_ssa_base = base_var;
13219 else
13220 base_var = adjustments[j].new_ssa_base;
13221 if (SSA_NAME_IS_DEFAULT_DEF (name))
13223 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13224 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13225 tree new_decl = unshare_expr (adjustments[j].new_decl);
13226 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13227 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13228 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13229 gimple stmt = gimple_build_assign (name, new_decl);
13230 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13232 else
13233 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13238 struct modify_stmt_info info;
13239 info.adjustments = adjustments;
13241 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13243 gimple_stmt_iterator gsi;
13245 gsi = gsi_start_bb (bb);
13246 while (!gsi_end_p (gsi))
13248 gimple stmt = gsi_stmt (gsi);
13249 info.stmt = stmt;
13250 struct walk_stmt_info wi;
13252 memset (&wi, 0, sizeof (wi));
13253 info.modified = false;
13254 wi.info = &info;
13255 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13257 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13259 tree retval = gimple_return_retval (return_stmt);
13260 if (!retval)
13262 gsi_remove (&gsi, true);
13263 continue;
13266 /* Replace `return foo' with `retval_array[iter] = foo'. */
13267 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13268 retval_array, iter, NULL, NULL);
13269 stmt = gimple_build_assign (ref, retval);
13270 gsi_replace (&gsi, stmt, true);
13271 info.modified = true;
13274 if (info.modified)
13276 update_stmt (stmt);
13277 if (maybe_clean_eh_stmt (stmt))
13278 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13280 gsi_next (&gsi);
13285 /* Adjust the argument types in NODE to their appropriate vector
13286 counterparts. */
13288 static void
13289 simd_clone_adjust (struct cgraph_node *node)
13291 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13293 targetm.simd_clone.adjust (node);
13295 tree retval = simd_clone_adjust_return_type (node);
13296 ipa_parm_adjustment_vec adjustments
13297 = simd_clone_adjust_argument_types (node);
13299 push_gimplify_context ();
13301 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13303 /* Adjust all uses of vector arguments accordingly. Adjust all
13304 return values accordingly. */
13305 tree iter = create_tmp_var (unsigned_type_node, "iter");
13306 tree iter1 = make_ssa_name (iter);
13307 tree iter2 = make_ssa_name (iter);
13308 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13310 /* Initialize the iteration variable. */
13311 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13312 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13313 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13314 /* Insert the SIMD array and iv initialization at function
13315 entry. */
13316 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13318 pop_gimplify_context (NULL);
13320 /* Create a new BB right before the original exit BB, to hold the
13321 iteration increment and the condition/branch. */
13322 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13323 basic_block incr_bb = create_empty_bb (orig_exit);
13324 add_bb_to_loop (incr_bb, body_bb->loop_father);
13325 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13326 flag. Set it now to be a FALLTHRU_EDGE. */
13327 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13328 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13329 for (unsigned i = 0;
13330 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13332 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13333 redirect_edge_succ (e, incr_bb);
13335 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13336 e->probability = REG_BR_PROB_BASE;
13337 gsi = gsi_last_bb (incr_bb);
13338 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13339 build_int_cst (unsigned_type_node, 1));
13340 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13342 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13343 struct loop *loop = alloc_loop ();
13344 cfun->has_force_vectorize_loops = true;
13345 loop->safelen = node->simdclone->simdlen;
13346 loop->force_vectorize = true;
13347 loop->header = body_bb;
13349 /* Branch around the body if the mask applies. */
13350 if (node->simdclone->inbranch)
13352 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13353 tree mask_array
13354 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13355 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13356 tree aref = build4 (ARRAY_REF,
13357 TREE_TYPE (TREE_TYPE (mask_array)),
13358 mask_array, iter1,
13359 NULL, NULL);
13360 g = gimple_build_assign (mask, aref);
13361 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13362 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13363 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13365 aref = build1 (VIEW_CONVERT_EXPR,
13366 build_nonstandard_integer_type (bitsize, 0), mask);
13367 mask = make_ssa_name (TREE_TYPE (aref));
13368 g = gimple_build_assign (mask, aref);
13369 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13372 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13373 NULL, NULL);
13374 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13375 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13376 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13379 /* Generate the condition. */
13380 g = gimple_build_cond (LT_EXPR,
13381 iter2,
13382 build_int_cst (unsigned_type_node,
13383 node->simdclone->simdlen),
13384 NULL, NULL);
13385 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13386 e = split_block (incr_bb, gsi_stmt (gsi));
13387 basic_block latch_bb = e->dest;
13388 basic_block new_exit_bb;
13389 new_exit_bb = split_block_after_labels (latch_bb)->dest;
13390 loop->latch = latch_bb;
13392 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13394 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13395 /* The successor of incr_bb is already pointing to latch_bb; just
13396 change the flags.
13397 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13398 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13400 gphi *phi = create_phi_node (iter1, body_bb);
13401 edge preheader_edge = find_edge (entry_bb, body_bb);
13402 edge latch_edge = single_succ_edge (latch_bb);
13403 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13404 UNKNOWN_LOCATION);
13405 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13407 /* Generate the new return. */
13408 gsi = gsi_last_bb (new_exit_bb);
13409 if (retval
13410 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13411 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13412 retval = TREE_OPERAND (retval, 0);
13413 else if (retval)
13415 retval = build1 (VIEW_CONVERT_EXPR,
13416 TREE_TYPE (TREE_TYPE (node->decl)),
13417 retval);
13418 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13419 false, GSI_CONTINUE_LINKING);
13421 g = gimple_build_return (retval);
13422 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13424 /* Handle aligned clauses by replacing default defs of the aligned
13425 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13426 lhs. Handle linear by adding PHIs. */
13427 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13428 if (node->simdclone->args[i].alignment
13429 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13430 && (node->simdclone->args[i].alignment
13431 & (node->simdclone->args[i].alignment - 1)) == 0
13432 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13433 == POINTER_TYPE)
13435 unsigned int alignment = node->simdclone->args[i].alignment;
13436 tree orig_arg = node->simdclone->args[i].orig_arg;
13437 tree def = ssa_default_def (cfun, orig_arg);
13438 if (def && !has_zero_uses (def))
13440 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13441 gimple_seq seq = NULL;
13442 bool need_cvt = false;
13443 gcall *call
13444 = gimple_build_call (fn, 2, def, size_int (alignment));
13445 g = call;
13446 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13447 ptr_type_node))
13448 need_cvt = true;
13449 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13450 gimple_call_set_lhs (g, t);
13451 gimple_seq_add_stmt_without_update (&seq, g);
13452 if (need_cvt)
13454 t = make_ssa_name (orig_arg);
13455 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13456 gimple_seq_add_stmt_without_update (&seq, g);
13458 gsi_insert_seq_on_edge_immediate
13459 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13461 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13462 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13463 entry_bb);
13464 node->create_edge (cgraph_node::get_create (fn),
13465 call, entry_bb->count, freq);
13467 imm_use_iterator iter;
13468 use_operand_p use_p;
13469 gimple use_stmt;
13470 tree repl = gimple_get_lhs (g);
13471 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13472 if (is_gimple_debug (use_stmt) || use_stmt == call)
13473 continue;
13474 else
13475 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13476 SET_USE (use_p, repl);
13479 else if (node->simdclone->args[i].arg_type
13480 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13482 tree orig_arg = node->simdclone->args[i].orig_arg;
13483 tree def = ssa_default_def (cfun, orig_arg);
13484 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13485 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13486 if (def && !has_zero_uses (def))
13488 iter1 = make_ssa_name (orig_arg);
13489 iter2 = make_ssa_name (orig_arg);
13490 phi = create_phi_node (iter1, body_bb);
13491 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13492 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13493 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13494 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13495 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13496 ? TREE_TYPE (orig_arg) : sizetype;
13497 tree addcst
13498 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13499 g = gimple_build_assign (iter2, code, iter1, addcst);
13500 gsi = gsi_last_bb (incr_bb);
13501 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13503 imm_use_iterator iter;
13504 use_operand_p use_p;
13505 gimple use_stmt;
13506 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13507 if (use_stmt == phi)
13508 continue;
13509 else
13510 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13511 SET_USE (use_p, iter1);
13515 calculate_dominance_info (CDI_DOMINATORS);
13516 add_loop (loop, loop->header->loop_father);
13517 update_ssa (TODO_update_ssa);
13519 pop_cfun ();
13522 /* If the function in NODE is tagged as an elemental SIMD function,
13523 create the appropriate SIMD clones. */
13525 static void
13526 expand_simd_clones (struct cgraph_node *node)
13528 tree attr = lookup_attribute ("omp declare simd",
13529 DECL_ATTRIBUTES (node->decl));
13530 if (attr == NULL_TREE
13531 || node->global.inlined_to
13532 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13533 return;
13535 /* Ignore
13536 #pragma omp declare simd
13537 extern int foo ();
13538 in C, there we don't know the argument types at all. */
13539 if (!node->definition
13540 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13541 return;
13545 /* Start with parsing the "omp declare simd" attribute(s). */
13546 bool inbranch_clause_specified;
13547 struct cgraph_simd_clone *clone_info
13548 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13549 &inbranch_clause_specified);
13550 if (clone_info == NULL)
13551 continue;
13553 int orig_simdlen = clone_info->simdlen;
13554 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13555 /* The target can return 0 (no simd clones should be created),
13556 1 (just one ISA of simd clones should be created) or higher
13557 count of ISA variants. In that case, clone_info is initialized
13558 for the first ISA variant. */
13559 int count
13560 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13561 base_type, 0);
13562 if (count == 0)
13563 continue;
13565 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13566 also create one inbranch and one !inbranch clone of it. */
13567 for (int i = 0; i < count * 2; i++)
13569 struct cgraph_simd_clone *clone = clone_info;
13570 if (inbranch_clause_specified && (i & 1) != 0)
13571 continue;
13573 if (i != 0)
13575 clone = simd_clone_struct_alloc (clone_info->nargs
13576 + ((i & 1) != 0));
13577 simd_clone_struct_copy (clone, clone_info);
13578 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13579 and simd_clone_adjust_argument_types did to the first
13580 clone's info. */
13581 clone->nargs -= clone_info->inbranch;
13582 clone->simdlen = orig_simdlen;
13583 /* And call the target hook again to get the right ISA. */
13584 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13585 base_type,
13586 i / 2);
13587 if ((i & 1) != 0)
13588 clone->inbranch = 1;
13591 /* simd_clone_mangle might fail if such a clone has been created
13592 already. */
13593 tree id = simd_clone_mangle (node, clone);
13594 if (id == NULL_TREE)
13595 continue;
13597 /* Only when we are sure we want to create the clone actually
13598 clone the function (or definitions) or create another
13599 extern FUNCTION_DECL (for prototypes without definitions). */
13600 struct cgraph_node *n = simd_clone_create (node);
13601 if (n == NULL)
13602 continue;
13604 n->simdclone = clone;
13605 clone->origin = node;
13606 clone->next_clone = NULL;
13607 if (node->simd_clones == NULL)
13609 clone->prev_clone = n;
13610 node->simd_clones = n;
13612 else
13614 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13615 clone->prev_clone->simdclone->next_clone = n;
13616 node->simd_clones->simdclone->prev_clone = n;
13618 symtab->change_decl_assembler_name (n->decl, id);
13619 /* And finally adjust the return type, parameters and for
13620 definitions also function body. */
13621 if (node->definition)
13622 simd_clone_adjust (n);
13623 else
13625 simd_clone_adjust_return_type (n);
13626 simd_clone_adjust_argument_types (n);
13630 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13633 /* Entry point for IPA simd clone creation pass. */
13635 static unsigned int
13636 ipa_omp_simd_clone (void)
13638 struct cgraph_node *node;
13639 FOR_EACH_FUNCTION (node)
13640 expand_simd_clones (node);
13641 return 0;
13644 namespace {
13646 const pass_data pass_data_omp_simd_clone =
13648 SIMPLE_IPA_PASS, /* type */
13649 "simdclone", /* name */
13650 OPTGROUP_NONE, /* optinfo_flags */
13651 TV_NONE, /* tv_id */
13652 ( PROP_ssa | PROP_cfg ), /* properties_required */
13653 0, /* properties_provided */
13654 0, /* properties_destroyed */
13655 0, /* todo_flags_start */
13656 0, /* todo_flags_finish */
13659 class pass_omp_simd_clone : public simple_ipa_opt_pass
13661 public:
13662 pass_omp_simd_clone(gcc::context *ctxt)
13663 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13666 /* opt_pass methods: */
13667 virtual bool gate (function *);
13668 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
13671 bool
13672 pass_omp_simd_clone::gate (function *)
13674 return ((flag_openmp || flag_openmp_simd
13675 || flag_cilkplus
13676 || (in_lto_p && !flag_wpa))
13677 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13680 } // anon namespace
13682 simple_ipa_opt_pass *
13683 make_pass_omp_simd_clone (gcc::context *ctxt)
13685 return new pass_omp_simd_clone (ctxt);
13688 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13689 adds their addresses and sizes to constructor-vector V_CTOR. */
13690 static void
13691 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13692 vec<constructor_elt, va_gc> *v_ctor)
13694 unsigned len = vec_safe_length (v_decls);
13695 for (unsigned i = 0; i < len; i++)
13697 tree it = (*v_decls)[i];
13698 bool is_function = TREE_CODE (it) != VAR_DECL;
13700 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13701 if (!is_function)
13702 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13703 fold_convert (const_ptr_type_node,
13704 DECL_SIZE_UNIT (it)));
13708 /* Create new symbols containing (address, size) pairs for global variables,
13709 marked with "omp declare target" attribute, as well as addresses for the
13710 functions, which are outlined offloading regions. */
13711 void
13712 omp_finish_file (void)
13714 unsigned num_funcs = vec_safe_length (offload_funcs);
13715 unsigned num_vars = vec_safe_length (offload_vars);
13717 if (num_funcs == 0 && num_vars == 0)
13718 return;
13720 if (targetm_common.have_named_sections)
13722 vec<constructor_elt, va_gc> *v_f, *v_v;
13723 vec_alloc (v_f, num_funcs);
13724 vec_alloc (v_v, num_vars * 2);
13726 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13727 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13729 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13730 num_vars * 2);
13731 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13732 num_funcs);
13733 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13734 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13735 tree ctor_v = build_constructor (vars_decl_type, v_v);
13736 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13737 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13738 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13739 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13740 get_identifier (".offload_func_table"),
13741 funcs_decl_type);
13742 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13743 get_identifier (".offload_var_table"),
13744 vars_decl_type);
13745 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13746 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13747 otherwise a joint table in a binary will contain padding between
13748 tables from multiple object files. */
13749 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13750 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13751 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13752 DECL_INITIAL (funcs_decl) = ctor_f;
13753 DECL_INITIAL (vars_decl) = ctor_v;
13754 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13755 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13757 varpool_node::finalize_decl (vars_decl);
13758 varpool_node::finalize_decl (funcs_decl);
13760 else
13762 for (unsigned i = 0; i < num_funcs; i++)
13764 tree it = (*offload_funcs)[i];
13765 targetm.record_offload_symbol (it);
13767 for (unsigned i = 0; i < num_vars; i++)
13769 tree it = (*offload_vars)[i];
13770 targetm.record_offload_symbol (it);
13775 #include "gt-omp-low.h"