mn10300: Use the STC bb-reorder algorithm at -Os
[official-gcc.git] / gcc / omp-low.c
blobb444864f0d1992fe95d28c98f9ea99a6901c5308
1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "cfghooks.h"
30 #include "tree.h"
31 #include "gimple.h"
32 #include "rtl.h"
33 #include "ssa.h"
34 #include "alias.h"
35 #include "fold-const.h"
36 #include "stor-layout.h"
37 #include "cfganal.h"
38 #include "internal-fn.h"
39 #include "gimple-fold.h"
40 #include "gimplify.h"
41 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
43 #include "gimple-walk.h"
44 #include "tree-iterator.h"
45 #include "tree-inline.h"
46 #include "langhooks.h"
47 #include "diagnostic-core.h"
48 #include "cgraph.h"
49 #include "tree-cfg.h"
50 #include "tree-into-ssa.h"
51 #include "flags.h"
52 #include "insn-config.h"
53 #include "expmed.h"
54 #include "dojump.h"
55 #include "explow.h"
56 #include "calls.h"
57 #include "emit-rtl.h"
58 #include "varasm.h"
59 #include "stmt.h"
60 #include "expr.h"
61 #include "tree-dfa.h"
62 #include "tree-ssa.h"
63 #include "tree-pass.h"
64 #include "except.h"
65 #include "splay-tree.h"
66 #include "insn-codes.h"
67 #include "optabs.h"
68 #include "cfgloop.h"
69 #include "target.h"
70 #include "common/common-target.h"
71 #include "omp-low.h"
72 #include "gimple-low.h"
73 #include "tree-cfgcleanup.h"
74 #include "pretty-print.h"
75 #include "alloc-pool.h"
76 #include "symbol-summary.h"
77 #include "ipa-prop.h"
78 #include "tree-nested.h"
79 #include "tree-eh.h"
80 #include "cilk.h"
81 #include "context.h"
82 #include "lto-section-names.h"
83 #include "gomp-constants.h"
85 /* Lowering of OMP parallel and workshare constructs proceeds in two
86 phases. The first phase scans the function looking for OMP statements
87 and then for variables that must be replaced to satisfy data sharing
88 clauses. The second phase expands code for the constructs, as well as
89 re-gimplifying things when variables have been replaced with complex
90 expressions.
92 Final code generation is done by pass_expand_omp. The flowgraph is
93 scanned for regions which are then moved to a new
94 function, to be invoked by the thread library, or offloaded. */
96 /* OMP region information. Every parallel and workshare
97 directive is enclosed between two markers, the OMP_* directive
98 and a corresponding GIMPLE_OMP_RETURN statement. */
100 struct omp_region
102 /* The enclosing region. */
103 struct omp_region *outer;
105 /* First child region. */
106 struct omp_region *inner;
108 /* Next peer region. */
109 struct omp_region *next;
111 /* Block containing the omp directive as its last stmt. */
112 basic_block entry;
114 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
115 basic_block exit;
117 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
118 basic_block cont;
120 /* If this is a combined parallel+workshare region, this is a list
121 of additional arguments needed by the combined parallel+workshare
122 library call. */
123 vec<tree, va_gc> *ws_args;
125 /* The code for the omp directive of this region. */
126 enum gimple_code type;
128 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
129 enum omp_clause_schedule_kind sched_kind;
131 /* True if this is a combined parallel+workshare region. */
132 bool is_combined_parallel;
134 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
135 a depend clause. */
136 gomp_ordered *ord_stmt;
139 /* Levels of parallelism as defined by OpenACC. Increasing numbers
140 correspond to deeper loop nesting levels. */
141 #define MASK_GANG 1
142 #define MASK_WORKER 2
143 #define MASK_VECTOR 4
145 /* Context structure. Used to store information about each parallel
146 directive in the code. */
148 struct omp_context
150 /* This field must be at the beginning, as we do "inheritance": Some
151 callback functions for tree-inline.c (e.g., omp_copy_decl)
152 receive a copy_body_data pointer that is up-casted to an
153 omp_context pointer. */
154 copy_body_data cb;
156 /* The tree of contexts corresponding to the encountered constructs. */
157 struct omp_context *outer;
158 gimple *stmt;
160 /* Map variables to fields in a structure that allows communication
161 between sending and receiving threads. */
162 splay_tree field_map;
163 tree record_type;
164 tree sender_decl;
165 tree receiver_decl;
167 /* These are used just by task contexts, if task firstprivate fn is
168 needed. srecord_type is used to communicate from the thread
169 that encountered the task construct to task firstprivate fn,
170 record_type is allocated by GOMP_task, initialized by task firstprivate
171 fn and passed to the task body fn. */
172 splay_tree sfield_map;
173 tree srecord_type;
175 /* A chain of variables to add to the top-level block surrounding the
176 construct. In the case of a parallel, this is in the child function. */
177 tree block_vars;
179 /* A map of reduction pointer variables. For accelerators, each
180 reduction variable is replaced with an array. Each thread, in turn,
181 is assigned to a slot on that array. */
182 splay_tree reduction_map;
184 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
185 barriers should jump to during omplower pass. */
186 tree cancel_label;
188 /* What to do with variables with implicitly determined sharing
189 attributes. */
190 enum omp_clause_default_kind default_kind;
192 /* Nesting depth of this context. Used to beautify error messages re
193 invalid gotos. The outermost ctx is depth 1, with depth 0 being
194 reserved for the main body of the function. */
195 int depth;
197 /* True if this parallel directive is nested within another. */
198 bool is_nested;
200 /* True if this construct can be cancelled. */
201 bool cancellable;
203 /* For OpenACC loops, a mask of gang, worker and vector used at
204 levels below this one. */
205 int gwv_below;
206 /* For OpenACC loops, a mask of gang, worker and vector used at
207 this level and above. For parallel and kernels clauses, a mask
208 indicating which of num_gangs/num_workers/num_vectors was used. */
209 int gwv_this;
212 /* A structure holding the elements of:
213 for (V = N1; V cond N2; V += STEP) [...] */
215 struct omp_for_data_loop
217 tree v, n1, n2, step;
218 enum tree_code cond_code;
221 /* A structure describing the main elements of a parallel loop. */
223 struct omp_for_data
225 struct omp_for_data_loop loop;
226 tree chunk_size;
227 gomp_for *for_stmt;
228 tree pre, iter_type;
229 int collapse;
230 int ordered;
231 bool have_nowait, have_ordered, simd_schedule;
232 enum omp_clause_schedule_kind sched_kind;
233 struct omp_for_data_loop *loops;
237 static splay_tree all_contexts;
238 static int taskreg_nesting_level;
239 static int target_nesting_level;
240 static struct omp_region *root_omp_region;
241 static bitmap task_shared_vars;
242 static vec<omp_context *> taskreg_contexts;
244 static void scan_omp (gimple_seq *, omp_context *);
245 static tree scan_omp_1_op (tree *, int *, void *);
246 static gphi *find_phi_with_arg_on_edge (tree, edge);
248 #define WALK_SUBSTMTS \
249 case GIMPLE_BIND: \
250 case GIMPLE_TRY: \
251 case GIMPLE_CATCH: \
252 case GIMPLE_EH_FILTER: \
253 case GIMPLE_TRANSACTION: \
254 /* The sub-statements for these should be walked. */ \
255 *handled_ops_p = false; \
256 break;
258 /* Helper function to get the name of the array containing the partial
259 reductions for OpenACC reductions. */
260 static const char *
261 oacc_get_reduction_array_id (tree node)
263 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
264 int len = strlen ("OACC") + strlen (id);
265 char *temp_name = XALLOCAVEC (char, len + 1);
266 snprintf (temp_name, len + 1, "OACC%s", id);
267 return IDENTIFIER_POINTER (get_identifier (temp_name));
270 /* Determine the number of threads OpenACC threads used to determine the
271 size of the array of partial reductions. Currently, this is num_gangs
272 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
273 because it is independed of the device used. */
275 static tree
276 oacc_max_threads (omp_context *ctx)
278 tree nthreads, vector_length, gangs, clauses;
280 gangs = fold_convert (sizetype, integer_one_node);
281 vector_length = gangs;
283 /* The reduction clause may be nested inside a loop directive.
284 Scan for the innermost vector_length clause. */
285 for (omp_context *oc = ctx; oc; oc = oc->outer)
287 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
288 || (gimple_omp_target_kind (oc->stmt)
289 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
290 continue;
292 clauses = gimple_omp_target_clauses (oc->stmt);
294 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
295 if (vector_length)
296 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
297 sizetype,
298 OMP_CLAUSE_VECTOR_LENGTH_EXPR
299 (vector_length));
300 else
301 vector_length = fold_convert (sizetype, integer_one_node);
303 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
304 if (gangs)
305 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
306 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
307 else
308 gangs = fold_convert (sizetype, integer_one_node);
310 break;
313 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
315 return nthreads;
318 /* If DECL is the artificial dummy VAR_DECL created for non-static
319 data member privatization, return the underlying "this" parameter,
320 otherwise return NULL. */
322 tree
323 omp_member_access_dummy_var (tree decl)
325 if (!VAR_P (decl)
326 || !DECL_ARTIFICIAL (decl)
327 || !DECL_IGNORED_P (decl)
328 || !DECL_HAS_VALUE_EXPR_P (decl)
329 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
330 return NULL_TREE;
332 tree v = DECL_VALUE_EXPR (decl);
333 if (TREE_CODE (v) != COMPONENT_REF)
334 return NULL_TREE;
336 while (1)
337 switch (TREE_CODE (v))
339 case COMPONENT_REF:
340 case MEM_REF:
341 case INDIRECT_REF:
342 CASE_CONVERT:
343 case POINTER_PLUS_EXPR:
344 v = TREE_OPERAND (v, 0);
345 continue;
346 case PARM_DECL:
347 if (DECL_CONTEXT (v) == current_function_decl
348 && DECL_ARTIFICIAL (v)
349 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
350 return v;
351 return NULL_TREE;
352 default:
353 return NULL_TREE;
357 /* Helper for unshare_and_remap, called through walk_tree. */
359 static tree
360 unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
362 tree *pair = (tree *) data;
363 if (*tp == pair[0])
365 *tp = unshare_expr (pair[1]);
366 *walk_subtrees = 0;
368 else if (IS_TYPE_OR_DECL_P (*tp))
369 *walk_subtrees = 0;
370 return NULL_TREE;
373 /* Return unshare_expr (X) with all occurrences of FROM
374 replaced with TO. */
376 static tree
377 unshare_and_remap (tree x, tree from, tree to)
379 tree pair[2] = { from, to };
380 x = unshare_expr (x);
381 walk_tree (&x, unshare_and_remap_1, pair, NULL);
382 return x;
385 /* Holds offload tables with decls. */
386 vec<tree, va_gc> *offload_funcs, *offload_vars;
388 /* Convenience function for calling scan_omp_1_op on tree operands. */
390 static inline tree
391 scan_omp_op (tree *tp, omp_context *ctx)
393 struct walk_stmt_info wi;
395 memset (&wi, 0, sizeof (wi));
396 wi.info = ctx;
397 wi.want_locations = true;
399 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
402 static void lower_omp (gimple_seq *, omp_context *);
403 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
404 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
406 /* Find an OMP clause of type KIND within CLAUSES. */
408 tree
409 find_omp_clause (tree clauses, enum omp_clause_code kind)
411 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
412 if (OMP_CLAUSE_CODE (clauses) == kind)
413 return clauses;
415 return NULL_TREE;
418 /* Return true if CTX is for an omp parallel. */
420 static inline bool
421 is_parallel_ctx (omp_context *ctx)
423 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
427 /* Return true if CTX is for an omp task. */
429 static inline bool
430 is_task_ctx (omp_context *ctx)
432 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
436 /* Return true if CTX is for an omp taskloop. */
438 static inline bool
439 is_taskloop_ctx (omp_context *ctx)
441 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
442 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
446 /* Return true if CTX is for an omp parallel or omp task. */
448 static inline bool
449 is_taskreg_ctx (omp_context *ctx)
451 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
455 /* Return true if REGION is a combined parallel+workshare region. */
457 static inline bool
458 is_combined_parallel (struct omp_region *region)
460 return region->is_combined_parallel;
464 /* Extract the header elements of parallel loop FOR_STMT and store
465 them into *FD. */
467 static void
468 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
469 struct omp_for_data_loop *loops)
471 tree t, var, *collapse_iter, *collapse_count;
472 tree count = NULL_TREE, iter_type = long_integer_type_node;
473 struct omp_for_data_loop *loop;
474 int i;
475 struct omp_for_data_loop dummy_loop;
476 location_t loc = gimple_location (for_stmt);
477 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
478 bool distribute = gimple_omp_for_kind (for_stmt)
479 == GF_OMP_FOR_KIND_DISTRIBUTE;
480 bool taskloop = gimple_omp_for_kind (for_stmt)
481 == GF_OMP_FOR_KIND_TASKLOOP;
482 tree iterv, countv;
484 fd->for_stmt = for_stmt;
485 fd->pre = NULL;
486 if (gimple_omp_for_collapse (for_stmt) > 1)
487 fd->loops = loops;
488 else
489 fd->loops = &fd->loop;
491 fd->have_nowait = distribute || simd;
492 fd->have_ordered = false;
493 fd->collapse = 1;
494 fd->ordered = 0;
495 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
496 fd->chunk_size = NULL_TREE;
497 fd->simd_schedule = false;
498 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
499 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
500 collapse_iter = NULL;
501 collapse_count = NULL;
503 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
504 switch (OMP_CLAUSE_CODE (t))
506 case OMP_CLAUSE_NOWAIT:
507 fd->have_nowait = true;
508 break;
509 case OMP_CLAUSE_ORDERED:
510 fd->have_ordered = true;
511 if (OMP_CLAUSE_ORDERED_EXPR (t))
512 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
513 break;
514 case OMP_CLAUSE_SCHEDULE:
515 gcc_assert (!distribute && !taskloop);
516 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
517 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
518 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
519 break;
520 case OMP_CLAUSE_DIST_SCHEDULE:
521 gcc_assert (distribute);
522 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
523 break;
524 case OMP_CLAUSE_COLLAPSE:
525 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
526 if (fd->collapse > 1)
528 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
529 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
531 break;
532 default:
533 break;
535 if (fd->ordered && fd->collapse == 1 && loops != NULL)
537 fd->loops = loops;
538 iterv = NULL_TREE;
539 countv = NULL_TREE;
540 collapse_iter = &iterv;
541 collapse_count = &countv;
544 /* FIXME: for now map schedule(auto) to schedule(static).
545 There should be analysis to determine whether all iterations
546 are approximately the same amount of work (then schedule(static)
547 is best) or if it varies (then schedule(dynamic,N) is better). */
548 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
550 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
551 gcc_assert (fd->chunk_size == NULL);
553 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
554 if (taskloop)
555 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
556 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
557 gcc_assert (fd->chunk_size == NULL);
558 else if (fd->chunk_size == NULL)
560 /* We only need to compute a default chunk size for ordered
561 static loops and dynamic loops. */
562 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
563 || fd->have_ordered)
564 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
565 ? integer_zero_node : integer_one_node;
568 int cnt = fd->ordered ? fd->ordered : fd->collapse;
569 for (i = 0; i < cnt; i++)
571 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
572 loop = &fd->loop;
573 else if (loops != NULL)
574 loop = loops + i;
575 else
576 loop = &dummy_loop;
578 loop->v = gimple_omp_for_index (for_stmt, i);
579 gcc_assert (SSA_VAR_P (loop->v));
580 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
581 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
582 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
583 loop->n1 = gimple_omp_for_initial (for_stmt, i);
585 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
586 loop->n2 = gimple_omp_for_final (for_stmt, i);
587 switch (loop->cond_code)
589 case LT_EXPR:
590 case GT_EXPR:
591 break;
592 case NE_EXPR:
593 gcc_assert (gimple_omp_for_kind (for_stmt)
594 == GF_OMP_FOR_KIND_CILKSIMD
595 || (gimple_omp_for_kind (for_stmt)
596 == GF_OMP_FOR_KIND_CILKFOR));
597 break;
598 case LE_EXPR:
599 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
600 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
601 else
602 loop->n2 = fold_build2_loc (loc,
603 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
604 build_int_cst (TREE_TYPE (loop->n2), 1));
605 loop->cond_code = LT_EXPR;
606 break;
607 case GE_EXPR:
608 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
609 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
610 else
611 loop->n2 = fold_build2_loc (loc,
612 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
613 build_int_cst (TREE_TYPE (loop->n2), 1));
614 loop->cond_code = GT_EXPR;
615 break;
616 default:
617 gcc_unreachable ();
620 t = gimple_omp_for_incr (for_stmt, i);
621 gcc_assert (TREE_OPERAND (t, 0) == var);
622 switch (TREE_CODE (t))
624 case PLUS_EXPR:
625 loop->step = TREE_OPERAND (t, 1);
626 break;
627 case POINTER_PLUS_EXPR:
628 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
629 break;
630 case MINUS_EXPR:
631 loop->step = TREE_OPERAND (t, 1);
632 loop->step = fold_build1_loc (loc,
633 NEGATE_EXPR, TREE_TYPE (loop->step),
634 loop->step);
635 break;
636 default:
637 gcc_unreachable ();
640 if (simd
641 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
642 && !fd->have_ordered))
644 if (fd->collapse == 1)
645 iter_type = TREE_TYPE (loop->v);
646 else if (i == 0
647 || TYPE_PRECISION (iter_type)
648 < TYPE_PRECISION (TREE_TYPE (loop->v)))
649 iter_type
650 = build_nonstandard_integer_type
651 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
653 else if (iter_type != long_long_unsigned_type_node)
655 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
656 iter_type = long_long_unsigned_type_node;
657 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
658 && TYPE_PRECISION (TREE_TYPE (loop->v))
659 >= TYPE_PRECISION (iter_type))
661 tree n;
663 if (loop->cond_code == LT_EXPR)
664 n = fold_build2_loc (loc,
665 PLUS_EXPR, TREE_TYPE (loop->v),
666 loop->n2, loop->step);
667 else
668 n = loop->n1;
669 if (TREE_CODE (n) != INTEGER_CST
670 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
671 iter_type = long_long_unsigned_type_node;
673 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
674 > TYPE_PRECISION (iter_type))
676 tree n1, n2;
678 if (loop->cond_code == LT_EXPR)
680 n1 = loop->n1;
681 n2 = fold_build2_loc (loc,
682 PLUS_EXPR, TREE_TYPE (loop->v),
683 loop->n2, loop->step);
685 else
687 n1 = fold_build2_loc (loc,
688 MINUS_EXPR, TREE_TYPE (loop->v),
689 loop->n2, loop->step);
690 n2 = loop->n1;
692 if (TREE_CODE (n1) != INTEGER_CST
693 || TREE_CODE (n2) != INTEGER_CST
694 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
695 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
696 iter_type = long_long_unsigned_type_node;
700 if (i >= fd->collapse)
701 continue;
703 if (collapse_count && *collapse_count == NULL)
705 t = fold_binary (loop->cond_code, boolean_type_node,
706 fold_convert (TREE_TYPE (loop->v), loop->n1),
707 fold_convert (TREE_TYPE (loop->v), loop->n2));
708 if (t && integer_zerop (t))
709 count = build_zero_cst (long_long_unsigned_type_node);
710 else if ((i == 0 || count != NULL_TREE)
711 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
712 && TREE_CONSTANT (loop->n1)
713 && TREE_CONSTANT (loop->n2)
714 && TREE_CODE (loop->step) == INTEGER_CST)
716 tree itype = TREE_TYPE (loop->v);
718 if (POINTER_TYPE_P (itype))
719 itype = signed_type_for (itype);
720 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
721 t = fold_build2_loc (loc,
722 PLUS_EXPR, itype,
723 fold_convert_loc (loc, itype, loop->step), t);
724 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
725 fold_convert_loc (loc, itype, loop->n2));
726 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
727 fold_convert_loc (loc, itype, loop->n1));
728 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
729 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
730 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
731 fold_build1_loc (loc, NEGATE_EXPR, itype,
732 fold_convert_loc (loc, itype,
733 loop->step)));
734 else
735 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
736 fold_convert_loc (loc, itype, loop->step));
737 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
738 if (count != NULL_TREE)
739 count = fold_build2_loc (loc,
740 MULT_EXPR, long_long_unsigned_type_node,
741 count, t);
742 else
743 count = t;
744 if (TREE_CODE (count) != INTEGER_CST)
745 count = NULL_TREE;
747 else if (count && !integer_zerop (count))
748 count = NULL_TREE;
752 if (count
753 && !simd
754 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
755 || fd->have_ordered))
757 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
758 iter_type = long_long_unsigned_type_node;
759 else
760 iter_type = long_integer_type_node;
762 else if (collapse_iter && *collapse_iter != NULL)
763 iter_type = TREE_TYPE (*collapse_iter);
764 fd->iter_type = iter_type;
765 if (collapse_iter && *collapse_iter == NULL)
766 *collapse_iter = create_tmp_var (iter_type, ".iter");
767 if (collapse_count && *collapse_count == NULL)
769 if (count)
770 *collapse_count = fold_convert_loc (loc, iter_type, count);
771 else
772 *collapse_count = create_tmp_var (iter_type, ".count");
775 if (fd->collapse > 1 || (fd->ordered && loops))
777 fd->loop.v = *collapse_iter;
778 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
779 fd->loop.n2 = *collapse_count;
780 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
781 fd->loop.cond_code = LT_EXPR;
783 else if (loops)
784 loops[0] = fd->loop;
786 /* For OpenACC loops, force a chunk size of one, as this avoids the default
787 scheduling where several subsequent iterations are being executed by the
788 same thread. */
789 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
791 gcc_assert (fd->chunk_size == NULL_TREE);
792 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
797 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
798 is the immediate dominator of PAR_ENTRY_BB, return true if there
799 are no data dependencies that would prevent expanding the parallel
800 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
802 When expanding a combined parallel+workshare region, the call to
803 the child function may need additional arguments in the case of
804 GIMPLE_OMP_FOR regions. In some cases, these arguments are
805 computed out of variables passed in from the parent to the child
806 via 'struct .omp_data_s'. For instance:
808 #pragma omp parallel for schedule (guided, i * 4)
809 for (j ...)
811 Is lowered into:
813 # BLOCK 2 (PAR_ENTRY_BB)
814 .omp_data_o.i = i;
815 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
817 # BLOCK 3 (WS_ENTRY_BB)
818 .omp_data_i = &.omp_data_o;
819 D.1667 = .omp_data_i->i;
820 D.1598 = D.1667 * 4;
821 #pragma omp for schedule (guided, D.1598)
823 When we outline the parallel region, the call to the child function
824 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
825 that value is computed *after* the call site. So, in principle we
826 cannot do the transformation.
828 To see whether the code in WS_ENTRY_BB blocks the combined
829 parallel+workshare call, we collect all the variables used in the
830 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
831 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
832 call.
834 FIXME. If we had the SSA form built at this point, we could merely
835 hoist the code in block 3 into block 2 and be done with it. But at
836 this point we don't have dataflow information and though we could
837 hack something up here, it is really not worth the aggravation. */
839 static bool
840 workshare_safe_to_combine_p (basic_block ws_entry_bb)
842 struct omp_for_data fd;
843 gimple *ws_stmt = last_stmt (ws_entry_bb);
845 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
846 return true;
848 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
850 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
852 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
853 return false;
854 if (fd.iter_type != long_integer_type_node)
855 return false;
857 /* FIXME. We give up too easily here. If any of these arguments
858 are not constants, they will likely involve variables that have
859 been mapped into fields of .omp_data_s for sharing with the child
860 function. With appropriate data flow, it would be possible to
861 see through this. */
862 if (!is_gimple_min_invariant (fd.loop.n1)
863 || !is_gimple_min_invariant (fd.loop.n2)
864 || !is_gimple_min_invariant (fd.loop.step)
865 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
866 return false;
868 return true;
872 static int omp_max_vf (void);
874 /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
875 presence (SIMD_SCHEDULE). */
877 static tree
878 omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
880 if (!simd_schedule)
881 return chunk_size;
883 int vf = omp_max_vf ();
884 if (vf == 1)
885 return chunk_size;
887 tree type = TREE_TYPE (chunk_size);
888 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
889 build_int_cst (type, vf - 1));
890 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
891 build_int_cst (type, -vf));
895 /* Collect additional arguments needed to emit a combined
896 parallel+workshare call. WS_STMT is the workshare directive being
897 expanded. */
899 static vec<tree, va_gc> *
900 get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
902 tree t;
903 location_t loc = gimple_location (ws_stmt);
904 vec<tree, va_gc> *ws_args;
906 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
908 struct omp_for_data fd;
909 tree n1, n2;
911 extract_omp_for_data (for_stmt, &fd, NULL);
912 n1 = fd.loop.n1;
913 n2 = fd.loop.n2;
915 if (gimple_omp_for_combined_into_p (for_stmt))
917 tree innerc
918 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
919 OMP_CLAUSE__LOOPTEMP_);
920 gcc_assert (innerc);
921 n1 = OMP_CLAUSE_DECL (innerc);
922 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
923 OMP_CLAUSE__LOOPTEMP_);
924 gcc_assert (innerc);
925 n2 = OMP_CLAUSE_DECL (innerc);
928 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
930 t = fold_convert_loc (loc, long_integer_type_node, n1);
931 ws_args->quick_push (t);
933 t = fold_convert_loc (loc, long_integer_type_node, n2);
934 ws_args->quick_push (t);
936 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
937 ws_args->quick_push (t);
939 if (fd.chunk_size)
941 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
942 t = omp_adjust_chunk_size (t, fd.simd_schedule);
943 ws_args->quick_push (t);
946 return ws_args;
948 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
950 /* Number of sections is equal to the number of edges from the
951 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
952 the exit of the sections region. */
953 basic_block bb = single_succ (gimple_bb (ws_stmt));
954 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
955 vec_alloc (ws_args, 1);
956 ws_args->quick_push (t);
957 return ws_args;
960 gcc_unreachable ();
964 /* Discover whether REGION is a combined parallel+workshare region. */
966 static void
967 determine_parallel_type (struct omp_region *region)
969 basic_block par_entry_bb, par_exit_bb;
970 basic_block ws_entry_bb, ws_exit_bb;
972 if (region == NULL || region->inner == NULL
973 || region->exit == NULL || region->inner->exit == NULL
974 || region->inner->cont == NULL)
975 return;
977 /* We only support parallel+for and parallel+sections. */
978 if (region->type != GIMPLE_OMP_PARALLEL
979 || (region->inner->type != GIMPLE_OMP_FOR
980 && region->inner->type != GIMPLE_OMP_SECTIONS))
981 return;
983 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
984 WS_EXIT_BB -> PAR_EXIT_BB. */
985 par_entry_bb = region->entry;
986 par_exit_bb = region->exit;
987 ws_entry_bb = region->inner->entry;
988 ws_exit_bb = region->inner->exit;
990 if (single_succ (par_entry_bb) == ws_entry_bb
991 && single_succ (ws_exit_bb) == par_exit_bb
992 && workshare_safe_to_combine_p (ws_entry_bb)
993 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
994 || (last_and_only_stmt (ws_entry_bb)
995 && last_and_only_stmt (par_exit_bb))))
997 gimple *par_stmt = last_stmt (par_entry_bb);
998 gimple *ws_stmt = last_stmt (ws_entry_bb);
1000 if (region->inner->type == GIMPLE_OMP_FOR)
1002 /* If this is a combined parallel loop, we need to determine
1003 whether or not to use the combined library calls. There
1004 are two cases where we do not apply the transformation:
1005 static loops and any kind of ordered loop. In the first
1006 case, we already open code the loop so there is no need
1007 to do anything else. In the latter case, the combined
1008 parallel loop call would still need extra synchronization
1009 to implement ordered semantics, so there would not be any
1010 gain in using the combined call. */
1011 tree clauses = gimple_omp_for_clauses (ws_stmt);
1012 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
1013 if (c == NULL
1014 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
1015 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1017 region->is_combined_parallel = false;
1018 region->inner->is_combined_parallel = false;
1019 return;
1023 region->is_combined_parallel = true;
1024 region->inner->is_combined_parallel = true;
1025 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
1030 /* Return true if EXPR is variable sized. */
1032 static inline bool
1033 is_variable_sized (const_tree expr)
1035 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1038 /* Return true if DECL is a reference type. */
1040 static inline bool
1041 is_reference (tree decl)
1043 return lang_hooks.decls.omp_privatize_by_reference (decl);
1046 /* Return the type of a decl. If the decl is reference type,
1047 return its base type. */
1048 static inline tree
1049 get_base_type (tree decl)
1051 tree type = TREE_TYPE (decl);
1052 if (is_reference (decl))
1053 type = TREE_TYPE (type);
1054 return type;
1057 /* Lookup variables. The "maybe" form
1058 allows for the variable form to not have been entered, otherwise we
1059 assert that the variable must have been entered. */
1061 static inline tree
1062 lookup_decl (tree var, omp_context *ctx)
1064 tree *n = ctx->cb.decl_map->get (var);
1065 return *n;
1068 static inline tree
1069 maybe_lookup_decl (const_tree var, omp_context *ctx)
1071 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
1072 return n ? *n : NULL_TREE;
1075 static inline tree
1076 lookup_field (tree var, omp_context *ctx)
1078 splay_tree_node n;
1079 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1080 return (tree) n->value;
1083 static inline tree
1084 lookup_sfield (splay_tree_key key, omp_context *ctx)
1086 splay_tree_node n;
1087 n = splay_tree_lookup (ctx->sfield_map
1088 ? ctx->sfield_map : ctx->field_map, key);
1089 return (tree) n->value;
1092 static inline tree
1093 lookup_sfield (tree var, omp_context *ctx)
1095 return lookup_sfield ((splay_tree_key) var, ctx);
1098 static inline tree
1099 maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1101 splay_tree_node n;
1102 n = splay_tree_lookup (ctx->field_map, key);
1103 return n ? (tree) n->value : NULL_TREE;
1106 static inline tree
1107 maybe_lookup_field (tree var, omp_context *ctx)
1109 return maybe_lookup_field ((splay_tree_key) var, ctx);
1112 static inline tree
1113 lookup_oacc_reduction (const char *id, omp_context *ctx)
1115 splay_tree_node n;
1116 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
1117 return (tree) n->value;
1120 static inline tree
1121 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
1123 splay_tree_node n = NULL;
1124 if (ctx->reduction_map)
1125 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
1126 return n ? (tree) n->value : NULL_TREE;
1129 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1130 the parallel context if DECL is to be shared. */
1132 static bool
1133 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1135 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1136 return true;
1138 /* We can only use copy-in/copy-out semantics for shared variables
1139 when we know the value is not accessible from an outer scope. */
1140 if (shared_ctx)
1142 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1144 /* ??? Trivially accessible from anywhere. But why would we even
1145 be passing an address in this case? Should we simply assert
1146 this to be false, or should we have a cleanup pass that removes
1147 these from the list of mappings? */
1148 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1149 return true;
1151 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1152 without analyzing the expression whether or not its location
1153 is accessible to anyone else. In the case of nested parallel
1154 regions it certainly may be. */
1155 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1156 return true;
1158 /* Do not use copy-in/copy-out for variables that have their
1159 address taken. */
1160 if (TREE_ADDRESSABLE (decl))
1161 return true;
1163 /* lower_send_shared_vars only uses copy-in, but not copy-out
1164 for these. */
1165 if (TREE_READONLY (decl)
1166 || ((TREE_CODE (decl) == RESULT_DECL
1167 || TREE_CODE (decl) == PARM_DECL)
1168 && DECL_BY_REFERENCE (decl)))
1169 return false;
1171 /* Disallow copy-in/out in nested parallel if
1172 decl is shared in outer parallel, otherwise
1173 each thread could store the shared variable
1174 in its own copy-in location, making the
1175 variable no longer really shared. */
1176 if (shared_ctx->is_nested)
1178 omp_context *up;
1180 for (up = shared_ctx->outer; up; up = up->outer)
1181 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1182 break;
1184 if (up)
1186 tree c;
1188 for (c = gimple_omp_taskreg_clauses (up->stmt);
1189 c; c = OMP_CLAUSE_CHAIN (c))
1190 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1191 && OMP_CLAUSE_DECL (c) == decl)
1192 break;
1194 if (c)
1195 goto maybe_mark_addressable_and_ret;
1199 /* For tasks avoid using copy-in/out. As tasks can be
1200 deferred or executed in different thread, when GOMP_task
1201 returns, the task hasn't necessarily terminated. */
1202 if (is_task_ctx (shared_ctx))
1204 tree outer;
1205 maybe_mark_addressable_and_ret:
1206 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1207 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
1209 /* Taking address of OUTER in lower_send_shared_vars
1210 might need regimplification of everything that uses the
1211 variable. */
1212 if (!task_shared_vars)
1213 task_shared_vars = BITMAP_ALLOC (NULL);
1214 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1215 TREE_ADDRESSABLE (outer) = 1;
1217 return true;
1221 return false;
1224 /* Construct a new automatic decl similar to VAR. */
1226 static tree
1227 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1229 tree copy = copy_var_decl (var, name, type);
1231 DECL_CONTEXT (copy) = current_function_decl;
1232 DECL_CHAIN (copy) = ctx->block_vars;
1233 /* If VAR is listed in task_shared_vars, it means it wasn't
1234 originally addressable and is just because task needs to take
1235 it's address. But we don't need to take address of privatizations
1236 from that var. */
1237 if (TREE_ADDRESSABLE (var)
1238 && task_shared_vars
1239 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1240 TREE_ADDRESSABLE (copy) = 0;
1241 ctx->block_vars = copy;
1243 return copy;
1246 static tree
1247 omp_copy_decl_1 (tree var, omp_context *ctx)
1249 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1252 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1253 as appropriate. */
1254 static tree
1255 omp_build_component_ref (tree obj, tree field)
1257 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1258 if (TREE_THIS_VOLATILE (field))
1259 TREE_THIS_VOLATILE (ret) |= 1;
1260 if (TREE_READONLY (field))
1261 TREE_READONLY (ret) |= 1;
1262 return ret;
1265 /* Build tree nodes to access the field for VAR on the receiver side. */
1267 static tree
1268 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1270 tree x, field = lookup_field (var, ctx);
1272 /* If the receiver record type was remapped in the child function,
1273 remap the field into the new record type. */
1274 x = maybe_lookup_field (field, ctx);
1275 if (x != NULL)
1276 field = x;
1278 x = build_simple_mem_ref (ctx->receiver_decl);
1279 TREE_THIS_NOTRAP (x) = 1;
1280 x = omp_build_component_ref (x, field);
1281 if (by_ref)
1282 x = build_simple_mem_ref (x);
1284 return x;
1287 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1288 of a parallel, this is a component reference; for workshare constructs
1289 this is some variable. */
1291 static tree
1292 build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1294 tree x;
1296 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1297 x = var;
1298 else if (is_variable_sized (var))
1300 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1301 x = build_outer_var_ref (x, ctx, lastprivate);
1302 x = build_simple_mem_ref (x);
1304 else if (is_taskreg_ctx (ctx))
1306 bool by_ref = use_pointer_for_field (var, NULL);
1307 x = build_receiver_ref (var, by_ref, ctx);
1309 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1310 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1312 /* #pragma omp simd isn't a worksharing construct, and can reference even
1313 private vars in its linear etc. clauses. */
1314 x = NULL_TREE;
1315 if (ctx->outer && is_taskreg_ctx (ctx))
1316 x = lookup_decl (var, ctx->outer);
1317 else if (ctx->outer)
1318 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1319 if (x == NULL_TREE)
1320 x = var;
1322 else if (lastprivate && is_taskloop_ctx (ctx))
1324 gcc_assert (ctx->outer);
1325 splay_tree_node n
1326 = splay_tree_lookup (ctx->outer->field_map,
1327 (splay_tree_key) &DECL_UID (var));
1328 if (n == NULL)
1330 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1331 x = var;
1332 else
1333 x = lookup_decl (var, ctx->outer);
1335 else
1337 tree field = (tree) n->value;
1338 /* If the receiver record type was remapped in the child function,
1339 remap the field into the new record type. */
1340 x = maybe_lookup_field (field, ctx->outer);
1341 if (x != NULL)
1342 field = x;
1344 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1345 x = omp_build_component_ref (x, field);
1346 if (use_pointer_for_field (var, ctx->outer))
1347 x = build_simple_mem_ref (x);
1350 else if (ctx->outer)
1351 x = lookup_decl (var, ctx->outer);
1352 else if (is_reference (var))
1353 /* This can happen with orphaned constructs. If var is reference, it is
1354 possible it is shared and as such valid. */
1355 x = var;
1356 else if (omp_member_access_dummy_var (var))
1357 x = var;
1358 else
1359 gcc_unreachable ();
1361 if (x == var)
1363 tree t = omp_member_access_dummy_var (var);
1364 if (t)
1366 x = DECL_VALUE_EXPR (var);
1367 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1368 if (o != t)
1369 x = unshare_and_remap (x, t, o);
1370 else
1371 x = unshare_expr (x);
1375 if (is_reference (var))
1376 x = build_simple_mem_ref (x);
1378 return x;
1381 /* Build tree nodes to access the field for VAR on the sender side. */
1383 static tree
1384 build_sender_ref (splay_tree_key key, omp_context *ctx)
1386 tree field = lookup_sfield (key, ctx);
1387 return omp_build_component_ref (ctx->sender_decl, field);
1390 static tree
1391 build_sender_ref (tree var, omp_context *ctx)
1393 return build_sender_ref ((splay_tree_key) var, ctx);
1396 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1398 static void
1399 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1401 tree field, type, sfield = NULL_TREE;
1402 splay_tree_key key = (splay_tree_key) var;
1404 if ((mask & 8) != 0)
1406 key = (splay_tree_key) &DECL_UID (var);
1407 gcc_checking_assert (key != (splay_tree_key) var);
1409 gcc_assert ((mask & 1) == 0
1410 || !splay_tree_lookup (ctx->field_map, key));
1411 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1412 || !splay_tree_lookup (ctx->sfield_map, key));
1413 gcc_assert ((mask & 3) == 3
1414 || !is_gimple_omp_oacc (ctx->stmt));
1416 type = TREE_TYPE (var);
1417 if (mask & 4)
1419 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1420 type = build_pointer_type (build_pointer_type (type));
1422 else if (by_ref)
1423 type = build_pointer_type (type);
1424 else if ((mask & 3) == 1 && is_reference (var))
1425 type = TREE_TYPE (type);
1427 field = build_decl (DECL_SOURCE_LOCATION (var),
1428 FIELD_DECL, DECL_NAME (var), type);
1430 /* Remember what variable this field was created for. This does have a
1431 side effect of making dwarf2out ignore this member, so for helpful
1432 debugging we clear it later in delete_omp_context. */
1433 DECL_ABSTRACT_ORIGIN (field) = var;
1434 if (type == TREE_TYPE (var))
1436 DECL_ALIGN (field) = DECL_ALIGN (var);
1437 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1438 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1440 else
1441 DECL_ALIGN (field) = TYPE_ALIGN (type);
1443 if ((mask & 3) == 3)
1445 insert_field_into_struct (ctx->record_type, field);
1446 if (ctx->srecord_type)
1448 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1449 FIELD_DECL, DECL_NAME (var), type);
1450 DECL_ABSTRACT_ORIGIN (sfield) = var;
1451 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1452 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1453 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1454 insert_field_into_struct (ctx->srecord_type, sfield);
1457 else
1459 if (ctx->srecord_type == NULL_TREE)
1461 tree t;
1463 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1464 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1465 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1467 sfield = build_decl (DECL_SOURCE_LOCATION (t),
1468 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1469 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1470 insert_field_into_struct (ctx->srecord_type, sfield);
1471 splay_tree_insert (ctx->sfield_map,
1472 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1473 (splay_tree_value) sfield);
1476 sfield = field;
1477 insert_field_into_struct ((mask & 1) ? ctx->record_type
1478 : ctx->srecord_type, field);
1481 if (mask & 1)
1482 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
1483 if ((mask & 2) && ctx->sfield_map)
1484 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1487 static tree
1488 install_var_local (tree var, omp_context *ctx)
1490 tree new_var = omp_copy_decl_1 (var, ctx);
1491 insert_decl_map (&ctx->cb, var, new_var);
1492 return new_var;
1495 /* Adjust the replacement for DECL in CTX for the new context. This means
1496 copying the DECL_VALUE_EXPR, and fixing up the type. */
1498 static void
1499 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1501 tree new_decl, size;
1503 new_decl = lookup_decl (decl, ctx);
1505 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1507 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1508 && DECL_HAS_VALUE_EXPR_P (decl))
1510 tree ve = DECL_VALUE_EXPR (decl);
1511 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1512 SET_DECL_VALUE_EXPR (new_decl, ve);
1513 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1516 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1518 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1519 if (size == error_mark_node)
1520 size = TYPE_SIZE (TREE_TYPE (new_decl));
1521 DECL_SIZE (new_decl) = size;
1523 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1524 if (size == error_mark_node)
1525 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1526 DECL_SIZE_UNIT (new_decl) = size;
1530 /* The callback for remap_decl. Search all containing contexts for a
1531 mapping of the variable; this avoids having to duplicate the splay
1532 tree ahead of time. We know a mapping doesn't already exist in the
1533 given context. Create new mappings to implement default semantics. */
1535 static tree
1536 omp_copy_decl (tree var, copy_body_data *cb)
1538 omp_context *ctx = (omp_context *) cb;
1539 tree new_var;
1541 if (TREE_CODE (var) == LABEL_DECL)
1543 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1544 DECL_CONTEXT (new_var) = current_function_decl;
1545 insert_decl_map (&ctx->cb, var, new_var);
1546 return new_var;
1549 while (!is_taskreg_ctx (ctx))
1551 ctx = ctx->outer;
1552 if (ctx == NULL)
1553 return var;
1554 new_var = maybe_lookup_decl (var, ctx);
1555 if (new_var)
1556 return new_var;
1559 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1560 return var;
1562 return error_mark_node;
1566 /* Debugging dumps for parallel regions. */
1567 void dump_omp_region (FILE *, struct omp_region *, int);
1568 void debug_omp_region (struct omp_region *);
1569 void debug_all_omp_regions (void);
1571 /* Dump the parallel region tree rooted at REGION. */
1573 void
1574 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1576 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1577 gimple_code_name[region->type]);
1579 if (region->inner)
1580 dump_omp_region (file, region->inner, indent + 4);
1582 if (region->cont)
1584 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1585 region->cont->index);
1588 if (region->exit)
1589 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1590 region->exit->index);
1591 else
1592 fprintf (file, "%*s[no exit marker]\n", indent, "");
1594 if (region->next)
1595 dump_omp_region (file, region->next, indent);
1598 DEBUG_FUNCTION void
1599 debug_omp_region (struct omp_region *region)
1601 dump_omp_region (stderr, region, 0);
1604 DEBUG_FUNCTION void
1605 debug_all_omp_regions (void)
1607 dump_omp_region (stderr, root_omp_region, 0);
1611 /* Create a new parallel region starting at STMT inside region PARENT. */
1613 static struct omp_region *
1614 new_omp_region (basic_block bb, enum gimple_code type,
1615 struct omp_region *parent)
1617 struct omp_region *region = XCNEW (struct omp_region);
1619 region->outer = parent;
1620 region->entry = bb;
1621 region->type = type;
1623 if (parent)
1625 /* This is a nested region. Add it to the list of inner
1626 regions in PARENT. */
1627 region->next = parent->inner;
1628 parent->inner = region;
1630 else
1632 /* This is a toplevel region. Add it to the list of toplevel
1633 regions in ROOT_OMP_REGION. */
1634 region->next = root_omp_region;
1635 root_omp_region = region;
1638 return region;
1641 /* Release the memory associated with the region tree rooted at REGION. */
1643 static void
1644 free_omp_region_1 (struct omp_region *region)
1646 struct omp_region *i, *n;
1648 for (i = region->inner; i ; i = n)
1650 n = i->next;
1651 free_omp_region_1 (i);
1654 free (region);
1657 /* Release the memory for the entire omp region tree. */
1659 void
1660 free_omp_regions (void)
1662 struct omp_region *r, *n;
1663 for (r = root_omp_region; r ; r = n)
1665 n = r->next;
1666 free_omp_region_1 (r);
1668 root_omp_region = NULL;
1672 /* Create a new context, with OUTER_CTX being the surrounding context. */
1674 static omp_context *
1675 new_omp_context (gimple *stmt, omp_context *outer_ctx)
1677 omp_context *ctx = XCNEW (omp_context);
1679 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1680 (splay_tree_value) ctx);
1681 ctx->stmt = stmt;
1683 if (outer_ctx)
1685 ctx->outer = outer_ctx;
1686 ctx->cb = outer_ctx->cb;
1687 ctx->cb.block = NULL;
1688 ctx->depth = outer_ctx->depth + 1;
1689 ctx->reduction_map = outer_ctx->reduction_map;
1691 else
1693 ctx->cb.src_fn = current_function_decl;
1694 ctx->cb.dst_fn = current_function_decl;
1695 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1696 gcc_checking_assert (ctx->cb.src_node);
1697 ctx->cb.dst_node = ctx->cb.src_node;
1698 ctx->cb.src_cfun = cfun;
1699 ctx->cb.copy_decl = omp_copy_decl;
1700 ctx->cb.eh_lp_nr = 0;
1701 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1702 ctx->depth = 1;
1705 ctx->cb.decl_map = new hash_map<tree, tree>;
1707 return ctx;
1710 static gimple_seq maybe_catch_exception (gimple_seq);
1712 /* Finalize task copyfn. */
1714 static void
1715 finalize_task_copyfn (gomp_task *task_stmt)
1717 struct function *child_cfun;
1718 tree child_fn;
1719 gimple_seq seq = NULL, new_seq;
1720 gbind *bind;
1722 child_fn = gimple_omp_task_copy_fn (task_stmt);
1723 if (child_fn == NULL_TREE)
1724 return;
1726 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1727 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1729 push_cfun (child_cfun);
1730 bind = gimplify_body (child_fn, false);
1731 gimple_seq_add_stmt (&seq, bind);
1732 new_seq = maybe_catch_exception (seq);
1733 if (new_seq != seq)
1735 bind = gimple_build_bind (NULL, new_seq, NULL);
1736 seq = NULL;
1737 gimple_seq_add_stmt (&seq, bind);
1739 gimple_set_body (child_fn, seq);
1740 pop_cfun ();
1742 /* Inform the callgraph about the new function. */
1743 cgraph_node *node = cgraph_node::get_create (child_fn);
1744 node->parallelized_function = 1;
1745 cgraph_node::add_new_function (child_fn, false);
1748 /* Destroy a omp_context data structures. Called through the splay tree
1749 value delete callback. */
1751 static void
1752 delete_omp_context (splay_tree_value value)
1754 omp_context *ctx = (omp_context *) value;
1756 delete ctx->cb.decl_map;
1758 if (ctx->field_map)
1759 splay_tree_delete (ctx->field_map);
1760 if (ctx->sfield_map)
1761 splay_tree_delete (ctx->sfield_map);
1762 /* Reduction map is copied to nested contexts, so only delete it in the
1763 owner. */
1764 if (ctx->reduction_map
1765 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1766 && is_gimple_omp_offloaded (ctx->stmt)
1767 && is_gimple_omp_oacc (ctx->stmt))
1768 splay_tree_delete (ctx->reduction_map);
1770 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1771 it produces corrupt debug information. */
1772 if (ctx->record_type)
1774 tree t;
1775 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1776 DECL_ABSTRACT_ORIGIN (t) = NULL;
1778 if (ctx->srecord_type)
1780 tree t;
1781 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1782 DECL_ABSTRACT_ORIGIN (t) = NULL;
1785 if (is_task_ctx (ctx))
1786 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1788 XDELETE (ctx);
1791 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1792 context. */
1794 static void
1795 fixup_child_record_type (omp_context *ctx)
1797 tree f, type = ctx->record_type;
1799 /* ??? It isn't sufficient to just call remap_type here, because
1800 variably_modified_type_p doesn't work the way we expect for
1801 record types. Testing each field for whether it needs remapping
1802 and creating a new record by hand works, however. */
1803 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1804 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1805 break;
1806 if (f)
1808 tree name, new_fields = NULL;
1810 type = lang_hooks.types.make_type (RECORD_TYPE);
1811 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1812 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1813 TYPE_DECL, name, type);
1814 TYPE_NAME (type) = name;
1816 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1818 tree new_f = copy_node (f);
1819 DECL_CONTEXT (new_f) = type;
1820 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1821 DECL_CHAIN (new_f) = new_fields;
1822 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1823 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1824 &ctx->cb, NULL);
1825 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1826 &ctx->cb, NULL);
1827 new_fields = new_f;
1829 /* Arrange to be able to look up the receiver field
1830 given the sender field. */
1831 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1832 (splay_tree_value) new_f);
1834 TYPE_FIELDS (type) = nreverse (new_fields);
1835 layout_type (type);
1838 /* In a target region we never modify any of the pointers in *.omp_data_i,
1839 so attempt to help the optimizers. */
1840 if (is_gimple_omp_offloaded (ctx->stmt))
1841 type = build_qualified_type (type, TYPE_QUAL_CONST);
1843 TREE_TYPE (ctx->receiver_decl)
1844 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1847 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1848 specified by CLAUSES. */
1850 static void
1851 scan_sharing_clauses (tree clauses, omp_context *ctx)
1853 tree c, decl;
1854 bool scan_array_reductions = false;
1856 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1858 bool by_ref;
1860 switch (OMP_CLAUSE_CODE (c))
1862 case OMP_CLAUSE_PRIVATE:
1863 decl = OMP_CLAUSE_DECL (c);
1864 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1865 goto do_private;
1866 else if (!is_variable_sized (decl))
1867 install_var_local (decl, ctx);
1868 break;
1870 case OMP_CLAUSE_SHARED:
1871 decl = OMP_CLAUSE_DECL (c);
1872 /* Ignore shared directives in teams construct. */
1873 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1875 /* Global variables don't need to be copied,
1876 the receiver side will use them directly. */
1877 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1878 if (is_global_var (odecl))
1879 break;
1880 insert_decl_map (&ctx->cb, decl, odecl);
1881 break;
1883 gcc_assert (is_taskreg_ctx (ctx));
1884 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1885 || !is_variable_sized (decl));
1886 /* Global variables don't need to be copied,
1887 the receiver side will use them directly. */
1888 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1889 break;
1890 by_ref = use_pointer_for_field (decl, ctx);
1891 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1892 break;
1893 if (! TREE_READONLY (decl)
1894 || TREE_ADDRESSABLE (decl)
1895 || by_ref
1896 || is_reference (decl))
1898 install_var_field (decl, by_ref, 3, ctx);
1899 install_var_local (decl, ctx);
1900 break;
1902 /* We don't need to copy const scalar vars back. */
1903 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1904 goto do_private;
1906 case OMP_CLAUSE_REDUCTION:
1907 decl = OMP_CLAUSE_DECL (c);
1908 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1909 && TREE_CODE (decl) == MEM_REF)
1911 tree t = TREE_OPERAND (decl, 0);
1912 if (TREE_CODE (t) == INDIRECT_REF
1913 || TREE_CODE (t) == ADDR_EXPR)
1914 t = TREE_OPERAND (t, 0);
1915 install_var_local (t, ctx);
1916 if (is_taskreg_ctx (ctx)
1917 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1918 && !is_variable_sized (t))
1920 by_ref = use_pointer_for_field (t, ctx);
1921 install_var_field (t, by_ref, 3, ctx);
1923 break;
1925 goto do_private;
1927 case OMP_CLAUSE_LASTPRIVATE:
1928 /* Let the corresponding firstprivate clause create
1929 the variable. */
1930 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1931 break;
1932 /* FALLTHRU */
1934 case OMP_CLAUSE_FIRSTPRIVATE:
1935 if (is_gimple_omp_oacc (ctx->stmt))
1937 sorry ("clause not supported yet");
1938 break;
1940 /* FALLTHRU */
1941 case OMP_CLAUSE_LINEAR:
1942 decl = OMP_CLAUSE_DECL (c);
1943 do_private:
1944 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1945 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1946 && is_gimple_omp_offloaded (ctx->stmt))
1948 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1949 install_var_field (decl, !is_reference (decl), 3, ctx);
1950 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1951 install_var_field (decl, true, 3, ctx);
1952 else
1953 install_var_field (decl, false, 3, ctx);
1955 if (is_variable_sized (decl))
1957 if (is_task_ctx (ctx))
1958 install_var_field (decl, false, 1, ctx);
1959 break;
1961 else if (is_taskreg_ctx (ctx))
1963 bool global
1964 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1965 by_ref = use_pointer_for_field (decl, NULL);
1967 if (is_task_ctx (ctx)
1968 && (global || by_ref || is_reference (decl)))
1970 install_var_field (decl, false, 1, ctx);
1971 if (!global)
1972 install_var_field (decl, by_ref, 2, ctx);
1974 else if (!global)
1975 install_var_field (decl, by_ref, 3, ctx);
1977 install_var_local (decl, ctx);
1978 if (is_gimple_omp_oacc (ctx->stmt)
1979 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1981 /* Create a decl for the reduction array. */
1982 tree var = OMP_CLAUSE_DECL (c);
1983 tree type = get_base_type (var);
1984 tree ptype = build_pointer_type (type);
1985 tree array = create_tmp_var (ptype,
1986 oacc_get_reduction_array_id (var));
1987 omp_context *octx = (ctx->field_map ? ctx : ctx->outer);
1988 install_var_field (array, true, 3, octx);
1989 install_var_local (array, octx);
1991 /* Insert it into the current context. */
1992 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1993 oacc_get_reduction_array_id (var),
1994 (splay_tree_value) array);
1995 splay_tree_insert (ctx->reduction_map,
1996 (splay_tree_key) array,
1997 (splay_tree_value) array);
1999 break;
2001 case OMP_CLAUSE_USE_DEVICE_PTR:
2002 decl = OMP_CLAUSE_DECL (c);
2003 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2004 install_var_field (decl, true, 3, ctx);
2005 else
2006 install_var_field (decl, false, 3, ctx);
2007 if (DECL_SIZE (decl)
2008 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2010 tree decl2 = DECL_VALUE_EXPR (decl);
2011 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2012 decl2 = TREE_OPERAND (decl2, 0);
2013 gcc_assert (DECL_P (decl2));
2014 install_var_local (decl2, ctx);
2016 install_var_local (decl, ctx);
2017 break;
2019 case OMP_CLAUSE_IS_DEVICE_PTR:
2020 decl = OMP_CLAUSE_DECL (c);
2021 goto do_private;
2023 case OMP_CLAUSE__LOOPTEMP_:
2024 gcc_assert (is_taskreg_ctx (ctx));
2025 decl = OMP_CLAUSE_DECL (c);
2026 install_var_field (decl, false, 3, ctx);
2027 install_var_local (decl, ctx);
2028 break;
2030 case OMP_CLAUSE_COPYPRIVATE:
2031 case OMP_CLAUSE_COPYIN:
2032 decl = OMP_CLAUSE_DECL (c);
2033 by_ref = use_pointer_for_field (decl, NULL);
2034 install_var_field (decl, by_ref, 3, ctx);
2035 break;
2037 case OMP_CLAUSE_DEFAULT:
2038 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
2039 break;
2041 case OMP_CLAUSE_FINAL:
2042 case OMP_CLAUSE_IF:
2043 case OMP_CLAUSE_NUM_THREADS:
2044 case OMP_CLAUSE_NUM_TEAMS:
2045 case OMP_CLAUSE_THREAD_LIMIT:
2046 case OMP_CLAUSE_DEVICE:
2047 case OMP_CLAUSE_SCHEDULE:
2048 case OMP_CLAUSE_DIST_SCHEDULE:
2049 case OMP_CLAUSE_DEPEND:
2050 case OMP_CLAUSE_PRIORITY:
2051 case OMP_CLAUSE_GRAINSIZE:
2052 case OMP_CLAUSE_NUM_TASKS:
2053 case OMP_CLAUSE__CILK_FOR_COUNT_:
2054 case OMP_CLAUSE_NUM_GANGS:
2055 case OMP_CLAUSE_NUM_WORKERS:
2056 case OMP_CLAUSE_VECTOR_LENGTH:
2057 if (ctx->outer)
2058 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
2059 break;
2061 case OMP_CLAUSE_TO:
2062 case OMP_CLAUSE_FROM:
2063 case OMP_CLAUSE_MAP:
2064 if (ctx->outer)
2065 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2066 decl = OMP_CLAUSE_DECL (c);
2067 /* Global variables with "omp declare target" attribute
2068 don't need to be copied, the receiver side will use them
2069 directly. */
2070 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2071 && DECL_P (decl)
2072 && (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2073 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2074 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2075 && varpool_node::get_create (decl)->offloadable)
2076 break;
2077 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2078 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
2080 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2081 not offloaded; there is nothing to map for those. */
2082 if (!is_gimple_omp_offloaded (ctx->stmt)
2083 && !POINTER_TYPE_P (TREE_TYPE (decl))
2084 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
2085 break;
2087 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2088 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2090 if (TREE_CODE (decl) == COMPONENT_REF
2091 || (TREE_CODE (decl) == INDIRECT_REF
2092 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2093 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2094 == REFERENCE_TYPE)))
2095 break;
2096 if (DECL_SIZE (decl)
2097 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2099 tree decl2 = DECL_VALUE_EXPR (decl);
2100 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2101 decl2 = TREE_OPERAND (decl2, 0);
2102 gcc_assert (DECL_P (decl2));
2103 install_var_local (decl2, ctx);
2105 install_var_local (decl, ctx);
2106 break;
2108 if (DECL_P (decl))
2110 if (DECL_SIZE (decl)
2111 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2113 tree decl2 = DECL_VALUE_EXPR (decl);
2114 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2115 decl2 = TREE_OPERAND (decl2, 0);
2116 gcc_assert (DECL_P (decl2));
2117 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2118 && OMP_CLAUSE_MAP_PRIVATE (c))
2119 install_var_field (decl2, true, 11, ctx);
2120 else
2121 install_var_field (decl2, true, 3, ctx);
2122 install_var_local (decl2, ctx);
2123 install_var_local (decl, ctx);
2125 else
2127 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2128 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2129 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2130 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2131 install_var_field (decl, true, 7, ctx);
2132 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2133 && OMP_CLAUSE_MAP_PRIVATE (c))
2134 install_var_field (decl, true, 11, ctx);
2135 else
2136 install_var_field (decl, true, 3, ctx);
2137 if (is_gimple_omp_offloaded (ctx->stmt))
2138 install_var_local (decl, ctx);
2141 else
2143 tree base = get_base_address (decl);
2144 tree nc = OMP_CLAUSE_CHAIN (c);
2145 if (DECL_P (base)
2146 && nc != NULL_TREE
2147 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2148 && OMP_CLAUSE_DECL (nc) == base
2149 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
2150 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2152 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2153 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2155 else
2157 if (ctx->outer)
2159 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2160 decl = OMP_CLAUSE_DECL (c);
2162 gcc_assert (!splay_tree_lookup (ctx->field_map,
2163 (splay_tree_key) decl));
2164 tree field
2165 = build_decl (OMP_CLAUSE_LOCATION (c),
2166 FIELD_DECL, NULL_TREE, ptr_type_node);
2167 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
2168 insert_field_into_struct (ctx->record_type, field);
2169 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2170 (splay_tree_value) field);
2173 break;
2175 case OMP_CLAUSE_NOWAIT:
2176 case OMP_CLAUSE_ORDERED:
2177 case OMP_CLAUSE_COLLAPSE:
2178 case OMP_CLAUSE_UNTIED:
2179 case OMP_CLAUSE_MERGEABLE:
2180 case OMP_CLAUSE_PROC_BIND:
2181 case OMP_CLAUSE_SAFELEN:
2182 case OMP_CLAUSE_SIMDLEN:
2183 case OMP_CLAUSE_THREADS:
2184 case OMP_CLAUSE_SIMD:
2185 case OMP_CLAUSE_NOGROUP:
2186 case OMP_CLAUSE_DEFAULTMAP:
2187 case OMP_CLAUSE_ASYNC:
2188 case OMP_CLAUSE_WAIT:
2189 case OMP_CLAUSE_GANG:
2190 case OMP_CLAUSE_WORKER:
2191 case OMP_CLAUSE_VECTOR:
2192 break;
2194 case OMP_CLAUSE_ALIGNED:
2195 decl = OMP_CLAUSE_DECL (c);
2196 if (is_global_var (decl)
2197 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2198 install_var_local (decl, ctx);
2199 break;
2201 case OMP_CLAUSE_DEVICE_RESIDENT:
2202 case OMP_CLAUSE_USE_DEVICE:
2203 case OMP_CLAUSE__CACHE_:
2204 case OMP_CLAUSE_INDEPENDENT:
2205 case OMP_CLAUSE_AUTO:
2206 case OMP_CLAUSE_SEQ:
2207 sorry ("Clause not supported yet");
2208 break;
2210 default:
2211 gcc_unreachable ();
2215 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2217 switch (OMP_CLAUSE_CODE (c))
2219 case OMP_CLAUSE_LASTPRIVATE:
2220 /* Let the corresponding firstprivate clause create
2221 the variable. */
2222 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2223 scan_array_reductions = true;
2224 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2225 break;
2226 /* FALLTHRU */
2228 case OMP_CLAUSE_FIRSTPRIVATE:
2229 if (is_gimple_omp_oacc (ctx->stmt))
2231 sorry ("clause not supported yet");
2232 break;
2234 /* FALLTHRU */
2235 case OMP_CLAUSE_PRIVATE:
2236 case OMP_CLAUSE_LINEAR:
2237 case OMP_CLAUSE_IS_DEVICE_PTR:
2238 decl = OMP_CLAUSE_DECL (c);
2239 if (is_variable_sized (decl))
2241 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2242 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2243 && is_gimple_omp_offloaded (ctx->stmt))
2245 tree decl2 = DECL_VALUE_EXPR (decl);
2246 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2247 decl2 = TREE_OPERAND (decl2, 0);
2248 gcc_assert (DECL_P (decl2));
2249 install_var_local (decl2, ctx);
2250 fixup_remapped_decl (decl2, ctx, false);
2252 install_var_local (decl, ctx);
2254 fixup_remapped_decl (decl, ctx,
2255 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2256 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2257 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2258 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2259 scan_array_reductions = true;
2260 break;
2262 case OMP_CLAUSE_REDUCTION:
2263 decl = OMP_CLAUSE_DECL (c);
2264 if (TREE_CODE (decl) != MEM_REF)
2266 if (is_variable_sized (decl))
2267 install_var_local (decl, ctx);
2268 fixup_remapped_decl (decl, ctx, false);
2270 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2271 scan_array_reductions = true;
2272 break;
2274 case OMP_CLAUSE_SHARED:
2275 /* Ignore shared directives in teams construct. */
2276 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2277 break;
2278 decl = OMP_CLAUSE_DECL (c);
2279 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2280 break;
2281 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2283 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2284 ctx->outer)))
2285 break;
2286 bool by_ref = use_pointer_for_field (decl, ctx);
2287 install_var_field (decl, by_ref, 11, ctx);
2288 break;
2290 fixup_remapped_decl (decl, ctx, false);
2291 break;
2293 case OMP_CLAUSE_MAP:
2294 if (!is_gimple_omp_offloaded (ctx->stmt))
2295 break;
2296 decl = OMP_CLAUSE_DECL (c);
2297 if (DECL_P (decl)
2298 && (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2299 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2300 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2301 && varpool_node::get_create (decl)->offloadable)
2302 break;
2303 if (DECL_P (decl))
2305 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2306 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2307 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2308 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2310 tree new_decl = lookup_decl (decl, ctx);
2311 TREE_TYPE (new_decl)
2312 = remap_type (TREE_TYPE (decl), &ctx->cb);
2314 else if (DECL_SIZE (decl)
2315 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2317 tree decl2 = DECL_VALUE_EXPR (decl);
2318 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2319 decl2 = TREE_OPERAND (decl2, 0);
2320 gcc_assert (DECL_P (decl2));
2321 fixup_remapped_decl (decl2, ctx, false);
2322 fixup_remapped_decl (decl, ctx, true);
2324 else
2325 fixup_remapped_decl (decl, ctx, false);
2327 break;
2329 case OMP_CLAUSE_COPYPRIVATE:
2330 case OMP_CLAUSE_COPYIN:
2331 case OMP_CLAUSE_DEFAULT:
2332 case OMP_CLAUSE_IF:
2333 case OMP_CLAUSE_NUM_THREADS:
2334 case OMP_CLAUSE_NUM_TEAMS:
2335 case OMP_CLAUSE_THREAD_LIMIT:
2336 case OMP_CLAUSE_DEVICE:
2337 case OMP_CLAUSE_SCHEDULE:
2338 case OMP_CLAUSE_DIST_SCHEDULE:
2339 case OMP_CLAUSE_NOWAIT:
2340 case OMP_CLAUSE_ORDERED:
2341 case OMP_CLAUSE_COLLAPSE:
2342 case OMP_CLAUSE_UNTIED:
2343 case OMP_CLAUSE_FINAL:
2344 case OMP_CLAUSE_MERGEABLE:
2345 case OMP_CLAUSE_PROC_BIND:
2346 case OMP_CLAUSE_SAFELEN:
2347 case OMP_CLAUSE_SIMDLEN:
2348 case OMP_CLAUSE_ALIGNED:
2349 case OMP_CLAUSE_DEPEND:
2350 case OMP_CLAUSE__LOOPTEMP_:
2351 case OMP_CLAUSE_TO:
2352 case OMP_CLAUSE_FROM:
2353 case OMP_CLAUSE_PRIORITY:
2354 case OMP_CLAUSE_GRAINSIZE:
2355 case OMP_CLAUSE_NUM_TASKS:
2356 case OMP_CLAUSE_THREADS:
2357 case OMP_CLAUSE_SIMD:
2358 case OMP_CLAUSE_NOGROUP:
2359 case OMP_CLAUSE_DEFAULTMAP:
2360 case OMP_CLAUSE_USE_DEVICE_PTR:
2361 case OMP_CLAUSE__CILK_FOR_COUNT_:
2362 case OMP_CLAUSE_ASYNC:
2363 case OMP_CLAUSE_WAIT:
2364 case OMP_CLAUSE_NUM_GANGS:
2365 case OMP_CLAUSE_NUM_WORKERS:
2366 case OMP_CLAUSE_VECTOR_LENGTH:
2367 case OMP_CLAUSE_GANG:
2368 case OMP_CLAUSE_WORKER:
2369 case OMP_CLAUSE_VECTOR:
2370 break;
2372 case OMP_CLAUSE_DEVICE_RESIDENT:
2373 case OMP_CLAUSE_USE_DEVICE:
2374 case OMP_CLAUSE__CACHE_:
2375 case OMP_CLAUSE_INDEPENDENT:
2376 case OMP_CLAUSE_AUTO:
2377 case OMP_CLAUSE_SEQ:
2378 sorry ("Clause not supported yet");
2379 break;
2381 default:
2382 gcc_unreachable ();
2386 gcc_checking_assert (!scan_array_reductions
2387 || !is_gimple_omp_oacc (ctx->stmt));
2388 if (scan_array_reductions)
2389 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2390 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2391 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2393 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2394 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2396 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2397 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2398 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2399 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2400 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2401 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2404 /* Create a new name for omp child function. Returns an identifier. If
2405 IS_CILK_FOR is true then the suffix for the child function is
2406 "_cilk_for_fn." */
2408 static tree
2409 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2411 if (is_cilk_for)
2412 return clone_function_name (current_function_decl, "_cilk_for_fn");
2413 return clone_function_name (current_function_decl,
2414 task_copy ? "_omp_cpyfn" : "_omp_fn");
2417 /* Returns the type of the induction variable for the child function for
2418 _Cilk_for and the types for _high and _low variables based on TYPE. */
2420 static tree
2421 cilk_for_check_loop_diff_type (tree type)
2423 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2425 if (TYPE_UNSIGNED (type))
2426 return uint32_type_node;
2427 else
2428 return integer_type_node;
2430 else
2432 if (TYPE_UNSIGNED (type))
2433 return uint64_type_node;
2434 else
2435 return long_long_integer_type_node;
2439 /* Build a decl for the omp child function. It'll not contain a body
2440 yet, just the bare decl. */
2442 static void
2443 create_omp_child_function (omp_context *ctx, bool task_copy)
2445 tree decl, type, name, t;
2447 tree cilk_for_count
2448 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2449 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2450 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2451 tree cilk_var_type = NULL_TREE;
2453 name = create_omp_child_function_name (task_copy,
2454 cilk_for_count != NULL_TREE);
2455 if (task_copy)
2456 type = build_function_type_list (void_type_node, ptr_type_node,
2457 ptr_type_node, NULL_TREE);
2458 else if (cilk_for_count)
2460 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2461 cilk_var_type = cilk_for_check_loop_diff_type (type);
2462 type = build_function_type_list (void_type_node, ptr_type_node,
2463 cilk_var_type, cilk_var_type, NULL_TREE);
2465 else
2466 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2468 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2470 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2471 || !task_copy);
2472 if (!task_copy)
2473 ctx->cb.dst_fn = decl;
2474 else
2475 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2477 TREE_STATIC (decl) = 1;
2478 TREE_USED (decl) = 1;
2479 DECL_ARTIFICIAL (decl) = 1;
2480 DECL_IGNORED_P (decl) = 0;
2481 TREE_PUBLIC (decl) = 0;
2482 DECL_UNINLINABLE (decl) = 1;
2483 DECL_EXTERNAL (decl) = 0;
2484 DECL_CONTEXT (decl) = NULL_TREE;
2485 DECL_INITIAL (decl) = make_node (BLOCK);
2486 if (cgraph_node::get (current_function_decl)->offloadable)
2487 cgraph_node::get_create (decl)->offloadable = 1;
2488 else
2490 omp_context *octx;
2491 for (octx = ctx; octx; octx = octx->outer)
2492 if (is_gimple_omp_offloaded (octx->stmt))
2494 cgraph_node::get_create (decl)->offloadable = 1;
2495 #ifdef ENABLE_OFFLOADING
2496 g->have_offload = true;
2497 #endif
2498 break;
2502 if (cgraph_node::get_create (decl)->offloadable
2503 && !lookup_attribute ("omp declare target",
2504 DECL_ATTRIBUTES (current_function_decl)))
2505 DECL_ATTRIBUTES (decl)
2506 = tree_cons (get_identifier ("omp target entrypoint"),
2507 NULL_TREE, DECL_ATTRIBUTES (decl));
2509 t = build_decl (DECL_SOURCE_LOCATION (decl),
2510 RESULT_DECL, NULL_TREE, void_type_node);
2511 DECL_ARTIFICIAL (t) = 1;
2512 DECL_IGNORED_P (t) = 1;
2513 DECL_CONTEXT (t) = decl;
2514 DECL_RESULT (decl) = t;
2516 /* _Cilk_for's child function requires two extra parameters called
2517 __low and __high that are set the by Cilk runtime when it calls this
2518 function. */
2519 if (cilk_for_count)
2521 t = build_decl (DECL_SOURCE_LOCATION (decl),
2522 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2523 DECL_ARTIFICIAL (t) = 1;
2524 DECL_NAMELESS (t) = 1;
2525 DECL_ARG_TYPE (t) = ptr_type_node;
2526 DECL_CONTEXT (t) = current_function_decl;
2527 TREE_USED (t) = 1;
2528 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2529 DECL_ARGUMENTS (decl) = t;
2531 t = build_decl (DECL_SOURCE_LOCATION (decl),
2532 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2533 DECL_ARTIFICIAL (t) = 1;
2534 DECL_NAMELESS (t) = 1;
2535 DECL_ARG_TYPE (t) = ptr_type_node;
2536 DECL_CONTEXT (t) = current_function_decl;
2537 TREE_USED (t) = 1;
2538 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2539 DECL_ARGUMENTS (decl) = t;
2542 tree data_name = get_identifier (".omp_data_i");
2543 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2544 ptr_type_node);
2545 DECL_ARTIFICIAL (t) = 1;
2546 DECL_NAMELESS (t) = 1;
2547 DECL_ARG_TYPE (t) = ptr_type_node;
2548 DECL_CONTEXT (t) = current_function_decl;
2549 TREE_USED (t) = 1;
2550 TREE_READONLY (t) = 1;
2551 if (cilk_for_count)
2552 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2553 DECL_ARGUMENTS (decl) = t;
2554 if (!task_copy)
2555 ctx->receiver_decl = t;
2556 else
2558 t = build_decl (DECL_SOURCE_LOCATION (decl),
2559 PARM_DECL, get_identifier (".omp_data_o"),
2560 ptr_type_node);
2561 DECL_ARTIFICIAL (t) = 1;
2562 DECL_NAMELESS (t) = 1;
2563 DECL_ARG_TYPE (t) = ptr_type_node;
2564 DECL_CONTEXT (t) = current_function_decl;
2565 TREE_USED (t) = 1;
2566 TREE_ADDRESSABLE (t) = 1;
2567 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2568 DECL_ARGUMENTS (decl) = t;
2571 /* Allocate memory for the function structure. The call to
2572 allocate_struct_function clobbers CFUN, so we need to restore
2573 it afterward. */
2574 push_struct_function (decl);
2575 cfun->function_end_locus = gimple_location (ctx->stmt);
2576 pop_cfun ();
2579 /* Callback for walk_gimple_seq. Check if combined parallel
2580 contains gimple_omp_for_combined_into_p OMP_FOR. */
2582 static tree
2583 find_combined_for (gimple_stmt_iterator *gsi_p,
2584 bool *handled_ops_p,
2585 struct walk_stmt_info *wi)
2587 gimple *stmt = gsi_stmt (*gsi_p);
2589 *handled_ops_p = true;
2590 switch (gimple_code (stmt))
2592 WALK_SUBSTMTS;
2594 case GIMPLE_OMP_FOR:
2595 if (gimple_omp_for_combined_into_p (stmt)
2596 && gimple_omp_for_kind (stmt)
2597 == *(const enum gf_mask *) (wi->info))
2599 wi->info = stmt;
2600 return integer_zero_node;
2602 break;
2603 default:
2604 break;
2606 return NULL;
2609 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2611 static void
2612 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2613 omp_context *outer_ctx)
2615 struct walk_stmt_info wi;
2617 memset (&wi, 0, sizeof (wi));
2618 wi.val_only = true;
2619 wi.info = (void *) &msk;
2620 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2621 if (wi.info != (void *) &msk)
2623 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2624 struct omp_for_data fd;
2625 extract_omp_for_data (for_stmt, &fd, NULL);
2626 /* We need two temporaries with fd.loop.v type (istart/iend)
2627 and then (fd.collapse - 1) temporaries with the same
2628 type for count2 ... countN-1 vars if not constant. */
2629 size_t count = 2, i;
2630 tree type = fd.iter_type;
2631 if (fd.collapse > 1
2632 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2634 count += fd.collapse - 1;
2635 /* For taskloop, if there are lastprivate clauses on the inner
2636 GIMPLE_OMP_FOR, add one more temporaries for the total number
2637 of iterations (product of count1 ... countN-1). */
2638 if (msk == GF_OMP_FOR_KIND_TASKLOOP
2639 && find_omp_clause (gimple_omp_for_clauses (for_stmt),
2640 OMP_CLAUSE_LASTPRIVATE))
2641 count++;
2643 for (i = 0; i < count; i++)
2645 tree temp = create_tmp_var (type);
2646 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2647 insert_decl_map (&outer_ctx->cb, temp, temp);
2648 OMP_CLAUSE_DECL (c) = temp;
2649 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2650 gimple_omp_taskreg_set_clauses (stmt, c);
2655 /* Scan an OpenMP parallel directive. */
2657 static void
2658 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2660 omp_context *ctx;
2661 tree name;
2662 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2664 /* Ignore parallel directives with empty bodies, unless there
2665 are copyin clauses. */
2666 if (optimize > 0
2667 && empty_body_p (gimple_omp_body (stmt))
2668 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2669 OMP_CLAUSE_COPYIN) == NULL)
2671 gsi_replace (gsi, gimple_build_nop (), false);
2672 return;
2675 if (gimple_omp_parallel_combined_p (stmt))
2676 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2678 ctx = new_omp_context (stmt, outer_ctx);
2679 taskreg_contexts.safe_push (ctx);
2680 if (taskreg_nesting_level > 1)
2681 ctx->is_nested = true;
2682 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2683 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2684 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2685 name = create_tmp_var_name (".omp_data_s");
2686 name = build_decl (gimple_location (stmt),
2687 TYPE_DECL, name, ctx->record_type);
2688 DECL_ARTIFICIAL (name) = 1;
2689 DECL_NAMELESS (name) = 1;
2690 TYPE_NAME (ctx->record_type) = name;
2691 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2692 create_omp_child_function (ctx, false);
2693 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2695 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2696 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2698 if (TYPE_FIELDS (ctx->record_type) == NULL)
2699 ctx->record_type = ctx->receiver_decl = NULL;
2702 /* Scan an OpenMP task directive. */
2704 static void
2705 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2707 omp_context *ctx;
2708 tree name, t;
2709 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2711 /* Ignore task directives with empty bodies. */
2712 if (optimize > 0
2713 && empty_body_p (gimple_omp_body (stmt)))
2715 gsi_replace (gsi, gimple_build_nop (), false);
2716 return;
2719 if (gimple_omp_task_taskloop_p (stmt))
2720 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2722 ctx = new_omp_context (stmt, outer_ctx);
2723 taskreg_contexts.safe_push (ctx);
2724 if (taskreg_nesting_level > 1)
2725 ctx->is_nested = true;
2726 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2727 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2728 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2729 name = create_tmp_var_name (".omp_data_s");
2730 name = build_decl (gimple_location (stmt),
2731 TYPE_DECL, name, ctx->record_type);
2732 DECL_ARTIFICIAL (name) = 1;
2733 DECL_NAMELESS (name) = 1;
2734 TYPE_NAME (ctx->record_type) = name;
2735 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2736 create_omp_child_function (ctx, false);
2737 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2739 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2741 if (ctx->srecord_type)
2743 name = create_tmp_var_name (".omp_data_a");
2744 name = build_decl (gimple_location (stmt),
2745 TYPE_DECL, name, ctx->srecord_type);
2746 DECL_ARTIFICIAL (name) = 1;
2747 DECL_NAMELESS (name) = 1;
2748 TYPE_NAME (ctx->srecord_type) = name;
2749 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2750 create_omp_child_function (ctx, true);
2753 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2755 if (TYPE_FIELDS (ctx->record_type) == NULL)
2757 ctx->record_type = ctx->receiver_decl = NULL;
2758 t = build_int_cst (long_integer_type_node, 0);
2759 gimple_omp_task_set_arg_size (stmt, t);
2760 t = build_int_cst (long_integer_type_node, 1);
2761 gimple_omp_task_set_arg_align (stmt, t);
2766 /* If any decls have been made addressable during scan_omp,
2767 adjust their fields if needed, and layout record types
2768 of parallel/task constructs. */
2770 static void
2771 finish_taskreg_scan (omp_context *ctx)
2773 if (ctx->record_type == NULL_TREE)
2774 return;
2776 /* If any task_shared_vars were needed, verify all
2777 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2778 statements if use_pointer_for_field hasn't changed
2779 because of that. If it did, update field types now. */
2780 if (task_shared_vars)
2782 tree c;
2784 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2785 c; c = OMP_CLAUSE_CHAIN (c))
2786 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2787 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2789 tree decl = OMP_CLAUSE_DECL (c);
2791 /* Global variables don't need to be copied,
2792 the receiver side will use them directly. */
2793 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2794 continue;
2795 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2796 || !use_pointer_for_field (decl, ctx))
2797 continue;
2798 tree field = lookup_field (decl, ctx);
2799 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2800 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2801 continue;
2802 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2803 TREE_THIS_VOLATILE (field) = 0;
2804 DECL_USER_ALIGN (field) = 0;
2805 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2806 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2807 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2808 if (ctx->srecord_type)
2810 tree sfield = lookup_sfield (decl, ctx);
2811 TREE_TYPE (sfield) = TREE_TYPE (field);
2812 TREE_THIS_VOLATILE (sfield) = 0;
2813 DECL_USER_ALIGN (sfield) = 0;
2814 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2815 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2816 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2821 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2823 layout_type (ctx->record_type);
2824 fixup_child_record_type (ctx);
2826 else
2828 location_t loc = gimple_location (ctx->stmt);
2829 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2830 /* Move VLA fields to the end. */
2831 p = &TYPE_FIELDS (ctx->record_type);
2832 while (*p)
2833 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2834 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2836 *q = *p;
2837 *p = TREE_CHAIN (*p);
2838 TREE_CHAIN (*q) = NULL_TREE;
2839 q = &TREE_CHAIN (*q);
2841 else
2842 p = &DECL_CHAIN (*p);
2843 *p = vla_fields;
2844 if (gimple_omp_task_taskloop_p (ctx->stmt))
2846 /* Move fields corresponding to first and second _looptemp_
2847 clause first. There are filled by GOMP_taskloop
2848 and thus need to be in specific positions. */
2849 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2850 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2851 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2852 OMP_CLAUSE__LOOPTEMP_);
2853 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2854 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2855 p = &TYPE_FIELDS (ctx->record_type);
2856 while (*p)
2857 if (*p == f1 || *p == f2)
2858 *p = DECL_CHAIN (*p);
2859 else
2860 p = &DECL_CHAIN (*p);
2861 DECL_CHAIN (f1) = f2;
2862 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2863 TYPE_FIELDS (ctx->record_type) = f1;
2864 if (ctx->srecord_type)
2866 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2867 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2868 p = &TYPE_FIELDS (ctx->srecord_type);
2869 while (*p)
2870 if (*p == f1 || *p == f2)
2871 *p = DECL_CHAIN (*p);
2872 else
2873 p = &DECL_CHAIN (*p);
2874 DECL_CHAIN (f1) = f2;
2875 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2876 TYPE_FIELDS (ctx->srecord_type) = f1;
2879 layout_type (ctx->record_type);
2880 fixup_child_record_type (ctx);
2881 if (ctx->srecord_type)
2882 layout_type (ctx->srecord_type);
2883 tree t = fold_convert_loc (loc, long_integer_type_node,
2884 TYPE_SIZE_UNIT (ctx->record_type));
2885 gimple_omp_task_set_arg_size (ctx->stmt, t);
2886 t = build_int_cst (long_integer_type_node,
2887 TYPE_ALIGN_UNIT (ctx->record_type));
2888 gimple_omp_task_set_arg_align (ctx->stmt, t);
2893 static omp_context *
2894 enclosing_target_ctx (omp_context *ctx)
2896 while (ctx != NULL
2897 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2898 ctx = ctx->outer;
2899 gcc_assert (ctx != NULL);
2900 return ctx;
2903 static bool
2904 oacc_loop_or_target_p (gimple *stmt)
2906 enum gimple_code outer_type = gimple_code (stmt);
2907 return ((outer_type == GIMPLE_OMP_TARGET
2908 && ((gimple_omp_target_kind (stmt)
2909 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2910 || (gimple_omp_target_kind (stmt)
2911 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2912 || (outer_type == GIMPLE_OMP_FOR
2913 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2916 /* Scan a GIMPLE_OMP_FOR. */
2918 static void
2919 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2921 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
2922 omp_context *ctx;
2923 size_t i;
2924 tree clauses = gimple_omp_for_clauses (stmt);
2926 if (outer_ctx)
2927 outer_type = gimple_code (outer_ctx->stmt);
2929 ctx = new_omp_context (stmt, outer_ctx);
2931 if (is_gimple_omp_oacc (stmt))
2933 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2934 ctx->gwv_this = outer_ctx->gwv_this;
2935 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2937 int val;
2938 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2939 val = MASK_GANG;
2940 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2941 val = MASK_WORKER;
2942 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2943 val = MASK_VECTOR;
2944 else
2945 continue;
2946 ctx->gwv_this |= val;
2947 if (!outer_ctx)
2949 /* Skip; not nested inside a region. */
2950 continue;
2952 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2954 /* Skip; not nested inside an OpenACC region. */
2955 continue;
2957 if (outer_type == GIMPLE_OMP_FOR)
2958 outer_ctx->gwv_below |= val;
2959 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2961 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2962 if (gimple_omp_target_kind (enclosing->stmt)
2963 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2964 error_at (gimple_location (stmt),
2965 "no arguments allowed to gang, worker and vector clauses inside parallel");
2970 scan_sharing_clauses (clauses, ctx);
2972 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2973 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2975 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2976 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2977 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2978 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2980 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2982 if (is_gimple_omp_oacc (stmt))
2984 if (ctx->gwv_this & ctx->gwv_below)
2985 error_at (gimple_location (stmt),
2986 "gang, worker and vector may occur only once in a loop nest");
2987 else if (ctx->gwv_below != 0
2988 && ctx->gwv_this > ctx->gwv_below)
2989 error_at (gimple_location (stmt),
2990 "gang, worker and vector must occur in this order in a loop nest");
2991 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2992 outer_ctx->gwv_below |= ctx->gwv_below;
2996 /* Scan an OpenMP sections directive. */
2998 static void
2999 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3001 omp_context *ctx;
3003 ctx = new_omp_context (stmt, outer_ctx);
3004 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3005 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3008 /* Scan an OpenMP single directive. */
3010 static void
3011 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3013 omp_context *ctx;
3014 tree name;
3016 ctx = new_omp_context (stmt, outer_ctx);
3017 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3018 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3019 name = create_tmp_var_name (".omp_copy_s");
3020 name = build_decl (gimple_location (stmt),
3021 TYPE_DECL, name, ctx->record_type);
3022 TYPE_NAME (ctx->record_type) = name;
3024 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3025 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3027 if (TYPE_FIELDS (ctx->record_type) == NULL)
3028 ctx->record_type = NULL;
3029 else
3030 layout_type (ctx->record_type);
3033 /* Scan a GIMPLE_OMP_TARGET. */
3035 static void
3036 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3038 omp_context *ctx;
3039 tree name;
3040 bool offloaded = is_gimple_omp_offloaded (stmt);
3041 tree clauses = gimple_omp_target_clauses (stmt);
3043 ctx = new_omp_context (stmt, outer_ctx);
3044 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3045 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3046 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3047 name = create_tmp_var_name (".omp_data_t");
3048 name = build_decl (gimple_location (stmt),
3049 TYPE_DECL, name, ctx->record_type);
3050 DECL_ARTIFICIAL (name) = 1;
3051 DECL_NAMELESS (name) = 1;
3052 TYPE_NAME (ctx->record_type) = name;
3053 TYPE_ARTIFICIAL (ctx->record_type) = 1;
3054 if (offloaded)
3056 if (is_gimple_omp_oacc (stmt))
3057 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
3058 0, 0);
3060 create_omp_child_function (ctx, false);
3061 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3064 if (is_gimple_omp_oacc (stmt))
3066 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3068 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
3069 ctx->gwv_this |= MASK_GANG;
3070 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
3071 ctx->gwv_this |= MASK_WORKER;
3072 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
3073 ctx->gwv_this |= MASK_VECTOR;
3077 scan_sharing_clauses (clauses, ctx);
3078 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3080 if (TYPE_FIELDS (ctx->record_type) == NULL)
3081 ctx->record_type = ctx->receiver_decl = NULL;
3082 else
3084 TYPE_FIELDS (ctx->record_type)
3085 = nreverse (TYPE_FIELDS (ctx->record_type));
3086 #ifdef ENABLE_CHECKING
3087 tree field;
3088 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3089 for (field = TYPE_FIELDS (ctx->record_type);
3090 field;
3091 field = DECL_CHAIN (field))
3092 gcc_assert (DECL_ALIGN (field) == align);
3093 #endif
3094 layout_type (ctx->record_type);
3095 if (offloaded)
3096 fixup_child_record_type (ctx);
3100 /* Scan an OpenMP teams directive. */
3102 static void
3103 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3105 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3106 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3107 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3110 /* Check nesting restrictions. */
3111 static bool
3112 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3114 tree c;
3116 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3117 inside an OpenACC CTX. */
3118 if (!(is_gimple_omp (stmt)
3119 && is_gimple_omp_oacc (stmt)))
3121 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
3122 if (is_gimple_omp (ctx_->stmt)
3123 && is_gimple_omp_oacc (ctx_->stmt))
3125 error_at (gimple_location (stmt),
3126 "non-OpenACC construct inside of OpenACC region");
3127 return false;
3131 if (ctx != NULL)
3133 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3134 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3136 c = NULL_TREE;
3137 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3139 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3140 if (c && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD)
3141 return true;
3143 error_at (gimple_location (stmt),
3144 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3145 " may not be nested inside simd region");
3146 return false;
3148 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3150 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3151 || (gimple_omp_for_kind (stmt)
3152 != GF_OMP_FOR_KIND_DISTRIBUTE))
3153 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3155 error_at (gimple_location (stmt),
3156 "only distribute or parallel constructs are allowed to "
3157 "be closely nested inside teams construct");
3158 return false;
3162 switch (gimple_code (stmt))
3164 case GIMPLE_OMP_FOR:
3165 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3166 return true;
3167 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3169 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3171 error_at (gimple_location (stmt),
3172 "distribute construct must be closely nested inside "
3173 "teams construct");
3174 return false;
3176 return true;
3178 /* We split taskloop into task and nested taskloop in it. */
3179 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3180 return true;
3181 /* FALLTHRU */
3182 case GIMPLE_CALL:
3183 if (is_gimple_call (stmt)
3184 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3185 == BUILT_IN_GOMP_CANCEL
3186 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3187 == BUILT_IN_GOMP_CANCELLATION_POINT))
3189 const char *bad = NULL;
3190 const char *kind = NULL;
3191 if (ctx == NULL)
3193 error_at (gimple_location (stmt), "orphaned %qs construct",
3194 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3195 == BUILT_IN_GOMP_CANCEL
3196 ? "#pragma omp cancel"
3197 : "#pragma omp cancellation point");
3198 return false;
3200 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3201 ? tree_to_shwi (gimple_call_arg (stmt, 0))
3202 : 0)
3204 case 1:
3205 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3206 bad = "#pragma omp parallel";
3207 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3208 == BUILT_IN_GOMP_CANCEL
3209 && !integer_zerop (gimple_call_arg (stmt, 1)))
3210 ctx->cancellable = true;
3211 kind = "parallel";
3212 break;
3213 case 2:
3214 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3215 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3216 bad = "#pragma omp for";
3217 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3218 == BUILT_IN_GOMP_CANCEL
3219 && !integer_zerop (gimple_call_arg (stmt, 1)))
3221 ctx->cancellable = true;
3222 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3223 OMP_CLAUSE_NOWAIT))
3224 warning_at (gimple_location (stmt), 0,
3225 "%<#pragma omp cancel for%> inside "
3226 "%<nowait%> for construct");
3227 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3228 OMP_CLAUSE_ORDERED))
3229 warning_at (gimple_location (stmt), 0,
3230 "%<#pragma omp cancel for%> inside "
3231 "%<ordered%> for construct");
3233 kind = "for";
3234 break;
3235 case 4:
3236 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3237 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3238 bad = "#pragma omp sections";
3239 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3240 == BUILT_IN_GOMP_CANCEL
3241 && !integer_zerop (gimple_call_arg (stmt, 1)))
3243 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3245 ctx->cancellable = true;
3246 if (find_omp_clause (gimple_omp_sections_clauses
3247 (ctx->stmt),
3248 OMP_CLAUSE_NOWAIT))
3249 warning_at (gimple_location (stmt), 0,
3250 "%<#pragma omp cancel sections%> inside "
3251 "%<nowait%> sections construct");
3253 else
3255 gcc_assert (ctx->outer
3256 && gimple_code (ctx->outer->stmt)
3257 == GIMPLE_OMP_SECTIONS);
3258 ctx->outer->cancellable = true;
3259 if (find_omp_clause (gimple_omp_sections_clauses
3260 (ctx->outer->stmt),
3261 OMP_CLAUSE_NOWAIT))
3262 warning_at (gimple_location (stmt), 0,
3263 "%<#pragma omp cancel sections%> inside "
3264 "%<nowait%> sections construct");
3267 kind = "sections";
3268 break;
3269 case 8:
3270 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3271 bad = "#pragma omp task";
3272 else
3273 ctx->cancellable = true;
3274 kind = "taskgroup";
3275 break;
3276 default:
3277 error_at (gimple_location (stmt), "invalid arguments");
3278 return false;
3280 if (bad)
3282 error_at (gimple_location (stmt),
3283 "%<%s %s%> construct not closely nested inside of %qs",
3284 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3285 == BUILT_IN_GOMP_CANCEL
3286 ? "#pragma omp cancel"
3287 : "#pragma omp cancellation point", kind, bad);
3288 return false;
3291 /* FALLTHRU */
3292 case GIMPLE_OMP_SECTIONS:
3293 case GIMPLE_OMP_SINGLE:
3294 for (; ctx != NULL; ctx = ctx->outer)
3295 switch (gimple_code (ctx->stmt))
3297 case GIMPLE_OMP_FOR:
3298 case GIMPLE_OMP_SECTIONS:
3299 case GIMPLE_OMP_SINGLE:
3300 case GIMPLE_OMP_ORDERED:
3301 case GIMPLE_OMP_MASTER:
3302 case GIMPLE_OMP_TASK:
3303 case GIMPLE_OMP_CRITICAL:
3304 if (is_gimple_call (stmt))
3306 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3307 != BUILT_IN_GOMP_BARRIER)
3308 return true;
3309 error_at (gimple_location (stmt),
3310 "barrier region may not be closely nested inside "
3311 "of work-sharing, critical, ordered, master or "
3312 "explicit task region");
3313 return false;
3315 error_at (gimple_location (stmt),
3316 "work-sharing region may not be closely nested inside "
3317 "of work-sharing, critical, ordered, master or explicit "
3318 "task region");
3319 return false;
3320 case GIMPLE_OMP_PARALLEL:
3321 return true;
3322 default:
3323 break;
3325 break;
3326 case GIMPLE_OMP_MASTER:
3327 for (; ctx != NULL; ctx = ctx->outer)
3328 switch (gimple_code (ctx->stmt))
3330 case GIMPLE_OMP_FOR:
3331 case GIMPLE_OMP_SECTIONS:
3332 case GIMPLE_OMP_SINGLE:
3333 case GIMPLE_OMP_TASK:
3334 error_at (gimple_location (stmt),
3335 "master region may not be closely nested inside "
3336 "of work-sharing or explicit task region");
3337 return false;
3338 case GIMPLE_OMP_PARALLEL:
3339 return true;
3340 default:
3341 break;
3343 break;
3344 case GIMPLE_OMP_TASK:
3345 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3346 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3347 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3348 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3350 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3351 error_at (OMP_CLAUSE_LOCATION (c),
3352 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3353 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3354 return false;
3356 break;
3357 case GIMPLE_OMP_ORDERED:
3358 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3359 c; c = OMP_CLAUSE_CHAIN (c))
3361 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3363 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3364 || (ctx == NULL
3365 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD));
3366 continue;
3368 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3369 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3370 || kind == OMP_CLAUSE_DEPEND_SINK)
3372 tree oclause;
3373 /* Look for containing ordered(N) loop. */
3374 if (ctx == NULL
3375 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3376 || (oclause
3377 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3378 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3380 error_at (OMP_CLAUSE_LOCATION (c),
3381 "%<depend%> clause must be closely nested "
3382 "inside an ordered loop");
3383 return false;
3385 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3387 error_at (OMP_CLAUSE_LOCATION (c),
3388 "%<depend%> clause must be closely nested "
3389 "inside a loop with %<ordered%> clause with "
3390 "a parameter");
3391 return false;
3394 else
3396 error_at (OMP_CLAUSE_LOCATION (c),
3397 "invalid depend kind in omp ordered depend");
3398 return false;
3401 for (; ctx != NULL; ctx = ctx->outer)
3402 switch (gimple_code (ctx->stmt))
3404 case GIMPLE_OMP_CRITICAL:
3405 case GIMPLE_OMP_TASK:
3406 error_at (gimple_location (stmt),
3407 "ordered region may not be closely nested inside "
3408 "of critical or explicit task region");
3409 return false;
3410 case GIMPLE_OMP_FOR:
3411 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3412 OMP_CLAUSE_ORDERED) == NULL)
3414 error_at (gimple_location (stmt),
3415 "ordered region must be closely nested inside "
3416 "a loop region with an ordered clause");
3417 return false;
3419 return true;
3420 case GIMPLE_OMP_PARALLEL:
3421 error_at (gimple_location (stmt),
3422 "ordered region must be closely nested inside "
3423 "a loop region with an ordered clause");
3424 return false;
3425 default:
3426 break;
3428 break;
3429 case GIMPLE_OMP_CRITICAL:
3431 tree this_stmt_name
3432 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3433 for (; ctx != NULL; ctx = ctx->outer)
3434 if (gomp_critical *other_crit
3435 = dyn_cast <gomp_critical *> (ctx->stmt))
3436 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3438 error_at (gimple_location (stmt),
3439 "critical region may not be nested inside a critical "
3440 "region with the same name");
3441 return false;
3444 break;
3445 case GIMPLE_OMP_TEAMS:
3446 if (ctx == NULL
3447 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3448 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3450 error_at (gimple_location (stmt),
3451 "teams construct not closely nested inside of target "
3452 "region");
3453 return false;
3455 break;
3456 case GIMPLE_OMP_TARGET:
3457 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3458 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3459 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3460 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3462 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3463 error_at (OMP_CLAUSE_LOCATION (c),
3464 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3465 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3466 return false;
3468 for (; ctx != NULL; ctx = ctx->outer)
3470 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3472 if (is_gimple_omp (stmt)
3473 && is_gimple_omp_oacc (stmt)
3474 && is_gimple_omp (ctx->stmt))
3476 error_at (gimple_location (stmt),
3477 "OpenACC construct inside of non-OpenACC region");
3478 return false;
3480 continue;
3483 const char *stmt_name, *ctx_stmt_name;
3484 switch (gimple_omp_target_kind (stmt))
3486 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3487 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3488 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3489 case GF_OMP_TARGET_KIND_ENTER_DATA:
3490 stmt_name = "target enter data"; break;
3491 case GF_OMP_TARGET_KIND_EXIT_DATA:
3492 stmt_name = "target exit data"; break;
3493 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3494 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3495 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3496 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3497 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3498 stmt_name = "enter/exit data"; break;
3499 default: gcc_unreachable ();
3501 switch (gimple_omp_target_kind (ctx->stmt))
3503 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3504 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3505 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3506 ctx_stmt_name = "parallel"; break;
3507 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3508 ctx_stmt_name = "kernels"; break;
3509 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3510 default: gcc_unreachable ();
3513 /* OpenACC/OpenMP mismatch? */
3514 if (is_gimple_omp_oacc (stmt)
3515 != is_gimple_omp_oacc (ctx->stmt))
3517 error_at (gimple_location (stmt),
3518 "%s %s construct inside of %s %s region",
3519 (is_gimple_omp_oacc (stmt)
3520 ? "OpenACC" : "OpenMP"), stmt_name,
3521 (is_gimple_omp_oacc (ctx->stmt)
3522 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3523 return false;
3525 if (is_gimple_omp_offloaded (ctx->stmt))
3527 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3528 if (is_gimple_omp_oacc (ctx->stmt))
3530 error_at (gimple_location (stmt),
3531 "%s construct inside of %s region",
3532 stmt_name, ctx_stmt_name);
3533 return false;
3535 else
3537 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3538 warning_at (gimple_location (stmt), 0,
3539 "%s construct inside of %s region",
3540 stmt_name, ctx_stmt_name);
3544 break;
3545 default:
3546 break;
3548 return true;
3552 /* Helper function scan_omp.
3554 Callback for walk_tree or operators in walk_gimple_stmt used to
3555 scan for OMP directives in TP. */
3557 static tree
3558 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3560 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3561 omp_context *ctx = (omp_context *) wi->info;
3562 tree t = *tp;
3564 switch (TREE_CODE (t))
3566 case VAR_DECL:
3567 case PARM_DECL:
3568 case LABEL_DECL:
3569 case RESULT_DECL:
3570 if (ctx)
3571 *tp = remap_decl (t, &ctx->cb);
3572 break;
3574 default:
3575 if (ctx && TYPE_P (t))
3576 *tp = remap_type (t, &ctx->cb);
3577 else if (!DECL_P (t))
3579 *walk_subtrees = 1;
3580 if (ctx)
3582 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3583 if (tem != TREE_TYPE (t))
3585 if (TREE_CODE (t) == INTEGER_CST)
3586 *tp = wide_int_to_tree (tem, t);
3587 else
3588 TREE_TYPE (t) = tem;
3592 break;
3595 return NULL_TREE;
3598 /* Return true if FNDECL is a setjmp or a longjmp. */
3600 static bool
3601 setjmp_or_longjmp_p (const_tree fndecl)
3603 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3604 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3605 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3606 return true;
3608 tree declname = DECL_NAME (fndecl);
3609 if (!declname)
3610 return false;
3611 const char *name = IDENTIFIER_POINTER (declname);
3612 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3616 /* Helper function for scan_omp.
3618 Callback for walk_gimple_stmt used to scan for OMP directives in
3619 the current statement in GSI. */
3621 static tree
3622 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3623 struct walk_stmt_info *wi)
3625 gimple *stmt = gsi_stmt (*gsi);
3626 omp_context *ctx = (omp_context *) wi->info;
3628 if (gimple_has_location (stmt))
3629 input_location = gimple_location (stmt);
3631 /* Check the nesting restrictions. */
3632 bool remove = false;
3633 if (is_gimple_omp (stmt))
3634 remove = !check_omp_nesting_restrictions (stmt, ctx);
3635 else if (is_gimple_call (stmt))
3637 tree fndecl = gimple_call_fndecl (stmt);
3638 if (fndecl)
3640 if (setjmp_or_longjmp_p (fndecl)
3641 && ctx
3642 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3643 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3645 remove = true;
3646 error_at (gimple_location (stmt),
3647 "setjmp/longjmp inside simd construct");
3649 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3650 switch (DECL_FUNCTION_CODE (fndecl))
3652 case BUILT_IN_GOMP_BARRIER:
3653 case BUILT_IN_GOMP_CANCEL:
3654 case BUILT_IN_GOMP_CANCELLATION_POINT:
3655 case BUILT_IN_GOMP_TASKYIELD:
3656 case BUILT_IN_GOMP_TASKWAIT:
3657 case BUILT_IN_GOMP_TASKGROUP_START:
3658 case BUILT_IN_GOMP_TASKGROUP_END:
3659 remove = !check_omp_nesting_restrictions (stmt, ctx);
3660 break;
3661 default:
3662 break;
3666 if (remove)
3668 stmt = gimple_build_nop ();
3669 gsi_replace (gsi, stmt, false);
3672 *handled_ops_p = true;
3674 switch (gimple_code (stmt))
3676 case GIMPLE_OMP_PARALLEL:
3677 taskreg_nesting_level++;
3678 scan_omp_parallel (gsi, ctx);
3679 taskreg_nesting_level--;
3680 break;
3682 case GIMPLE_OMP_TASK:
3683 taskreg_nesting_level++;
3684 scan_omp_task (gsi, ctx);
3685 taskreg_nesting_level--;
3686 break;
3688 case GIMPLE_OMP_FOR:
3689 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3690 break;
3692 case GIMPLE_OMP_SECTIONS:
3693 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3694 break;
3696 case GIMPLE_OMP_SINGLE:
3697 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3698 break;
3700 case GIMPLE_OMP_SECTION:
3701 case GIMPLE_OMP_MASTER:
3702 case GIMPLE_OMP_TASKGROUP:
3703 case GIMPLE_OMP_ORDERED:
3704 case GIMPLE_OMP_CRITICAL:
3705 ctx = new_omp_context (stmt, ctx);
3706 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3707 break;
3709 case GIMPLE_OMP_TARGET:
3710 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3711 break;
3713 case GIMPLE_OMP_TEAMS:
3714 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3715 break;
3717 case GIMPLE_BIND:
3719 tree var;
3721 *handled_ops_p = false;
3722 if (ctx)
3723 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3724 var ;
3725 var = DECL_CHAIN (var))
3726 insert_decl_map (&ctx->cb, var, var);
3728 break;
3729 default:
3730 *handled_ops_p = false;
3731 break;
3734 return NULL_TREE;
3738 /* Scan all the statements starting at the current statement. CTX
3739 contains context information about the OMP directives and
3740 clauses found during the scan. */
3742 static void
3743 scan_omp (gimple_seq *body_p, omp_context *ctx)
3745 location_t saved_location;
3746 struct walk_stmt_info wi;
3748 memset (&wi, 0, sizeof (wi));
3749 wi.info = ctx;
3750 wi.want_locations = true;
3752 saved_location = input_location;
3753 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3754 input_location = saved_location;
3757 /* Re-gimplification and code generation routines. */
3759 /* Build a call to GOMP_barrier. */
3761 static gimple *
3762 build_omp_barrier (tree lhs)
3764 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3765 : BUILT_IN_GOMP_BARRIER);
3766 gcall *g = gimple_build_call (fndecl, 0);
3767 if (lhs)
3768 gimple_call_set_lhs (g, lhs);
3769 return g;
3772 /* If a context was created for STMT when it was scanned, return it. */
3774 static omp_context *
3775 maybe_lookup_ctx (gimple *stmt)
3777 splay_tree_node n;
3778 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3779 return n ? (omp_context *) n->value : NULL;
3783 /* Find the mapping for DECL in CTX or the immediately enclosing
3784 context that has a mapping for DECL.
3786 If CTX is a nested parallel directive, we may have to use the decl
3787 mappings created in CTX's parent context. Suppose that we have the
3788 following parallel nesting (variable UIDs showed for clarity):
3790 iD.1562 = 0;
3791 #omp parallel shared(iD.1562) -> outer parallel
3792 iD.1562 = iD.1562 + 1;
3794 #omp parallel shared (iD.1562) -> inner parallel
3795 iD.1562 = iD.1562 - 1;
3797 Each parallel structure will create a distinct .omp_data_s structure
3798 for copying iD.1562 in/out of the directive:
3800 outer parallel .omp_data_s.1.i -> iD.1562
3801 inner parallel .omp_data_s.2.i -> iD.1562
3803 A shared variable mapping will produce a copy-out operation before
3804 the parallel directive and a copy-in operation after it. So, in
3805 this case we would have:
3807 iD.1562 = 0;
3808 .omp_data_o.1.i = iD.1562;
3809 #omp parallel shared(iD.1562) -> outer parallel
3810 .omp_data_i.1 = &.omp_data_o.1
3811 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3813 .omp_data_o.2.i = iD.1562; -> **
3814 #omp parallel shared(iD.1562) -> inner parallel
3815 .omp_data_i.2 = &.omp_data_o.2
3816 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3819 ** This is a problem. The symbol iD.1562 cannot be referenced
3820 inside the body of the outer parallel region. But since we are
3821 emitting this copy operation while expanding the inner parallel
3822 directive, we need to access the CTX structure of the outer
3823 parallel directive to get the correct mapping:
3825 .omp_data_o.2.i = .omp_data_i.1->i
3827 Since there may be other workshare or parallel directives enclosing
3828 the parallel directive, it may be necessary to walk up the context
3829 parent chain. This is not a problem in general because nested
3830 parallelism happens only rarely. */
3832 static tree
3833 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3835 tree t;
3836 omp_context *up;
3838 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3839 t = maybe_lookup_decl (decl, up);
3841 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3843 return t ? t : decl;
3847 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3848 in outer contexts. */
3850 static tree
3851 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3853 tree t = NULL;
3854 omp_context *up;
3856 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3857 t = maybe_lookup_decl (decl, up);
3859 return t ? t : decl;
3863 /* Construct the initialization value for reduction operation OP. */
3865 tree
3866 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
3868 switch (op)
3870 case PLUS_EXPR:
3871 case MINUS_EXPR:
3872 case BIT_IOR_EXPR:
3873 case BIT_XOR_EXPR:
3874 case TRUTH_OR_EXPR:
3875 case TRUTH_ORIF_EXPR:
3876 case TRUTH_XOR_EXPR:
3877 case NE_EXPR:
3878 return build_zero_cst (type);
3880 case MULT_EXPR:
3881 case TRUTH_AND_EXPR:
3882 case TRUTH_ANDIF_EXPR:
3883 case EQ_EXPR:
3884 return fold_convert_loc (loc, type, integer_one_node);
3886 case BIT_AND_EXPR:
3887 return fold_convert_loc (loc, type, integer_minus_one_node);
3889 case MAX_EXPR:
3890 if (SCALAR_FLOAT_TYPE_P (type))
3892 REAL_VALUE_TYPE max, min;
3893 if (HONOR_INFINITIES (type))
3895 real_inf (&max);
3896 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3898 else
3899 real_maxval (&min, 1, TYPE_MODE (type));
3900 return build_real (type, min);
3902 else if (POINTER_TYPE_P (type))
3904 wide_int min
3905 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3906 return wide_int_to_tree (type, min);
3908 else
3910 gcc_assert (INTEGRAL_TYPE_P (type));
3911 return TYPE_MIN_VALUE (type);
3914 case MIN_EXPR:
3915 if (SCALAR_FLOAT_TYPE_P (type))
3917 REAL_VALUE_TYPE max;
3918 if (HONOR_INFINITIES (type))
3919 real_inf (&max);
3920 else
3921 real_maxval (&max, 0, TYPE_MODE (type));
3922 return build_real (type, max);
3924 else if (POINTER_TYPE_P (type))
3926 wide_int max
3927 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3928 return wide_int_to_tree (type, max);
3930 else
3932 gcc_assert (INTEGRAL_TYPE_P (type));
3933 return TYPE_MAX_VALUE (type);
3936 default:
3937 gcc_unreachable ();
3941 /* Construct the initialization value for reduction CLAUSE. */
3943 tree
3944 omp_reduction_init (tree clause, tree type)
3946 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
3947 OMP_CLAUSE_REDUCTION_CODE (clause), type);
3950 /* Return alignment to be assumed for var in CLAUSE, which should be
3951 OMP_CLAUSE_ALIGNED. */
3953 static tree
3954 omp_clause_aligned_alignment (tree clause)
3956 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3957 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3959 /* Otherwise return implementation defined alignment. */
3960 unsigned int al = 1;
3961 machine_mode mode, vmode;
3962 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3963 if (vs)
3964 vs = 1 << floor_log2 (vs);
3965 static enum mode_class classes[]
3966 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3967 for (int i = 0; i < 4; i += 2)
3968 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3969 mode != VOIDmode;
3970 mode = GET_MODE_WIDER_MODE (mode))
3972 vmode = targetm.vectorize.preferred_simd_mode (mode);
3973 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3974 continue;
3975 while (vs
3976 && GET_MODE_SIZE (vmode) < vs
3977 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3978 vmode = GET_MODE_2XWIDER_MODE (vmode);
3980 tree type = lang_hooks.types.type_for_mode (mode, 1);
3981 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3982 continue;
3983 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3984 / GET_MODE_SIZE (mode));
3985 if (TYPE_MODE (type) != vmode)
3986 continue;
3987 if (TYPE_ALIGN_UNIT (type) > al)
3988 al = TYPE_ALIGN_UNIT (type);
3990 return build_int_cst (integer_type_node, al);
3993 /* Return maximum possible vectorization factor for the target. */
3995 static int
3996 omp_max_vf (void)
3998 if (!optimize
3999 || optimize_debug
4000 || !flag_tree_loop_optimize
4001 || (!flag_tree_loop_vectorize
4002 && (global_options_set.x_flag_tree_loop_vectorize
4003 || global_options_set.x_flag_tree_vectorize)))
4004 return 1;
4006 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4007 if (vs)
4009 vs = 1 << floor_log2 (vs);
4010 return vs;
4012 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
4013 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4014 return GET_MODE_NUNITS (vqimode);
4015 return 1;
4018 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4019 privatization. */
4021 static bool
4022 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4023 tree &idx, tree &lane, tree &ivar, tree &lvar)
4025 if (max_vf == 0)
4027 max_vf = omp_max_vf ();
4028 if (max_vf > 1)
4030 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4031 OMP_CLAUSE_SAFELEN);
4032 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4033 max_vf = 1;
4034 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4035 max_vf) == -1)
4036 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4038 if (max_vf > 1)
4040 idx = create_tmp_var (unsigned_type_node);
4041 lane = create_tmp_var (unsigned_type_node);
4044 if (max_vf == 1)
4045 return false;
4047 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4048 tree avar = create_tmp_var_raw (atype);
4049 if (TREE_ADDRESSABLE (new_var))
4050 TREE_ADDRESSABLE (avar) = 1;
4051 DECL_ATTRIBUTES (avar)
4052 = tree_cons (get_identifier ("omp simd array"), NULL,
4053 DECL_ATTRIBUTES (avar));
4054 gimple_add_tmp_var (avar);
4055 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4056 NULL_TREE, NULL_TREE);
4057 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4058 NULL_TREE, NULL_TREE);
4059 if (DECL_P (new_var))
4061 SET_DECL_VALUE_EXPR (new_var, lvar);
4062 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4064 return true;
4067 /* Helper function of lower_rec_input_clauses. For a reference
4068 in simd reduction, add an underlying variable it will reference. */
4070 static void
4071 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4073 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4074 if (TREE_CONSTANT (z))
4076 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4077 get_name (new_vard));
4078 gimple_add_tmp_var (z);
4079 TREE_ADDRESSABLE (z) = 1;
4080 z = build_fold_addr_expr_loc (loc, z);
4081 gimplify_assign (new_vard, z, ilist);
4085 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4086 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4087 private variables. Initialization statements go in ILIST, while calls
4088 to destructors go in DLIST. */
4090 static void
4091 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4092 omp_context *ctx, struct omp_for_data *fd)
4094 tree c, dtor, copyin_seq, x, ptr;
4095 bool copyin_by_ref = false;
4096 bool lastprivate_firstprivate = false;
4097 bool reduction_omp_orig_ref = false;
4098 int pass;
4099 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4100 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4101 int max_vf = 0;
4102 tree lane = NULL_TREE, idx = NULL_TREE;
4103 tree ivar = NULL_TREE, lvar = NULL_TREE;
4104 gimple_seq llist[2] = { NULL, NULL };
4106 copyin_seq = NULL;
4108 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4109 with data sharing clauses referencing variable sized vars. That
4110 is unnecessarily hard to support and very unlikely to result in
4111 vectorized code anyway. */
4112 if (is_simd)
4113 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4114 switch (OMP_CLAUSE_CODE (c))
4116 case OMP_CLAUSE_LINEAR:
4117 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4118 max_vf = 1;
4119 /* FALLTHRU */
4120 case OMP_CLAUSE_PRIVATE:
4121 case OMP_CLAUSE_FIRSTPRIVATE:
4122 case OMP_CLAUSE_LASTPRIVATE:
4123 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4124 max_vf = 1;
4125 break;
4126 case OMP_CLAUSE_REDUCTION:
4127 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4128 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4129 max_vf = 1;
4130 break;
4131 default:
4132 continue;
4135 /* Do all the fixed sized types in the first pass, and the variable sized
4136 types in the second pass. This makes sure that the scalar arguments to
4137 the variable sized types are processed before we use them in the
4138 variable sized operations. */
4139 for (pass = 0; pass < 2; ++pass)
4141 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4143 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4144 tree var, new_var;
4145 bool by_ref;
4146 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4148 switch (c_kind)
4150 case OMP_CLAUSE_PRIVATE:
4151 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4152 continue;
4153 break;
4154 case OMP_CLAUSE_SHARED:
4155 /* Ignore shared directives in teams construct. */
4156 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4157 continue;
4158 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4160 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4161 || is_global_var (OMP_CLAUSE_DECL (c)));
4162 continue;
4164 case OMP_CLAUSE_FIRSTPRIVATE:
4165 case OMP_CLAUSE_COPYIN:
4166 break;
4167 case OMP_CLAUSE_LINEAR:
4168 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4169 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4170 lastprivate_firstprivate = true;
4171 break;
4172 case OMP_CLAUSE_REDUCTION:
4173 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4174 reduction_omp_orig_ref = true;
4175 break;
4176 case OMP_CLAUSE__LOOPTEMP_:
4177 /* Handle _looptemp_ clauses only on parallel/task. */
4178 if (fd)
4179 continue;
4180 break;
4181 case OMP_CLAUSE_LASTPRIVATE:
4182 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4184 lastprivate_firstprivate = true;
4185 if (pass != 0 || is_taskloop_ctx (ctx))
4186 continue;
4188 /* Even without corresponding firstprivate, if
4189 decl is Fortran allocatable, it needs outer var
4190 reference. */
4191 else if (pass == 0
4192 && lang_hooks.decls.omp_private_outer_ref
4193 (OMP_CLAUSE_DECL (c)))
4194 lastprivate_firstprivate = true;
4195 break;
4196 case OMP_CLAUSE_ALIGNED:
4197 if (pass == 0)
4198 continue;
4199 var = OMP_CLAUSE_DECL (c);
4200 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4201 && !is_global_var (var))
4203 new_var = maybe_lookup_decl (var, ctx);
4204 if (new_var == NULL_TREE)
4205 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4206 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4207 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4208 omp_clause_aligned_alignment (c));
4209 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4210 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4211 gimplify_and_add (x, ilist);
4213 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4214 && is_global_var (var))
4216 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4217 new_var = lookup_decl (var, ctx);
4218 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4219 t = build_fold_addr_expr_loc (clause_loc, t);
4220 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4221 t = build_call_expr_loc (clause_loc, t2, 2, t,
4222 omp_clause_aligned_alignment (c));
4223 t = fold_convert_loc (clause_loc, ptype, t);
4224 x = create_tmp_var (ptype);
4225 t = build2 (MODIFY_EXPR, ptype, x, t);
4226 gimplify_and_add (t, ilist);
4227 t = build_simple_mem_ref_loc (clause_loc, x);
4228 SET_DECL_VALUE_EXPR (new_var, t);
4229 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4231 continue;
4232 default:
4233 continue;
4236 new_var = var = OMP_CLAUSE_DECL (c);
4237 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4239 var = TREE_OPERAND (var, 0);
4240 if (TREE_CODE (var) == INDIRECT_REF
4241 || TREE_CODE (var) == ADDR_EXPR)
4242 var = TREE_OPERAND (var, 0);
4243 if (is_variable_sized (var))
4245 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4246 var = DECL_VALUE_EXPR (var);
4247 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4248 var = TREE_OPERAND (var, 0);
4249 gcc_assert (DECL_P (var));
4251 new_var = var;
4253 if (c_kind != OMP_CLAUSE_COPYIN)
4254 new_var = lookup_decl (var, ctx);
4256 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4258 if (pass != 0)
4259 continue;
4261 /* C/C++ array section reductions. */
4262 else if (c_kind == OMP_CLAUSE_REDUCTION
4263 && var != OMP_CLAUSE_DECL (c))
4265 if (pass == 0)
4266 continue;
4268 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4269 if (TREE_CODE (orig_var) == INDIRECT_REF
4270 || TREE_CODE (orig_var) == ADDR_EXPR)
4271 orig_var = TREE_OPERAND (orig_var, 0);
4272 tree d = OMP_CLAUSE_DECL (c);
4273 tree type = TREE_TYPE (d);
4274 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4275 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4276 const char *name = get_name (orig_var);
4277 if (TREE_CONSTANT (v))
4279 x = create_tmp_var_raw (type, name);
4280 gimple_add_tmp_var (x);
4281 TREE_ADDRESSABLE (x) = 1;
4282 x = build_fold_addr_expr_loc (clause_loc, x);
4284 else
4286 tree atmp
4287 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4288 tree t = maybe_lookup_decl (v, ctx);
4289 if (t)
4290 v = t;
4291 else
4292 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4293 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4294 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4295 TREE_TYPE (v), v,
4296 build_int_cst (TREE_TYPE (v), 1));
4297 t = fold_build2_loc (clause_loc, MULT_EXPR,
4298 TREE_TYPE (v), t,
4299 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4300 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4301 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4304 tree ptype = build_pointer_type (TREE_TYPE (type));
4305 x = fold_convert_loc (clause_loc, ptype, x);
4306 tree y = create_tmp_var (ptype, name);
4307 gimplify_assign (y, x, ilist);
4308 x = y;
4309 if (TREE_CODE (TREE_OPERAND (d, 0)) == ADDR_EXPR)
4311 if (orig_var != var)
4313 gcc_assert (is_variable_sized (orig_var));
4314 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4316 gimplify_assign (new_var, x, ilist);
4317 tree new_orig_var = lookup_decl (orig_var, ctx);
4318 tree t = build_fold_indirect_ref (new_var);
4319 DECL_IGNORED_P (new_var) = 0;
4320 TREE_THIS_NOTRAP (t);
4321 SET_DECL_VALUE_EXPR (new_orig_var, t);
4322 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4324 else
4326 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4327 build_int_cst (ptype, 0));
4328 SET_DECL_VALUE_EXPR (new_var, x);
4329 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4332 else
4334 gcc_assert (orig_var == var);
4335 if (TREE_CODE (TREE_OPERAND (d, 0)) == INDIRECT_REF)
4337 x = create_tmp_var (ptype, name);
4338 TREE_ADDRESSABLE (x) = 1;
4339 gimplify_assign (x, y, ilist);
4340 x = build_fold_addr_expr_loc (clause_loc, x);
4342 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4343 gimplify_assign (new_var, x, ilist);
4345 tree y1 = create_tmp_var (ptype, NULL);
4346 gimplify_assign (y1, y, ilist);
4347 tree i2 = NULL_TREE, y2 = NULL_TREE;
4348 tree body2 = NULL_TREE, end2 = NULL_TREE;
4349 tree y3 = NULL_TREE, y4 = NULL_TREE;
4350 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4352 y2 = create_tmp_var (ptype, NULL);
4353 gimplify_assign (y2, y, ilist);
4354 tree ref = build_outer_var_ref (var, ctx);
4355 /* For ref build_outer_var_ref already performs this. */
4356 if (TREE_CODE (TREE_OPERAND (d, 0)) == INDIRECT_REF)
4357 gcc_assert (is_reference (var));
4358 else if (TREE_CODE (TREE_OPERAND (d, 0)) == ADDR_EXPR)
4359 ref = build_fold_addr_expr (ref);
4360 else if (is_reference (var))
4361 ref = build_fold_addr_expr (ref);
4362 ref = fold_convert_loc (clause_loc, ptype, ref);
4363 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4364 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4366 y3 = create_tmp_var (ptype, NULL);
4367 gimplify_assign (y3, unshare_expr (ref), ilist);
4369 if (is_simd)
4371 y4 = create_tmp_var (ptype, NULL);
4372 gimplify_assign (y4, ref, dlist);
4375 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4376 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4377 tree body = create_artificial_label (UNKNOWN_LOCATION);
4378 tree end = create_artificial_label (UNKNOWN_LOCATION);
4379 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4380 if (y2)
4382 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4383 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4384 body2 = create_artificial_label (UNKNOWN_LOCATION);
4385 end2 = create_artificial_label (UNKNOWN_LOCATION);
4386 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4388 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4390 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4391 tree decl_placeholder
4392 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4393 SET_DECL_VALUE_EXPR (decl_placeholder,
4394 build_simple_mem_ref (y1));
4395 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4396 SET_DECL_VALUE_EXPR (placeholder,
4397 y3 ? build_simple_mem_ref (y3)
4398 : error_mark_node);
4399 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4400 x = lang_hooks.decls.omp_clause_default_ctor
4401 (c, build_simple_mem_ref (y1),
4402 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4403 if (x)
4404 gimplify_and_add (x, ilist);
4405 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4407 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4408 lower_omp (&tseq, ctx);
4409 gimple_seq_add_seq (ilist, tseq);
4411 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4412 if (is_simd)
4414 SET_DECL_VALUE_EXPR (decl_placeholder,
4415 build_simple_mem_ref (y2));
4416 SET_DECL_VALUE_EXPR (placeholder,
4417 build_simple_mem_ref (y4));
4418 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4419 lower_omp (&tseq, ctx);
4420 gimple_seq_add_seq (dlist, tseq);
4421 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4423 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4424 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4425 x = lang_hooks.decls.omp_clause_dtor
4426 (c, build_simple_mem_ref (y2));
4427 if (x)
4429 gimple_seq tseq = NULL;
4430 dtor = x;
4431 gimplify_stmt (&dtor, &tseq);
4432 gimple_seq_add_seq (dlist, tseq);
4435 else
4437 x = omp_reduction_init (c, TREE_TYPE (type));
4438 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4440 /* reduction(-:var) sums up the partial results, so it
4441 acts identically to reduction(+:var). */
4442 if (code == MINUS_EXPR)
4443 code = PLUS_EXPR;
4445 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4446 if (is_simd)
4448 x = build2 (code, TREE_TYPE (type),
4449 build_simple_mem_ref (y4),
4450 build_simple_mem_ref (y2));
4451 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4454 gimple *g
4455 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4456 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4457 gimple_seq_add_stmt (ilist, g);
4458 if (y3)
4460 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4461 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4462 gimple_seq_add_stmt (ilist, g);
4464 g = gimple_build_assign (i, PLUS_EXPR, i,
4465 build_int_cst (TREE_TYPE (i), 1));
4466 gimple_seq_add_stmt (ilist, g);
4467 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4468 gimple_seq_add_stmt (ilist, g);
4469 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4470 if (y2)
4472 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4473 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4474 gimple_seq_add_stmt (dlist, g);
4475 if (y4)
4477 g = gimple_build_assign
4478 (y4, POINTER_PLUS_EXPR, y4,
4479 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4480 gimple_seq_add_stmt (dlist, g);
4482 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4483 build_int_cst (TREE_TYPE (i2), 1));
4484 gimple_seq_add_stmt (dlist, g);
4485 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4486 gimple_seq_add_stmt (dlist, g);
4487 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4489 continue;
4491 else if (is_variable_sized (var))
4493 /* For variable sized types, we need to allocate the
4494 actual storage here. Call alloca and store the
4495 result in the pointer decl that we created elsewhere. */
4496 if (pass == 0)
4497 continue;
4499 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4501 gcall *stmt;
4502 tree tmp, atmp;
4504 ptr = DECL_VALUE_EXPR (new_var);
4505 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4506 ptr = TREE_OPERAND (ptr, 0);
4507 gcc_assert (DECL_P (ptr));
4508 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4510 /* void *tmp = __builtin_alloca */
4511 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4512 stmt = gimple_build_call (atmp, 2, x,
4513 size_int (DECL_ALIGN (var)));
4514 tmp = create_tmp_var_raw (ptr_type_node);
4515 gimple_add_tmp_var (tmp);
4516 gimple_call_set_lhs (stmt, tmp);
4518 gimple_seq_add_stmt (ilist, stmt);
4520 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4521 gimplify_assign (ptr, x, ilist);
4524 else if (is_reference (var))
4526 /* For references that are being privatized for Fortran,
4527 allocate new backing storage for the new pointer
4528 variable. This allows us to avoid changing all the
4529 code that expects a pointer to something that expects
4530 a direct variable. */
4531 if (pass == 0)
4532 continue;
4534 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4535 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4537 x = build_receiver_ref (var, false, ctx);
4538 x = build_fold_addr_expr_loc (clause_loc, x);
4540 else if (TREE_CONSTANT (x))
4542 /* For reduction in SIMD loop, defer adding the
4543 initialization of the reference, because if we decide
4544 to use SIMD array for it, the initilization could cause
4545 expansion ICE. */
4546 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4547 x = NULL_TREE;
4548 else
4550 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4551 get_name (var));
4552 gimple_add_tmp_var (x);
4553 TREE_ADDRESSABLE (x) = 1;
4554 x = build_fold_addr_expr_loc (clause_loc, x);
4557 else
4559 tree atmp
4560 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4561 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4562 tree al = size_int (TYPE_ALIGN (rtype));
4563 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4566 if (x)
4568 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4569 gimplify_assign (new_var, x, ilist);
4572 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4574 else if (c_kind == OMP_CLAUSE_REDUCTION
4575 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4577 if (pass == 0)
4578 continue;
4580 else if (pass != 0)
4581 continue;
4583 switch (OMP_CLAUSE_CODE (c))
4585 case OMP_CLAUSE_SHARED:
4586 /* Ignore shared directives in teams construct. */
4587 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4588 continue;
4589 /* Shared global vars are just accessed directly. */
4590 if (is_global_var (new_var))
4591 break;
4592 /* For taskloop firstprivate/lastprivate, represented
4593 as firstprivate and shared clause on the task, new_var
4594 is the firstprivate var. */
4595 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4596 break;
4597 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4598 needs to be delayed until after fixup_child_record_type so
4599 that we get the correct type during the dereference. */
4600 by_ref = use_pointer_for_field (var, ctx);
4601 x = build_receiver_ref (var, by_ref, ctx);
4602 SET_DECL_VALUE_EXPR (new_var, x);
4603 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4605 /* ??? If VAR is not passed by reference, and the variable
4606 hasn't been initialized yet, then we'll get a warning for
4607 the store into the omp_data_s structure. Ideally, we'd be
4608 able to notice this and not store anything at all, but
4609 we're generating code too early. Suppress the warning. */
4610 if (!by_ref)
4611 TREE_NO_WARNING (var) = 1;
4612 break;
4614 case OMP_CLAUSE_LASTPRIVATE:
4615 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4616 break;
4617 /* FALLTHRU */
4619 case OMP_CLAUSE_PRIVATE:
4620 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4621 x = build_outer_var_ref (var, ctx);
4622 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4624 if (is_task_ctx (ctx))
4625 x = build_receiver_ref (var, false, ctx);
4626 else
4627 x = build_outer_var_ref (var, ctx);
4629 else
4630 x = NULL;
4631 do_private:
4632 tree nx;
4633 nx = lang_hooks.decls.omp_clause_default_ctor
4634 (c, unshare_expr (new_var), x);
4635 if (is_simd)
4637 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4638 if ((TREE_ADDRESSABLE (new_var) || nx || y
4639 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4640 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4641 idx, lane, ivar, lvar))
4643 if (nx)
4644 x = lang_hooks.decls.omp_clause_default_ctor
4645 (c, unshare_expr (ivar), x);
4646 if (nx && x)
4647 gimplify_and_add (x, &llist[0]);
4648 if (y)
4650 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4651 if (y)
4653 gimple_seq tseq = NULL;
4655 dtor = y;
4656 gimplify_stmt (&dtor, &tseq);
4657 gimple_seq_add_seq (&llist[1], tseq);
4660 break;
4663 if (nx)
4664 gimplify_and_add (nx, ilist);
4665 /* FALLTHRU */
4667 do_dtor:
4668 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4669 if (x)
4671 gimple_seq tseq = NULL;
4673 dtor = x;
4674 gimplify_stmt (&dtor, &tseq);
4675 gimple_seq_add_seq (dlist, tseq);
4677 break;
4679 case OMP_CLAUSE_LINEAR:
4680 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4681 goto do_firstprivate;
4682 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4683 x = NULL;
4684 else
4685 x = build_outer_var_ref (var, ctx);
4686 goto do_private;
4688 case OMP_CLAUSE_FIRSTPRIVATE:
4689 if (is_task_ctx (ctx))
4691 if (is_reference (var) || is_variable_sized (var))
4692 goto do_dtor;
4693 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
4694 ctx))
4695 || use_pointer_for_field (var, NULL))
4697 x = build_receiver_ref (var, false, ctx);
4698 SET_DECL_VALUE_EXPR (new_var, x);
4699 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4700 goto do_dtor;
4703 do_firstprivate:
4704 x = build_outer_var_ref (var, ctx);
4705 if (is_simd)
4707 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4708 && gimple_omp_for_combined_into_p (ctx->stmt))
4710 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4711 tree stept = TREE_TYPE (t);
4712 tree ct = find_omp_clause (clauses,
4713 OMP_CLAUSE__LOOPTEMP_);
4714 gcc_assert (ct);
4715 tree l = OMP_CLAUSE_DECL (ct);
4716 tree n1 = fd->loop.n1;
4717 tree step = fd->loop.step;
4718 tree itype = TREE_TYPE (l);
4719 if (POINTER_TYPE_P (itype))
4720 itype = signed_type_for (itype);
4721 l = fold_build2 (MINUS_EXPR, itype, l, n1);
4722 if (TYPE_UNSIGNED (itype)
4723 && fd->loop.cond_code == GT_EXPR)
4724 l = fold_build2 (TRUNC_DIV_EXPR, itype,
4725 fold_build1 (NEGATE_EXPR, itype, l),
4726 fold_build1 (NEGATE_EXPR,
4727 itype, step));
4728 else
4729 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
4730 t = fold_build2 (MULT_EXPR, stept,
4731 fold_convert (stept, l), t);
4733 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4735 x = lang_hooks.decls.omp_clause_linear_ctor
4736 (c, new_var, x, t);
4737 gimplify_and_add (x, ilist);
4738 goto do_dtor;
4741 if (POINTER_TYPE_P (TREE_TYPE (x)))
4742 x = fold_build2 (POINTER_PLUS_EXPR,
4743 TREE_TYPE (x), x, t);
4744 else
4745 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4748 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4749 || TREE_ADDRESSABLE (new_var))
4750 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4751 idx, lane, ivar, lvar))
4753 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4755 tree iv = create_tmp_var (TREE_TYPE (new_var));
4756 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4757 gimplify_and_add (x, ilist);
4758 gimple_stmt_iterator gsi
4759 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4760 gassign *g
4761 = gimple_build_assign (unshare_expr (lvar), iv);
4762 gsi_insert_before_without_update (&gsi, g,
4763 GSI_SAME_STMT);
4764 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4765 enum tree_code code = PLUS_EXPR;
4766 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4767 code = POINTER_PLUS_EXPR;
4768 g = gimple_build_assign (iv, code, iv, t);
4769 gsi_insert_before_without_update (&gsi, g,
4770 GSI_SAME_STMT);
4771 break;
4773 x = lang_hooks.decls.omp_clause_copy_ctor
4774 (c, unshare_expr (ivar), x);
4775 gimplify_and_add (x, &llist[0]);
4776 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4777 if (x)
4779 gimple_seq tseq = NULL;
4781 dtor = x;
4782 gimplify_stmt (&dtor, &tseq);
4783 gimple_seq_add_seq (&llist[1], tseq);
4785 break;
4788 x = lang_hooks.decls.omp_clause_copy_ctor
4789 (c, unshare_expr (new_var), x);
4790 gimplify_and_add (x, ilist);
4791 goto do_dtor;
4793 case OMP_CLAUSE__LOOPTEMP_:
4794 gcc_assert (is_taskreg_ctx (ctx));
4795 x = build_outer_var_ref (var, ctx);
4796 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4797 gimplify_and_add (x, ilist);
4798 break;
4800 case OMP_CLAUSE_COPYIN:
4801 by_ref = use_pointer_for_field (var, NULL);
4802 x = build_receiver_ref (var, by_ref, ctx);
4803 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4804 append_to_statement_list (x, &copyin_seq);
4805 copyin_by_ref |= by_ref;
4806 break;
4808 case OMP_CLAUSE_REDUCTION:
4809 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4811 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4812 gimple *tseq;
4813 x = build_outer_var_ref (var, ctx);
4815 if (is_reference (var)
4816 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4817 TREE_TYPE (x)))
4818 x = build_fold_addr_expr_loc (clause_loc, x);
4819 SET_DECL_VALUE_EXPR (placeholder, x);
4820 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4821 tree new_vard = new_var;
4822 if (is_reference (var))
4824 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4825 new_vard = TREE_OPERAND (new_var, 0);
4826 gcc_assert (DECL_P (new_vard));
4828 if (is_simd
4829 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4830 idx, lane, ivar, lvar))
4832 if (new_vard == new_var)
4834 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4835 SET_DECL_VALUE_EXPR (new_var, ivar);
4837 else
4839 SET_DECL_VALUE_EXPR (new_vard,
4840 build_fold_addr_expr (ivar));
4841 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4843 x = lang_hooks.decls.omp_clause_default_ctor
4844 (c, unshare_expr (ivar),
4845 build_outer_var_ref (var, ctx));
4846 if (x)
4847 gimplify_and_add (x, &llist[0]);
4848 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4850 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4851 lower_omp (&tseq, ctx);
4852 gimple_seq_add_seq (&llist[0], tseq);
4854 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4855 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4856 lower_omp (&tseq, ctx);
4857 gimple_seq_add_seq (&llist[1], tseq);
4858 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4859 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4860 if (new_vard == new_var)
4861 SET_DECL_VALUE_EXPR (new_var, lvar);
4862 else
4863 SET_DECL_VALUE_EXPR (new_vard,
4864 build_fold_addr_expr (lvar));
4865 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4866 if (x)
4868 tseq = NULL;
4869 dtor = x;
4870 gimplify_stmt (&dtor, &tseq);
4871 gimple_seq_add_seq (&llist[1], tseq);
4873 break;
4875 /* If this is a reference to constant size reduction var
4876 with placeholder, we haven't emitted the initializer
4877 for it because it is undesirable if SIMD arrays are used.
4878 But if they aren't used, we need to emit the deferred
4879 initialization now. */
4880 else if (is_reference (var) && is_simd)
4881 handle_simd_reference (clause_loc, new_vard, ilist);
4882 x = lang_hooks.decls.omp_clause_default_ctor
4883 (c, unshare_expr (new_var),
4884 build_outer_var_ref (var, ctx));
4885 if (x)
4886 gimplify_and_add (x, ilist);
4887 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4889 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4890 lower_omp (&tseq, ctx);
4891 gimple_seq_add_seq (ilist, tseq);
4893 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4894 if (is_simd)
4896 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4897 lower_omp (&tseq, ctx);
4898 gimple_seq_add_seq (dlist, tseq);
4899 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4901 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4902 goto do_dtor;
4904 else
4906 x = omp_reduction_init (c, TREE_TYPE (new_var));
4907 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4908 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4910 /* reduction(-:var) sums up the partial results, so it
4911 acts identically to reduction(+:var). */
4912 if (code == MINUS_EXPR)
4913 code = PLUS_EXPR;
4915 tree new_vard = new_var;
4916 if (is_simd && is_reference (var))
4918 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4919 new_vard = TREE_OPERAND (new_var, 0);
4920 gcc_assert (DECL_P (new_vard));
4922 if (is_simd
4923 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4924 idx, lane, ivar, lvar))
4926 tree ref = build_outer_var_ref (var, ctx);
4928 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4930 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4931 ref = build_outer_var_ref (var, ctx);
4932 gimplify_assign (ref, x, &llist[1]);
4934 if (new_vard != new_var)
4936 SET_DECL_VALUE_EXPR (new_vard,
4937 build_fold_addr_expr (lvar));
4938 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4941 else
4943 if (is_reference (var) && is_simd)
4944 handle_simd_reference (clause_loc, new_vard, ilist);
4945 gimplify_assign (new_var, x, ilist);
4946 if (is_simd)
4948 tree ref = build_outer_var_ref (var, ctx);
4950 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4951 ref = build_outer_var_ref (var, ctx);
4952 gimplify_assign (ref, x, dlist);
4956 break;
4958 default:
4959 gcc_unreachable ();
4964 if (lane)
4966 tree uid = create_tmp_var (ptr_type_node, "simduid");
4967 /* Don't want uninit warnings on simduid, it is always uninitialized,
4968 but we use it not for the value, but for the DECL_UID only. */
4969 TREE_NO_WARNING (uid) = 1;
4970 gimple *g
4971 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4972 gimple_call_set_lhs (g, lane);
4973 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4974 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4975 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4976 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4977 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4978 gimple_omp_for_set_clauses (ctx->stmt, c);
4979 g = gimple_build_assign (lane, INTEGER_CST,
4980 build_int_cst (unsigned_type_node, 0));
4981 gimple_seq_add_stmt (ilist, g);
4982 for (int i = 0; i < 2; i++)
4983 if (llist[i])
4985 tree vf = create_tmp_var (unsigned_type_node);
4986 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4987 gimple_call_set_lhs (g, vf);
4988 gimple_seq *seq = i == 0 ? ilist : dlist;
4989 gimple_seq_add_stmt (seq, g);
4990 tree t = build_int_cst (unsigned_type_node, 0);
4991 g = gimple_build_assign (idx, INTEGER_CST, t);
4992 gimple_seq_add_stmt (seq, g);
4993 tree body = create_artificial_label (UNKNOWN_LOCATION);
4994 tree header = create_artificial_label (UNKNOWN_LOCATION);
4995 tree end = create_artificial_label (UNKNOWN_LOCATION);
4996 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4997 gimple_seq_add_stmt (seq, gimple_build_label (body));
4998 gimple_seq_add_seq (seq, llist[i]);
4999 t = build_int_cst (unsigned_type_node, 1);
5000 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5001 gimple_seq_add_stmt (seq, g);
5002 gimple_seq_add_stmt (seq, gimple_build_label (header));
5003 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5004 gimple_seq_add_stmt (seq, g);
5005 gimple_seq_add_stmt (seq, gimple_build_label (end));
5009 /* The copyin sequence is not to be executed by the main thread, since
5010 that would result in self-copies. Perhaps not visible to scalars,
5011 but it certainly is to C++ operator=. */
5012 if (copyin_seq)
5014 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5016 x = build2 (NE_EXPR, boolean_type_node, x,
5017 build_int_cst (TREE_TYPE (x), 0));
5018 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5019 gimplify_and_add (x, ilist);
5022 /* If any copyin variable is passed by reference, we must ensure the
5023 master thread doesn't modify it before it is copied over in all
5024 threads. Similarly for variables in both firstprivate and
5025 lastprivate clauses we need to ensure the lastprivate copying
5026 happens after firstprivate copying in all threads. And similarly
5027 for UDRs if initializer expression refers to omp_orig. */
5028 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5030 /* Don't add any barrier for #pragma omp simd or
5031 #pragma omp distribute. */
5032 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5033 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5034 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5037 /* If max_vf is non-zero, then we can use only a vectorization factor
5038 up to the max_vf we chose. So stick it into the safelen clause. */
5039 if (max_vf)
5041 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5042 OMP_CLAUSE_SAFELEN);
5043 if (c == NULL_TREE
5044 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5045 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5046 max_vf) == 1))
5048 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5049 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5050 max_vf);
5051 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5052 gimple_omp_for_set_clauses (ctx->stmt, c);
5058 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5059 both parallel and workshare constructs. PREDICATE may be NULL if it's
5060 always true. */
5062 static void
5063 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5064 omp_context *ctx)
5066 tree x, c, label = NULL, orig_clauses = clauses;
5067 bool par_clauses = false;
5068 tree simduid = NULL, lastlane = NULL;
5070 /* Early exit if there are no lastprivate or linear clauses. */
5071 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5072 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5073 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5074 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5075 break;
5076 if (clauses == NULL)
5078 /* If this was a workshare clause, see if it had been combined
5079 with its parallel. In that case, look for the clauses on the
5080 parallel statement itself. */
5081 if (is_parallel_ctx (ctx))
5082 return;
5084 ctx = ctx->outer;
5085 if (ctx == NULL || !is_parallel_ctx (ctx))
5086 return;
5088 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5089 OMP_CLAUSE_LASTPRIVATE);
5090 if (clauses == NULL)
5091 return;
5092 par_clauses = true;
5095 if (predicate)
5097 gcond *stmt;
5098 tree label_true, arm1, arm2;
5100 label = create_artificial_label (UNKNOWN_LOCATION);
5101 label_true = create_artificial_label (UNKNOWN_LOCATION);
5102 arm1 = TREE_OPERAND (predicate, 0);
5103 arm2 = TREE_OPERAND (predicate, 1);
5104 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5105 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5106 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5107 label_true, label);
5108 gimple_seq_add_stmt (stmt_list, stmt);
5109 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5112 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5113 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5115 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5116 if (simduid)
5117 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5120 for (c = clauses; c ;)
5122 tree var, new_var;
5123 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5125 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5126 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5127 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5129 var = OMP_CLAUSE_DECL (c);
5130 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5131 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5132 && is_taskloop_ctx (ctx))
5134 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5135 new_var = lookup_decl (var, ctx->outer);
5137 else
5138 new_var = lookup_decl (var, ctx);
5140 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5142 tree val = DECL_VALUE_EXPR (new_var);
5143 if (TREE_CODE (val) == ARRAY_REF
5144 && VAR_P (TREE_OPERAND (val, 0))
5145 && lookup_attribute ("omp simd array",
5146 DECL_ATTRIBUTES (TREE_OPERAND (val,
5147 0))))
5149 if (lastlane == NULL)
5151 lastlane = create_tmp_var (unsigned_type_node);
5152 gcall *g
5153 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5154 2, simduid,
5155 TREE_OPERAND (val, 1));
5156 gimple_call_set_lhs (g, lastlane);
5157 gimple_seq_add_stmt (stmt_list, g);
5159 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5160 TREE_OPERAND (val, 0), lastlane,
5161 NULL_TREE, NULL_TREE);
5165 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5166 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5168 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5169 gimple_seq_add_seq (stmt_list,
5170 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5171 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5173 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5174 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5176 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5177 gimple_seq_add_seq (stmt_list,
5178 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5179 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5182 x = NULL_TREE;
5183 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5184 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5186 gcc_checking_assert (is_taskloop_ctx (ctx));
5187 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5188 ctx->outer->outer);
5189 if (is_global_var (ovar))
5190 x = ovar;
5192 if (!x)
5193 x = build_outer_var_ref (var, ctx, true);
5194 if (is_reference (var))
5195 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5196 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5197 gimplify_and_add (x, stmt_list);
5199 c = OMP_CLAUSE_CHAIN (c);
5200 if (c == NULL && !par_clauses)
5202 /* If this was a workshare clause, see if it had been combined
5203 with its parallel. In that case, continue looking for the
5204 clauses also on the parallel statement itself. */
5205 if (is_parallel_ctx (ctx))
5206 break;
5208 ctx = ctx->outer;
5209 if (ctx == NULL || !is_parallel_ctx (ctx))
5210 break;
5212 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5213 OMP_CLAUSE_LASTPRIVATE);
5214 par_clauses = true;
5218 if (label)
5219 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5222 static void
5223 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
5224 tree tid, tree var, tree new_var)
5226 /* The atomic add at the end of the sum creates unnecessary
5227 write contention on accelerators. To work around this,
5228 create an array to store the partial reductions. Later, in
5229 lower_omp_for (for openacc), the values of array will be
5230 combined. */
5232 tree t = NULL_TREE, array, x;
5233 tree type = get_base_type (var);
5234 gimple *stmt;
5236 /* Now insert the partial reductions into the array. */
5238 /* Find the reduction array. */
5240 tree ptype = build_pointer_type (type);
5242 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
5243 t = build_receiver_ref (t, false, ctx->outer);
5245 array = create_tmp_var (ptype);
5246 gimplify_assign (array, t, stmt_seqp);
5248 tree ptr = create_tmp_var (TREE_TYPE (array));
5250 /* Find the reduction array. */
5252 /* testing a unary conversion. */
5253 tree offset = create_tmp_var (sizetype);
5254 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
5255 stmt_seqp);
5256 t = create_tmp_var (sizetype);
5257 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
5258 stmt_seqp);
5259 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
5260 gimple_seq_add_stmt (stmt_seqp, stmt);
5262 /* Offset expression. Does the POINTER_PLUS_EXPR take care
5263 of adding sizeof(var) to the array? */
5264 ptr = create_tmp_var (ptype);
5265 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
5266 offset);
5267 gimple_seq_add_stmt (stmt_seqp, stmt);
5269 /* Move the local sum to gfc$sum[i]. */
5270 x = unshare_expr (build_simple_mem_ref (ptr));
5271 stmt = gimplify_assign (x, new_var, stmt_seqp);
5274 /* Generate code to implement the REDUCTION clauses. */
5276 static void
5277 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5279 gimple_seq sub_seq = NULL;
5280 gimple *stmt;
5281 tree x, c, tid = NULL_TREE;
5282 int count = 0;
5284 /* SIMD reductions are handled in lower_rec_input_clauses. */
5285 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5286 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5287 return;
5289 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5290 update in that case, otherwise use a lock. */
5291 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5292 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5294 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5295 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5297 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5298 count = -1;
5299 break;
5301 count++;
5304 if (count == 0)
5305 return;
5307 /* Initialize thread info for OpenACC. */
5308 if (is_gimple_omp_oacc (ctx->stmt))
5310 /* Get the current thread id. */
5311 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
5312 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
5313 gimple *stmt = gimple_build_call (call, 0);
5314 gimple_call_set_lhs (stmt, tid);
5315 gimple_seq_add_stmt (stmt_seqp, stmt);
5318 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5320 tree var, ref, new_var, orig_var;
5321 enum tree_code code;
5322 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5324 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5325 continue;
5327 orig_var = var = OMP_CLAUSE_DECL (c);
5328 if (TREE_CODE (var) == MEM_REF)
5330 var = TREE_OPERAND (var, 0);
5331 if (TREE_CODE (var) == INDIRECT_REF
5332 || TREE_CODE (var) == ADDR_EXPR)
5333 var = TREE_OPERAND (var, 0);
5334 orig_var = var;
5335 if (is_variable_sized (var))
5337 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5338 var = DECL_VALUE_EXPR (var);
5339 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5340 var = TREE_OPERAND (var, 0);
5341 gcc_assert (DECL_P (var));
5344 new_var = lookup_decl (var, ctx);
5345 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5346 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5347 ref = build_outer_var_ref (var, ctx);
5348 code = OMP_CLAUSE_REDUCTION_CODE (c);
5350 /* reduction(-:var) sums up the partial results, so it acts
5351 identically to reduction(+:var). */
5352 if (code == MINUS_EXPR)
5353 code = PLUS_EXPR;
5355 if (is_gimple_omp_oacc (ctx->stmt))
5357 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
5359 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
5361 else if (count == 1)
5363 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5365 addr = save_expr (addr);
5366 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5367 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5368 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5369 gimplify_and_add (x, stmt_seqp);
5370 return;
5372 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5374 tree d = OMP_CLAUSE_DECL (c);
5375 tree type = TREE_TYPE (d);
5376 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5377 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5378 tree ptype = build_pointer_type (TREE_TYPE (type));
5379 /* For ref build_outer_var_ref already performs this, so
5380 only new_var needs a dereference. */
5381 if (TREE_CODE (TREE_OPERAND (d, 0)) == INDIRECT_REF)
5383 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5384 gcc_assert (is_reference (var) && var == orig_var);
5386 else if (TREE_CODE (TREE_OPERAND (d, 0)) == ADDR_EXPR)
5388 if (orig_var == var)
5390 new_var = build_fold_addr_expr (new_var);
5391 ref = build_fold_addr_expr (ref);
5394 else
5396 gcc_assert (orig_var == var);
5397 if (is_reference (var))
5398 ref = build_fold_addr_expr (ref);
5400 if (DECL_P (v))
5402 tree t = maybe_lookup_decl (v, ctx);
5403 if (t)
5404 v = t;
5405 else
5406 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5407 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5409 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5410 ref = fold_convert_loc (clause_loc, ptype, ref);
5411 tree m = create_tmp_var (ptype, NULL);
5412 gimplify_assign (m, new_var, stmt_seqp);
5413 new_var = m;
5414 m = create_tmp_var (ptype, NULL);
5415 gimplify_assign (m, ref, stmt_seqp);
5416 ref = m;
5417 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5418 tree body = create_artificial_label (UNKNOWN_LOCATION);
5419 tree end = create_artificial_label (UNKNOWN_LOCATION);
5420 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5421 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5422 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5423 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5425 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5426 tree decl_placeholder
5427 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5428 SET_DECL_VALUE_EXPR (placeholder, out);
5429 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5430 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5431 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5432 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5433 gimple_seq_add_seq (&sub_seq,
5434 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5435 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5436 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5437 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5439 else
5441 x = build2 (code, TREE_TYPE (out), out, priv);
5442 out = unshare_expr (out);
5443 gimplify_assign (out, x, &sub_seq);
5445 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5446 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5447 gimple_seq_add_stmt (&sub_seq, g);
5448 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5449 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5450 gimple_seq_add_stmt (&sub_seq, g);
5451 g = gimple_build_assign (i, PLUS_EXPR, i,
5452 build_int_cst (TREE_TYPE (i), 1));
5453 gimple_seq_add_stmt (&sub_seq, g);
5454 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5455 gimple_seq_add_stmt (&sub_seq, g);
5456 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5458 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5460 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5462 if (is_reference (var)
5463 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5464 TREE_TYPE (ref)))
5465 ref = build_fold_addr_expr_loc (clause_loc, ref);
5466 SET_DECL_VALUE_EXPR (placeholder, ref);
5467 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5468 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5469 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5470 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5471 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5473 else
5475 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5476 ref = build_outer_var_ref (var, ctx);
5477 gimplify_assign (ref, x, &sub_seq);
5481 if (is_gimple_omp_oacc (ctx->stmt))
5482 return;
5484 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5486 gimple_seq_add_stmt (stmt_seqp, stmt);
5488 gimple_seq_add_seq (stmt_seqp, sub_seq);
5490 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5492 gimple_seq_add_stmt (stmt_seqp, stmt);
5496 /* Generate code to implement the COPYPRIVATE clauses. */
5498 static void
5499 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
5500 omp_context *ctx)
5502 tree c;
5504 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5506 tree var, new_var, ref, x;
5507 bool by_ref;
5508 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5510 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
5511 continue;
5513 var = OMP_CLAUSE_DECL (c);
5514 by_ref = use_pointer_for_field (var, NULL);
5516 ref = build_sender_ref (var, ctx);
5517 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
5518 if (by_ref)
5520 x = build_fold_addr_expr_loc (clause_loc, new_var);
5521 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
5523 gimplify_assign (ref, x, slist);
5525 ref = build_receiver_ref (var, false, ctx);
5526 if (by_ref)
5528 ref = fold_convert_loc (clause_loc,
5529 build_pointer_type (TREE_TYPE (new_var)),
5530 ref);
5531 ref = build_fold_indirect_ref_loc (clause_loc, ref);
5533 if (is_reference (var))
5535 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
5536 ref = build_simple_mem_ref_loc (clause_loc, ref);
5537 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5539 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
5540 gimplify_and_add (x, rlist);
5545 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
5546 and REDUCTION from the sender (aka parent) side. */
5548 static void
5549 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
5550 omp_context *ctx)
5552 tree c, t;
5553 int ignored_looptemp = 0;
5554 bool is_taskloop = false;
5556 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
5557 by GOMP_taskloop. */
5558 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
5560 ignored_looptemp = 2;
5561 is_taskloop = true;
5564 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5566 tree val, ref, x, var;
5567 bool by_ref, do_in = false, do_out = false;
5568 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5570 switch (OMP_CLAUSE_CODE (c))
5572 case OMP_CLAUSE_PRIVATE:
5573 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
5574 break;
5575 continue;
5576 case OMP_CLAUSE_FIRSTPRIVATE:
5577 case OMP_CLAUSE_COPYIN:
5578 case OMP_CLAUSE_LASTPRIVATE:
5579 case OMP_CLAUSE_REDUCTION:
5580 break;
5581 case OMP_CLAUSE_SHARED:
5582 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5583 break;
5584 continue;
5585 case OMP_CLAUSE__LOOPTEMP_:
5586 if (ignored_looptemp)
5588 ignored_looptemp--;
5589 continue;
5591 break;
5592 default:
5593 continue;
5596 val = OMP_CLAUSE_DECL (c);
5597 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
5598 && TREE_CODE (val) == MEM_REF)
5600 val = TREE_OPERAND (val, 0);
5601 if (TREE_CODE (val) == INDIRECT_REF
5602 || TREE_CODE (val) == ADDR_EXPR)
5603 val = TREE_OPERAND (val, 0);
5604 if (is_variable_sized (val))
5605 continue;
5608 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
5609 outer taskloop region. */
5610 omp_context *ctx_for_o = ctx;
5611 if (is_taskloop
5612 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
5613 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5614 ctx_for_o = ctx->outer;
5616 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
5618 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
5619 && is_global_var (var))
5620 continue;
5622 t = omp_member_access_dummy_var (var);
5623 if (t)
5625 var = DECL_VALUE_EXPR (var);
5626 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
5627 if (o != t)
5628 var = unshare_and_remap (var, t, o);
5629 else
5630 var = unshare_expr (var);
5633 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
5635 /* Handle taskloop firstprivate/lastprivate, where the
5636 lastprivate on GIMPLE_OMP_TASK is represented as
5637 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
5638 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
5639 x = omp_build_component_ref (ctx->sender_decl, f);
5640 if (use_pointer_for_field (val, ctx))
5641 var = build_fold_addr_expr (var);
5642 gimplify_assign (x, var, ilist);
5643 DECL_ABSTRACT_ORIGIN (f) = NULL;
5644 continue;
5647 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
5648 || val == OMP_CLAUSE_DECL (c))
5649 && is_variable_sized (val))
5650 continue;
5651 by_ref = use_pointer_for_field (val, NULL);
5653 switch (OMP_CLAUSE_CODE (c))
5655 case OMP_CLAUSE_PRIVATE:
5656 case OMP_CLAUSE_FIRSTPRIVATE:
5657 case OMP_CLAUSE_COPYIN:
5658 case OMP_CLAUSE__LOOPTEMP_:
5659 do_in = true;
5660 break;
5662 case OMP_CLAUSE_LASTPRIVATE:
5663 if (by_ref || is_reference (val))
5665 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
5666 continue;
5667 do_in = true;
5669 else
5671 do_out = true;
5672 if (lang_hooks.decls.omp_private_outer_ref (val))
5673 do_in = true;
5675 break;
5677 case OMP_CLAUSE_REDUCTION:
5678 do_in = true;
5679 if (val == OMP_CLAUSE_DECL (c))
5680 do_out = !(by_ref || is_reference (val));
5681 else
5682 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
5683 break;
5685 default:
5686 gcc_unreachable ();
5689 if (do_in)
5691 ref = build_sender_ref (val, ctx);
5692 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
5693 gimplify_assign (ref, x, ilist);
5694 if (is_task_ctx (ctx))
5695 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
5698 if (do_out)
5700 ref = build_sender_ref (val, ctx);
5701 gimplify_assign (var, ref, olist);
5706 /* Generate code to implement SHARED from the sender (aka parent)
5707 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
5708 list things that got automatically shared. */
5710 static void
5711 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
5713 tree var, ovar, nvar, t, f, x, record_type;
5715 if (ctx->record_type == NULL)
5716 return;
5718 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
5719 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
5721 ovar = DECL_ABSTRACT_ORIGIN (f);
5722 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
5723 continue;
5725 nvar = maybe_lookup_decl (ovar, ctx);
5726 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
5727 continue;
5729 /* If CTX is a nested parallel directive. Find the immediately
5730 enclosing parallel or workshare construct that contains a
5731 mapping for OVAR. */
5732 var = lookup_decl_in_outer_ctx (ovar, ctx);
5734 t = omp_member_access_dummy_var (var);
5735 if (t)
5737 var = DECL_VALUE_EXPR (var);
5738 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
5739 if (o != t)
5740 var = unshare_and_remap (var, t, o);
5741 else
5742 var = unshare_expr (var);
5745 if (use_pointer_for_field (ovar, ctx))
5747 x = build_sender_ref (ovar, ctx);
5748 var = build_fold_addr_expr (var);
5749 gimplify_assign (x, var, ilist);
5751 else
5753 x = build_sender_ref (ovar, ctx);
5754 gimplify_assign (x, var, ilist);
5756 if (!TREE_READONLY (var)
5757 /* We don't need to receive a new reference to a result
5758 or parm decl. In fact we may not store to it as we will
5759 invalidate any pending RSO and generate wrong gimple
5760 during inlining. */
5761 && !((TREE_CODE (var) == RESULT_DECL
5762 || TREE_CODE (var) == PARM_DECL)
5763 && DECL_BY_REFERENCE (var)))
5765 x = build_sender_ref (ovar, ctx);
5766 gimplify_assign (var, x, olist);
5773 /* A convenience function to build an empty GIMPLE_COND with just the
5774 condition. */
5776 static gcond *
5777 gimple_build_cond_empty (tree cond)
5779 enum tree_code pred_code;
5780 tree lhs, rhs;
5782 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
5783 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
5786 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
5787 bool = false);
5789 /* Build the function calls to GOMP_parallel_start etc to actually
5790 generate the parallel operation. REGION is the parallel region
5791 being expanded. BB is the block where to insert the code. WS_ARGS
5792 will be set if this is a call to a combined parallel+workshare
5793 construct, it contains the list of additional arguments needed by
5794 the workshare construct. */
5796 static void
5797 expand_parallel_call (struct omp_region *region, basic_block bb,
5798 gomp_parallel *entry_stmt,
5799 vec<tree, va_gc> *ws_args)
5801 tree t, t1, t2, val, cond, c, clauses, flags;
5802 gimple_stmt_iterator gsi;
5803 gimple *stmt;
5804 enum built_in_function start_ix;
5805 int start_ix2;
5806 location_t clause_loc;
5807 vec<tree, va_gc> *args;
5809 clauses = gimple_omp_parallel_clauses (entry_stmt);
5811 /* Determine what flavor of GOMP_parallel we will be
5812 emitting. */
5813 start_ix = BUILT_IN_GOMP_PARALLEL;
5814 if (is_combined_parallel (region))
5816 switch (region->inner->type)
5818 case GIMPLE_OMP_FOR:
5819 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
5820 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
5821 + (region->inner->sched_kind
5822 == OMP_CLAUSE_SCHEDULE_RUNTIME
5823 ? 3 : region->inner->sched_kind));
5824 start_ix = (enum built_in_function)start_ix2;
5825 break;
5826 case GIMPLE_OMP_SECTIONS:
5827 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
5828 break;
5829 default:
5830 gcc_unreachable ();
5834 /* By default, the value of NUM_THREADS is zero (selected at run time)
5835 and there is no conditional. */
5836 cond = NULL_TREE;
5837 val = build_int_cst (unsigned_type_node, 0);
5838 flags = build_int_cst (unsigned_type_node, 0);
5840 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5841 if (c)
5842 cond = OMP_CLAUSE_IF_EXPR (c);
5844 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
5845 if (c)
5847 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
5848 clause_loc = OMP_CLAUSE_LOCATION (c);
5850 else
5851 clause_loc = gimple_location (entry_stmt);
5853 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
5854 if (c)
5855 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
5857 /* Ensure 'val' is of the correct type. */
5858 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
5860 /* If we found the clause 'if (cond)', build either
5861 (cond != 0) or (cond ? val : 1u). */
5862 if (cond)
5864 cond = gimple_boolify (cond);
5866 if (integer_zerop (val))
5867 val = fold_build2_loc (clause_loc,
5868 EQ_EXPR, unsigned_type_node, cond,
5869 build_int_cst (TREE_TYPE (cond), 0));
5870 else
5872 basic_block cond_bb, then_bb, else_bb;
5873 edge e, e_then, e_else;
5874 tree tmp_then, tmp_else, tmp_join, tmp_var;
5876 tmp_var = create_tmp_var (TREE_TYPE (val));
5877 if (gimple_in_ssa_p (cfun))
5879 tmp_then = make_ssa_name (tmp_var);
5880 tmp_else = make_ssa_name (tmp_var);
5881 tmp_join = make_ssa_name (tmp_var);
5883 else
5885 tmp_then = tmp_var;
5886 tmp_else = tmp_var;
5887 tmp_join = tmp_var;
5890 e = split_block_after_labels (bb);
5891 cond_bb = e->src;
5892 bb = e->dest;
5893 remove_edge (e);
5895 then_bb = create_empty_bb (cond_bb);
5896 else_bb = create_empty_bb (then_bb);
5897 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
5898 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
5900 stmt = gimple_build_cond_empty (cond);
5901 gsi = gsi_start_bb (cond_bb);
5902 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5904 gsi = gsi_start_bb (then_bb);
5905 expand_omp_build_assign (&gsi, tmp_then, val, true);
5907 gsi = gsi_start_bb (else_bb);
5908 expand_omp_build_assign (&gsi, tmp_else,
5909 build_int_cst (unsigned_type_node, 1),
5910 true);
5912 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
5913 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
5914 add_bb_to_loop (then_bb, cond_bb->loop_father);
5915 add_bb_to_loop (else_bb, cond_bb->loop_father);
5916 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
5917 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
5919 if (gimple_in_ssa_p (cfun))
5921 gphi *phi = create_phi_node (tmp_join, bb);
5922 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
5923 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
5926 val = tmp_join;
5929 gsi = gsi_start_bb (bb);
5930 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
5931 false, GSI_CONTINUE_LINKING);
5934 gsi = gsi_last_bb (bb);
5935 t = gimple_omp_parallel_data_arg (entry_stmt);
5936 if (t == NULL)
5937 t1 = null_pointer_node;
5938 else
5939 t1 = build_fold_addr_expr (t);
5940 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5942 vec_alloc (args, 4 + vec_safe_length (ws_args));
5943 args->quick_push (t2);
5944 args->quick_push (t1);
5945 args->quick_push (val);
5946 if (ws_args)
5947 args->splice (*ws_args);
5948 args->quick_push (flags);
5950 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
5951 builtin_decl_explicit (start_ix), args);
5953 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5954 false, GSI_CONTINUE_LINKING);
5957 /* Insert a function call whose name is FUNC_NAME with the information from
5958 ENTRY_STMT into the basic_block BB. */
5960 static void
5961 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
5962 vec <tree, va_gc> *ws_args)
5964 tree t, t1, t2;
5965 gimple_stmt_iterator gsi;
5966 vec <tree, va_gc> *args;
5968 gcc_assert (vec_safe_length (ws_args) == 2);
5969 tree func_name = (*ws_args)[0];
5970 tree grain = (*ws_args)[1];
5972 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5973 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5974 gcc_assert (count != NULL_TREE);
5975 count = OMP_CLAUSE_OPERAND (count, 0);
5977 gsi = gsi_last_bb (bb);
5978 t = gimple_omp_parallel_data_arg (entry_stmt);
5979 if (t == NULL)
5980 t1 = null_pointer_node;
5981 else
5982 t1 = build_fold_addr_expr (t);
5983 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5985 vec_alloc (args, 4);
5986 args->quick_push (t2);
5987 args->quick_push (t1);
5988 args->quick_push (count);
5989 args->quick_push (grain);
5990 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5992 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5993 GSI_CONTINUE_LINKING);
5996 /* Build the function call to GOMP_task to actually
5997 generate the task operation. BB is the block where to insert the code. */
5999 static void
6000 expand_task_call (struct omp_region *region, basic_block bb,
6001 gomp_task *entry_stmt)
6003 tree t1, t2, t3;
6004 gimple_stmt_iterator gsi;
6005 location_t loc = gimple_location (entry_stmt);
6007 tree clauses = gimple_omp_task_clauses (entry_stmt);
6009 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6010 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6011 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6012 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6013 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6014 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6016 unsigned int iflags
6017 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6018 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6019 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6021 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6022 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6023 tree num_tasks = NULL_TREE;
6024 bool ull = false;
6025 if (taskloop_p)
6027 gimple *g = last_stmt (region->outer->entry);
6028 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6029 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6030 struct omp_for_data fd;
6031 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6032 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6033 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6034 OMP_CLAUSE__LOOPTEMP_);
6035 startvar = OMP_CLAUSE_DECL (startvar);
6036 endvar = OMP_CLAUSE_DECL (endvar);
6037 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6038 if (fd.loop.cond_code == LT_EXPR)
6039 iflags |= GOMP_TASK_FLAG_UP;
6040 tree tclauses = gimple_omp_for_clauses (g);
6041 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6042 if (num_tasks)
6043 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6044 else
6046 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6047 if (num_tasks)
6049 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6050 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6052 else
6053 num_tasks = integer_zero_node;
6055 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6056 if (ifc == NULL_TREE)
6057 iflags |= GOMP_TASK_FLAG_IF;
6058 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6059 iflags |= GOMP_TASK_FLAG_NOGROUP;
6060 ull = fd.iter_type == long_long_unsigned_type_node;
6062 else if (priority)
6063 iflags |= GOMP_TASK_FLAG_PRIORITY;
6065 tree flags = build_int_cst (unsigned_type_node, iflags);
6067 tree cond = boolean_true_node;
6068 if (ifc)
6070 if (taskloop_p)
6072 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6073 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6074 build_int_cst (unsigned_type_node,
6075 GOMP_TASK_FLAG_IF),
6076 build_int_cst (unsigned_type_node, 0));
6077 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6078 flags, t);
6080 else
6081 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6084 if (finalc)
6086 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6087 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6088 build_int_cst (unsigned_type_node,
6089 GOMP_TASK_FLAG_FINAL),
6090 build_int_cst (unsigned_type_node, 0));
6091 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6093 if (depend)
6094 depend = OMP_CLAUSE_DECL (depend);
6095 else
6096 depend = build_int_cst (ptr_type_node, 0);
6097 if (priority)
6098 priority = fold_convert (integer_type_node,
6099 OMP_CLAUSE_PRIORITY_EXPR (priority));
6100 else
6101 priority = integer_zero_node;
6103 gsi = gsi_last_bb (bb);
6104 tree t = gimple_omp_task_data_arg (entry_stmt);
6105 if (t == NULL)
6106 t2 = null_pointer_node;
6107 else
6108 t2 = build_fold_addr_expr_loc (loc, t);
6109 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6110 t = gimple_omp_task_copy_fn (entry_stmt);
6111 if (t == NULL)
6112 t3 = null_pointer_node;
6113 else
6114 t3 = build_fold_addr_expr_loc (loc, t);
6116 if (taskloop_p)
6117 t = build_call_expr (ull
6118 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6119 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6120 11, t1, t2, t3,
6121 gimple_omp_task_arg_size (entry_stmt),
6122 gimple_omp_task_arg_align (entry_stmt), flags,
6123 num_tasks, priority, startvar, endvar, step);
6124 else
6125 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6126 9, t1, t2, t3,
6127 gimple_omp_task_arg_size (entry_stmt),
6128 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6129 depend, priority);
6131 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6132 false, GSI_CONTINUE_LINKING);
6136 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6137 catch handler and return it. This prevents programs from violating the
6138 structured block semantics with throws. */
6140 static gimple_seq
6141 maybe_catch_exception (gimple_seq body)
6143 gimple *g;
6144 tree decl;
6146 if (!flag_exceptions)
6147 return body;
6149 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6150 decl = lang_hooks.eh_protect_cleanup_actions ();
6151 else
6152 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6154 g = gimple_build_eh_must_not_throw (decl);
6155 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6156 GIMPLE_TRY_CATCH);
6158 return gimple_seq_alloc_with_stmt (g);
6161 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6163 static tree
6164 vec2chain (vec<tree, va_gc> *v)
6166 tree chain = NULL_TREE, t;
6167 unsigned ix;
6169 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6171 DECL_CHAIN (t) = chain;
6172 chain = t;
6175 return chain;
6179 /* Remove barriers in REGION->EXIT's block. Note that this is only
6180 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6181 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6182 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6183 removed. */
6185 static void
6186 remove_exit_barrier (struct omp_region *region)
6188 gimple_stmt_iterator gsi;
6189 basic_block exit_bb;
6190 edge_iterator ei;
6191 edge e;
6192 gimple *stmt;
6193 int any_addressable_vars = -1;
6195 exit_bb = region->exit;
6197 /* If the parallel region doesn't return, we don't have REGION->EXIT
6198 block at all. */
6199 if (! exit_bb)
6200 return;
6202 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6203 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6204 statements that can appear in between are extremely limited -- no
6205 memory operations at all. Here, we allow nothing at all, so the
6206 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6207 gsi = gsi_last_bb (exit_bb);
6208 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6209 gsi_prev (&gsi);
6210 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6211 return;
6213 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6215 gsi = gsi_last_bb (e->src);
6216 if (gsi_end_p (gsi))
6217 continue;
6218 stmt = gsi_stmt (gsi);
6219 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6220 && !gimple_omp_return_nowait_p (stmt))
6222 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6223 in many cases. If there could be tasks queued, the barrier
6224 might be needed to let the tasks run before some local
6225 variable of the parallel that the task uses as shared
6226 runs out of scope. The task can be spawned either
6227 from within current function (this would be easy to check)
6228 or from some function it calls and gets passed an address
6229 of such a variable. */
6230 if (any_addressable_vars < 0)
6232 gomp_parallel *parallel_stmt
6233 = as_a <gomp_parallel *> (last_stmt (region->entry));
6234 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6235 tree local_decls, block, decl;
6236 unsigned ix;
6238 any_addressable_vars = 0;
6239 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6240 if (TREE_ADDRESSABLE (decl))
6242 any_addressable_vars = 1;
6243 break;
6245 for (block = gimple_block (stmt);
6246 !any_addressable_vars
6247 && block
6248 && TREE_CODE (block) == BLOCK;
6249 block = BLOCK_SUPERCONTEXT (block))
6251 for (local_decls = BLOCK_VARS (block);
6252 local_decls;
6253 local_decls = DECL_CHAIN (local_decls))
6254 if (TREE_ADDRESSABLE (local_decls))
6256 any_addressable_vars = 1;
6257 break;
6259 if (block == gimple_block (parallel_stmt))
6260 break;
6263 if (!any_addressable_vars)
6264 gimple_omp_return_set_nowait (stmt);
6269 static void
6270 remove_exit_barriers (struct omp_region *region)
6272 if (region->type == GIMPLE_OMP_PARALLEL)
6273 remove_exit_barrier (region);
6275 if (region->inner)
6277 region = region->inner;
6278 remove_exit_barriers (region);
6279 while (region->next)
6281 region = region->next;
6282 remove_exit_barriers (region);
6287 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
6288 calls. These can't be declared as const functions, but
6289 within one parallel body they are constant, so they can be
6290 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
6291 which are declared const. Similarly for task body, except
6292 that in untied task omp_get_thread_num () can change at any task
6293 scheduling point. */
6295 static void
6296 optimize_omp_library_calls (gimple *entry_stmt)
6298 basic_block bb;
6299 gimple_stmt_iterator gsi;
6300 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6301 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
6302 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6303 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
6304 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
6305 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
6306 OMP_CLAUSE_UNTIED) != NULL);
6308 FOR_EACH_BB_FN (bb, cfun)
6309 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
6311 gimple *call = gsi_stmt (gsi);
6312 tree decl;
6314 if (is_gimple_call (call)
6315 && (decl = gimple_call_fndecl (call))
6316 && DECL_EXTERNAL (decl)
6317 && TREE_PUBLIC (decl)
6318 && DECL_INITIAL (decl) == NULL)
6320 tree built_in;
6322 if (DECL_NAME (decl) == thr_num_id)
6324 /* In #pragma omp task untied omp_get_thread_num () can change
6325 during the execution of the task region. */
6326 if (untied_task)
6327 continue;
6328 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6330 else if (DECL_NAME (decl) == num_thr_id)
6331 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6332 else
6333 continue;
6335 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
6336 || gimple_call_num_args (call) != 0)
6337 continue;
6339 if (flag_exceptions && !TREE_NOTHROW (decl))
6340 continue;
6342 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
6343 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
6344 TREE_TYPE (TREE_TYPE (built_in))))
6345 continue;
6347 gimple_call_set_fndecl (call, built_in);
6352 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
6353 regimplified. */
6355 static tree
6356 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
6358 tree t = *tp;
6360 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6361 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
6362 return t;
6364 if (TREE_CODE (t) == ADDR_EXPR)
6365 recompute_tree_invariant_for_addr_expr (t);
6367 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
6368 return NULL_TREE;
6371 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
6373 static void
6374 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
6375 bool after)
6377 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
6378 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
6379 !after, after ? GSI_CONTINUE_LINKING
6380 : GSI_SAME_STMT);
6381 gimple *stmt = gimple_build_assign (to, from);
6382 if (after)
6383 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
6384 else
6385 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
6386 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
6387 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
6389 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
6390 gimple_regimplify_operands (stmt, &gsi);
6394 /* Expand the OpenMP parallel or task directive starting at REGION. */
6396 static void
6397 expand_omp_taskreg (struct omp_region *region)
6399 basic_block entry_bb, exit_bb, new_bb;
6400 struct function *child_cfun;
6401 tree child_fn, block, t;
6402 gimple_stmt_iterator gsi;
6403 gimple *entry_stmt, *stmt;
6404 edge e;
6405 vec<tree, va_gc> *ws_args;
6407 entry_stmt = last_stmt (region->entry);
6408 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
6409 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
6411 entry_bb = region->entry;
6412 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
6413 exit_bb = region->cont;
6414 else
6415 exit_bb = region->exit;
6417 bool is_cilk_for
6418 = (flag_cilkplus
6419 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
6420 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
6421 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
6423 if (is_cilk_for)
6424 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
6425 and the inner statement contains the name of the built-in function
6426 and grain. */
6427 ws_args = region->inner->ws_args;
6428 else if (is_combined_parallel (region))
6429 ws_args = region->ws_args;
6430 else
6431 ws_args = NULL;
6433 if (child_cfun->cfg)
6435 /* Due to inlining, it may happen that we have already outlined
6436 the region, in which case all we need to do is make the
6437 sub-graph unreachable and emit the parallel call. */
6438 edge entry_succ_e, exit_succ_e;
6440 entry_succ_e = single_succ_edge (entry_bb);
6442 gsi = gsi_last_bb (entry_bb);
6443 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
6444 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
6445 gsi_remove (&gsi, true);
6447 new_bb = entry_bb;
6448 if (exit_bb)
6450 exit_succ_e = single_succ_edge (exit_bb);
6451 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
6453 remove_edge_and_dominated_blocks (entry_succ_e);
6455 else
6457 unsigned srcidx, dstidx, num;
6459 /* If the parallel region needs data sent from the parent
6460 function, then the very first statement (except possible
6461 tree profile counter updates) of the parallel body
6462 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
6463 &.OMP_DATA_O is passed as an argument to the child function,
6464 we need to replace it with the argument as seen by the child
6465 function.
6467 In most cases, this will end up being the identity assignment
6468 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
6469 a function call that has been inlined, the original PARM_DECL
6470 .OMP_DATA_I may have been converted into a different local
6471 variable. In which case, we need to keep the assignment. */
6472 if (gimple_omp_taskreg_data_arg (entry_stmt))
6474 basic_block entry_succ_bb
6475 = single_succ_p (entry_bb) ? single_succ (entry_bb)
6476 : FALLTHRU_EDGE (entry_bb)->dest;
6477 tree arg;
6478 gimple *parcopy_stmt = NULL;
6480 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
6482 gimple *stmt;
6484 gcc_assert (!gsi_end_p (gsi));
6485 stmt = gsi_stmt (gsi);
6486 if (gimple_code (stmt) != GIMPLE_ASSIGN)
6487 continue;
6489 if (gimple_num_ops (stmt) == 2)
6491 tree arg = gimple_assign_rhs1 (stmt);
6493 /* We're ignore the subcode because we're
6494 effectively doing a STRIP_NOPS. */
6496 if (TREE_CODE (arg) == ADDR_EXPR
6497 && TREE_OPERAND (arg, 0)
6498 == gimple_omp_taskreg_data_arg (entry_stmt))
6500 parcopy_stmt = stmt;
6501 break;
6506 gcc_assert (parcopy_stmt != NULL);
6507 arg = DECL_ARGUMENTS (child_fn);
6509 if (!gimple_in_ssa_p (cfun))
6511 if (gimple_assign_lhs (parcopy_stmt) == arg)
6512 gsi_remove (&gsi, true);
6513 else
6515 /* ?? Is setting the subcode really necessary ?? */
6516 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
6517 gimple_assign_set_rhs1 (parcopy_stmt, arg);
6520 else
6522 tree lhs = gimple_assign_lhs (parcopy_stmt);
6523 gcc_assert (SSA_NAME_VAR (lhs) == arg);
6524 /* We'd like to set the rhs to the default def in the child_fn,
6525 but it's too early to create ssa names in the child_fn.
6526 Instead, we set the rhs to the parm. In
6527 move_sese_region_to_fn, we introduce a default def for the
6528 parm, map the parm to it's default def, and once we encounter
6529 this stmt, replace the parm with the default def. */
6530 gimple_assign_set_rhs1 (parcopy_stmt, arg);
6531 update_stmt (parcopy_stmt);
6535 /* Declare local variables needed in CHILD_CFUN. */
6536 block = DECL_INITIAL (child_fn);
6537 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
6538 /* The gimplifier could record temporaries in parallel/task block
6539 rather than in containing function's local_decls chain,
6540 which would mean cgraph missed finalizing them. Do it now. */
6541 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
6542 if (TREE_CODE (t) == VAR_DECL
6543 && TREE_STATIC (t)
6544 && !DECL_EXTERNAL (t))
6545 varpool_node::finalize_decl (t);
6546 DECL_SAVED_TREE (child_fn) = NULL;
6547 /* We'll create a CFG for child_fn, so no gimple body is needed. */
6548 gimple_set_body (child_fn, NULL);
6549 TREE_USED (block) = 1;
6551 /* Reset DECL_CONTEXT on function arguments. */
6552 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
6553 DECL_CONTEXT (t) = child_fn;
6555 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
6556 so that it can be moved to the child function. */
6557 gsi = gsi_last_bb (entry_bb);
6558 stmt = gsi_stmt (gsi);
6559 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
6560 || gimple_code (stmt) == GIMPLE_OMP_TASK));
6561 e = split_block (entry_bb, stmt);
6562 gsi_remove (&gsi, true);
6563 entry_bb = e->dest;
6564 edge e2 = NULL;
6565 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
6566 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
6567 else
6569 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
6570 gcc_assert (e2->dest == region->exit);
6571 remove_edge (BRANCH_EDGE (entry_bb));
6572 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
6573 gsi = gsi_last_bb (region->exit);
6574 gcc_assert (!gsi_end_p (gsi)
6575 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6576 gsi_remove (&gsi, true);
6579 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
6580 if (exit_bb)
6582 gsi = gsi_last_bb (exit_bb);
6583 gcc_assert (!gsi_end_p (gsi)
6584 && (gimple_code (gsi_stmt (gsi))
6585 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
6586 stmt = gimple_build_return (NULL);
6587 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
6588 gsi_remove (&gsi, true);
6591 /* Move the parallel region into CHILD_CFUN. */
6593 if (gimple_in_ssa_p (cfun))
6595 init_tree_ssa (child_cfun);
6596 init_ssa_operands (child_cfun);
6597 child_cfun->gimple_df->in_ssa_p = true;
6598 block = NULL_TREE;
6600 else
6601 block = gimple_block (entry_stmt);
6603 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
6604 if (exit_bb)
6605 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
6606 if (e2)
6608 basic_block dest_bb = e2->dest;
6609 if (!exit_bb)
6610 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
6611 remove_edge (e2);
6612 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
6614 /* When the OMP expansion process cannot guarantee an up-to-date
6615 loop tree arrange for the child function to fixup loops. */
6616 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
6617 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
6619 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
6620 num = vec_safe_length (child_cfun->local_decls);
6621 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
6623 t = (*child_cfun->local_decls)[srcidx];
6624 if (DECL_CONTEXT (t) == cfun->decl)
6625 continue;
6626 if (srcidx != dstidx)
6627 (*child_cfun->local_decls)[dstidx] = t;
6628 dstidx++;
6630 if (dstidx != num)
6631 vec_safe_truncate (child_cfun->local_decls, dstidx);
6633 /* Inform the callgraph about the new function. */
6634 child_cfun->curr_properties = cfun->curr_properties;
6635 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
6636 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
6637 cgraph_node *node = cgraph_node::get_create (child_fn);
6638 node->parallelized_function = 1;
6639 cgraph_node::add_new_function (child_fn, true);
6641 /* Fix the callgraph edges for child_cfun. Those for cfun will be
6642 fixed in a following pass. */
6643 push_cfun (child_cfun);
6644 if (optimize)
6645 optimize_omp_library_calls (entry_stmt);
6646 cgraph_edge::rebuild_edges ();
6648 /* Some EH regions might become dead, see PR34608. If
6649 pass_cleanup_cfg isn't the first pass to happen with the
6650 new child, these dead EH edges might cause problems.
6651 Clean them up now. */
6652 if (flag_exceptions)
6654 basic_block bb;
6655 bool changed = false;
6657 FOR_EACH_BB_FN (bb, cfun)
6658 changed |= gimple_purge_dead_eh_edges (bb);
6659 if (changed)
6660 cleanup_tree_cfg ();
6662 if (gimple_in_ssa_p (cfun))
6663 update_ssa (TODO_update_ssa);
6664 #ifdef ENABLE_CHECKING
6665 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
6666 verify_loop_structure ();
6667 #endif
6668 pop_cfun ();
6671 /* Emit a library call to launch the children threads. */
6672 if (is_cilk_for)
6673 expand_cilk_for_call (new_bb,
6674 as_a <gomp_parallel *> (entry_stmt), ws_args);
6675 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
6676 expand_parallel_call (region, new_bb,
6677 as_a <gomp_parallel *> (entry_stmt), ws_args);
6678 else
6679 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
6680 if (gimple_in_ssa_p (cfun))
6681 update_ssa (TODO_update_ssa_only_virtuals);
6685 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
6686 of the combined collapse > 1 loop constructs, generate code like:
6687 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
6688 if (cond3 is <)
6689 adj = STEP3 - 1;
6690 else
6691 adj = STEP3 + 1;
6692 count3 = (adj + N32 - N31) / STEP3;
6693 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
6694 if (cond2 is <)
6695 adj = STEP2 - 1;
6696 else
6697 adj = STEP2 + 1;
6698 count2 = (adj + N22 - N21) / STEP2;
6699 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
6700 if (cond1 is <)
6701 adj = STEP1 - 1;
6702 else
6703 adj = STEP1 + 1;
6704 count1 = (adj + N12 - N11) / STEP1;
6705 count = count1 * count2 * count3;
6706 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
6707 count = 0;
6708 and set ZERO_ITER_BB to that bb. If this isn't the outermost
6709 of the combined loop constructs, just initialize COUNTS array
6710 from the _looptemp_ clauses. */
6712 /* NOTE: It *could* be better to moosh all of the BBs together,
6713 creating one larger BB with all the computation and the unexpected
6714 jump at the end. I.e.
6716 bool zero3, zero2, zero1, zero;
6718 zero3 = N32 c3 N31;
6719 count3 = (N32 - N31) /[cl] STEP3;
6720 zero2 = N22 c2 N21;
6721 count2 = (N22 - N21) /[cl] STEP2;
6722 zero1 = N12 c1 N11;
6723 count1 = (N12 - N11) /[cl] STEP1;
6724 zero = zero3 || zero2 || zero1;
6725 count = count1 * count2 * count3;
6726 if (__builtin_expect(zero, false)) goto zero_iter_bb;
6728 After all, we expect the zero=false, and thus we expect to have to
6729 evaluate all of the comparison expressions, so short-circuiting
6730 oughtn't be a win. Since the condition isn't protecting a
6731 denominator, we're not concerned about divide-by-zero, so we can
6732 fully evaluate count even if a numerator turned out to be wrong.
6734 It seems like putting this all together would create much better
6735 scheduling opportunities, and less pressure on the chip's branch
6736 predictor. */
6738 static void
6739 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
6740 basic_block &entry_bb, tree *counts,
6741 basic_block &zero_iter1_bb, int &first_zero_iter1,
6742 basic_block &zero_iter2_bb, int &first_zero_iter2,
6743 basic_block &l2_dom_bb)
6745 tree t, type = TREE_TYPE (fd->loop.v);
6746 edge e, ne;
6747 int i;
6749 /* Collapsed loops need work for expansion into SSA form. */
6750 gcc_assert (!gimple_in_ssa_p (cfun));
6752 if (gimple_omp_for_combined_into_p (fd->for_stmt)
6753 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
6755 gcc_assert (fd->ordered == 0);
6756 /* First two _looptemp_ clauses are for istart/iend, counts[0]
6757 isn't supposed to be handled, as the inner loop doesn't
6758 use it. */
6759 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6760 OMP_CLAUSE__LOOPTEMP_);
6761 gcc_assert (innerc);
6762 for (i = 0; i < fd->collapse; i++)
6764 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6765 OMP_CLAUSE__LOOPTEMP_);
6766 gcc_assert (innerc);
6767 if (i)
6768 counts[i] = OMP_CLAUSE_DECL (innerc);
6769 else
6770 counts[0] = NULL_TREE;
6772 return;
6775 for (i = fd->collapse; i < fd->ordered; i++)
6777 tree itype = TREE_TYPE (fd->loops[i].v);
6778 counts[i] = NULL_TREE;
6779 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
6780 fold_convert (itype, fd->loops[i].n1),
6781 fold_convert (itype, fd->loops[i].n2));
6782 if (t && integer_zerop (t))
6784 for (i = fd->collapse; i < fd->ordered; i++)
6785 counts[i] = build_int_cst (type, 0);
6786 break;
6789 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
6791 tree itype = TREE_TYPE (fd->loops[i].v);
6793 if (i >= fd->collapse && counts[i])
6794 continue;
6795 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
6796 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
6797 fold_convert (itype, fd->loops[i].n1),
6798 fold_convert (itype, fd->loops[i].n2)))
6799 == NULL_TREE || !integer_onep (t)))
6801 gcond *cond_stmt;
6802 tree n1, n2;
6803 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
6804 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
6805 true, GSI_SAME_STMT);
6806 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
6807 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
6808 true, GSI_SAME_STMT);
6809 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
6810 NULL_TREE, NULL_TREE);
6811 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
6812 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6813 expand_omp_regimplify_p, NULL, NULL)
6814 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6815 expand_omp_regimplify_p, NULL, NULL))
6817 *gsi = gsi_for_stmt (cond_stmt);
6818 gimple_regimplify_operands (cond_stmt, gsi);
6820 e = split_block (entry_bb, cond_stmt);
6821 basic_block &zero_iter_bb
6822 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
6823 int &first_zero_iter
6824 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
6825 if (zero_iter_bb == NULL)
6827 gassign *assign_stmt;
6828 first_zero_iter = i;
6829 zero_iter_bb = create_empty_bb (entry_bb);
6830 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
6831 *gsi = gsi_after_labels (zero_iter_bb);
6832 if (i < fd->collapse)
6833 assign_stmt = gimple_build_assign (fd->loop.n2,
6834 build_zero_cst (type));
6835 else
6837 counts[i] = create_tmp_reg (type, ".count");
6838 assign_stmt
6839 = gimple_build_assign (counts[i], build_zero_cst (type));
6841 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
6842 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
6843 entry_bb);
6845 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
6846 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
6847 e->flags = EDGE_TRUE_VALUE;
6848 e->probability = REG_BR_PROB_BASE - ne->probability;
6849 if (l2_dom_bb == NULL)
6850 l2_dom_bb = entry_bb;
6851 entry_bb = e->dest;
6852 *gsi = gsi_last_bb (entry_bb);
6855 if (POINTER_TYPE_P (itype))
6856 itype = signed_type_for (itype);
6857 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
6858 ? -1 : 1));
6859 t = fold_build2 (PLUS_EXPR, itype,
6860 fold_convert (itype, fd->loops[i].step), t);
6861 t = fold_build2 (PLUS_EXPR, itype, t,
6862 fold_convert (itype, fd->loops[i].n2));
6863 t = fold_build2 (MINUS_EXPR, itype, t,
6864 fold_convert (itype, fd->loops[i].n1));
6865 /* ?? We could probably use CEIL_DIV_EXPR instead of
6866 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
6867 generate the same code in the end because generically we
6868 don't know that the values involved must be negative for
6869 GT?? */
6870 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
6871 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6872 fold_build1 (NEGATE_EXPR, itype, t),
6873 fold_build1 (NEGATE_EXPR, itype,
6874 fold_convert (itype,
6875 fd->loops[i].step)));
6876 else
6877 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
6878 fold_convert (itype, fd->loops[i].step));
6879 t = fold_convert (type, t);
6880 if (TREE_CODE (t) == INTEGER_CST)
6881 counts[i] = t;
6882 else
6884 if (i < fd->collapse || i != first_zero_iter2)
6885 counts[i] = create_tmp_reg (type, ".count");
6886 expand_omp_build_assign (gsi, counts[i], t);
6888 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
6890 if (i == 0)
6891 t = counts[0];
6892 else
6893 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
6894 expand_omp_build_assign (gsi, fd->loop.n2, t);
6900 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
6901 T = V;
6902 V3 = N31 + (T % count3) * STEP3;
6903 T = T / count3;
6904 V2 = N21 + (T % count2) * STEP2;
6905 T = T / count2;
6906 V1 = N11 + T * STEP1;
6907 if this loop doesn't have an inner loop construct combined with it.
6908 If it does have an inner loop construct combined with it and the
6909 iteration count isn't known constant, store values from counts array
6910 into its _looptemp_ temporaries instead. */
6912 static void
6913 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
6914 tree *counts, gimple *inner_stmt, tree startvar)
6916 int i;
6917 if (gimple_omp_for_combined_p (fd->for_stmt))
6919 /* If fd->loop.n2 is constant, then no propagation of the counts
6920 is needed, they are constant. */
6921 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
6922 return;
6924 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
6925 ? gimple_omp_taskreg_clauses (inner_stmt)
6926 : gimple_omp_for_clauses (inner_stmt);
6927 /* First two _looptemp_ clauses are for istart/iend, counts[0]
6928 isn't supposed to be handled, as the inner loop doesn't
6929 use it. */
6930 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6931 gcc_assert (innerc);
6932 for (i = 0; i < fd->collapse; i++)
6934 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6935 OMP_CLAUSE__LOOPTEMP_);
6936 gcc_assert (innerc);
6937 if (i)
6939 tree tem = OMP_CLAUSE_DECL (innerc);
6940 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
6941 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
6942 false, GSI_CONTINUE_LINKING);
6943 gassign *stmt = gimple_build_assign (tem, t);
6944 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
6947 return;
6950 tree type = TREE_TYPE (fd->loop.v);
6951 tree tem = create_tmp_reg (type, ".tem");
6952 gassign *stmt = gimple_build_assign (tem, startvar);
6953 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
6955 for (i = fd->collapse - 1; i >= 0; i--)
6957 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
6958 itype = vtype;
6959 if (POINTER_TYPE_P (vtype))
6960 itype = signed_type_for (vtype);
6961 if (i != 0)
6962 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
6963 else
6964 t = tem;
6965 t = fold_convert (itype, t);
6966 t = fold_build2 (MULT_EXPR, itype, t,
6967 fold_convert (itype, fd->loops[i].step));
6968 if (POINTER_TYPE_P (vtype))
6969 t = fold_build_pointer_plus (fd->loops[i].n1, t);
6970 else
6971 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
6972 t = force_gimple_operand_gsi (gsi, t,
6973 DECL_P (fd->loops[i].v)
6974 && TREE_ADDRESSABLE (fd->loops[i].v),
6975 NULL_TREE, false,
6976 GSI_CONTINUE_LINKING);
6977 stmt = gimple_build_assign (fd->loops[i].v, t);
6978 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
6979 if (i != 0)
6981 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
6982 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
6983 false, GSI_CONTINUE_LINKING);
6984 stmt = gimple_build_assign (tem, t);
6985 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
6991 /* Helper function for expand_omp_for_*. Generate code like:
6992 L10:
6993 V3 += STEP3;
6994 if (V3 cond3 N32) goto BODY_BB; else goto L11;
6995 L11:
6996 V3 = N31;
6997 V2 += STEP2;
6998 if (V2 cond2 N22) goto BODY_BB; else goto L12;
6999 L12:
7000 V2 = N21;
7001 V1 += STEP1;
7002 goto BODY_BB; */
7004 static basic_block
7005 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7006 basic_block body_bb)
7008 basic_block last_bb, bb, collapse_bb = NULL;
7009 int i;
7010 gimple_stmt_iterator gsi;
7011 edge e;
7012 tree t;
7013 gimple *stmt;
7015 last_bb = cont_bb;
7016 for (i = fd->collapse - 1; i >= 0; i--)
7018 tree vtype = TREE_TYPE (fd->loops[i].v);
7020 bb = create_empty_bb (last_bb);
7021 add_bb_to_loop (bb, last_bb->loop_father);
7022 gsi = gsi_start_bb (bb);
7024 if (i < fd->collapse - 1)
7026 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7027 e->probability = REG_BR_PROB_BASE / 8;
7029 t = fd->loops[i + 1].n1;
7030 t = force_gimple_operand_gsi (&gsi, t,
7031 DECL_P (fd->loops[i + 1].v)
7032 && TREE_ADDRESSABLE (fd->loops[i
7033 + 1].v),
7034 NULL_TREE, false,
7035 GSI_CONTINUE_LINKING);
7036 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7037 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7039 else
7040 collapse_bb = bb;
7042 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7044 if (POINTER_TYPE_P (vtype))
7045 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7046 else
7047 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7048 t = force_gimple_operand_gsi (&gsi, t,
7049 DECL_P (fd->loops[i].v)
7050 && TREE_ADDRESSABLE (fd->loops[i].v),
7051 NULL_TREE, false, GSI_CONTINUE_LINKING);
7052 stmt = gimple_build_assign (fd->loops[i].v, t);
7053 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7055 if (i > 0)
7057 t = fd->loops[i].n2;
7058 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7059 false, GSI_CONTINUE_LINKING);
7060 tree v = fd->loops[i].v;
7061 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7062 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7063 false, GSI_CONTINUE_LINKING);
7064 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7065 stmt = gimple_build_cond_empty (t);
7066 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7067 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7068 e->probability = REG_BR_PROB_BASE * 7 / 8;
7070 else
7071 make_edge (bb, body_bb, EDGE_FALLTHRU);
7072 last_bb = bb;
7075 return collapse_bb;
7079 /* Expand #pragma omp ordered depend(source). */
7081 static void
7082 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7083 tree *counts, location_t loc)
7085 enum built_in_function source_ix
7086 = fd->iter_type == long_integer_type_node
7087 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7088 gimple *g
7089 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7090 build_fold_addr_expr (counts[fd->ordered]));
7091 gimple_set_location (g, loc);
7092 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7095 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7097 static void
7098 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7099 tree *counts, tree c, location_t loc)
7101 auto_vec<tree, 10> args;
7102 enum built_in_function sink_ix
7103 = fd->iter_type == long_integer_type_node
7104 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7105 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7106 int i;
7107 gimple_stmt_iterator gsi2 = *gsi;
7108 bool warned_step = false;
7110 for (i = 0; i < fd->ordered; i++)
7112 off = TREE_PURPOSE (deps);
7113 if (!integer_zerop (off))
7115 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7116 || fd->loops[i].cond_code == GT_EXPR);
7117 bool forward = fd->loops[i].cond_code == LT_EXPR;
7118 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7119 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
7120 "lexically later iteration");
7121 break;
7123 deps = TREE_CHAIN (deps);
7125 /* If all offsets corresponding to the collapsed loops are zero,
7126 this depend clause can be ignored. FIXME: but there is still a
7127 flush needed. We need to emit one __sync_synchronize () for it
7128 though (perhaps conditionally)? Solve this together with the
7129 conservative dependence folding optimization.
7130 if (i >= fd->collapse)
7131 return; */
7133 deps = OMP_CLAUSE_DECL (c);
7134 gsi_prev (&gsi2);
7135 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
7136 edge e2 = split_block_after_labels (e1->dest);
7138 *gsi = gsi_after_labels (e1->dest);
7139 for (i = 0; i < fd->ordered; i++)
7141 tree itype = TREE_TYPE (fd->loops[i].v);
7142 if (POINTER_TYPE_P (itype))
7143 itype = sizetype;
7144 if (i)
7145 deps = TREE_CHAIN (deps);
7146 off = TREE_PURPOSE (deps);
7147 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
7149 if (integer_zerop (off))
7150 t = boolean_true_node;
7151 else
7153 tree a;
7154 tree co = fold_convert_loc (loc, itype, off);
7155 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7157 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7158 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
7159 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
7160 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
7161 co);
7163 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7164 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7165 fd->loops[i].v, co);
7166 else
7167 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7168 fd->loops[i].v, co);
7169 if (fd->loops[i].cond_code == LT_EXPR)
7171 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7172 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
7173 fd->loops[i].n1);
7174 else
7175 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
7176 fd->loops[i].n2);
7178 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7179 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
7180 fd->loops[i].n2);
7181 else
7182 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
7183 fd->loops[i].n1);
7185 if (cond)
7186 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
7187 else
7188 cond = t;
7190 off = fold_convert_loc (loc, itype, off);
7192 if (fd->loops[i].cond_code == LT_EXPR
7193 ? !integer_onep (fd->loops[i].step)
7194 : !integer_minus_onep (fd->loops[i].step))
7196 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7197 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
7198 fold_build1_loc (loc, NEGATE_EXPR, itype,
7199 s));
7200 else
7201 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
7202 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
7203 build_int_cst (itype, 0));
7204 if (integer_zerop (t) && !warned_step)
7206 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
7207 "in the iteration space");
7208 warned_step = true;
7210 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
7211 cond, t);
7214 if (i <= fd->collapse - 1 && fd->collapse > 1)
7215 t = fd->loop.v;
7216 else if (counts[i])
7217 t = counts[i];
7218 else
7220 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7221 fd->loops[i].v, fd->loops[i].n1);
7222 t = fold_convert_loc (loc, fd->iter_type, t);
7224 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7225 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
7226 fold_build1_loc (loc, NEGATE_EXPR, itype,
7227 s));
7228 else
7229 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
7230 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7231 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
7232 off = fold_convert_loc (loc, fd->iter_type, off);
7233 if (i <= fd->collapse - 1 && fd->collapse > 1)
7235 if (i)
7236 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
7237 off);
7238 if (i < fd->collapse - 1)
7240 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
7241 counts[i]);
7242 continue;
7245 off = unshare_expr (off);
7246 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
7247 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
7248 true, GSI_SAME_STMT);
7249 args.safe_push (t);
7251 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
7252 gimple_set_location (g, loc);
7253 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7255 *gsi = gsi_last_bb (e1->src);
7256 cond = unshare_expr (cond);
7257 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
7258 GSI_CONTINUE_LINKING);
7259 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
7260 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
7261 e3->probability = REG_BR_PROB_BASE / 8;
7262 e1->probability = REG_BR_PROB_BASE - e3->probability;
7263 e1->flags = EDGE_TRUE_VALUE;
7264 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
7266 *gsi = gsi_after_labels (e2->dest);
7269 /* Expand all #pragma omp ordered depend(source) and
7270 #pragma omp ordered depend(sink:...) constructs in the current
7271 #pragma omp for ordered(n) region. */
7273 static void
7274 expand_omp_ordered_source_sink (struct omp_region *region,
7275 struct omp_for_data *fd, tree *counts,
7276 basic_block cont_bb)
7278 struct omp_region *inner;
7279 int i;
7280 for (i = fd->collapse - 1; i < fd->ordered; i++)
7281 if (i == fd->collapse - 1 && fd->collapse > 1)
7282 counts[i] = NULL_TREE;
7283 else if (i >= fd->collapse && !cont_bb)
7284 counts[i] = build_zero_cst (fd->iter_type);
7285 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
7286 && integer_onep (fd->loops[i].step))
7287 counts[i] = NULL_TREE;
7288 else
7289 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
7290 tree atype
7291 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
7292 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
7293 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
7295 for (inner = region->inner; inner; inner = inner->next)
7296 if (inner->type == GIMPLE_OMP_ORDERED)
7298 gomp_ordered *ord_stmt = inner->ord_stmt;
7299 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
7300 location_t loc = gimple_location (ord_stmt);
7301 tree c;
7302 for (c = gimple_omp_ordered_clauses (ord_stmt);
7303 c; c = OMP_CLAUSE_CHAIN (c))
7304 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
7305 break;
7306 if (c)
7307 expand_omp_ordered_source (&gsi, fd, counts, loc);
7308 for (c = gimple_omp_ordered_clauses (ord_stmt);
7309 c; c = OMP_CLAUSE_CHAIN (c))
7310 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
7311 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
7312 gsi_remove (&gsi, true);
7316 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
7317 collapsed. */
7319 static basic_block
7320 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
7321 basic_block cont_bb, basic_block body_bb,
7322 bool ordered_lastprivate)
7324 if (fd->ordered == fd->collapse)
7325 return cont_bb;
7327 if (!cont_bb)
7329 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7330 for (int i = fd->collapse; i < fd->ordered; i++)
7332 tree type = TREE_TYPE (fd->loops[i].v);
7333 tree n1 = fold_convert (type, fd->loops[i].n1);
7334 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
7335 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7336 size_int (i - fd->collapse + 1),
7337 NULL_TREE, NULL_TREE);
7338 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
7340 return NULL;
7343 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
7345 tree t, type = TREE_TYPE (fd->loops[i].v);
7346 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7347 expand_omp_build_assign (&gsi, fd->loops[i].v,
7348 fold_convert (type, fd->loops[i].n1));
7349 if (counts[i])
7350 expand_omp_build_assign (&gsi, counts[i],
7351 build_zero_cst (fd->iter_type));
7352 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7353 size_int (i - fd->collapse + 1),
7354 NULL_TREE, NULL_TREE);
7355 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
7356 if (!gsi_end_p (gsi))
7357 gsi_prev (&gsi);
7358 else
7359 gsi = gsi_last_bb (body_bb);
7360 edge e1 = split_block (body_bb, gsi_stmt (gsi));
7361 basic_block new_body = e1->dest;
7362 if (body_bb == cont_bb)
7363 cont_bb = new_body;
7364 edge e2 = NULL;
7365 basic_block new_header;
7366 if (EDGE_COUNT (cont_bb->preds) > 0)
7368 gsi = gsi_last_bb (cont_bb);
7369 if (POINTER_TYPE_P (type))
7370 t = fold_build_pointer_plus (fd->loops[i].v,
7371 fold_convert (sizetype,
7372 fd->loops[i].step));
7373 else
7374 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
7375 fold_convert (type, fd->loops[i].step));
7376 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7377 if (counts[i])
7379 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
7380 build_int_cst (fd->iter_type, 1));
7381 expand_omp_build_assign (&gsi, counts[i], t);
7382 t = counts[i];
7384 else
7386 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7387 fd->loops[i].v, fd->loops[i].n1);
7388 t = fold_convert (fd->iter_type, t);
7389 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7390 true, GSI_SAME_STMT);
7392 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7393 size_int (i - fd->collapse + 1),
7394 NULL_TREE, NULL_TREE);
7395 expand_omp_build_assign (&gsi, aref, t);
7396 gsi_prev (&gsi);
7397 e2 = split_block (cont_bb, gsi_stmt (gsi));
7398 new_header = e2->dest;
7400 else
7401 new_header = cont_bb;
7402 gsi = gsi_after_labels (new_header);
7403 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
7404 true, GSI_SAME_STMT);
7405 tree n2
7406 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
7407 true, NULL_TREE, true, GSI_SAME_STMT);
7408 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
7409 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
7410 edge e3 = split_block (new_header, gsi_stmt (gsi));
7411 cont_bb = e3->dest;
7412 remove_edge (e1);
7413 make_edge (body_bb, new_header, EDGE_FALLTHRU);
7414 e3->flags = EDGE_FALSE_VALUE;
7415 e3->probability = REG_BR_PROB_BASE / 8;
7416 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
7417 e1->probability = REG_BR_PROB_BASE - e3->probability;
7419 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
7420 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
7422 if (e2)
7424 struct loop *loop = alloc_loop ();
7425 loop->header = new_header;
7426 loop->latch = e2->src;
7427 add_loop (loop, body_bb->loop_father);
7431 /* If there are any lastprivate clauses and it is possible some loops
7432 might have zero iterations, ensure all the decls are initialized,
7433 otherwise we could crash evaluating C++ class iterators with lastprivate
7434 clauses. */
7435 bool need_inits = false;
7436 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
7437 if (need_inits)
7439 tree type = TREE_TYPE (fd->loops[i].v);
7440 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7441 expand_omp_build_assign (&gsi, fd->loops[i].v,
7442 fold_convert (type, fd->loops[i].n1));
7444 else
7446 tree type = TREE_TYPE (fd->loops[i].v);
7447 tree this_cond = fold_build2 (fd->loops[i].cond_code,
7448 boolean_type_node,
7449 fold_convert (type, fd->loops[i].n1),
7450 fold_convert (type, fd->loops[i].n2));
7451 if (!integer_onep (this_cond))
7452 need_inits = true;
7455 return cont_bb;
7459 /* A subroutine of expand_omp_for. Generate code for a parallel
7460 loop with any schedule. Given parameters:
7462 for (V = N1; V cond N2; V += STEP) BODY;
7464 where COND is "<" or ">", we generate pseudocode
7466 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
7467 if (more) goto L0; else goto L3;
7469 V = istart0;
7470 iend = iend0;
7472 BODY;
7473 V += STEP;
7474 if (V cond iend) goto L1; else goto L2;
7476 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
7479 If this is a combined omp parallel loop, instead of the call to
7480 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
7481 If this is gimple_omp_for_combined_p loop, then instead of assigning
7482 V and iend in L0 we assign the first two _looptemp_ clause decls of the
7483 inner GIMPLE_OMP_FOR and V += STEP; and
7484 if (V cond iend) goto L1; else goto L2; are removed.
7486 For collapsed loops, given parameters:
7487 collapse(3)
7488 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7489 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7490 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7491 BODY;
7493 we generate pseudocode
7495 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
7496 if (cond3 is <)
7497 adj = STEP3 - 1;
7498 else
7499 adj = STEP3 + 1;
7500 count3 = (adj + N32 - N31) / STEP3;
7501 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
7502 if (cond2 is <)
7503 adj = STEP2 - 1;
7504 else
7505 adj = STEP2 + 1;
7506 count2 = (adj + N22 - N21) / STEP2;
7507 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
7508 if (cond1 is <)
7509 adj = STEP1 - 1;
7510 else
7511 adj = STEP1 + 1;
7512 count1 = (adj + N12 - N11) / STEP1;
7513 count = count1 * count2 * count3;
7514 goto Z1;
7516 count = 0;
7518 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
7519 if (more) goto L0; else goto L3;
7521 V = istart0;
7522 T = V;
7523 V3 = N31 + (T % count3) * STEP3;
7524 T = T / count3;
7525 V2 = N21 + (T % count2) * STEP2;
7526 T = T / count2;
7527 V1 = N11 + T * STEP1;
7528 iend = iend0;
7530 BODY;
7531 V += 1;
7532 if (V < iend) goto L10; else goto L2;
7533 L10:
7534 V3 += STEP3;
7535 if (V3 cond3 N32) goto L1; else goto L11;
7536 L11:
7537 V3 = N31;
7538 V2 += STEP2;
7539 if (V2 cond2 N22) goto L1; else goto L12;
7540 L12:
7541 V2 = N21;
7542 V1 += STEP1;
7543 goto L1;
7545 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
7550 static void
7551 expand_omp_for_generic (struct omp_region *region,
7552 struct omp_for_data *fd,
7553 enum built_in_function start_fn,
7554 enum built_in_function next_fn,
7555 gimple *inner_stmt)
7557 tree type, istart0, iend0, iend;
7558 tree t, vmain, vback, bias = NULL_TREE;
7559 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
7560 basic_block l2_bb = NULL, l3_bb = NULL;
7561 gimple_stmt_iterator gsi;
7562 gassign *assign_stmt;
7563 bool in_combined_parallel = is_combined_parallel (region);
7564 bool broken_loop = region->cont == NULL;
7565 edge e, ne;
7566 tree *counts = NULL;
7567 int i;
7568 bool ordered_lastprivate = false;
7570 gcc_assert (!broken_loop || !in_combined_parallel);
7571 gcc_assert (fd->iter_type == long_integer_type_node
7572 || !in_combined_parallel);
7574 entry_bb = region->entry;
7575 cont_bb = region->cont;
7576 collapse_bb = NULL;
7577 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7578 gcc_assert (broken_loop
7579 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7580 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
7581 l1_bb = single_succ (l0_bb);
7582 if (!broken_loop)
7584 l2_bb = create_empty_bb (cont_bb);
7585 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
7586 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
7587 == l1_bb));
7588 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7590 else
7591 l2_bb = NULL;
7592 l3_bb = BRANCH_EDGE (entry_bb)->dest;
7593 exit_bb = region->exit;
7595 gsi = gsi_last_bb (entry_bb);
7597 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7598 if (fd->ordered
7599 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
7600 OMP_CLAUSE_LASTPRIVATE))
7601 ordered_lastprivate = false;
7602 if (fd->collapse > 1 || fd->ordered)
7604 int first_zero_iter1 = -1, first_zero_iter2 = -1;
7605 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
7607 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
7608 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7609 zero_iter1_bb, first_zero_iter1,
7610 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
7612 if (zero_iter1_bb)
7614 /* Some counts[i] vars might be uninitialized if
7615 some loop has zero iterations. But the body shouldn't
7616 be executed in that case, so just avoid uninit warnings. */
7617 for (i = first_zero_iter1;
7618 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7619 if (SSA_VAR_P (counts[i]))
7620 TREE_NO_WARNING (counts[i]) = 1;
7621 gsi_prev (&gsi);
7622 e = split_block (entry_bb, gsi_stmt (gsi));
7623 entry_bb = e->dest;
7624 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
7625 gsi = gsi_last_bb (entry_bb);
7626 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
7627 get_immediate_dominator (CDI_DOMINATORS,
7628 zero_iter1_bb));
7630 if (zero_iter2_bb)
7632 /* Some counts[i] vars might be uninitialized if
7633 some loop has zero iterations. But the body shouldn't
7634 be executed in that case, so just avoid uninit warnings. */
7635 for (i = first_zero_iter2; i < fd->ordered; i++)
7636 if (SSA_VAR_P (counts[i]))
7637 TREE_NO_WARNING (counts[i]) = 1;
7638 if (zero_iter1_bb)
7639 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
7640 else
7642 gsi_prev (&gsi);
7643 e = split_block (entry_bb, gsi_stmt (gsi));
7644 entry_bb = e->dest;
7645 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
7646 gsi = gsi_last_bb (entry_bb);
7647 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
7648 get_immediate_dominator
7649 (CDI_DOMINATORS, zero_iter2_bb));
7652 if (fd->collapse == 1)
7654 counts[0] = fd->loop.n2;
7655 fd->loop = fd->loops[0];
7659 type = TREE_TYPE (fd->loop.v);
7660 istart0 = create_tmp_var (fd->iter_type, ".istart0");
7661 iend0 = create_tmp_var (fd->iter_type, ".iend0");
7662 TREE_ADDRESSABLE (istart0) = 1;
7663 TREE_ADDRESSABLE (iend0) = 1;
7665 /* See if we need to bias by LLONG_MIN. */
7666 if (fd->iter_type == long_long_unsigned_type_node
7667 && TREE_CODE (type) == INTEGER_TYPE
7668 && !TYPE_UNSIGNED (type)
7669 && fd->ordered == 0)
7671 tree n1, n2;
7673 if (fd->loop.cond_code == LT_EXPR)
7675 n1 = fd->loop.n1;
7676 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
7678 else
7680 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
7681 n2 = fd->loop.n1;
7683 if (TREE_CODE (n1) != INTEGER_CST
7684 || TREE_CODE (n2) != INTEGER_CST
7685 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
7686 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
7689 gimple_stmt_iterator gsif = gsi;
7690 gsi_prev (&gsif);
7692 tree arr = NULL_TREE;
7693 if (in_combined_parallel)
7695 gcc_assert (fd->ordered == 0);
7696 /* In a combined parallel loop, emit a call to
7697 GOMP_loop_foo_next. */
7698 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
7699 build_fold_addr_expr (istart0),
7700 build_fold_addr_expr (iend0));
7702 else
7704 tree t0, t1, t2, t3, t4;
7705 /* If this is not a combined parallel loop, emit a call to
7706 GOMP_loop_foo_start in ENTRY_BB. */
7707 t4 = build_fold_addr_expr (iend0);
7708 t3 = build_fold_addr_expr (istart0);
7709 if (fd->ordered)
7711 t0 = build_int_cst (unsigned_type_node,
7712 fd->ordered - fd->collapse + 1);
7713 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
7714 fd->ordered
7715 - fd->collapse + 1),
7716 ".omp_counts");
7717 DECL_NAMELESS (arr) = 1;
7718 TREE_ADDRESSABLE (arr) = 1;
7719 TREE_STATIC (arr) = 1;
7720 vec<constructor_elt, va_gc> *v;
7721 vec_alloc (v, fd->ordered - fd->collapse + 1);
7722 int idx;
7724 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
7726 tree c;
7727 if (idx == 0 && fd->collapse > 1)
7728 c = fd->loop.n2;
7729 else
7730 c = counts[idx + fd->collapse - 1];
7731 tree purpose = size_int (idx);
7732 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
7733 if (TREE_CODE (c) != INTEGER_CST)
7734 TREE_STATIC (arr) = 0;
7737 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
7738 if (!TREE_STATIC (arr))
7739 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
7740 void_type_node, arr),
7741 true, NULL_TREE, true, GSI_SAME_STMT);
7742 t1 = build_fold_addr_expr (arr);
7743 t2 = NULL_TREE;
7745 else
7747 t2 = fold_convert (fd->iter_type, fd->loop.step);
7748 t1 = fd->loop.n2;
7749 t0 = fd->loop.n1;
7750 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7752 tree innerc
7753 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7754 OMP_CLAUSE__LOOPTEMP_);
7755 gcc_assert (innerc);
7756 t0 = OMP_CLAUSE_DECL (innerc);
7757 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7758 OMP_CLAUSE__LOOPTEMP_);
7759 gcc_assert (innerc);
7760 t1 = OMP_CLAUSE_DECL (innerc);
7762 if (POINTER_TYPE_P (TREE_TYPE (t0))
7763 && TYPE_PRECISION (TREE_TYPE (t0))
7764 != TYPE_PRECISION (fd->iter_type))
7766 /* Avoid casting pointers to integer of a different size. */
7767 tree itype = signed_type_for (type);
7768 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
7769 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
7771 else
7773 t1 = fold_convert (fd->iter_type, t1);
7774 t0 = fold_convert (fd->iter_type, t0);
7776 if (bias)
7778 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
7779 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
7782 if (fd->iter_type == long_integer_type_node || fd->ordered)
7784 if (fd->chunk_size)
7786 t = fold_convert (fd->iter_type, fd->chunk_size);
7787 t = omp_adjust_chunk_size (t, fd->simd_schedule);
7788 if (fd->ordered)
7789 t = build_call_expr (builtin_decl_explicit (start_fn),
7790 5, t0, t1, t, t3, t4);
7791 else
7792 t = build_call_expr (builtin_decl_explicit (start_fn),
7793 6, t0, t1, t2, t, t3, t4);
7795 else if (fd->ordered)
7796 t = build_call_expr (builtin_decl_explicit (start_fn),
7797 4, t0, t1, t3, t4);
7798 else
7799 t = build_call_expr (builtin_decl_explicit (start_fn),
7800 5, t0, t1, t2, t3, t4);
7802 else
7804 tree t5;
7805 tree c_bool_type;
7806 tree bfn_decl;
7808 /* The GOMP_loop_ull_*start functions have additional boolean
7809 argument, true for < loops and false for > loops.
7810 In Fortran, the C bool type can be different from
7811 boolean_type_node. */
7812 bfn_decl = builtin_decl_explicit (start_fn);
7813 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
7814 t5 = build_int_cst (c_bool_type,
7815 fd->loop.cond_code == LT_EXPR ? 1 : 0);
7816 if (fd->chunk_size)
7818 tree bfn_decl = builtin_decl_explicit (start_fn);
7819 t = fold_convert (fd->iter_type, fd->chunk_size);
7820 t = omp_adjust_chunk_size (t, fd->simd_schedule);
7821 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
7823 else
7824 t = build_call_expr (builtin_decl_explicit (start_fn),
7825 6, t5, t0, t1, t2, t3, t4);
7828 if (TREE_TYPE (t) != boolean_type_node)
7829 t = fold_build2 (NE_EXPR, boolean_type_node,
7830 t, build_int_cst (TREE_TYPE (t), 0));
7831 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7832 true, GSI_SAME_STMT);
7833 if (arr && !TREE_STATIC (arr))
7835 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
7836 TREE_THIS_VOLATILE (clobber) = 1;
7837 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
7838 GSI_SAME_STMT);
7840 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7842 /* Remove the GIMPLE_OMP_FOR statement. */
7843 gsi_remove (&gsi, true);
7845 if (gsi_end_p (gsif))
7846 gsif = gsi_after_labels (gsi_bb (gsif));
7847 gsi_next (&gsif);
7849 /* Iteration setup for sequential loop goes in L0_BB. */
7850 tree startvar = fd->loop.v;
7851 tree endvar = NULL_TREE;
7853 if (gimple_omp_for_combined_p (fd->for_stmt))
7855 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
7856 && gimple_omp_for_kind (inner_stmt)
7857 == GF_OMP_FOR_KIND_SIMD);
7858 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
7859 OMP_CLAUSE__LOOPTEMP_);
7860 gcc_assert (innerc);
7861 startvar = OMP_CLAUSE_DECL (innerc);
7862 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7863 OMP_CLAUSE__LOOPTEMP_);
7864 gcc_assert (innerc);
7865 endvar = OMP_CLAUSE_DECL (innerc);
7868 gsi = gsi_start_bb (l0_bb);
7869 t = istart0;
7870 if (fd->ordered && fd->collapse == 1)
7871 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
7872 fold_convert (fd->iter_type, fd->loop.step));
7873 else if (bias)
7874 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
7875 if (fd->ordered && fd->collapse == 1)
7877 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
7878 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
7879 fd->loop.n1, fold_convert (sizetype, t));
7880 else
7882 t = fold_convert (TREE_TYPE (startvar), t);
7883 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
7884 fd->loop.n1, t);
7887 else
7889 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
7890 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
7891 t = fold_convert (TREE_TYPE (startvar), t);
7893 t = force_gimple_operand_gsi (&gsi, t,
7894 DECL_P (startvar)
7895 && TREE_ADDRESSABLE (startvar),
7896 NULL_TREE, false, GSI_CONTINUE_LINKING);
7897 assign_stmt = gimple_build_assign (startvar, t);
7898 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7900 t = iend0;
7901 if (fd->ordered && fd->collapse == 1)
7902 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
7903 fold_convert (fd->iter_type, fd->loop.step));
7904 else if (bias)
7905 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
7906 if (fd->ordered && fd->collapse == 1)
7908 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
7909 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
7910 fd->loop.n1, fold_convert (sizetype, t));
7911 else
7913 t = fold_convert (TREE_TYPE (startvar), t);
7914 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
7915 fd->loop.n1, t);
7918 else
7920 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
7921 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
7922 t = fold_convert (TREE_TYPE (startvar), t);
7924 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7925 false, GSI_CONTINUE_LINKING);
7926 if (endvar)
7928 assign_stmt = gimple_build_assign (endvar, iend);
7929 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7930 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
7931 assign_stmt = gimple_build_assign (fd->loop.v, iend);
7932 else
7933 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
7934 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7936 /* Handle linear clause adjustments. */
7937 tree itercnt = NULL_TREE;
7938 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
7939 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
7940 c; c = OMP_CLAUSE_CHAIN (c))
7941 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
7942 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
7944 tree d = OMP_CLAUSE_DECL (c);
7945 bool is_ref = is_reference (d);
7946 tree t = d, a, dest;
7947 if (is_ref)
7948 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
7949 tree type = TREE_TYPE (t);
7950 if (POINTER_TYPE_P (type))
7951 type = sizetype;
7952 dest = unshare_expr (t);
7953 tree v = create_tmp_var (TREE_TYPE (t), NULL);
7954 expand_omp_build_assign (&gsif, v, t);
7955 if (itercnt == NULL_TREE)
7957 itercnt = startvar;
7958 tree n1 = fd->loop.n1;
7959 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
7961 itercnt
7962 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
7963 itercnt);
7964 n1 = fold_convert (TREE_TYPE (itercnt), n1);
7966 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
7967 itercnt, n1);
7968 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
7969 itercnt, fd->loop.step);
7970 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
7971 NULL_TREE, false,
7972 GSI_CONTINUE_LINKING);
7974 a = fold_build2 (MULT_EXPR, type,
7975 fold_convert (type, itercnt),
7976 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
7977 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
7978 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
7979 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7980 false, GSI_CONTINUE_LINKING);
7981 assign_stmt = gimple_build_assign (dest, t);
7982 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7984 if (fd->collapse > 1)
7985 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7987 if (fd->ordered)
7989 /* Until now, counts array contained number of iterations or
7990 variable containing it for ith loop. From now on, we need
7991 those counts only for collapsed loops, and only for the 2nd
7992 till the last collapsed one. Move those one element earlier,
7993 we'll use counts[fd->collapse - 1] for the first source/sink
7994 iteration counter and so on and counts[fd->ordered]
7995 as the array holding the current counter values for
7996 depend(source). */
7997 if (fd->collapse > 1)
7998 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
7999 if (broken_loop)
8001 int i;
8002 for (i = fd->collapse; i < fd->ordered; i++)
8004 tree type = TREE_TYPE (fd->loops[i].v);
8005 tree this_cond
8006 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8007 fold_convert (type, fd->loops[i].n1),
8008 fold_convert (type, fd->loops[i].n2));
8009 if (!integer_onep (this_cond))
8010 break;
8012 if (i < fd->ordered)
8014 cont_bb
8015 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8016 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8017 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8018 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8019 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8020 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8021 make_edge (cont_bb, l1_bb, 0);
8022 l2_bb = create_empty_bb (cont_bb);
8023 broken_loop = false;
8026 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8027 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8028 ordered_lastprivate);
8029 if (counts[fd->collapse - 1])
8031 gcc_assert (fd->collapse == 1);
8032 gsi = gsi_last_bb (l0_bb);
8033 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8034 istart0, true);
8035 gsi = gsi_last_bb (cont_bb);
8036 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8037 build_int_cst (fd->iter_type, 1));
8038 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8039 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8040 size_zero_node, NULL_TREE, NULL_TREE);
8041 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8042 t = counts[fd->collapse - 1];
8044 else if (fd->collapse > 1)
8045 t = fd->loop.v;
8046 else
8048 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8049 fd->loops[0].v, fd->loops[0].n1);
8050 t = fold_convert (fd->iter_type, t);
8052 gsi = gsi_last_bb (l0_bb);
8053 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8054 size_zero_node, NULL_TREE, NULL_TREE);
8055 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8056 false, GSI_CONTINUE_LINKING);
8057 expand_omp_build_assign (&gsi, aref, t, true);
8060 if (!broken_loop)
8062 /* Code to control the increment and predicate for the sequential
8063 loop goes in the CONT_BB. */
8064 gsi = gsi_last_bb (cont_bb);
8065 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8066 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8067 vmain = gimple_omp_continue_control_use (cont_stmt);
8068 vback = gimple_omp_continue_control_def (cont_stmt);
8070 if (!gimple_omp_for_combined_p (fd->for_stmt))
8072 if (POINTER_TYPE_P (type))
8073 t = fold_build_pointer_plus (vmain, fd->loop.step);
8074 else
8075 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8076 t = force_gimple_operand_gsi (&gsi, t,
8077 DECL_P (vback)
8078 && TREE_ADDRESSABLE (vback),
8079 NULL_TREE, true, GSI_SAME_STMT);
8080 assign_stmt = gimple_build_assign (vback, t);
8081 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8083 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8085 if (fd->collapse > 1)
8086 t = fd->loop.v;
8087 else
8089 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8090 fd->loops[0].v, fd->loops[0].n1);
8091 t = fold_convert (fd->iter_type, t);
8093 tree aref = build4 (ARRAY_REF, fd->iter_type,
8094 counts[fd->ordered], size_zero_node,
8095 NULL_TREE, NULL_TREE);
8096 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8097 true, GSI_SAME_STMT);
8098 expand_omp_build_assign (&gsi, aref, t);
8101 t = build2 (fd->loop.cond_code, boolean_type_node,
8102 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8103 iend);
8104 gcond *cond_stmt = gimple_build_cond_empty (t);
8105 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8108 /* Remove GIMPLE_OMP_CONTINUE. */
8109 gsi_remove (&gsi, true);
8111 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
8112 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
8114 /* Emit code to get the next parallel iteration in L2_BB. */
8115 gsi = gsi_start_bb (l2_bb);
8117 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8118 build_fold_addr_expr (istart0),
8119 build_fold_addr_expr (iend0));
8120 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8121 false, GSI_CONTINUE_LINKING);
8122 if (TREE_TYPE (t) != boolean_type_node)
8123 t = fold_build2 (NE_EXPR, boolean_type_node,
8124 t, build_int_cst (TREE_TYPE (t), 0));
8125 gcond *cond_stmt = gimple_build_cond_empty (t);
8126 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
8129 /* Add the loop cleanup function. */
8130 gsi = gsi_last_bb (exit_bb);
8131 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
8132 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
8133 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8134 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
8135 else
8136 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
8137 gcall *call_stmt = gimple_build_call (t, 0);
8138 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8139 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
8140 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
8141 if (fd->ordered)
8143 tree arr = counts[fd->ordered];
8144 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8145 TREE_THIS_VOLATILE (clobber) = 1;
8146 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
8147 GSI_SAME_STMT);
8149 gsi_remove (&gsi, true);
8151 /* Connect the new blocks. */
8152 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
8153 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
8155 if (!broken_loop)
8157 gimple_seq phis;
8159 e = find_edge (cont_bb, l3_bb);
8160 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
8162 phis = phi_nodes (l3_bb);
8163 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
8165 gimple *phi = gsi_stmt (gsi);
8166 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
8167 PHI_ARG_DEF_FROM_EDGE (phi, e));
8169 remove_edge (e);
8171 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
8172 e = find_edge (cont_bb, l1_bb);
8173 if (e == NULL)
8175 e = BRANCH_EDGE (cont_bb);
8176 gcc_assert (single_succ (e->dest) == l1_bb);
8178 if (gimple_omp_for_combined_p (fd->for_stmt))
8180 remove_edge (e);
8181 e = NULL;
8183 else if (fd->collapse > 1)
8185 remove_edge (e);
8186 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
8188 else
8189 e->flags = EDGE_TRUE_VALUE;
8190 if (e)
8192 e->probability = REG_BR_PROB_BASE * 7 / 8;
8193 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
8195 else
8197 e = find_edge (cont_bb, l2_bb);
8198 e->flags = EDGE_FALLTHRU;
8200 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
8202 if (gimple_in_ssa_p (cfun))
8204 /* Add phis to the outer loop that connect to the phis in the inner,
8205 original loop, and move the loop entry value of the inner phi to
8206 the loop entry value of the outer phi. */
8207 gphi_iterator psi;
8208 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
8210 source_location locus;
8211 gphi *nphi;
8212 gphi *exit_phi = psi.phi ();
8214 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
8215 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
8217 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
8218 edge latch_to_l1 = find_edge (latch, l1_bb);
8219 gphi *inner_phi
8220 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
8222 tree t = gimple_phi_result (exit_phi);
8223 tree new_res = copy_ssa_name (t, NULL);
8224 nphi = create_phi_node (new_res, l0_bb);
8226 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
8227 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
8228 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
8229 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
8230 add_phi_arg (nphi, t, entry_to_l0, locus);
8232 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
8233 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
8235 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
8239 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
8240 recompute_dominator (CDI_DOMINATORS, l2_bb));
8241 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
8242 recompute_dominator (CDI_DOMINATORS, l3_bb));
8243 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
8244 recompute_dominator (CDI_DOMINATORS, l0_bb));
8245 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
8246 recompute_dominator (CDI_DOMINATORS, l1_bb));
8248 /* We enter expand_omp_for_generic with a loop. This original loop may
8249 have its own loop struct, or it may be part of an outer loop struct
8250 (which may be the fake loop). */
8251 struct loop *outer_loop = entry_bb->loop_father;
8252 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
8254 add_bb_to_loop (l2_bb, outer_loop);
8256 /* We've added a new loop around the original loop. Allocate the
8257 corresponding loop struct. */
8258 struct loop *new_loop = alloc_loop ();
8259 new_loop->header = l0_bb;
8260 new_loop->latch = l2_bb;
8261 add_loop (new_loop, outer_loop);
8263 /* Allocate a loop structure for the original loop unless we already
8264 had one. */
8265 if (!orig_loop_has_loop_struct
8266 && !gimple_omp_for_combined_p (fd->for_stmt))
8268 struct loop *orig_loop = alloc_loop ();
8269 orig_loop->header = l1_bb;
8270 /* The loop may have multiple latches. */
8271 add_loop (orig_loop, new_loop);
8277 /* A subroutine of expand_omp_for. Generate code for a parallel
8278 loop with static schedule and no specified chunk size. Given
8279 parameters:
8281 for (V = N1; V cond N2; V += STEP) BODY;
8283 where COND is "<" or ">", we generate pseudocode
8285 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
8286 if (cond is <)
8287 adj = STEP - 1;
8288 else
8289 adj = STEP + 1;
8290 if ((__typeof (V)) -1 > 0 && cond is >)
8291 n = -(adj + N2 - N1) / -STEP;
8292 else
8293 n = (adj + N2 - N1) / STEP;
8294 q = n / nthreads;
8295 tt = n % nthreads;
8296 if (threadid < tt) goto L3; else goto L4;
8298 tt = 0;
8299 q = q + 1;
8301 s0 = q * threadid + tt;
8302 e0 = s0 + q;
8303 V = s0 * STEP + N1;
8304 if (s0 >= e0) goto L2; else goto L0;
8306 e = e0 * STEP + N1;
8308 BODY;
8309 V += STEP;
8310 if (V cond e) goto L1;
8314 static void
8315 expand_omp_for_static_nochunk (struct omp_region *region,
8316 struct omp_for_data *fd,
8317 gimple *inner_stmt)
8319 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
8320 tree type, itype, vmain, vback;
8321 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
8322 basic_block body_bb, cont_bb, collapse_bb = NULL;
8323 basic_block fin_bb;
8324 gimple_stmt_iterator gsi;
8325 edge ep;
8326 bool broken_loop = region->cont == NULL;
8327 tree *counts = NULL;
8328 tree n1, n2, step;
8330 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
8331 != GF_OMP_FOR_KIND_OACC_LOOP)
8332 || !inner_stmt);
8334 itype = type = TREE_TYPE (fd->loop.v);
8335 if (POINTER_TYPE_P (type))
8336 itype = signed_type_for (type);
8338 entry_bb = region->entry;
8339 cont_bb = region->cont;
8340 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8341 fin_bb = BRANCH_EDGE (entry_bb)->dest;
8342 gcc_assert (broken_loop
8343 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
8344 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8345 body_bb = single_succ (seq_start_bb);
8346 if (!broken_loop)
8348 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
8349 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
8350 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8352 exit_bb = region->exit;
8354 /* Iteration space partitioning goes in ENTRY_BB. */
8355 gsi = gsi_last_bb (entry_bb);
8356 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8358 if (fd->collapse > 1)
8360 int first_zero_iter = -1, dummy = -1;
8361 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
8363 counts = XALLOCAVEC (tree, fd->collapse);
8364 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8365 fin_bb, first_zero_iter,
8366 dummy_bb, dummy, l2_dom_bb);
8367 t = NULL_TREE;
8369 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
8370 t = integer_one_node;
8371 else
8372 t = fold_binary (fd->loop.cond_code, boolean_type_node,
8373 fold_convert (type, fd->loop.n1),
8374 fold_convert (type, fd->loop.n2));
8375 if (fd->collapse == 1
8376 && TYPE_UNSIGNED (type)
8377 && (t == NULL_TREE || !integer_onep (t)))
8379 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
8380 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
8381 true, GSI_SAME_STMT);
8382 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
8383 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
8384 true, GSI_SAME_STMT);
8385 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
8386 NULL_TREE, NULL_TREE);
8387 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8388 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8389 expand_omp_regimplify_p, NULL, NULL)
8390 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8391 expand_omp_regimplify_p, NULL, NULL))
8393 gsi = gsi_for_stmt (cond_stmt);
8394 gimple_regimplify_operands (cond_stmt, &gsi);
8396 ep = split_block (entry_bb, cond_stmt);
8397 ep->flags = EDGE_TRUE_VALUE;
8398 entry_bb = ep->dest;
8399 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
8400 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
8401 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
8402 if (gimple_in_ssa_p (cfun))
8404 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
8405 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
8406 !gsi_end_p (gpi); gsi_next (&gpi))
8408 gphi *phi = gpi.phi ();
8409 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
8410 ep, UNKNOWN_LOCATION);
8413 gsi = gsi_last_bb (entry_bb);
8416 switch (gimple_omp_for_kind (fd->for_stmt))
8418 case GF_OMP_FOR_KIND_FOR:
8419 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
8420 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8421 break;
8422 case GF_OMP_FOR_KIND_DISTRIBUTE:
8423 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
8424 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
8425 break;
8426 case GF_OMP_FOR_KIND_OACC_LOOP:
8427 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
8428 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
8429 break;
8430 default:
8431 gcc_unreachable ();
8433 nthreads = build_call_expr (nthreads, 0);
8434 nthreads = fold_convert (itype, nthreads);
8435 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
8436 true, GSI_SAME_STMT);
8437 threadid = build_call_expr (threadid, 0);
8438 threadid = fold_convert (itype, threadid);
8439 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
8440 true, GSI_SAME_STMT);
8442 n1 = fd->loop.n1;
8443 n2 = fd->loop.n2;
8444 step = fd->loop.step;
8445 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8447 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8448 OMP_CLAUSE__LOOPTEMP_);
8449 gcc_assert (innerc);
8450 n1 = OMP_CLAUSE_DECL (innerc);
8451 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8452 OMP_CLAUSE__LOOPTEMP_);
8453 gcc_assert (innerc);
8454 n2 = OMP_CLAUSE_DECL (innerc);
8456 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
8457 true, NULL_TREE, true, GSI_SAME_STMT);
8458 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
8459 true, NULL_TREE, true, GSI_SAME_STMT);
8460 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
8461 true, NULL_TREE, true, GSI_SAME_STMT);
8463 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
8464 t = fold_build2 (PLUS_EXPR, itype, step, t);
8465 t = fold_build2 (PLUS_EXPR, itype, t, n2);
8466 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
8467 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
8468 t = fold_build2 (TRUNC_DIV_EXPR, itype,
8469 fold_build1 (NEGATE_EXPR, itype, t),
8470 fold_build1 (NEGATE_EXPR, itype, step));
8471 else
8472 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
8473 t = fold_convert (itype, t);
8474 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
8476 q = create_tmp_reg (itype, "q");
8477 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
8478 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
8479 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
8481 tt = create_tmp_reg (itype, "tt");
8482 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
8483 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
8484 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
8486 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
8487 gcond *cond_stmt = gimple_build_cond_empty (t);
8488 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8490 second_bb = split_block (entry_bb, cond_stmt)->dest;
8491 gsi = gsi_last_bb (second_bb);
8492 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8494 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
8495 GSI_SAME_STMT);
8496 gassign *assign_stmt
8497 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
8498 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8500 third_bb = split_block (second_bb, assign_stmt)->dest;
8501 gsi = gsi_last_bb (third_bb);
8502 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8504 t = build2 (MULT_EXPR, itype, q, threadid);
8505 t = build2 (PLUS_EXPR, itype, t, tt);
8506 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
8508 t = fold_build2 (PLUS_EXPR, itype, s0, q);
8509 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
8511 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
8512 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8514 /* Remove the GIMPLE_OMP_FOR statement. */
8515 gsi_remove (&gsi, true);
8517 /* Setup code for sequential iteration goes in SEQ_START_BB. */
8518 gsi = gsi_start_bb (seq_start_bb);
8520 tree startvar = fd->loop.v;
8521 tree endvar = NULL_TREE;
8523 if (gimple_omp_for_combined_p (fd->for_stmt))
8525 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
8526 ? gimple_omp_parallel_clauses (inner_stmt)
8527 : gimple_omp_for_clauses (inner_stmt);
8528 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
8529 gcc_assert (innerc);
8530 startvar = OMP_CLAUSE_DECL (innerc);
8531 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8532 OMP_CLAUSE__LOOPTEMP_);
8533 gcc_assert (innerc);
8534 endvar = OMP_CLAUSE_DECL (innerc);
8536 t = fold_convert (itype, s0);
8537 t = fold_build2 (MULT_EXPR, itype, t, step);
8538 if (POINTER_TYPE_P (type))
8539 t = fold_build_pointer_plus (n1, t);
8540 else
8541 t = fold_build2 (PLUS_EXPR, type, t, n1);
8542 t = fold_convert (TREE_TYPE (startvar), t);
8543 t = force_gimple_operand_gsi (&gsi, t,
8544 DECL_P (startvar)
8545 && TREE_ADDRESSABLE (startvar),
8546 NULL_TREE, false, GSI_CONTINUE_LINKING);
8547 assign_stmt = gimple_build_assign (startvar, t);
8548 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8550 t = fold_convert (itype, e0);
8551 t = fold_build2 (MULT_EXPR, itype, t, step);
8552 if (POINTER_TYPE_P (type))
8553 t = fold_build_pointer_plus (n1, t);
8554 else
8555 t = fold_build2 (PLUS_EXPR, type, t, n1);
8556 t = fold_convert (TREE_TYPE (startvar), t);
8557 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8558 false, GSI_CONTINUE_LINKING);
8559 if (endvar)
8561 assign_stmt = gimple_build_assign (endvar, e);
8562 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8563 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
8564 assign_stmt = gimple_build_assign (fd->loop.v, e);
8565 else
8566 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
8567 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8569 /* Handle linear clause adjustments. */
8570 tree itercnt = NULL_TREE;
8571 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8572 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8573 c; c = OMP_CLAUSE_CHAIN (c))
8574 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8575 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8577 tree d = OMP_CLAUSE_DECL (c);
8578 bool is_ref = is_reference (d);
8579 tree t = d, a, dest;
8580 if (is_ref)
8581 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8582 if (itercnt == NULL_TREE)
8584 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8586 itercnt = fold_build2 (MINUS_EXPR, itype,
8587 fold_convert (itype, n1),
8588 fold_convert (itype, fd->loop.n1));
8589 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
8590 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
8591 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8592 NULL_TREE, false,
8593 GSI_CONTINUE_LINKING);
8595 else
8596 itercnt = s0;
8598 tree type = TREE_TYPE (t);
8599 if (POINTER_TYPE_P (type))
8600 type = sizetype;
8601 a = fold_build2 (MULT_EXPR, type,
8602 fold_convert (type, itercnt),
8603 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8604 dest = unshare_expr (t);
8605 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8606 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
8607 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8608 false, GSI_CONTINUE_LINKING);
8609 assign_stmt = gimple_build_assign (dest, t);
8610 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8612 if (fd->collapse > 1)
8613 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8615 if (!broken_loop)
8617 /* The code controlling the sequential loop replaces the
8618 GIMPLE_OMP_CONTINUE. */
8619 gsi = gsi_last_bb (cont_bb);
8620 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8621 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8622 vmain = gimple_omp_continue_control_use (cont_stmt);
8623 vback = gimple_omp_continue_control_def (cont_stmt);
8625 if (!gimple_omp_for_combined_p (fd->for_stmt))
8627 if (POINTER_TYPE_P (type))
8628 t = fold_build_pointer_plus (vmain, step);
8629 else
8630 t = fold_build2 (PLUS_EXPR, type, vmain, step);
8631 t = force_gimple_operand_gsi (&gsi, t,
8632 DECL_P (vback)
8633 && TREE_ADDRESSABLE (vback),
8634 NULL_TREE, true, GSI_SAME_STMT);
8635 assign_stmt = gimple_build_assign (vback, t);
8636 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8638 t = build2 (fd->loop.cond_code, boolean_type_node,
8639 DECL_P (vback) && TREE_ADDRESSABLE (vback)
8640 ? t : vback, e);
8641 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8644 /* Remove the GIMPLE_OMP_CONTINUE statement. */
8645 gsi_remove (&gsi, true);
8647 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
8648 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
8651 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
8652 gsi = gsi_last_bb (exit_bb);
8653 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
8655 t = gimple_omp_return_lhs (gsi_stmt (gsi));
8656 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
8657 gcc_checking_assert (t == NULL_TREE);
8658 else
8659 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
8661 gsi_remove (&gsi, true);
8663 /* Connect all the blocks. */
8664 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
8665 ep->probability = REG_BR_PROB_BASE / 4 * 3;
8666 ep = find_edge (entry_bb, second_bb);
8667 ep->flags = EDGE_TRUE_VALUE;
8668 ep->probability = REG_BR_PROB_BASE / 4;
8669 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
8670 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
8672 if (!broken_loop)
8674 ep = find_edge (cont_bb, body_bb);
8675 if (ep == NULL)
8677 ep = BRANCH_EDGE (cont_bb);
8678 gcc_assert (single_succ (ep->dest) == body_bb);
8680 if (gimple_omp_for_combined_p (fd->for_stmt))
8682 remove_edge (ep);
8683 ep = NULL;
8685 else if (fd->collapse > 1)
8687 remove_edge (ep);
8688 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
8690 else
8691 ep->flags = EDGE_TRUE_VALUE;
8692 find_edge (cont_bb, fin_bb)->flags
8693 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
8696 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
8697 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
8698 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
8700 set_immediate_dominator (CDI_DOMINATORS, body_bb,
8701 recompute_dominator (CDI_DOMINATORS, body_bb));
8702 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
8703 recompute_dominator (CDI_DOMINATORS, fin_bb));
8705 struct loop *loop = body_bb->loop_father;
8706 if (loop != entry_bb->loop_father)
8708 gcc_assert (loop->header == body_bb);
8709 gcc_assert (broken_loop
8710 || loop->latch == region->cont
8711 || single_pred (loop->latch) == region->cont);
8712 return;
8715 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
8717 loop = alloc_loop ();
8718 loop->header = body_bb;
8719 if (collapse_bb == NULL)
8720 loop->latch = cont_bb;
8721 add_loop (loop, body_bb->loop_father);
8725 /* Return phi in E->DEST with ARG on edge E. */
8727 static gphi *
8728 find_phi_with_arg_on_edge (tree arg, edge e)
8730 basic_block bb = e->dest;
8732 for (gphi_iterator gpi = gsi_start_phis (bb);
8733 !gsi_end_p (gpi);
8734 gsi_next (&gpi))
8736 gphi *phi = gpi.phi ();
8737 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
8738 return phi;
8741 return NULL;
8744 /* A subroutine of expand_omp_for. Generate code for a parallel
8745 loop with static schedule and a specified chunk size. Given
8746 parameters:
8748 for (V = N1; V cond N2; V += STEP) BODY;
8750 where COND is "<" or ">", we generate pseudocode
8752 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
8753 if (cond is <)
8754 adj = STEP - 1;
8755 else
8756 adj = STEP + 1;
8757 if ((__typeof (V)) -1 > 0 && cond is >)
8758 n = -(adj + N2 - N1) / -STEP;
8759 else
8760 n = (adj + N2 - N1) / STEP;
8761 trip = 0;
8762 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
8763 here so that V is defined
8764 if the loop is not entered
8766 s0 = (trip * nthreads + threadid) * CHUNK;
8767 e0 = min(s0 + CHUNK, n);
8768 if (s0 < n) goto L1; else goto L4;
8770 V = s0 * STEP + N1;
8771 e = e0 * STEP + N1;
8773 BODY;
8774 V += STEP;
8775 if (V cond e) goto L2; else goto L3;
8777 trip += 1;
8778 goto L0;
8782 static void
8783 expand_omp_for_static_chunk (struct omp_region *region,
8784 struct omp_for_data *fd, gimple *inner_stmt)
8786 tree n, s0, e0, e, t;
8787 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
8788 tree type, itype, vmain, vback, vextra;
8789 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
8790 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
8791 gimple_stmt_iterator gsi;
8792 edge se;
8793 bool broken_loop = region->cont == NULL;
8794 tree *counts = NULL;
8795 tree n1, n2, step;
8797 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
8798 != GF_OMP_FOR_KIND_OACC_LOOP)
8799 || !inner_stmt);
8801 itype = type = TREE_TYPE (fd->loop.v);
8802 if (POINTER_TYPE_P (type))
8803 itype = signed_type_for (type);
8805 entry_bb = region->entry;
8806 se = split_block (entry_bb, last_stmt (entry_bb));
8807 entry_bb = se->src;
8808 iter_part_bb = se->dest;
8809 cont_bb = region->cont;
8810 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
8811 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
8812 gcc_assert (broken_loop
8813 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
8814 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
8815 body_bb = single_succ (seq_start_bb);
8816 if (!broken_loop)
8818 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
8819 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
8820 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8821 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
8823 exit_bb = region->exit;
8825 /* Trip and adjustment setup goes in ENTRY_BB. */
8826 gsi = gsi_last_bb (entry_bb);
8827 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8829 if (fd->collapse > 1)
8831 int first_zero_iter = -1, dummy = -1;
8832 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
8834 counts = XALLOCAVEC (tree, fd->collapse);
8835 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8836 fin_bb, first_zero_iter,
8837 dummy_bb, dummy, l2_dom_bb);
8838 t = NULL_TREE;
8840 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
8841 t = integer_one_node;
8842 else
8843 t = fold_binary (fd->loop.cond_code, boolean_type_node,
8844 fold_convert (type, fd->loop.n1),
8845 fold_convert (type, fd->loop.n2));
8846 if (fd->collapse == 1
8847 && TYPE_UNSIGNED (type)
8848 && (t == NULL_TREE || !integer_onep (t)))
8850 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
8851 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
8852 true, GSI_SAME_STMT);
8853 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
8854 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
8855 true, GSI_SAME_STMT);
8856 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
8857 NULL_TREE, NULL_TREE);
8858 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8859 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
8860 expand_omp_regimplify_p, NULL, NULL)
8861 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
8862 expand_omp_regimplify_p, NULL, NULL))
8864 gsi = gsi_for_stmt (cond_stmt);
8865 gimple_regimplify_operands (cond_stmt, &gsi);
8867 se = split_block (entry_bb, cond_stmt);
8868 se->flags = EDGE_TRUE_VALUE;
8869 entry_bb = se->dest;
8870 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
8871 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
8872 se->probability = REG_BR_PROB_BASE / 2000 - 1;
8873 if (gimple_in_ssa_p (cfun))
8875 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
8876 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
8877 !gsi_end_p (gpi); gsi_next (&gpi))
8879 gphi *phi = gpi.phi ();
8880 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
8881 se, UNKNOWN_LOCATION);
8884 gsi = gsi_last_bb (entry_bb);
8887 switch (gimple_omp_for_kind (fd->for_stmt))
8889 case GF_OMP_FOR_KIND_FOR:
8890 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
8891 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
8892 break;
8893 case GF_OMP_FOR_KIND_DISTRIBUTE:
8894 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
8895 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
8896 break;
8897 case GF_OMP_FOR_KIND_OACC_LOOP:
8898 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
8899 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
8900 break;
8901 default:
8902 gcc_unreachable ();
8904 nthreads = build_call_expr (nthreads, 0);
8905 nthreads = fold_convert (itype, nthreads);
8906 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
8907 true, GSI_SAME_STMT);
8908 threadid = build_call_expr (threadid, 0);
8909 threadid = fold_convert (itype, threadid);
8910 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
8911 true, GSI_SAME_STMT);
8913 n1 = fd->loop.n1;
8914 n2 = fd->loop.n2;
8915 step = fd->loop.step;
8916 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8918 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8919 OMP_CLAUSE__LOOPTEMP_);
8920 gcc_assert (innerc);
8921 n1 = OMP_CLAUSE_DECL (innerc);
8922 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8923 OMP_CLAUSE__LOOPTEMP_);
8924 gcc_assert (innerc);
8925 n2 = OMP_CLAUSE_DECL (innerc);
8927 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
8928 true, NULL_TREE, true, GSI_SAME_STMT);
8929 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
8930 true, NULL_TREE, true, GSI_SAME_STMT);
8931 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
8932 true, NULL_TREE, true, GSI_SAME_STMT);
8933 tree chunk_size = fold_convert (itype, fd->chunk_size);
8934 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
8935 chunk_size
8936 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
8937 GSI_SAME_STMT);
8939 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
8940 t = fold_build2 (PLUS_EXPR, itype, step, t);
8941 t = fold_build2 (PLUS_EXPR, itype, t, n2);
8942 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
8943 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
8944 t = fold_build2 (TRUNC_DIV_EXPR, itype,
8945 fold_build1 (NEGATE_EXPR, itype, t),
8946 fold_build1 (NEGATE_EXPR, itype, step));
8947 else
8948 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
8949 t = fold_convert (itype, t);
8950 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8951 true, GSI_SAME_STMT);
8953 trip_var = create_tmp_reg (itype, ".trip");
8954 if (gimple_in_ssa_p (cfun))
8956 trip_init = make_ssa_name (trip_var);
8957 trip_main = make_ssa_name (trip_var);
8958 trip_back = make_ssa_name (trip_var);
8960 else
8962 trip_init = trip_var;
8963 trip_main = trip_var;
8964 trip_back = trip_var;
8967 gassign *assign_stmt
8968 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
8969 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8971 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
8972 t = fold_build2 (MULT_EXPR, itype, t, step);
8973 if (POINTER_TYPE_P (type))
8974 t = fold_build_pointer_plus (n1, t);
8975 else
8976 t = fold_build2 (PLUS_EXPR, type, t, n1);
8977 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8978 true, GSI_SAME_STMT);
8980 /* Remove the GIMPLE_OMP_FOR. */
8981 gsi_remove (&gsi, true);
8983 gimple_stmt_iterator gsif = gsi;
8985 /* Iteration space partitioning goes in ITER_PART_BB. */
8986 gsi = gsi_last_bb (iter_part_bb);
8988 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
8989 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
8990 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
8991 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8992 false, GSI_CONTINUE_LINKING);
8994 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
8995 t = fold_build2 (MIN_EXPR, itype, t, n);
8996 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8997 false, GSI_CONTINUE_LINKING);
8999 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9000 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9002 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9003 gsi = gsi_start_bb (seq_start_bb);
9005 tree startvar = fd->loop.v;
9006 tree endvar = NULL_TREE;
9008 if (gimple_omp_for_combined_p (fd->for_stmt))
9010 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9011 ? gimple_omp_parallel_clauses (inner_stmt)
9012 : gimple_omp_for_clauses (inner_stmt);
9013 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9014 gcc_assert (innerc);
9015 startvar = OMP_CLAUSE_DECL (innerc);
9016 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9017 OMP_CLAUSE__LOOPTEMP_);
9018 gcc_assert (innerc);
9019 endvar = OMP_CLAUSE_DECL (innerc);
9022 t = fold_convert (itype, s0);
9023 t = fold_build2 (MULT_EXPR, itype, t, step);
9024 if (POINTER_TYPE_P (type))
9025 t = fold_build_pointer_plus (n1, t);
9026 else
9027 t = fold_build2 (PLUS_EXPR, type, t, n1);
9028 t = fold_convert (TREE_TYPE (startvar), t);
9029 t = force_gimple_operand_gsi (&gsi, t,
9030 DECL_P (startvar)
9031 && TREE_ADDRESSABLE (startvar),
9032 NULL_TREE, false, GSI_CONTINUE_LINKING);
9033 assign_stmt = gimple_build_assign (startvar, t);
9034 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9036 t = fold_convert (itype, e0);
9037 t = fold_build2 (MULT_EXPR, itype, t, step);
9038 if (POINTER_TYPE_P (type))
9039 t = fold_build_pointer_plus (n1, t);
9040 else
9041 t = fold_build2 (PLUS_EXPR, type, t, n1);
9042 t = fold_convert (TREE_TYPE (startvar), t);
9043 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9044 false, GSI_CONTINUE_LINKING);
9045 if (endvar)
9047 assign_stmt = gimple_build_assign (endvar, e);
9048 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9049 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9050 assign_stmt = gimple_build_assign (fd->loop.v, e);
9051 else
9052 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9053 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9055 /* Handle linear clause adjustments. */
9056 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9057 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9058 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9059 c; c = OMP_CLAUSE_CHAIN (c))
9060 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9061 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9063 tree d = OMP_CLAUSE_DECL (c);
9064 bool is_ref = is_reference (d);
9065 tree t = d, a, dest;
9066 if (is_ref)
9067 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9068 tree type = TREE_TYPE (t);
9069 if (POINTER_TYPE_P (type))
9070 type = sizetype;
9071 dest = unshare_expr (t);
9072 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9073 expand_omp_build_assign (&gsif, v, t);
9074 if (itercnt == NULL_TREE)
9076 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9078 itercntbias
9079 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9080 fold_convert (itype, fd->loop.n1));
9081 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9082 itercntbias, step);
9083 itercntbias
9084 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9085 NULL_TREE, true,
9086 GSI_SAME_STMT);
9087 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9088 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9089 NULL_TREE, false,
9090 GSI_CONTINUE_LINKING);
9092 else
9093 itercnt = s0;
9095 a = fold_build2 (MULT_EXPR, type,
9096 fold_convert (type, itercnt),
9097 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9098 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9099 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
9100 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9101 false, GSI_CONTINUE_LINKING);
9102 assign_stmt = gimple_build_assign (dest, t);
9103 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9105 if (fd->collapse > 1)
9106 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9108 if (!broken_loop)
9110 /* The code controlling the sequential loop goes in CONT_BB,
9111 replacing the GIMPLE_OMP_CONTINUE. */
9112 gsi = gsi_last_bb (cont_bb);
9113 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9114 vmain = gimple_omp_continue_control_use (cont_stmt);
9115 vback = gimple_omp_continue_control_def (cont_stmt);
9117 if (!gimple_omp_for_combined_p (fd->for_stmt))
9119 if (POINTER_TYPE_P (type))
9120 t = fold_build_pointer_plus (vmain, step);
9121 else
9122 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9123 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
9124 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9125 true, GSI_SAME_STMT);
9126 assign_stmt = gimple_build_assign (vback, t);
9127 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9129 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
9130 t = build2 (EQ_EXPR, boolean_type_node,
9131 build_int_cst (itype, 0),
9132 build_int_cst (itype, 1));
9133 else
9134 t = build2 (fd->loop.cond_code, boolean_type_node,
9135 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9136 ? t : vback, e);
9137 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9140 /* Remove GIMPLE_OMP_CONTINUE. */
9141 gsi_remove (&gsi, true);
9143 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9144 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9146 /* Trip update code goes into TRIP_UPDATE_BB. */
9147 gsi = gsi_start_bb (trip_update_bb);
9149 t = build_int_cst (itype, 1);
9150 t = build2 (PLUS_EXPR, itype, trip_main, t);
9151 assign_stmt = gimple_build_assign (trip_back, t);
9152 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9155 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9156 gsi = gsi_last_bb (exit_bb);
9157 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9159 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9160 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
9161 gcc_checking_assert (t == NULL_TREE);
9162 else
9163 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9165 gsi_remove (&gsi, true);
9167 /* Connect the new blocks. */
9168 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
9169 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
9171 if (!broken_loop)
9173 se = find_edge (cont_bb, body_bb);
9174 if (se == NULL)
9176 se = BRANCH_EDGE (cont_bb);
9177 gcc_assert (single_succ (se->dest) == body_bb);
9179 if (gimple_omp_for_combined_p (fd->for_stmt))
9181 remove_edge (se);
9182 se = NULL;
9184 else if (fd->collapse > 1)
9186 remove_edge (se);
9187 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9189 else
9190 se->flags = EDGE_TRUE_VALUE;
9191 find_edge (cont_bb, trip_update_bb)->flags
9192 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9194 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
9197 if (gimple_in_ssa_p (cfun))
9199 gphi_iterator psi;
9200 gphi *phi;
9201 edge re, ene;
9202 edge_var_map *vm;
9203 size_t i;
9205 gcc_assert (fd->collapse == 1 && !broken_loop);
9207 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
9208 remove arguments of the phi nodes in fin_bb. We need to create
9209 appropriate phi nodes in iter_part_bb instead. */
9210 se = find_edge (iter_part_bb, fin_bb);
9211 re = single_succ_edge (trip_update_bb);
9212 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
9213 ene = single_succ_edge (entry_bb);
9215 psi = gsi_start_phis (fin_bb);
9216 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
9217 gsi_next (&psi), ++i)
9219 gphi *nphi;
9220 source_location locus;
9222 phi = psi.phi ();
9223 t = gimple_phi_result (phi);
9224 gcc_assert (t == redirect_edge_var_map_result (vm));
9226 if (!single_pred_p (fin_bb))
9227 t = copy_ssa_name (t, phi);
9229 nphi = create_phi_node (t, iter_part_bb);
9231 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
9232 locus = gimple_phi_arg_location_from_edge (phi, se);
9234 /* A special case -- fd->loop.v is not yet computed in
9235 iter_part_bb, we need to use vextra instead. */
9236 if (t == fd->loop.v)
9237 t = vextra;
9238 add_phi_arg (nphi, t, ene, locus);
9239 locus = redirect_edge_var_map_location (vm);
9240 tree back_arg = redirect_edge_var_map_def (vm);
9241 add_phi_arg (nphi, back_arg, re, locus);
9242 edge ce = find_edge (cont_bb, body_bb);
9243 if (ce == NULL)
9245 ce = BRANCH_EDGE (cont_bb);
9246 gcc_assert (single_succ (ce->dest) == body_bb);
9247 ce = single_succ_edge (ce->dest);
9249 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
9250 gcc_assert (inner_loop_phi != NULL);
9251 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
9252 find_edge (seq_start_bb, body_bb), locus);
9254 if (!single_pred_p (fin_bb))
9255 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
9257 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
9258 redirect_edge_var_map_clear (re);
9259 if (single_pred_p (fin_bb))
9260 while (1)
9262 psi = gsi_start_phis (fin_bb);
9263 if (gsi_end_p (psi))
9264 break;
9265 remove_phi_node (&psi, false);
9268 /* Make phi node for trip. */
9269 phi = create_phi_node (trip_main, iter_part_bb);
9270 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
9271 UNKNOWN_LOCATION);
9272 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
9273 UNKNOWN_LOCATION);
9276 if (!broken_loop)
9277 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
9278 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
9279 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
9280 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9281 recompute_dominator (CDI_DOMINATORS, fin_bb));
9282 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
9283 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
9284 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9285 recompute_dominator (CDI_DOMINATORS, body_bb));
9287 if (!broken_loop)
9289 struct loop *loop = body_bb->loop_father;
9290 struct loop *trip_loop = alloc_loop ();
9291 trip_loop->header = iter_part_bb;
9292 trip_loop->latch = trip_update_bb;
9293 add_loop (trip_loop, iter_part_bb->loop_father);
9295 if (loop != entry_bb->loop_father)
9297 gcc_assert (loop->header == body_bb);
9298 gcc_assert (loop->latch == region->cont
9299 || single_pred (loop->latch) == region->cont);
9300 trip_loop->inner = loop;
9301 return;
9304 if (!gimple_omp_for_combined_p (fd->for_stmt))
9306 loop = alloc_loop ();
9307 loop->header = body_bb;
9308 if (collapse_bb == NULL)
9309 loop->latch = cont_bb;
9310 add_loop (loop, trip_loop);
9315 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
9316 Given parameters:
9317 for (V = N1; V cond N2; V += STEP) BODY;
9319 where COND is "<" or ">" or "!=", we generate pseudocode
9321 for (ind_var = low; ind_var < high; ind_var++)
9323 V = n1 + (ind_var * STEP)
9325 <BODY>
9328 In the above pseudocode, low and high are function parameters of the
9329 child function. In the function below, we are inserting a temp.
9330 variable that will be making a call to two OMP functions that will not be
9331 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
9332 with _Cilk_for). These functions are replaced with low and high
9333 by the function that handles taskreg. */
9336 static void
9337 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
9339 bool broken_loop = region->cont == NULL;
9340 basic_block entry_bb = region->entry;
9341 basic_block cont_bb = region->cont;
9343 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9344 gcc_assert (broken_loop
9345 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
9346 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
9347 basic_block l1_bb, l2_bb;
9349 if (!broken_loop)
9351 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
9352 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9353 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
9354 l2_bb = BRANCH_EDGE (entry_bb)->dest;
9356 else
9358 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
9359 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
9360 l2_bb = single_succ (l1_bb);
9362 basic_block exit_bb = region->exit;
9363 basic_block l2_dom_bb = NULL;
9365 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
9367 /* Below statements until the "tree high_val = ..." are pseudo statements
9368 used to pass information to be used by expand_omp_taskreg.
9369 low_val and high_val will be replaced by the __low and __high
9370 parameter from the child function.
9372 The call_exprs part is a place-holder, it is mainly used
9373 to distinctly identify to the top-level part that this is
9374 where we should put low and high (reasoning given in header
9375 comment). */
9377 tree child_fndecl
9378 = gimple_omp_parallel_child_fn (
9379 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
9380 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
9381 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
9383 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
9384 high_val = t;
9385 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
9386 low_val = t;
9388 gcc_assert (low_val && high_val);
9390 tree type = TREE_TYPE (low_val);
9391 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
9392 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9394 /* Not needed in SSA form right now. */
9395 gcc_assert (!gimple_in_ssa_p (cfun));
9396 if (l2_dom_bb == NULL)
9397 l2_dom_bb = l1_bb;
9399 tree n1 = low_val;
9400 tree n2 = high_val;
9402 gimple *stmt = gimple_build_assign (ind_var, n1);
9404 /* Replace the GIMPLE_OMP_FOR statement. */
9405 gsi_replace (&gsi, stmt, true);
9407 if (!broken_loop)
9409 /* Code to control the increment goes in the CONT_BB. */
9410 gsi = gsi_last_bb (cont_bb);
9411 stmt = gsi_stmt (gsi);
9412 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
9413 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
9414 build_one_cst (type));
9416 /* Replace GIMPLE_OMP_CONTINUE. */
9417 gsi_replace (&gsi, stmt, true);
9420 /* Emit the condition in L1_BB. */
9421 gsi = gsi_after_labels (l1_bb);
9422 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
9423 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
9424 fd->loop.step);
9425 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
9426 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
9427 fd->loop.n1, fold_convert (sizetype, t));
9428 else
9429 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
9430 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
9431 t = fold_convert (TREE_TYPE (fd->loop.v), t);
9432 expand_omp_build_assign (&gsi, fd->loop.v, t);
9434 /* The condition is always '<' since the runtime will fill in the low
9435 and high values. */
9436 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
9437 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
9439 /* Remove GIMPLE_OMP_RETURN. */
9440 gsi = gsi_last_bb (exit_bb);
9441 gsi_remove (&gsi, true);
9443 /* Connect the new blocks. */
9444 remove_edge (FALLTHRU_EDGE (entry_bb));
9446 edge e, ne;
9447 if (!broken_loop)
9449 remove_edge (BRANCH_EDGE (entry_bb));
9450 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
9452 e = BRANCH_EDGE (l1_bb);
9453 ne = FALLTHRU_EDGE (l1_bb);
9454 e->flags = EDGE_TRUE_VALUE;
9456 else
9458 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
9460 ne = single_succ_edge (l1_bb);
9461 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
9464 ne->flags = EDGE_FALSE_VALUE;
9465 e->probability = REG_BR_PROB_BASE * 7 / 8;
9466 ne->probability = REG_BR_PROB_BASE / 8;
9468 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
9469 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
9470 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
9472 if (!broken_loop)
9474 struct loop *loop = alloc_loop ();
9475 loop->header = l1_bb;
9476 loop->latch = cont_bb;
9477 add_loop (loop, l1_bb->loop_father);
9478 loop->safelen = INT_MAX;
9481 /* Pick the correct library function based on the precision of the
9482 induction variable type. */
9483 tree lib_fun = NULL_TREE;
9484 if (TYPE_PRECISION (type) == 32)
9485 lib_fun = cilk_for_32_fndecl;
9486 else if (TYPE_PRECISION (type) == 64)
9487 lib_fun = cilk_for_64_fndecl;
9488 else
9489 gcc_unreachable ();
9491 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
9493 /* WS_ARGS contains the library function flavor to call:
9494 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
9495 user-defined grain value. If the user does not define one, then zero
9496 is passed in by the parser. */
9497 vec_alloc (region->ws_args, 2);
9498 region->ws_args->quick_push (lib_fun);
9499 region->ws_args->quick_push (fd->chunk_size);
9502 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
9503 loop. Given parameters:
9505 for (V = N1; V cond N2; V += STEP) BODY;
9507 where COND is "<" or ">", we generate pseudocode
9509 V = N1;
9510 goto L1;
9512 BODY;
9513 V += STEP;
9515 if (V cond N2) goto L0; else goto L2;
9518 For collapsed loops, given parameters:
9519 collapse(3)
9520 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
9521 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
9522 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
9523 BODY;
9525 we generate pseudocode
9527 if (cond3 is <)
9528 adj = STEP3 - 1;
9529 else
9530 adj = STEP3 + 1;
9531 count3 = (adj + N32 - N31) / STEP3;
9532 if (cond2 is <)
9533 adj = STEP2 - 1;
9534 else
9535 adj = STEP2 + 1;
9536 count2 = (adj + N22 - N21) / STEP2;
9537 if (cond1 is <)
9538 adj = STEP1 - 1;
9539 else
9540 adj = STEP1 + 1;
9541 count1 = (adj + N12 - N11) / STEP1;
9542 count = count1 * count2 * count3;
9543 V = 0;
9544 V1 = N11;
9545 V2 = N21;
9546 V3 = N31;
9547 goto L1;
9549 BODY;
9550 V += 1;
9551 V3 += STEP3;
9552 V2 += (V3 cond3 N32) ? 0 : STEP2;
9553 V3 = (V3 cond3 N32) ? V3 : N31;
9554 V1 += (V2 cond2 N22) ? 0 : STEP1;
9555 V2 = (V2 cond2 N22) ? V2 : N21;
9557 if (V < count) goto L0; else goto L2;
9562 static void
9563 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
9565 tree type, t;
9566 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
9567 gimple_stmt_iterator gsi;
9568 gimple *stmt;
9569 gcond *cond_stmt;
9570 bool broken_loop = region->cont == NULL;
9571 edge e, ne;
9572 tree *counts = NULL;
9573 int i;
9574 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9575 OMP_CLAUSE_SAFELEN);
9576 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9577 OMP_CLAUSE__SIMDUID_);
9578 tree n1, n2;
9580 type = TREE_TYPE (fd->loop.v);
9581 entry_bb = region->entry;
9582 cont_bb = region->cont;
9583 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9584 gcc_assert (broken_loop
9585 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
9586 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
9587 if (!broken_loop)
9589 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
9590 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9591 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
9592 l2_bb = BRANCH_EDGE (entry_bb)->dest;
9594 else
9596 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
9597 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
9598 l2_bb = single_succ (l1_bb);
9600 exit_bb = region->exit;
9601 l2_dom_bb = NULL;
9603 gsi = gsi_last_bb (entry_bb);
9605 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9606 /* Not needed in SSA form right now. */
9607 gcc_assert (!gimple_in_ssa_p (cfun));
9608 if (fd->collapse > 1)
9610 int first_zero_iter = -1, dummy = -1;
9611 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
9613 counts = XALLOCAVEC (tree, fd->collapse);
9614 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9615 zero_iter_bb, first_zero_iter,
9616 dummy_bb, dummy, l2_dom_bb);
9618 if (l2_dom_bb == NULL)
9619 l2_dom_bb = l1_bb;
9621 n1 = fd->loop.n1;
9622 n2 = fd->loop.n2;
9623 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9625 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9626 OMP_CLAUSE__LOOPTEMP_);
9627 gcc_assert (innerc);
9628 n1 = OMP_CLAUSE_DECL (innerc);
9629 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9630 OMP_CLAUSE__LOOPTEMP_);
9631 gcc_assert (innerc);
9632 n2 = OMP_CLAUSE_DECL (innerc);
9633 expand_omp_build_assign (&gsi, fd->loop.v,
9634 fold_convert (type, n1));
9635 if (fd->collapse > 1)
9637 gsi_prev (&gsi);
9638 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
9639 gsi_next (&gsi);
9642 else
9644 expand_omp_build_assign (&gsi, fd->loop.v,
9645 fold_convert (type, fd->loop.n1));
9646 if (fd->collapse > 1)
9647 for (i = 0; i < fd->collapse; i++)
9649 tree itype = TREE_TYPE (fd->loops[i].v);
9650 if (POINTER_TYPE_P (itype))
9651 itype = signed_type_for (itype);
9652 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
9653 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
9657 /* Remove the GIMPLE_OMP_FOR statement. */
9658 gsi_remove (&gsi, true);
9660 if (!broken_loop)
9662 /* Code to control the increment goes in the CONT_BB. */
9663 gsi = gsi_last_bb (cont_bb);
9664 stmt = gsi_stmt (gsi);
9665 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
9667 if (POINTER_TYPE_P (type))
9668 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
9669 else
9670 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
9671 expand_omp_build_assign (&gsi, fd->loop.v, t);
9673 if (fd->collapse > 1)
9675 i = fd->collapse - 1;
9676 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
9678 t = fold_convert (sizetype, fd->loops[i].step);
9679 t = fold_build_pointer_plus (fd->loops[i].v, t);
9681 else
9683 t = fold_convert (TREE_TYPE (fd->loops[i].v),
9684 fd->loops[i].step);
9685 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
9686 fd->loops[i].v, t);
9688 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
9690 for (i = fd->collapse - 1; i > 0; i--)
9692 tree itype = TREE_TYPE (fd->loops[i].v);
9693 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
9694 if (POINTER_TYPE_P (itype2))
9695 itype2 = signed_type_for (itype2);
9696 t = build3 (COND_EXPR, itype2,
9697 build2 (fd->loops[i].cond_code, boolean_type_node,
9698 fd->loops[i].v,
9699 fold_convert (itype, fd->loops[i].n2)),
9700 build_int_cst (itype2, 0),
9701 fold_convert (itype2, fd->loops[i - 1].step));
9702 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
9703 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
9704 else
9705 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
9706 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
9708 t = build3 (COND_EXPR, itype,
9709 build2 (fd->loops[i].cond_code, boolean_type_node,
9710 fd->loops[i].v,
9711 fold_convert (itype, fd->loops[i].n2)),
9712 fd->loops[i].v,
9713 fold_convert (itype, fd->loops[i].n1));
9714 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
9718 /* Remove GIMPLE_OMP_CONTINUE. */
9719 gsi_remove (&gsi, true);
9722 /* Emit the condition in L1_BB. */
9723 gsi = gsi_start_bb (l1_bb);
9725 t = fold_convert (type, n2);
9726 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9727 false, GSI_CONTINUE_LINKING);
9728 tree v = fd->loop.v;
9729 if (DECL_P (v) && TREE_ADDRESSABLE (v))
9730 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
9731 false, GSI_CONTINUE_LINKING);
9732 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
9733 cond_stmt = gimple_build_cond_empty (t);
9734 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
9735 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
9736 NULL, NULL)
9737 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
9738 NULL, NULL))
9740 gsi = gsi_for_stmt (cond_stmt);
9741 gimple_regimplify_operands (cond_stmt, &gsi);
9744 /* Remove GIMPLE_OMP_RETURN. */
9745 gsi = gsi_last_bb (exit_bb);
9746 gsi_remove (&gsi, true);
9748 /* Connect the new blocks. */
9749 remove_edge (FALLTHRU_EDGE (entry_bb));
9751 if (!broken_loop)
9753 remove_edge (BRANCH_EDGE (entry_bb));
9754 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
9756 e = BRANCH_EDGE (l1_bb);
9757 ne = FALLTHRU_EDGE (l1_bb);
9758 e->flags = EDGE_TRUE_VALUE;
9760 else
9762 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
9764 ne = single_succ_edge (l1_bb);
9765 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
9768 ne->flags = EDGE_FALSE_VALUE;
9769 e->probability = REG_BR_PROB_BASE * 7 / 8;
9770 ne->probability = REG_BR_PROB_BASE / 8;
9772 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
9773 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
9774 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
9776 if (!broken_loop)
9778 struct loop *loop = alloc_loop ();
9779 loop->header = l1_bb;
9780 loop->latch = cont_bb;
9781 add_loop (loop, l1_bb->loop_father);
9782 if (safelen == NULL_TREE)
9783 loop->safelen = INT_MAX;
9784 else
9786 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
9787 if (TREE_CODE (safelen) != INTEGER_CST)
9788 loop->safelen = 0;
9789 else if (!tree_fits_uhwi_p (safelen)
9790 || tree_to_uhwi (safelen) > INT_MAX)
9791 loop->safelen = INT_MAX;
9792 else
9793 loop->safelen = tree_to_uhwi (safelen);
9794 if (loop->safelen == 1)
9795 loop->safelen = 0;
9797 if (simduid)
9799 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
9800 cfun->has_simduid_loops = true;
9802 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
9803 the loop. */
9804 if ((flag_tree_loop_vectorize
9805 || (!global_options_set.x_flag_tree_loop_vectorize
9806 && !global_options_set.x_flag_tree_vectorize))
9807 && flag_tree_loop_optimize
9808 && loop->safelen > 1)
9810 loop->force_vectorize = true;
9811 cfun->has_force_vectorize_loops = true;
9814 else if (simduid)
9815 cfun->has_simduid_loops = true;
9818 /* Taskloop construct is represented after gimplification with
9819 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
9820 in between them. This routine expands the outer GIMPLE_OMP_FOR,
9821 which should just compute all the needed loop temporaries
9822 for GIMPLE_OMP_TASK. */
9824 static void
9825 expand_omp_taskloop_for_outer (struct omp_region *region,
9826 struct omp_for_data *fd,
9827 gimple *inner_stmt)
9829 tree type, bias = NULL_TREE;
9830 basic_block entry_bb, cont_bb, exit_bb;
9831 gimple_stmt_iterator gsi;
9832 gassign *assign_stmt;
9833 tree *counts = NULL;
9834 int i;
9836 gcc_assert (inner_stmt);
9837 gcc_assert (region->cont);
9838 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
9839 && gimple_omp_task_taskloop_p (inner_stmt));
9840 type = TREE_TYPE (fd->loop.v);
9842 /* See if we need to bias by LLONG_MIN. */
9843 if (fd->iter_type == long_long_unsigned_type_node
9844 && TREE_CODE (type) == INTEGER_TYPE
9845 && !TYPE_UNSIGNED (type))
9847 tree n1, n2;
9849 if (fd->loop.cond_code == LT_EXPR)
9851 n1 = fd->loop.n1;
9852 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
9854 else
9856 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
9857 n2 = fd->loop.n1;
9859 if (TREE_CODE (n1) != INTEGER_CST
9860 || TREE_CODE (n2) != INTEGER_CST
9861 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
9862 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
9865 entry_bb = region->entry;
9866 cont_bb = region->cont;
9867 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9868 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
9869 exit_bb = region->exit;
9871 gsi = gsi_last_bb (entry_bb);
9872 gimple *for_stmt = gsi_stmt (gsi);
9873 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
9874 if (fd->collapse > 1)
9876 int first_zero_iter = -1, dummy = -1;
9877 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
9879 counts = XALLOCAVEC (tree, fd->collapse);
9880 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9881 zero_iter_bb, first_zero_iter,
9882 dummy_bb, dummy, l2_dom_bb);
9884 if (zero_iter_bb)
9886 /* Some counts[i] vars might be uninitialized if
9887 some loop has zero iterations. But the body shouldn't
9888 be executed in that case, so just avoid uninit warnings. */
9889 for (i = first_zero_iter; i < fd->collapse; i++)
9890 if (SSA_VAR_P (counts[i]))
9891 TREE_NO_WARNING (counts[i]) = 1;
9892 gsi_prev (&gsi);
9893 edge e = split_block (entry_bb, gsi_stmt (gsi));
9894 entry_bb = e->dest;
9895 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
9896 gsi = gsi_last_bb (entry_bb);
9897 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
9898 get_immediate_dominator (CDI_DOMINATORS,
9899 zero_iter_bb));
9903 tree t0, t1;
9904 t1 = fd->loop.n2;
9905 t0 = fd->loop.n1;
9906 if (POINTER_TYPE_P (TREE_TYPE (t0))
9907 && TYPE_PRECISION (TREE_TYPE (t0))
9908 != TYPE_PRECISION (fd->iter_type))
9910 /* Avoid casting pointers to integer of a different size. */
9911 tree itype = signed_type_for (type);
9912 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
9913 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
9915 else
9917 t1 = fold_convert (fd->iter_type, t1);
9918 t0 = fold_convert (fd->iter_type, t0);
9920 if (bias)
9922 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
9923 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
9926 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
9927 OMP_CLAUSE__LOOPTEMP_);
9928 gcc_assert (innerc);
9929 tree startvar = OMP_CLAUSE_DECL (innerc);
9930 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
9931 gcc_assert (innerc);
9932 tree endvar = OMP_CLAUSE_DECL (innerc);
9933 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
9935 gcc_assert (innerc);
9936 for (i = 1; i < fd->collapse; i++)
9938 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9939 OMP_CLAUSE__LOOPTEMP_);
9940 gcc_assert (innerc);
9942 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9943 OMP_CLAUSE__LOOPTEMP_);
9944 if (innerc)
9946 /* If needed (inner taskloop has lastprivate clause), propagate
9947 down the total number of iterations. */
9948 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
9949 NULL_TREE, false,
9950 GSI_CONTINUE_LINKING);
9951 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9952 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9956 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
9957 GSI_CONTINUE_LINKING);
9958 assign_stmt = gimple_build_assign (startvar, t0);
9959 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9961 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
9962 GSI_CONTINUE_LINKING);
9963 assign_stmt = gimple_build_assign (endvar, t1);
9964 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9965 if (fd->collapse > 1)
9966 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9968 /* Remove the GIMPLE_OMP_FOR statement. */
9969 gsi = gsi_for_stmt (for_stmt);
9970 gsi_remove (&gsi, true);
9972 gsi = gsi_last_bb (cont_bb);
9973 gsi_remove (&gsi, true);
9975 gsi = gsi_last_bb (exit_bb);
9976 gsi_remove (&gsi, true);
9978 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
9979 remove_edge (BRANCH_EDGE (entry_bb));
9980 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
9981 remove_edge (BRANCH_EDGE (cont_bb));
9982 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
9983 set_immediate_dominator (CDI_DOMINATORS, region->entry,
9984 recompute_dominator (CDI_DOMINATORS, region->entry));
9987 /* Taskloop construct is represented after gimplification with
9988 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
9989 in between them. This routine expands the inner GIMPLE_OMP_FOR.
9990 GOMP_taskloop{,_ull} function arranges for each task to be given just
9991 a single range of iterations. */
9993 static void
9994 expand_omp_taskloop_for_inner (struct omp_region *region,
9995 struct omp_for_data *fd,
9996 gimple *inner_stmt)
9998 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
9999 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10000 basic_block fin_bb;
10001 gimple_stmt_iterator gsi;
10002 edge ep;
10003 bool broken_loop = region->cont == NULL;
10004 tree *counts = NULL;
10005 tree n1, n2, step;
10007 itype = type = TREE_TYPE (fd->loop.v);
10008 if (POINTER_TYPE_P (type))
10009 itype = signed_type_for (type);
10011 /* See if we need to bias by LLONG_MIN. */
10012 if (fd->iter_type == long_long_unsigned_type_node
10013 && TREE_CODE (type) == INTEGER_TYPE
10014 && !TYPE_UNSIGNED (type))
10016 tree n1, n2;
10018 if (fd->loop.cond_code == LT_EXPR)
10020 n1 = fd->loop.n1;
10021 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10023 else
10025 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10026 n2 = fd->loop.n1;
10028 if (TREE_CODE (n1) != INTEGER_CST
10029 || TREE_CODE (n2) != INTEGER_CST
10030 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10031 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10034 entry_bb = region->entry;
10035 cont_bb = region->cont;
10036 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10037 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10038 gcc_assert (broken_loop
10039 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10040 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10041 if (!broken_loop)
10043 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10044 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10046 exit_bb = region->exit;
10048 /* Iteration space partitioning goes in ENTRY_BB. */
10049 gsi = gsi_last_bb (entry_bb);
10050 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10052 if (fd->collapse > 1)
10054 int first_zero_iter = -1, dummy = -1;
10055 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10057 counts = XALLOCAVEC (tree, fd->collapse);
10058 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10059 fin_bb, first_zero_iter,
10060 dummy_bb, dummy, l2_dom_bb);
10061 t = NULL_TREE;
10063 else
10064 t = integer_one_node;
10066 step = fd->loop.step;
10067 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10068 OMP_CLAUSE__LOOPTEMP_);
10069 gcc_assert (innerc);
10070 n1 = OMP_CLAUSE_DECL (innerc);
10071 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10072 gcc_assert (innerc);
10073 n2 = OMP_CLAUSE_DECL (innerc);
10074 if (bias)
10076 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10077 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10079 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10080 true, NULL_TREE, true, GSI_SAME_STMT);
10081 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10082 true, NULL_TREE, true, GSI_SAME_STMT);
10083 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10084 true, NULL_TREE, true, GSI_SAME_STMT);
10086 tree startvar = fd->loop.v;
10087 tree endvar = NULL_TREE;
10089 if (gimple_omp_for_combined_p (fd->for_stmt))
10091 tree clauses = gimple_omp_for_clauses (inner_stmt);
10092 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
10093 gcc_assert (innerc);
10094 startvar = OMP_CLAUSE_DECL (innerc);
10095 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10096 OMP_CLAUSE__LOOPTEMP_);
10097 gcc_assert (innerc);
10098 endvar = OMP_CLAUSE_DECL (innerc);
10100 t = fold_convert (TREE_TYPE (startvar), n1);
10101 t = force_gimple_operand_gsi (&gsi, t,
10102 DECL_P (startvar)
10103 && TREE_ADDRESSABLE (startvar),
10104 NULL_TREE, false, GSI_CONTINUE_LINKING);
10105 gimple *assign_stmt = gimple_build_assign (startvar, t);
10106 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10108 t = fold_convert (TREE_TYPE (startvar), n2);
10109 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10110 false, GSI_CONTINUE_LINKING);
10111 if (endvar)
10113 assign_stmt = gimple_build_assign (endvar, e);
10114 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10115 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
10116 assign_stmt = gimple_build_assign (fd->loop.v, e);
10117 else
10118 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
10119 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10121 if (fd->collapse > 1)
10122 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10124 if (!broken_loop)
10126 /* The code controlling the sequential loop replaces the
10127 GIMPLE_OMP_CONTINUE. */
10128 gsi = gsi_last_bb (cont_bb);
10129 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10130 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
10131 vmain = gimple_omp_continue_control_use (cont_stmt);
10132 vback = gimple_omp_continue_control_def (cont_stmt);
10134 if (!gimple_omp_for_combined_p (fd->for_stmt))
10136 if (POINTER_TYPE_P (type))
10137 t = fold_build_pointer_plus (vmain, step);
10138 else
10139 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10140 t = force_gimple_operand_gsi (&gsi, t,
10141 DECL_P (vback)
10142 && TREE_ADDRESSABLE (vback),
10143 NULL_TREE, true, GSI_SAME_STMT);
10144 assign_stmt = gimple_build_assign (vback, t);
10145 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10147 t = build2 (fd->loop.cond_code, boolean_type_node,
10148 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10149 ? t : vback, e);
10150 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10153 /* Remove the GIMPLE_OMP_CONTINUE statement. */
10154 gsi_remove (&gsi, true);
10156 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10157 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10160 /* Remove the GIMPLE_OMP_FOR statement. */
10161 gsi = gsi_for_stmt (fd->for_stmt);
10162 gsi_remove (&gsi, true);
10164 /* Remove the GIMPLE_OMP_RETURN statement. */
10165 gsi = gsi_last_bb (exit_bb);
10166 gsi_remove (&gsi, true);
10168 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10169 if (!broken_loop)
10170 remove_edge (BRANCH_EDGE (entry_bb));
10171 else
10173 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
10174 region->outer->cont = NULL;
10177 /* Connect all the blocks. */
10178 if (!broken_loop)
10180 ep = find_edge (cont_bb, body_bb);
10181 if (gimple_omp_for_combined_p (fd->for_stmt))
10183 remove_edge (ep);
10184 ep = NULL;
10186 else if (fd->collapse > 1)
10188 remove_edge (ep);
10189 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10191 else
10192 ep->flags = EDGE_TRUE_VALUE;
10193 find_edge (cont_bb, fin_bb)->flags
10194 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10197 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10198 recompute_dominator (CDI_DOMINATORS, body_bb));
10199 if (!broken_loop)
10200 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10201 recompute_dominator (CDI_DOMINATORS, fin_bb));
10203 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
10205 struct loop *loop = alloc_loop ();
10206 loop->header = body_bb;
10207 if (collapse_bb == NULL)
10208 loop->latch = cont_bb;
10209 add_loop (loop, body_bb->loop_father);
10213 /* Expand the OMP loop defined by REGION. */
10215 static void
10216 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
10218 struct omp_for_data fd;
10219 struct omp_for_data_loop *loops;
10221 loops
10222 = (struct omp_for_data_loop *)
10223 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
10224 * sizeof (struct omp_for_data_loop));
10225 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
10226 &fd, loops);
10227 region->sched_kind = fd.sched_kind;
10229 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
10230 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
10231 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
10232 if (region->cont)
10234 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
10235 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
10236 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
10238 else
10239 /* If there isn't a continue then this is a degerate case where
10240 the introduction of abnormal edges during lowering will prevent
10241 original loops from being detected. Fix that up. */
10242 loops_state_set (LOOPS_NEED_FIXUP);
10244 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
10245 expand_omp_simd (region, &fd);
10246 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
10247 expand_cilk_for (region, &fd);
10248 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
10250 if (gimple_omp_for_combined_into_p (fd.for_stmt))
10251 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
10252 else
10253 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
10255 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
10256 && !fd.have_ordered)
10258 if (fd.chunk_size == NULL)
10259 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
10260 else
10261 expand_omp_for_static_chunk (region, &fd, inner_stmt);
10263 else
10265 int fn_index, start_ix, next_ix;
10267 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
10268 == GF_OMP_FOR_KIND_FOR);
10269 if (fd.chunk_size == NULL
10270 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
10271 fd.chunk_size = integer_zero_node;
10272 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
10273 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
10274 ? 3 : fd.sched_kind;
10275 if (!fd.ordered)
10276 fn_index += fd.have_ordered * 4;
10277 if (fd.ordered)
10278 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
10279 else
10280 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
10281 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
10282 if (fd.iter_type == long_long_unsigned_type_node)
10284 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
10285 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
10286 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
10287 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
10289 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
10290 (enum built_in_function) next_ix, inner_stmt);
10293 if (gimple_in_ssa_p (cfun))
10294 update_ssa (TODO_update_ssa_only_virtuals);
10298 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
10300 v = GOMP_sections_start (n);
10302 switch (v)
10304 case 0:
10305 goto L2;
10306 case 1:
10307 section 1;
10308 goto L1;
10309 case 2:
10311 case n:
10313 default:
10314 abort ();
10317 v = GOMP_sections_next ();
10318 goto L0;
10320 reduction;
10322 If this is a combined parallel sections, replace the call to
10323 GOMP_sections_start with call to GOMP_sections_next. */
10325 static void
10326 expand_omp_sections (struct omp_region *region)
10328 tree t, u, vin = NULL, vmain, vnext, l2;
10329 unsigned len;
10330 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
10331 gimple_stmt_iterator si, switch_si;
10332 gomp_sections *sections_stmt;
10333 gimple *stmt;
10334 gomp_continue *cont;
10335 edge_iterator ei;
10336 edge e;
10337 struct omp_region *inner;
10338 unsigned i, casei;
10339 bool exit_reachable = region->cont != NULL;
10341 gcc_assert (region->exit != NULL);
10342 entry_bb = region->entry;
10343 l0_bb = single_succ (entry_bb);
10344 l1_bb = region->cont;
10345 l2_bb = region->exit;
10346 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
10347 l2 = gimple_block_label (l2_bb);
10348 else
10350 /* This can happen if there are reductions. */
10351 len = EDGE_COUNT (l0_bb->succs);
10352 gcc_assert (len > 0);
10353 e = EDGE_SUCC (l0_bb, len - 1);
10354 si = gsi_last_bb (e->dest);
10355 l2 = NULL_TREE;
10356 if (gsi_end_p (si)
10357 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
10358 l2 = gimple_block_label (e->dest);
10359 else
10360 FOR_EACH_EDGE (e, ei, l0_bb->succs)
10362 si = gsi_last_bb (e->dest);
10363 if (gsi_end_p (si)
10364 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
10366 l2 = gimple_block_label (e->dest);
10367 break;
10371 if (exit_reachable)
10372 default_bb = create_empty_bb (l1_bb->prev_bb);
10373 else
10374 default_bb = create_empty_bb (l0_bb);
10376 /* We will build a switch() with enough cases for all the
10377 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
10378 and a default case to abort if something goes wrong. */
10379 len = EDGE_COUNT (l0_bb->succs);
10381 /* Use vec::quick_push on label_vec throughout, since we know the size
10382 in advance. */
10383 auto_vec<tree> label_vec (len);
10385 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
10386 GIMPLE_OMP_SECTIONS statement. */
10387 si = gsi_last_bb (entry_bb);
10388 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
10389 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
10390 vin = gimple_omp_sections_control (sections_stmt);
10391 if (!is_combined_parallel (region))
10393 /* If we are not inside a combined parallel+sections region,
10394 call GOMP_sections_start. */
10395 t = build_int_cst (unsigned_type_node, len - 1);
10396 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
10397 stmt = gimple_build_call (u, 1, t);
10399 else
10401 /* Otherwise, call GOMP_sections_next. */
10402 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
10403 stmt = gimple_build_call (u, 0);
10405 gimple_call_set_lhs (stmt, vin);
10406 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
10407 gsi_remove (&si, true);
10409 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
10410 L0_BB. */
10411 switch_si = gsi_last_bb (l0_bb);
10412 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
10413 if (exit_reachable)
10415 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
10416 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
10417 vmain = gimple_omp_continue_control_use (cont);
10418 vnext = gimple_omp_continue_control_def (cont);
10420 else
10422 vmain = vin;
10423 vnext = NULL_TREE;
10426 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
10427 label_vec.quick_push (t);
10428 i = 1;
10430 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
10431 for (inner = region->inner, casei = 1;
10432 inner;
10433 inner = inner->next, i++, casei++)
10435 basic_block s_entry_bb, s_exit_bb;
10437 /* Skip optional reduction region. */
10438 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
10440 --i;
10441 --casei;
10442 continue;
10445 s_entry_bb = inner->entry;
10446 s_exit_bb = inner->exit;
10448 t = gimple_block_label (s_entry_bb);
10449 u = build_int_cst (unsigned_type_node, casei);
10450 u = build_case_label (u, NULL, t);
10451 label_vec.quick_push (u);
10453 si = gsi_last_bb (s_entry_bb);
10454 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
10455 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
10456 gsi_remove (&si, true);
10457 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
10459 if (s_exit_bb == NULL)
10460 continue;
10462 si = gsi_last_bb (s_exit_bb);
10463 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
10464 gsi_remove (&si, true);
10466 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
10469 /* Error handling code goes in DEFAULT_BB. */
10470 t = gimple_block_label (default_bb);
10471 u = build_case_label (NULL, NULL, t);
10472 make_edge (l0_bb, default_bb, 0);
10473 add_bb_to_loop (default_bb, current_loops->tree_root);
10475 stmt = gimple_build_switch (vmain, u, label_vec);
10476 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
10477 gsi_remove (&switch_si, true);
10479 si = gsi_start_bb (default_bb);
10480 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
10481 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
10483 if (exit_reachable)
10485 tree bfn_decl;
10487 /* Code to get the next section goes in L1_BB. */
10488 si = gsi_last_bb (l1_bb);
10489 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
10491 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
10492 stmt = gimple_build_call (bfn_decl, 0);
10493 gimple_call_set_lhs (stmt, vnext);
10494 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
10495 gsi_remove (&si, true);
10497 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
10500 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
10501 si = gsi_last_bb (l2_bb);
10502 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
10503 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
10504 else if (gimple_omp_return_lhs (gsi_stmt (si)))
10505 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
10506 else
10507 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
10508 stmt = gimple_build_call (t, 0);
10509 if (gimple_omp_return_lhs (gsi_stmt (si)))
10510 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
10511 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
10512 gsi_remove (&si, true);
10514 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
10518 /* Expand code for an OpenMP single directive. We've already expanded
10519 much of the code, here we simply place the GOMP_barrier call. */
10521 static void
10522 expand_omp_single (struct omp_region *region)
10524 basic_block entry_bb, exit_bb;
10525 gimple_stmt_iterator si;
10527 entry_bb = region->entry;
10528 exit_bb = region->exit;
10530 si = gsi_last_bb (entry_bb);
10531 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
10532 gsi_remove (&si, true);
10533 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10535 si = gsi_last_bb (exit_bb);
10536 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
10538 tree t = gimple_omp_return_lhs (gsi_stmt (si));
10539 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
10541 gsi_remove (&si, true);
10542 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
10546 /* Generic expansion for OpenMP synchronization directives: master,
10547 ordered and critical. All we need to do here is remove the entry
10548 and exit markers for REGION. */
10550 static void
10551 expand_omp_synch (struct omp_region *region)
10553 basic_block entry_bb, exit_bb;
10554 gimple_stmt_iterator si;
10556 entry_bb = region->entry;
10557 exit_bb = region->exit;
10559 si = gsi_last_bb (entry_bb);
10560 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
10561 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
10562 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
10563 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
10564 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
10565 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
10566 gsi_remove (&si, true);
10567 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10569 if (exit_bb)
10571 si = gsi_last_bb (exit_bb);
10572 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
10573 gsi_remove (&si, true);
10574 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
10578 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
10579 operation as a normal volatile load. */
10581 static bool
10582 expand_omp_atomic_load (basic_block load_bb, tree addr,
10583 tree loaded_val, int index)
10585 enum built_in_function tmpbase;
10586 gimple_stmt_iterator gsi;
10587 basic_block store_bb;
10588 location_t loc;
10589 gimple *stmt;
10590 tree decl, call, type, itype;
10592 gsi = gsi_last_bb (load_bb);
10593 stmt = gsi_stmt (gsi);
10594 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
10595 loc = gimple_location (stmt);
10597 /* ??? If the target does not implement atomic_load_optab[mode], and mode
10598 is smaller than word size, then expand_atomic_load assumes that the load
10599 is atomic. We could avoid the builtin entirely in this case. */
10601 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
10602 decl = builtin_decl_explicit (tmpbase);
10603 if (decl == NULL_TREE)
10604 return false;
10606 type = TREE_TYPE (loaded_val);
10607 itype = TREE_TYPE (TREE_TYPE (decl));
10609 call = build_call_expr_loc (loc, decl, 2, addr,
10610 build_int_cst (NULL,
10611 gimple_omp_atomic_seq_cst_p (stmt)
10612 ? MEMMODEL_SEQ_CST
10613 : MEMMODEL_RELAXED));
10614 if (!useless_type_conversion_p (type, itype))
10615 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
10616 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
10618 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
10619 gsi_remove (&gsi, true);
10621 store_bb = single_succ (load_bb);
10622 gsi = gsi_last_bb (store_bb);
10623 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
10624 gsi_remove (&gsi, true);
10626 if (gimple_in_ssa_p (cfun))
10627 update_ssa (TODO_update_ssa_no_phi);
10629 return true;
10632 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
10633 operation as a normal volatile store. */
10635 static bool
10636 expand_omp_atomic_store (basic_block load_bb, tree addr,
10637 tree loaded_val, tree stored_val, int index)
10639 enum built_in_function tmpbase;
10640 gimple_stmt_iterator gsi;
10641 basic_block store_bb = single_succ (load_bb);
10642 location_t loc;
10643 gimple *stmt;
10644 tree decl, call, type, itype;
10645 machine_mode imode;
10646 bool exchange;
10648 gsi = gsi_last_bb (load_bb);
10649 stmt = gsi_stmt (gsi);
10650 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
10652 /* If the load value is needed, then this isn't a store but an exchange. */
10653 exchange = gimple_omp_atomic_need_value_p (stmt);
10655 gsi = gsi_last_bb (store_bb);
10656 stmt = gsi_stmt (gsi);
10657 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
10658 loc = gimple_location (stmt);
10660 /* ??? If the target does not implement atomic_store_optab[mode], and mode
10661 is smaller than word size, then expand_atomic_store assumes that the store
10662 is atomic. We could avoid the builtin entirely in this case. */
10664 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
10665 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
10666 decl = builtin_decl_explicit (tmpbase);
10667 if (decl == NULL_TREE)
10668 return false;
10670 type = TREE_TYPE (stored_val);
10672 /* Dig out the type of the function's second argument. */
10673 itype = TREE_TYPE (decl);
10674 itype = TYPE_ARG_TYPES (itype);
10675 itype = TREE_CHAIN (itype);
10676 itype = TREE_VALUE (itype);
10677 imode = TYPE_MODE (itype);
10679 if (exchange && !can_atomic_exchange_p (imode, true))
10680 return false;
10682 if (!useless_type_conversion_p (itype, type))
10683 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
10684 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
10685 build_int_cst (NULL,
10686 gimple_omp_atomic_seq_cst_p (stmt)
10687 ? MEMMODEL_SEQ_CST
10688 : MEMMODEL_RELAXED));
10689 if (exchange)
10691 if (!useless_type_conversion_p (type, itype))
10692 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
10693 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
10696 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
10697 gsi_remove (&gsi, true);
10699 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
10700 gsi = gsi_last_bb (load_bb);
10701 gsi_remove (&gsi, true);
10703 if (gimple_in_ssa_p (cfun))
10704 update_ssa (TODO_update_ssa_no_phi);
10706 return true;
10709 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
10710 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
10711 size of the data type, and thus usable to find the index of the builtin
10712 decl. Returns false if the expression is not of the proper form. */
10714 static bool
10715 expand_omp_atomic_fetch_op (basic_block load_bb,
10716 tree addr, tree loaded_val,
10717 tree stored_val, int index)
10719 enum built_in_function oldbase, newbase, tmpbase;
10720 tree decl, itype, call;
10721 tree lhs, rhs;
10722 basic_block store_bb = single_succ (load_bb);
10723 gimple_stmt_iterator gsi;
10724 gimple *stmt;
10725 location_t loc;
10726 enum tree_code code;
10727 bool need_old, need_new;
10728 machine_mode imode;
10729 bool seq_cst;
10731 /* We expect to find the following sequences:
10733 load_bb:
10734 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
10736 store_bb:
10737 val = tmp OP something; (or: something OP tmp)
10738 GIMPLE_OMP_STORE (val)
10740 ???FIXME: Allow a more flexible sequence.
10741 Perhaps use data flow to pick the statements.
10745 gsi = gsi_after_labels (store_bb);
10746 stmt = gsi_stmt (gsi);
10747 loc = gimple_location (stmt);
10748 if (!is_gimple_assign (stmt))
10749 return false;
10750 gsi_next (&gsi);
10751 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
10752 return false;
10753 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
10754 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
10755 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
10756 gcc_checking_assert (!need_old || !need_new);
10758 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
10759 return false;
10761 /* Check for one of the supported fetch-op operations. */
10762 code = gimple_assign_rhs_code (stmt);
10763 switch (code)
10765 case PLUS_EXPR:
10766 case POINTER_PLUS_EXPR:
10767 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
10768 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
10769 break;
10770 case MINUS_EXPR:
10771 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
10772 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
10773 break;
10774 case BIT_AND_EXPR:
10775 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
10776 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
10777 break;
10778 case BIT_IOR_EXPR:
10779 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
10780 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
10781 break;
10782 case BIT_XOR_EXPR:
10783 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
10784 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
10785 break;
10786 default:
10787 return false;
10790 /* Make sure the expression is of the proper form. */
10791 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
10792 rhs = gimple_assign_rhs2 (stmt);
10793 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
10794 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
10795 rhs = gimple_assign_rhs1 (stmt);
10796 else
10797 return false;
10799 tmpbase = ((enum built_in_function)
10800 ((need_new ? newbase : oldbase) + index + 1));
10801 decl = builtin_decl_explicit (tmpbase);
10802 if (decl == NULL_TREE)
10803 return false;
10804 itype = TREE_TYPE (TREE_TYPE (decl));
10805 imode = TYPE_MODE (itype);
10807 /* We could test all of the various optabs involved, but the fact of the
10808 matter is that (with the exception of i486 vs i586 and xadd) all targets
10809 that support any atomic operaton optab also implements compare-and-swap.
10810 Let optabs.c take care of expanding any compare-and-swap loop. */
10811 if (!can_compare_and_swap_p (imode, true))
10812 return false;
10814 gsi = gsi_last_bb (load_bb);
10815 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
10817 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
10818 It only requires that the operation happen atomically. Thus we can
10819 use the RELAXED memory model. */
10820 call = build_call_expr_loc (loc, decl, 3, addr,
10821 fold_convert_loc (loc, itype, rhs),
10822 build_int_cst (NULL,
10823 seq_cst ? MEMMODEL_SEQ_CST
10824 : MEMMODEL_RELAXED));
10826 if (need_old || need_new)
10828 lhs = need_old ? loaded_val : stored_val;
10829 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
10830 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
10832 else
10833 call = fold_convert_loc (loc, void_type_node, call);
10834 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
10835 gsi_remove (&gsi, true);
10837 gsi = gsi_last_bb (store_bb);
10838 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
10839 gsi_remove (&gsi, true);
10840 gsi = gsi_last_bb (store_bb);
10841 gsi_remove (&gsi, true);
10843 if (gimple_in_ssa_p (cfun))
10844 update_ssa (TODO_update_ssa_no_phi);
10846 return true;
10849 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
10851 oldval = *addr;
10852 repeat:
10853 newval = rhs; // with oldval replacing *addr in rhs
10854 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
10855 if (oldval != newval)
10856 goto repeat;
10858 INDEX is log2 of the size of the data type, and thus usable to find the
10859 index of the builtin decl. */
10861 static bool
10862 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
10863 tree addr, tree loaded_val, tree stored_val,
10864 int index)
10866 tree loadedi, storedi, initial, new_storedi, old_vali;
10867 tree type, itype, cmpxchg, iaddr;
10868 gimple_stmt_iterator si;
10869 basic_block loop_header = single_succ (load_bb);
10870 gimple *phi, *stmt;
10871 edge e;
10872 enum built_in_function fncode;
10874 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
10875 order to use the RELAXED memory model effectively. */
10876 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
10877 + index + 1);
10878 cmpxchg = builtin_decl_explicit (fncode);
10879 if (cmpxchg == NULL_TREE)
10880 return false;
10881 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
10882 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
10884 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
10885 return false;
10887 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
10888 si = gsi_last_bb (load_bb);
10889 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
10891 /* For floating-point values, we'll need to view-convert them to integers
10892 so that we can perform the atomic compare and swap. Simplify the
10893 following code by always setting up the "i"ntegral variables. */
10894 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
10896 tree iaddr_val;
10898 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
10899 true));
10900 iaddr_val
10901 = force_gimple_operand_gsi (&si,
10902 fold_convert (TREE_TYPE (iaddr), addr),
10903 false, NULL_TREE, true, GSI_SAME_STMT);
10904 stmt = gimple_build_assign (iaddr, iaddr_val);
10905 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
10906 loadedi = create_tmp_var (itype);
10907 if (gimple_in_ssa_p (cfun))
10908 loadedi = make_ssa_name (loadedi);
10910 else
10912 iaddr = addr;
10913 loadedi = loaded_val;
10916 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
10917 tree loaddecl = builtin_decl_explicit (fncode);
10918 if (loaddecl)
10919 initial
10920 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
10921 build_call_expr (loaddecl, 2, iaddr,
10922 build_int_cst (NULL_TREE,
10923 MEMMODEL_RELAXED)));
10924 else
10925 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
10926 build_int_cst (TREE_TYPE (iaddr), 0));
10928 initial
10929 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
10930 GSI_SAME_STMT);
10932 /* Move the value to the LOADEDI temporary. */
10933 if (gimple_in_ssa_p (cfun))
10935 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
10936 phi = create_phi_node (loadedi, loop_header);
10937 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
10938 initial);
10940 else
10941 gsi_insert_before (&si,
10942 gimple_build_assign (loadedi, initial),
10943 GSI_SAME_STMT);
10944 if (loadedi != loaded_val)
10946 gimple_stmt_iterator gsi2;
10947 tree x;
10949 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
10950 gsi2 = gsi_start_bb (loop_header);
10951 if (gimple_in_ssa_p (cfun))
10953 gassign *stmt;
10954 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
10955 true, GSI_SAME_STMT);
10956 stmt = gimple_build_assign (loaded_val, x);
10957 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
10959 else
10961 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
10962 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
10963 true, GSI_SAME_STMT);
10966 gsi_remove (&si, true);
10968 si = gsi_last_bb (store_bb);
10969 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
10971 if (iaddr == addr)
10972 storedi = stored_val;
10973 else
10974 storedi =
10975 force_gimple_operand_gsi (&si,
10976 build1 (VIEW_CONVERT_EXPR, itype,
10977 stored_val), true, NULL_TREE, true,
10978 GSI_SAME_STMT);
10980 /* Build the compare&swap statement. */
10981 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
10982 new_storedi = force_gimple_operand_gsi (&si,
10983 fold_convert (TREE_TYPE (loadedi),
10984 new_storedi),
10985 true, NULL_TREE,
10986 true, GSI_SAME_STMT);
10988 if (gimple_in_ssa_p (cfun))
10989 old_vali = loadedi;
10990 else
10992 old_vali = create_tmp_var (TREE_TYPE (loadedi));
10993 stmt = gimple_build_assign (old_vali, loadedi);
10994 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
10996 stmt = gimple_build_assign (loadedi, new_storedi);
10997 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11000 /* Note that we always perform the comparison as an integer, even for
11001 floating point. This allows the atomic operation to properly
11002 succeed even with NaNs and -0.0. */
11003 stmt = gimple_build_cond_empty
11004 (build2 (NE_EXPR, boolean_type_node,
11005 new_storedi, old_vali));
11006 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11008 /* Update cfg. */
11009 e = single_succ_edge (store_bb);
11010 e->flags &= ~EDGE_FALLTHRU;
11011 e->flags |= EDGE_FALSE_VALUE;
11013 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
11015 /* Copy the new value to loadedi (we already did that before the condition
11016 if we are not in SSA). */
11017 if (gimple_in_ssa_p (cfun))
11019 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
11020 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
11023 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
11024 gsi_remove (&si, true);
11026 struct loop *loop = alloc_loop ();
11027 loop->header = loop_header;
11028 loop->latch = store_bb;
11029 add_loop (loop, loop_header->loop_father);
11031 if (gimple_in_ssa_p (cfun))
11032 update_ssa (TODO_update_ssa_no_phi);
11034 return true;
11037 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
11039 GOMP_atomic_start ();
11040 *addr = rhs;
11041 GOMP_atomic_end ();
11043 The result is not globally atomic, but works so long as all parallel
11044 references are within #pragma omp atomic directives. According to
11045 responses received from omp@openmp.org, appears to be within spec.
11046 Which makes sense, since that's how several other compilers handle
11047 this situation as well.
11048 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
11049 expanding. STORED_VAL is the operand of the matching
11050 GIMPLE_OMP_ATOMIC_STORE.
11052 We replace
11053 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
11054 loaded_val = *addr;
11056 and replace
11057 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
11058 *addr = stored_val;
11061 static bool
11062 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
11063 tree addr, tree loaded_val, tree stored_val)
11065 gimple_stmt_iterator si;
11066 gassign *stmt;
11067 tree t;
11069 si = gsi_last_bb (load_bb);
11070 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
11072 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
11073 t = build_call_expr (t, 0);
11074 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
11076 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
11077 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11078 gsi_remove (&si, true);
11080 si = gsi_last_bb (store_bb);
11081 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
11083 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
11084 stored_val);
11085 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11087 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
11088 t = build_call_expr (t, 0);
11089 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
11090 gsi_remove (&si, true);
11092 if (gimple_in_ssa_p (cfun))
11093 update_ssa (TODO_update_ssa_no_phi);
11094 return true;
11097 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
11098 using expand_omp_atomic_fetch_op. If it failed, we try to
11099 call expand_omp_atomic_pipeline, and if it fails too, the
11100 ultimate fallback is wrapping the operation in a mutex
11101 (expand_omp_atomic_mutex). REGION is the atomic region built
11102 by build_omp_regions_1(). */
11104 static void
11105 expand_omp_atomic (struct omp_region *region)
11107 basic_block load_bb = region->entry, store_bb = region->exit;
11108 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
11109 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
11110 tree loaded_val = gimple_omp_atomic_load_lhs (load);
11111 tree addr = gimple_omp_atomic_load_rhs (load);
11112 tree stored_val = gimple_omp_atomic_store_val (store);
11113 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
11114 HOST_WIDE_INT index;
11116 /* Make sure the type is one of the supported sizes. */
11117 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
11118 index = exact_log2 (index);
11119 if (index >= 0 && index <= 4)
11121 unsigned int align = TYPE_ALIGN_UNIT (type);
11123 /* __sync builtins require strict data alignment. */
11124 if (exact_log2 (align) >= index)
11126 /* Atomic load. */
11127 if (loaded_val == stored_val
11128 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
11129 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
11130 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
11131 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
11132 return;
11134 /* Atomic store. */
11135 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
11136 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
11137 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
11138 && store_bb == single_succ (load_bb)
11139 && first_stmt (store_bb) == store
11140 && expand_omp_atomic_store (load_bb, addr, loaded_val,
11141 stored_val, index))
11142 return;
11144 /* When possible, use specialized atomic update functions. */
11145 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
11146 && store_bb == single_succ (load_bb)
11147 && expand_omp_atomic_fetch_op (load_bb, addr,
11148 loaded_val, stored_val, index))
11149 return;
11151 /* If we don't have specialized __sync builtins, try and implement
11152 as a compare and swap loop. */
11153 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
11154 loaded_val, stored_val, index))
11155 return;
11159 /* The ultimate fallback is wrapping the operation in a mutex. */
11160 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
11164 /* Encode an oacc launc argument. This matches the GOMP_LAUNCH_PACK
11165 macro on gomp-constants.h. We do not check for overflow. */
11167 static tree
11168 oacc_launch_pack (unsigned code, tree device, unsigned op)
11170 tree res;
11172 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
11173 if (device)
11175 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
11176 device, build_int_cst (unsigned_type_node,
11177 GOMP_LAUNCH_DEVICE_SHIFT));
11178 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
11180 return res;
11183 /* Look for compute grid dimension clauses and convert to an attribute
11184 attached to FN. This permits the target-side code to (a) massage
11185 the dimensions, (b) emit that data and (c) optimize. Non-constant
11186 dimensions are pushed onto ARGS.
11188 The attribute value is a TREE_LIST. A set of dimensions is
11189 represented as a list of INTEGER_CST. Those that are runtime
11190 expres are represented as an INTEGER_CST of zero.
11192 TOOO. Normally the attribute will just contain a single such list. If
11193 however it contains a list of lists, this will represent the use of
11194 device_type. Each member of the outer list is an assoc list of
11195 dimensions, keyed by the device type. The first entry will be the
11196 default. Well, that's the plan. */
11198 #define OACC_FN_ATTRIB "oacc function"
11200 /* Replace any existing oacc fn attribute with updated dimensions. */
11202 void
11203 replace_oacc_fn_attrib (tree fn, tree dims)
11205 tree ident = get_identifier (OACC_FN_ATTRIB);
11206 tree attribs = DECL_ATTRIBUTES (fn);
11208 /* If we happen to be present as the first attrib, drop it. */
11209 if (attribs && TREE_PURPOSE (attribs) == ident)
11210 attribs = TREE_CHAIN (attribs);
11211 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
11214 /* Scan CLAUSES for launch dimensions and attach them to the oacc
11215 function attribute. Push any that are non-constant onto the ARGS
11216 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
11218 static void
11219 set_oacc_fn_attrib (tree fn, tree clauses, vec<tree> *args)
11221 /* Must match GOMP_DIM ordering. */
11222 static const omp_clause_code ids[]
11223 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
11224 OMP_CLAUSE_VECTOR_LENGTH };
11225 unsigned ix;
11226 tree dims[GOMP_DIM_MAX];
11227 tree attr = NULL_TREE;
11228 unsigned non_const = 0;
11230 for (ix = GOMP_DIM_MAX; ix--;)
11232 tree clause = find_omp_clause (clauses, ids[ix]);
11233 tree dim = NULL_TREE;
11235 if (clause)
11236 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
11237 dims[ix] = dim;
11238 if (dim && TREE_CODE (dim) != INTEGER_CST)
11240 dim = integer_zero_node;
11241 non_const |= GOMP_DIM_MASK (ix);
11243 attr = tree_cons (NULL_TREE, dim, attr);
11246 replace_oacc_fn_attrib (fn, attr);
11248 if (non_const)
11250 /* Push a dynamic argument set. */
11251 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
11252 NULL_TREE, non_const));
11253 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
11254 if (non_const & GOMP_DIM_MASK (ix))
11255 args->safe_push (dims[ix]);
11259 /* Retrieve the oacc function attrib and return it. Non-oacc
11260 functions will return NULL. */
11262 tree
11263 get_oacc_fn_attrib (tree fn)
11265 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
11268 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
11270 static void
11271 expand_omp_target (struct omp_region *region)
11273 basic_block entry_bb, exit_bb, new_bb;
11274 struct function *child_cfun;
11275 tree child_fn, block, t;
11276 gimple_stmt_iterator gsi;
11277 gomp_target *entry_stmt;
11278 gimple *stmt;
11279 edge e;
11280 bool offloaded, data_region;
11282 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
11283 new_bb = region->entry;
11285 offloaded = is_gimple_omp_offloaded (entry_stmt);
11286 switch (gimple_omp_target_kind (entry_stmt))
11288 case GF_OMP_TARGET_KIND_REGION:
11289 case GF_OMP_TARGET_KIND_UPDATE:
11290 case GF_OMP_TARGET_KIND_ENTER_DATA:
11291 case GF_OMP_TARGET_KIND_EXIT_DATA:
11292 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11293 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11294 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11295 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11296 data_region = false;
11297 break;
11298 case GF_OMP_TARGET_KIND_DATA:
11299 case GF_OMP_TARGET_KIND_OACC_DATA:
11300 data_region = true;
11301 break;
11302 default:
11303 gcc_unreachable ();
11306 child_fn = NULL_TREE;
11307 child_cfun = NULL;
11308 if (offloaded)
11310 child_fn = gimple_omp_target_child_fn (entry_stmt);
11311 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
11314 /* Supported by expand_omp_taskreg, but not here. */
11315 if (child_cfun != NULL)
11316 gcc_checking_assert (!child_cfun->cfg);
11317 gcc_checking_assert (!gimple_in_ssa_p (cfun));
11319 entry_bb = region->entry;
11320 exit_bb = region->exit;
11322 if (offloaded)
11324 unsigned srcidx, dstidx, num;
11326 /* If the offloading region needs data sent from the parent
11327 function, then the very first statement (except possible
11328 tree profile counter updates) of the offloading body
11329 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
11330 &.OMP_DATA_O is passed as an argument to the child function,
11331 we need to replace it with the argument as seen by the child
11332 function.
11334 In most cases, this will end up being the identity assignment
11335 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
11336 a function call that has been inlined, the original PARM_DECL
11337 .OMP_DATA_I may have been converted into a different local
11338 variable. In which case, we need to keep the assignment. */
11339 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
11340 if (data_arg)
11342 basic_block entry_succ_bb = single_succ (entry_bb);
11343 gimple_stmt_iterator gsi;
11344 tree arg;
11345 gimple *tgtcopy_stmt = NULL;
11346 tree sender = TREE_VEC_ELT (data_arg, 0);
11348 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
11350 gcc_assert (!gsi_end_p (gsi));
11351 stmt = gsi_stmt (gsi);
11352 if (gimple_code (stmt) != GIMPLE_ASSIGN)
11353 continue;
11355 if (gimple_num_ops (stmt) == 2)
11357 tree arg = gimple_assign_rhs1 (stmt);
11359 /* We're ignoring the subcode because we're
11360 effectively doing a STRIP_NOPS. */
11362 if (TREE_CODE (arg) == ADDR_EXPR
11363 && TREE_OPERAND (arg, 0) == sender)
11365 tgtcopy_stmt = stmt;
11366 break;
11371 gcc_assert (tgtcopy_stmt != NULL);
11372 arg = DECL_ARGUMENTS (child_fn);
11374 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
11375 gsi_remove (&gsi, true);
11378 /* Declare local variables needed in CHILD_CFUN. */
11379 block = DECL_INITIAL (child_fn);
11380 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
11381 /* The gimplifier could record temporaries in the offloading block
11382 rather than in containing function's local_decls chain,
11383 which would mean cgraph missed finalizing them. Do it now. */
11384 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
11385 if (TREE_CODE (t) == VAR_DECL
11386 && TREE_STATIC (t)
11387 && !DECL_EXTERNAL (t))
11388 varpool_node::finalize_decl (t);
11389 DECL_SAVED_TREE (child_fn) = NULL;
11390 /* We'll create a CFG for child_fn, so no gimple body is needed. */
11391 gimple_set_body (child_fn, NULL);
11392 TREE_USED (block) = 1;
11394 /* Reset DECL_CONTEXT on function arguments. */
11395 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
11396 DECL_CONTEXT (t) = child_fn;
11398 /* Split ENTRY_BB at GIMPLE_*,
11399 so that it can be moved to the child function. */
11400 gsi = gsi_last_bb (entry_bb);
11401 stmt = gsi_stmt (gsi);
11402 gcc_assert (stmt
11403 && gimple_code (stmt) == gimple_code (entry_stmt));
11404 e = split_block (entry_bb, stmt);
11405 gsi_remove (&gsi, true);
11406 entry_bb = e->dest;
11407 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11409 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
11410 if (exit_bb)
11412 gsi = gsi_last_bb (exit_bb);
11413 gcc_assert (!gsi_end_p (gsi)
11414 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11415 stmt = gimple_build_return (NULL);
11416 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
11417 gsi_remove (&gsi, true);
11420 /* Move the offloading region into CHILD_CFUN. */
11422 block = gimple_block (entry_stmt);
11424 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
11425 if (exit_bb)
11426 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
11427 /* When the OMP expansion process cannot guarantee an up-to-date
11428 loop tree arrange for the child function to fixup loops. */
11429 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
11430 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
11432 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
11433 num = vec_safe_length (child_cfun->local_decls);
11434 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
11436 t = (*child_cfun->local_decls)[srcidx];
11437 if (DECL_CONTEXT (t) == cfun->decl)
11438 continue;
11439 if (srcidx != dstidx)
11440 (*child_cfun->local_decls)[dstidx] = t;
11441 dstidx++;
11443 if (dstidx != num)
11444 vec_safe_truncate (child_cfun->local_decls, dstidx);
11446 /* Inform the callgraph about the new function. */
11447 child_cfun->curr_properties = cfun->curr_properties;
11448 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
11449 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
11450 cgraph_node *node = cgraph_node::get_create (child_fn);
11451 node->parallelized_function = 1;
11452 cgraph_node::add_new_function (child_fn, true);
11454 #ifdef ENABLE_OFFLOADING
11455 /* Add the new function to the offload table. */
11456 vec_safe_push (offload_funcs, child_fn);
11457 #endif
11459 /* Fix the callgraph edges for child_cfun. Those for cfun will be
11460 fixed in a following pass. */
11461 push_cfun (child_cfun);
11462 cgraph_edge::rebuild_edges ();
11464 #ifdef ENABLE_OFFLOADING
11465 /* Prevent IPA from removing child_fn as unreachable, since there are no
11466 refs from the parent function to child_fn in offload LTO mode. */
11467 cgraph_node::get (child_fn)->mark_force_output ();
11468 #endif
11470 /* Some EH regions might become dead, see PR34608. If
11471 pass_cleanup_cfg isn't the first pass to happen with the
11472 new child, these dead EH edges might cause problems.
11473 Clean them up now. */
11474 if (flag_exceptions)
11476 basic_block bb;
11477 bool changed = false;
11479 FOR_EACH_BB_FN (bb, cfun)
11480 changed |= gimple_purge_dead_eh_edges (bb);
11481 if (changed)
11482 cleanup_tree_cfg ();
11484 #ifdef ENABLE_CHECKING
11485 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
11486 verify_loop_structure ();
11487 #endif
11488 pop_cfun ();
11491 /* Emit a library call to launch the offloading region, or do data
11492 transfers. */
11493 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
11494 enum built_in_function start_ix;
11495 location_t clause_loc;
11496 unsigned int flags_i = 0;
11498 switch (gimple_omp_target_kind (entry_stmt))
11500 case GF_OMP_TARGET_KIND_REGION:
11501 start_ix = BUILT_IN_GOMP_TARGET;
11502 break;
11503 case GF_OMP_TARGET_KIND_DATA:
11504 start_ix = BUILT_IN_GOMP_TARGET_DATA;
11505 break;
11506 case GF_OMP_TARGET_KIND_UPDATE:
11507 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
11508 break;
11509 case GF_OMP_TARGET_KIND_ENTER_DATA:
11510 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
11511 break;
11512 case GF_OMP_TARGET_KIND_EXIT_DATA:
11513 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
11514 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
11515 break;
11516 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11517 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11518 start_ix = BUILT_IN_GOACC_PARALLEL;
11519 break;
11520 case GF_OMP_TARGET_KIND_OACC_DATA:
11521 start_ix = BUILT_IN_GOACC_DATA_START;
11522 break;
11523 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11524 start_ix = BUILT_IN_GOACC_UPDATE;
11525 break;
11526 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11527 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
11528 break;
11529 default:
11530 gcc_unreachable ();
11533 clauses = gimple_omp_target_clauses (entry_stmt);
11535 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
11536 library choose) and there is no conditional. */
11537 cond = NULL_TREE;
11538 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
11540 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
11541 if (c)
11542 cond = OMP_CLAUSE_IF_EXPR (c);
11544 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
11545 if (c)
11547 /* Even if we pass it to all library function calls, it is currently only
11548 defined/used for the OpenMP target ones. */
11549 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
11550 || start_ix == BUILT_IN_GOMP_TARGET_DATA
11551 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
11552 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
11554 device = OMP_CLAUSE_DEVICE_ID (c);
11555 clause_loc = OMP_CLAUSE_LOCATION (c);
11557 else
11558 clause_loc = gimple_location (entry_stmt);
11560 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
11561 if (c)
11562 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
11564 /* Ensure 'device' is of the correct type. */
11565 device = fold_convert_loc (clause_loc, integer_type_node, device);
11567 /* If we found the clause 'if (cond)', build
11568 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
11569 if (cond)
11571 cond = gimple_boolify (cond);
11573 basic_block cond_bb, then_bb, else_bb;
11574 edge e;
11575 tree tmp_var;
11577 tmp_var = create_tmp_var (TREE_TYPE (device));
11578 if (offloaded)
11579 e = split_block_after_labels (new_bb);
11580 else
11582 gsi = gsi_last_bb (new_bb);
11583 gsi_prev (&gsi);
11584 e = split_block (new_bb, gsi_stmt (gsi));
11586 cond_bb = e->src;
11587 new_bb = e->dest;
11588 remove_edge (e);
11590 then_bb = create_empty_bb (cond_bb);
11591 else_bb = create_empty_bb (then_bb);
11592 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
11593 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
11595 stmt = gimple_build_cond_empty (cond);
11596 gsi = gsi_last_bb (cond_bb);
11597 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
11599 gsi = gsi_start_bb (then_bb);
11600 stmt = gimple_build_assign (tmp_var, device);
11601 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
11603 gsi = gsi_start_bb (else_bb);
11604 stmt = gimple_build_assign (tmp_var,
11605 build_int_cst (integer_type_node,
11606 GOMP_DEVICE_HOST_FALLBACK));
11607 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
11609 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
11610 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
11611 add_bb_to_loop (then_bb, cond_bb->loop_father);
11612 add_bb_to_loop (else_bb, cond_bb->loop_father);
11613 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
11614 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
11616 device = tmp_var;
11619 gsi = gsi_last_bb (new_bb);
11620 t = gimple_omp_target_data_arg (entry_stmt);
11621 if (t == NULL)
11623 t1 = size_zero_node;
11624 t2 = build_zero_cst (ptr_type_node);
11625 t3 = t2;
11626 t4 = t2;
11628 else
11630 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
11631 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
11632 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
11633 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
11634 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
11637 gimple *g;
11638 bool tagging = false;
11639 /* The maximum number used by any start_ix, without varargs. */
11640 auto_vec<tree, 11> args;
11641 args.quick_push (device);
11642 if (offloaded)
11643 args.quick_push (build_fold_addr_expr (child_fn));
11644 args.quick_push (t1);
11645 args.quick_push (t2);
11646 args.quick_push (t3);
11647 args.quick_push (t4);
11648 switch (start_ix)
11650 case BUILT_IN_GOACC_DATA_START:
11651 case BUILT_IN_GOMP_TARGET_DATA:
11652 break;
11653 case BUILT_IN_GOMP_TARGET:
11654 case BUILT_IN_GOMP_TARGET_UPDATE:
11655 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
11656 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
11657 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
11658 if (c)
11659 depend = OMP_CLAUSE_DECL (c);
11660 else
11661 depend = build_int_cst (ptr_type_node, 0);
11662 args.quick_push (depend);
11663 break;
11664 case BUILT_IN_GOACC_PARALLEL:
11666 set_oacc_fn_attrib (child_fn, clauses, &args);
11667 tagging = true;
11669 /* FALLTHRU */
11670 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
11671 case BUILT_IN_GOACC_UPDATE:
11673 tree t_async = NULL_TREE;
11675 /* If present, use the value specified by the respective
11676 clause, making sure that is of the correct type. */
11677 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
11678 if (c)
11679 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
11680 integer_type_node,
11681 OMP_CLAUSE_ASYNC_EXPR (c));
11682 else if (!tagging)
11683 /* Default values for t_async. */
11684 t_async = fold_convert_loc (gimple_location (entry_stmt),
11685 integer_type_node,
11686 build_int_cst (integer_type_node,
11687 GOMP_ASYNC_SYNC));
11688 if (tagging && t_async)
11690 unsigned HOST_WIDE_INT i_async;
11692 if (TREE_CODE (t_async) == INTEGER_CST)
11694 /* See if we can pack the async arg in to the tag's
11695 operand. */
11696 i_async = TREE_INT_CST_LOW (t_async);
11698 if (i_async < GOMP_LAUNCH_OP_MAX)
11699 t_async = NULL_TREE;
11701 if (t_async)
11702 i_async = GOMP_LAUNCH_OP_MAX;
11703 args.safe_push (oacc_launch_pack
11704 (GOMP_LAUNCH_ASYNC, NULL_TREE, i_async));
11706 if (t_async)
11707 args.safe_push (t_async);
11709 /* Save the argument index, and ... */
11710 unsigned t_wait_idx = args.length ();
11711 unsigned num_waits = 0;
11712 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
11713 if (!tagging || c)
11714 /* ... push a placeholder. */
11715 args.safe_push (integer_zero_node);
11717 for (; c; c = OMP_CLAUSE_CHAIN (c))
11718 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
11720 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
11721 integer_type_node,
11722 OMP_CLAUSE_WAIT_EXPR (c)));
11723 num_waits++;
11726 if (!tagging || num_waits)
11728 tree len;
11730 /* Now that we know the number, update the placeholder. */
11731 if (tagging)
11732 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
11733 else
11734 len = build_int_cst (integer_type_node, num_waits);
11735 len = fold_convert_loc (gimple_location (entry_stmt),
11736 unsigned_type_node, len);
11737 args[t_wait_idx] = len;
11740 break;
11741 default:
11742 gcc_unreachable ();
11744 if (tagging)
11745 /* Push terminal marker - zero. */
11746 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
11748 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
11749 gimple_set_location (g, gimple_location (entry_stmt));
11750 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
11751 if (!offloaded)
11753 g = gsi_stmt (gsi);
11754 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
11755 gsi_remove (&gsi, true);
11757 if (data_region && region->exit)
11759 gsi = gsi_last_bb (region->exit);
11760 g = gsi_stmt (gsi);
11761 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
11762 gsi_remove (&gsi, true);
11767 /* Expand the parallel region tree rooted at REGION. Expansion
11768 proceeds in depth-first order. Innermost regions are expanded
11769 first. This way, parallel regions that require a new function to
11770 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
11771 internal dependencies in their body. */
11773 static void
11774 expand_omp (struct omp_region *region)
11776 while (region)
11778 location_t saved_location;
11779 gimple *inner_stmt = NULL;
11781 /* First, determine whether this is a combined parallel+workshare
11782 region. */
11783 if (region->type == GIMPLE_OMP_PARALLEL)
11784 determine_parallel_type (region);
11786 if (region->type == GIMPLE_OMP_FOR
11787 && gimple_omp_for_combined_p (last_stmt (region->entry)))
11788 inner_stmt = last_stmt (region->inner->entry);
11790 if (region->inner)
11791 expand_omp (region->inner);
11793 saved_location = input_location;
11794 if (gimple_has_location (last_stmt (region->entry)))
11795 input_location = gimple_location (last_stmt (region->entry));
11797 switch (region->type)
11799 case GIMPLE_OMP_PARALLEL:
11800 case GIMPLE_OMP_TASK:
11801 expand_omp_taskreg (region);
11802 break;
11804 case GIMPLE_OMP_FOR:
11805 expand_omp_for (region, inner_stmt);
11806 break;
11808 case GIMPLE_OMP_SECTIONS:
11809 expand_omp_sections (region);
11810 break;
11812 case GIMPLE_OMP_SECTION:
11813 /* Individual omp sections are handled together with their
11814 parent GIMPLE_OMP_SECTIONS region. */
11815 break;
11817 case GIMPLE_OMP_SINGLE:
11818 expand_omp_single (region);
11819 break;
11821 case GIMPLE_OMP_ORDERED:
11823 gomp_ordered *ord_stmt
11824 = as_a <gomp_ordered *> (last_stmt (region->entry));
11825 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
11826 OMP_CLAUSE_DEPEND))
11828 /* We'll expand these when expanding corresponding
11829 worksharing region with ordered(n) clause. */
11830 gcc_assert (region->outer
11831 && region->outer->type == GIMPLE_OMP_FOR);
11832 region->ord_stmt = ord_stmt;
11833 break;
11836 /* FALLTHRU */
11837 case GIMPLE_OMP_MASTER:
11838 case GIMPLE_OMP_TASKGROUP:
11839 case GIMPLE_OMP_CRITICAL:
11840 case GIMPLE_OMP_TEAMS:
11841 expand_omp_synch (region);
11842 break;
11844 case GIMPLE_OMP_ATOMIC_LOAD:
11845 expand_omp_atomic (region);
11846 break;
11848 case GIMPLE_OMP_TARGET:
11849 expand_omp_target (region);
11850 break;
11852 default:
11853 gcc_unreachable ();
11856 input_location = saved_location;
11857 region = region->next;
11862 /* Helper for build_omp_regions. Scan the dominator tree starting at
11863 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
11864 true, the function ends once a single tree is built (otherwise, whole
11865 forest of OMP constructs may be built). */
11867 static void
11868 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
11869 bool single_tree)
11871 gimple_stmt_iterator gsi;
11872 gimple *stmt;
11873 basic_block son;
11875 gsi = gsi_last_bb (bb);
11876 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
11878 struct omp_region *region;
11879 enum gimple_code code;
11881 stmt = gsi_stmt (gsi);
11882 code = gimple_code (stmt);
11883 if (code == GIMPLE_OMP_RETURN)
11885 /* STMT is the return point out of region PARENT. Mark it
11886 as the exit point and make PARENT the immediately
11887 enclosing region. */
11888 gcc_assert (parent);
11889 region = parent;
11890 region->exit = bb;
11891 parent = parent->outer;
11893 else if (code == GIMPLE_OMP_ATOMIC_STORE)
11895 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
11896 GIMPLE_OMP_RETURN, but matches with
11897 GIMPLE_OMP_ATOMIC_LOAD. */
11898 gcc_assert (parent);
11899 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
11900 region = parent;
11901 region->exit = bb;
11902 parent = parent->outer;
11904 else if (code == GIMPLE_OMP_CONTINUE)
11906 gcc_assert (parent);
11907 parent->cont = bb;
11909 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
11911 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
11912 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
11914 else
11916 region = new_omp_region (bb, code, parent);
11917 /* Otherwise... */
11918 if (code == GIMPLE_OMP_TARGET)
11920 switch (gimple_omp_target_kind (stmt))
11922 case GF_OMP_TARGET_KIND_REGION:
11923 case GF_OMP_TARGET_KIND_DATA:
11924 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11925 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11926 case GF_OMP_TARGET_KIND_OACC_DATA:
11927 break;
11928 case GF_OMP_TARGET_KIND_UPDATE:
11929 case GF_OMP_TARGET_KIND_ENTER_DATA:
11930 case GF_OMP_TARGET_KIND_EXIT_DATA:
11931 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11932 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11933 /* ..., other than for those stand-alone directives... */
11934 region = NULL;
11935 break;
11936 default:
11937 gcc_unreachable ();
11940 else if (code == GIMPLE_OMP_ORDERED
11941 && find_omp_clause (gimple_omp_ordered_clauses
11942 (as_a <gomp_ordered *> (stmt)),
11943 OMP_CLAUSE_DEPEND))
11944 /* #pragma omp ordered depend is also just a stand-alone
11945 directive. */
11946 region = NULL;
11947 /* ..., this directive becomes the parent for a new region. */
11948 if (region)
11949 parent = region;
11953 if (single_tree && !parent)
11954 return;
11956 for (son = first_dom_son (CDI_DOMINATORS, bb);
11957 son;
11958 son = next_dom_son (CDI_DOMINATORS, son))
11959 build_omp_regions_1 (son, parent, single_tree);
11962 /* Builds the tree of OMP regions rooted at ROOT, storing it to
11963 root_omp_region. */
11965 static void
11966 build_omp_regions_root (basic_block root)
11968 gcc_assert (root_omp_region == NULL);
11969 build_omp_regions_1 (root, NULL, true);
11970 gcc_assert (root_omp_region != NULL);
11973 /* Expands omp construct (and its subconstructs) starting in HEAD. */
11975 void
11976 omp_expand_local (basic_block head)
11978 build_omp_regions_root (head);
11979 if (dump_file && (dump_flags & TDF_DETAILS))
11981 fprintf (dump_file, "\nOMP region tree\n\n");
11982 dump_omp_region (dump_file, root_omp_region, 0);
11983 fprintf (dump_file, "\n");
11986 remove_exit_barriers (root_omp_region);
11987 expand_omp (root_omp_region);
11989 free_omp_regions ();
11992 /* Scan the CFG and build a tree of OMP regions. Return the root of
11993 the OMP region tree. */
11995 static void
11996 build_omp_regions (void)
11998 gcc_assert (root_omp_region == NULL);
11999 calculate_dominance_info (CDI_DOMINATORS);
12000 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
12003 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
12005 static unsigned int
12006 execute_expand_omp (void)
12008 build_omp_regions ();
12010 if (!root_omp_region)
12011 return 0;
12013 if (dump_file)
12015 fprintf (dump_file, "\nOMP region tree\n\n");
12016 dump_omp_region (dump_file, root_omp_region, 0);
12017 fprintf (dump_file, "\n");
12020 remove_exit_barriers (root_omp_region);
12022 expand_omp (root_omp_region);
12024 #ifdef ENABLE_CHECKING
12025 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12026 verify_loop_structure ();
12027 #endif
12028 cleanup_tree_cfg ();
12030 free_omp_regions ();
12032 return 0;
12035 /* OMP expansion -- the default pass, run before creation of SSA form. */
12037 namespace {
12039 const pass_data pass_data_expand_omp =
12041 GIMPLE_PASS, /* type */
12042 "ompexp", /* name */
12043 OPTGROUP_NONE, /* optinfo_flags */
12044 TV_NONE, /* tv_id */
12045 PROP_gimple_any, /* properties_required */
12046 PROP_gimple_eomp, /* properties_provided */
12047 0, /* properties_destroyed */
12048 0, /* todo_flags_start */
12049 0, /* todo_flags_finish */
12052 class pass_expand_omp : public gimple_opt_pass
12054 public:
12055 pass_expand_omp (gcc::context *ctxt)
12056 : gimple_opt_pass (pass_data_expand_omp, ctxt)
12059 /* opt_pass methods: */
12060 virtual unsigned int execute (function *)
12062 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
12063 || flag_openmp_simd != 0)
12064 && !seen_error ());
12066 /* This pass always runs, to provide PROP_gimple_eomp.
12067 But often, there is nothing to do. */
12068 if (!gate)
12069 return 0;
12071 return execute_expand_omp ();
12074 }; // class pass_expand_omp
12076 } // anon namespace
12078 gimple_opt_pass *
12079 make_pass_expand_omp (gcc::context *ctxt)
12081 return new pass_expand_omp (ctxt);
12084 namespace {
12086 const pass_data pass_data_expand_omp_ssa =
12088 GIMPLE_PASS, /* type */
12089 "ompexpssa", /* name */
12090 OPTGROUP_NONE, /* optinfo_flags */
12091 TV_NONE, /* tv_id */
12092 PROP_cfg | PROP_ssa, /* properties_required */
12093 PROP_gimple_eomp, /* properties_provided */
12094 0, /* properties_destroyed */
12095 0, /* todo_flags_start */
12096 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
12099 class pass_expand_omp_ssa : public gimple_opt_pass
12101 public:
12102 pass_expand_omp_ssa (gcc::context *ctxt)
12103 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
12106 /* opt_pass methods: */
12107 virtual bool gate (function *fun)
12109 return !(fun->curr_properties & PROP_gimple_eomp);
12111 virtual unsigned int execute (function *) { return execute_expand_omp (); }
12113 }; // class pass_expand_omp_ssa
12115 } // anon namespace
12117 gimple_opt_pass *
12118 make_pass_expand_omp_ssa (gcc::context *ctxt)
12120 return new pass_expand_omp_ssa (ctxt);
12123 /* Routines to lower OMP directives into OMP-GIMPLE. */
12125 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
12126 convert it to gimple. */
12127 static void
12128 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
12130 gimple *stmt;
12132 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
12134 stmt = gimple_build_assign (dest, op, dest, src);
12135 gimple_seq_add_stmt (seq, stmt);
12136 return;
12139 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12140 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
12141 gimplify_assign (t, rdest, seq);
12142 rdest = t;
12144 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12145 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
12146 gimplify_assign (t, idest, seq);
12147 idest = t;
12149 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
12150 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
12151 gimplify_assign (t, rsrc, seq);
12152 rsrc = t;
12154 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
12155 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
12156 gimplify_assign (t, isrc, seq);
12157 isrc = t;
12159 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12160 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12161 tree result;
12163 if (op == PLUS_EXPR)
12165 stmt = gimple_build_assign (r, op, rdest, rsrc);
12166 gimple_seq_add_stmt (seq, stmt);
12168 stmt = gimple_build_assign (i, op, idest, isrc);
12169 gimple_seq_add_stmt (seq, stmt);
12171 else if (op == MULT_EXPR)
12173 /* Let x = a + ib = dest, y = c + id = src.
12174 x * y = (ac - bd) + i(ad + bc) */
12175 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12176 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12177 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12178 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
12180 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
12181 gimple_seq_add_stmt (seq, stmt);
12183 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
12184 gimple_seq_add_stmt (seq, stmt);
12186 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
12187 gimple_seq_add_stmt (seq, stmt);
12189 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
12190 gimple_seq_add_stmt (seq, stmt);
12192 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
12193 gimple_seq_add_stmt (seq, stmt);
12195 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
12196 gimple_seq_add_stmt (seq, stmt);
12198 else
12199 gcc_unreachable ();
12201 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
12202 gimplify_assign (dest, result, seq);
12205 /* Helper function to initialize local data for the reduction arrays.
12206 The reduction arrays need to be placed inside the calling function
12207 for accelerators, or else the host won't be able to preform the final
12208 reduction. */
12210 static void
12211 oacc_initialize_reduction_data (tree clauses, tree nthreads,
12212 gimple_seq *stmt_seqp, omp_context *ctx)
12214 tree c, t, oc;
12215 gimple *stmt;
12216 omp_context *octx;
12218 /* Find the innermost OpenACC parallel context. */
12219 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
12220 && (gimple_omp_target_kind (ctx->stmt)
12221 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
12222 octx = ctx;
12223 else
12224 octx = ctx->outer;
12225 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
12226 && (gimple_omp_target_kind (octx->stmt)
12227 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
12229 /* Extract the clauses. */
12230 oc = gimple_omp_target_clauses (octx->stmt);
12232 /* Find the last outer clause. */
12233 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
12236 /* Allocate arrays for each reduction variable. */
12237 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
12239 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
12240 continue;
12242 tree var = OMP_CLAUSE_DECL (c);
12243 tree type = get_base_type (var);
12244 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
12245 ctx);
12246 tree size, call;
12248 /* Calculate size of the reduction array. */
12249 t = create_tmp_var (TREE_TYPE (nthreads));
12250 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
12251 fold_convert (TREE_TYPE (nthreads),
12252 TYPE_SIZE_UNIT (type)));
12253 gimple_seq_add_stmt (stmt_seqp, stmt);
12255 size = create_tmp_var (sizetype);
12256 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
12258 /* Now allocate memory for it. */
12259 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
12260 stmt = gimple_build_call (call, 1, size);
12261 gimple_call_set_lhs (stmt, array);
12262 gimple_seq_add_stmt (stmt_seqp, stmt);
12264 /* Map this array into the accelerator. */
12266 /* Add the reduction array to the list of clauses. */
12267 tree x = array;
12268 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
12269 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
12270 OMP_CLAUSE_DECL (t) = x;
12271 OMP_CLAUSE_CHAIN (t) = NULL;
12272 if (oc)
12273 OMP_CLAUSE_CHAIN (oc) = t;
12274 else
12275 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
12276 OMP_CLAUSE_SIZE (t) = size;
12277 oc = t;
12281 /* Helper function to process the array of partial reductions. Nthreads
12282 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
12283 cannot be used here, because nthreads on the host may be different than
12284 on the accelerator. */
12286 static void
12287 oacc_finalize_reduction_data (tree clauses, tree nthreads,
12288 gimple_seq *stmt_seqp, omp_context *ctx)
12290 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
12291 gimple *stmt;
12293 /* Create for loop.
12295 let var = the original reduction variable
12296 let array = reduction variable array
12298 for (i = 0; i < nthreads; i++)
12299 var op= array[i]
12302 loop_header = create_artificial_label (UNKNOWN_LOCATION);
12303 loop_body = create_artificial_label (UNKNOWN_LOCATION);
12304 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
12306 /* Create and initialize an index variable. */
12307 tree ix = create_tmp_var (sizetype);
12308 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
12309 stmt_seqp);
12311 /* Insert the loop header label here. */
12312 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
12314 /* Exit loop if ix >= nthreads. */
12315 x = create_tmp_var (sizetype);
12316 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
12317 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
12318 gimple_seq_add_stmt (stmt_seqp, stmt);
12320 /* Insert the loop body label here. */
12321 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
12323 /* Collapse each reduction array, one element at a time. */
12324 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
12326 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
12327 continue;
12329 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
12331 /* reduction(-:var) sums up the partial results, so it acts
12332 identically to reduction(+:var). */
12333 if (reduction_code == MINUS_EXPR)
12334 reduction_code = PLUS_EXPR;
12336 /* Set up reduction variable var. */
12337 var = OMP_CLAUSE_DECL (c);
12338 type = get_base_type (var);
12339 array = lookup_oacc_reduction (oacc_get_reduction_array_id
12340 (OMP_CLAUSE_DECL (c)), ctx);
12342 /* Calculate the array offset. */
12343 tree offset = create_tmp_var (sizetype);
12344 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
12345 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
12346 gimple_seq_add_stmt (stmt_seqp, stmt);
12348 tree ptr = create_tmp_var (TREE_TYPE (array));
12349 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
12350 gimple_seq_add_stmt (stmt_seqp, stmt);
12352 /* Extract array[ix] into mem. */
12353 tree mem = create_tmp_var (type);
12354 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
12356 /* Find the original reduction variable. */
12357 if (is_reference (var))
12358 var = build_simple_mem_ref (var);
12360 tree t = create_tmp_var (type);
12362 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
12363 gimplify_and_add (unshare_expr(x), stmt_seqp);
12365 /* var = var op mem */
12366 switch (OMP_CLAUSE_REDUCTION_CODE (c))
12368 case TRUTH_ANDIF_EXPR:
12369 case TRUTH_ORIF_EXPR:
12370 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
12371 t, mem);
12372 gimplify_and_add (t, stmt_seqp);
12373 break;
12374 default:
12375 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
12376 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
12377 stmt_seqp);
12380 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
12381 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
12382 gimplify_and_add (unshare_expr(x), stmt_seqp);
12385 /* Increment the induction variable. */
12386 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
12387 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
12388 gimple_seq_add_stmt (stmt_seqp, stmt);
12390 /* Go back to the top of the loop. */
12391 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
12393 /* Place the loop exit label here. */
12394 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
12397 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
12398 scan that for reductions. */
12400 static void
12401 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
12402 gimple_seq *out_stmt_seqp, omp_context *ctx)
12404 gimple_stmt_iterator gsi;
12405 gimple_seq inner = NULL;
12407 /* A collapse clause may have inserted a new bind block. */
12408 gsi = gsi_start (*body);
12409 while (!gsi_end_p (gsi))
12411 gimple *stmt = gsi_stmt (gsi);
12412 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
12414 inner = gimple_bind_body (bind_stmt);
12415 body = &inner;
12416 gsi = gsi_start (*body);
12418 else if (dyn_cast <gomp_for *> (stmt))
12419 break;
12420 else
12421 gsi_next (&gsi);
12424 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
12426 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
12427 enter, exit;
12428 bool reduction_found = false;
12430 gimple *stmt = gsi_stmt (gsi);
12432 switch (gimple_code (stmt))
12434 case GIMPLE_OMP_FOR:
12435 clauses = gimple_omp_for_clauses (stmt);
12437 /* Search for a reduction clause. */
12438 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
12439 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
12441 reduction_found = true;
12442 break;
12445 if (!reduction_found)
12446 break;
12448 ctx = maybe_lookup_ctx (stmt);
12449 t = NULL_TREE;
12451 /* Extract the number of threads. */
12452 nthreads = create_tmp_var (sizetype);
12453 t = oacc_max_threads (ctx);
12454 gimplify_assign (nthreads, t, in_stmt_seqp);
12456 /* Determine if this is kernel will be executed on the host. */
12457 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
12458 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
12459 stmt = gimple_build_call (call, 0);
12460 gimple_call_set_lhs (stmt, acc_device);
12461 gimple_seq_add_stmt (in_stmt_seqp, stmt);
12463 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
12464 acc_device_host = create_tmp_var (integer_type_node,
12465 ".acc_device_host");
12466 gimplify_assign (acc_device_host,
12467 build_int_cst (integer_type_node,
12468 GOMP_DEVICE_HOST),
12469 in_stmt_seqp);
12471 enter = create_artificial_label (UNKNOWN_LOCATION);
12472 exit = create_artificial_label (UNKNOWN_LOCATION);
12474 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
12475 enter, exit);
12476 gimple_seq_add_stmt (in_stmt_seqp, stmt);
12477 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
12478 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
12479 integer_one_node),
12480 in_stmt_seqp);
12481 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
12483 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
12484 ctx);
12485 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
12486 break;
12487 default:
12488 // Scan for other directives which support reduction here.
12489 break;
12494 /* If ctx is a worksharing context inside of a cancellable parallel
12495 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
12496 and conditional branch to parallel's cancel_label to handle
12497 cancellation in the implicit barrier. */
12499 static void
12500 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
12502 gimple *omp_return = gimple_seq_last_stmt (*body);
12503 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
12504 if (gimple_omp_return_nowait_p (omp_return))
12505 return;
12506 if (ctx->outer
12507 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
12508 && ctx->outer->cancellable)
12510 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
12511 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
12512 tree lhs = create_tmp_var (c_bool_type);
12513 gimple_omp_return_set_lhs (omp_return, lhs);
12514 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
12515 gimple *g = gimple_build_cond (NE_EXPR, lhs,
12516 fold_convert (c_bool_type,
12517 boolean_false_node),
12518 ctx->outer->cancel_label, fallthru_label);
12519 gimple_seq_add_stmt (body, g);
12520 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
12524 /* Lower the OpenMP sections directive in the current statement in GSI_P.
12525 CTX is the enclosing OMP context for the current statement. */
12527 static void
12528 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
12530 tree block, control;
12531 gimple_stmt_iterator tgsi;
12532 gomp_sections *stmt;
12533 gimple *t;
12534 gbind *new_stmt, *bind;
12535 gimple_seq ilist, dlist, olist, new_body;
12537 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
12539 push_gimplify_context ();
12541 dlist = NULL;
12542 ilist = NULL;
12543 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
12544 &ilist, &dlist, ctx, NULL);
12546 new_body = gimple_omp_body (stmt);
12547 gimple_omp_set_body (stmt, NULL);
12548 tgsi = gsi_start (new_body);
12549 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
12551 omp_context *sctx;
12552 gimple *sec_start;
12554 sec_start = gsi_stmt (tgsi);
12555 sctx = maybe_lookup_ctx (sec_start);
12556 gcc_assert (sctx);
12558 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
12559 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
12560 GSI_CONTINUE_LINKING);
12561 gimple_omp_set_body (sec_start, NULL);
12563 if (gsi_one_before_end_p (tgsi))
12565 gimple_seq l = NULL;
12566 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
12567 &l, ctx);
12568 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
12569 gimple_omp_section_set_last (sec_start);
12572 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
12573 GSI_CONTINUE_LINKING);
12576 block = make_node (BLOCK);
12577 bind = gimple_build_bind (NULL, new_body, block);
12579 olist = NULL;
12580 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
12582 block = make_node (BLOCK);
12583 new_stmt = gimple_build_bind (NULL, NULL, block);
12584 gsi_replace (gsi_p, new_stmt, true);
12586 pop_gimplify_context (new_stmt);
12587 gimple_bind_append_vars (new_stmt, ctx->block_vars);
12588 BLOCK_VARS (block) = gimple_bind_vars (bind);
12589 if (BLOCK_VARS (block))
12590 TREE_USED (block) = 1;
12592 new_body = NULL;
12593 gimple_seq_add_seq (&new_body, ilist);
12594 gimple_seq_add_stmt (&new_body, stmt);
12595 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
12596 gimple_seq_add_stmt (&new_body, bind);
12598 control = create_tmp_var (unsigned_type_node, ".section");
12599 t = gimple_build_omp_continue (control, control);
12600 gimple_omp_sections_set_control (stmt, control);
12601 gimple_seq_add_stmt (&new_body, t);
12603 gimple_seq_add_seq (&new_body, olist);
12604 if (ctx->cancellable)
12605 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
12606 gimple_seq_add_seq (&new_body, dlist);
12608 new_body = maybe_catch_exception (new_body);
12610 t = gimple_build_omp_return
12611 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
12612 OMP_CLAUSE_NOWAIT));
12613 gimple_seq_add_stmt (&new_body, t);
12614 maybe_add_implicit_barrier_cancel (ctx, &new_body);
12616 gimple_bind_set_body (new_stmt, new_body);
12620 /* A subroutine of lower_omp_single. Expand the simple form of
12621 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
12623 if (GOMP_single_start ())
12624 BODY;
12625 [ GOMP_barrier (); ] -> unless 'nowait' is present.
12627 FIXME. It may be better to delay expanding the logic of this until
12628 pass_expand_omp. The expanded logic may make the job more difficult
12629 to a synchronization analysis pass. */
12631 static void
12632 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
12634 location_t loc = gimple_location (single_stmt);
12635 tree tlabel = create_artificial_label (loc);
12636 tree flabel = create_artificial_label (loc);
12637 gimple *call, *cond;
12638 tree lhs, decl;
12640 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
12641 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
12642 call = gimple_build_call (decl, 0);
12643 gimple_call_set_lhs (call, lhs);
12644 gimple_seq_add_stmt (pre_p, call);
12646 cond = gimple_build_cond (EQ_EXPR, lhs,
12647 fold_convert_loc (loc, TREE_TYPE (lhs),
12648 boolean_true_node),
12649 tlabel, flabel);
12650 gimple_seq_add_stmt (pre_p, cond);
12651 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
12652 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
12653 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
12657 /* A subroutine of lower_omp_single. Expand the simple form of
12658 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
12660 #pragma omp single copyprivate (a, b, c)
12662 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
12665 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
12667 BODY;
12668 copyout.a = a;
12669 copyout.b = b;
12670 copyout.c = c;
12671 GOMP_single_copy_end (&copyout);
12673 else
12675 a = copyout_p->a;
12676 b = copyout_p->b;
12677 c = copyout_p->c;
12679 GOMP_barrier ();
12682 FIXME. It may be better to delay expanding the logic of this until
12683 pass_expand_omp. The expanded logic may make the job more difficult
12684 to a synchronization analysis pass. */
12686 static void
12687 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
12688 omp_context *ctx)
12690 tree ptr_type, t, l0, l1, l2, bfn_decl;
12691 gimple_seq copyin_seq;
12692 location_t loc = gimple_location (single_stmt);
12694 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
12696 ptr_type = build_pointer_type (ctx->record_type);
12697 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
12699 l0 = create_artificial_label (loc);
12700 l1 = create_artificial_label (loc);
12701 l2 = create_artificial_label (loc);
12703 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
12704 t = build_call_expr_loc (loc, bfn_decl, 0);
12705 t = fold_convert_loc (loc, ptr_type, t);
12706 gimplify_assign (ctx->receiver_decl, t, pre_p);
12708 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
12709 build_int_cst (ptr_type, 0));
12710 t = build3 (COND_EXPR, void_type_node, t,
12711 build_and_jump (&l0), build_and_jump (&l1));
12712 gimplify_and_add (t, pre_p);
12714 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
12716 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
12718 copyin_seq = NULL;
12719 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
12720 &copyin_seq, ctx);
12722 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
12723 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
12724 t = build_call_expr_loc (loc, bfn_decl, 1, t);
12725 gimplify_and_add (t, pre_p);
12727 t = build_and_jump (&l2);
12728 gimplify_and_add (t, pre_p);
12730 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
12732 gimple_seq_add_seq (pre_p, copyin_seq);
12734 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
12738 /* Expand code for an OpenMP single directive. */
12740 static void
12741 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
12743 tree block;
12744 gimple *t;
12745 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
12746 gbind *bind;
12747 gimple_seq bind_body, bind_body_tail = NULL, dlist;
12749 push_gimplify_context ();
12751 block = make_node (BLOCK);
12752 bind = gimple_build_bind (NULL, NULL, block);
12753 gsi_replace (gsi_p, bind, true);
12754 bind_body = NULL;
12755 dlist = NULL;
12756 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
12757 &bind_body, &dlist, ctx, NULL);
12758 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
12760 gimple_seq_add_stmt (&bind_body, single_stmt);
12762 if (ctx->record_type)
12763 lower_omp_single_copy (single_stmt, &bind_body, ctx);
12764 else
12765 lower_omp_single_simple (single_stmt, &bind_body);
12767 gimple_omp_set_body (single_stmt, NULL);
12769 gimple_seq_add_seq (&bind_body, dlist);
12771 bind_body = maybe_catch_exception (bind_body);
12773 t = gimple_build_omp_return
12774 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
12775 OMP_CLAUSE_NOWAIT));
12776 gimple_seq_add_stmt (&bind_body_tail, t);
12777 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
12778 if (ctx->record_type)
12780 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
12781 tree clobber = build_constructor (ctx->record_type, NULL);
12782 TREE_THIS_VOLATILE (clobber) = 1;
12783 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
12784 clobber), GSI_SAME_STMT);
12786 gimple_seq_add_seq (&bind_body, bind_body_tail);
12787 gimple_bind_set_body (bind, bind_body);
12789 pop_gimplify_context (bind);
12791 gimple_bind_append_vars (bind, ctx->block_vars);
12792 BLOCK_VARS (block) = ctx->block_vars;
12793 if (BLOCK_VARS (block))
12794 TREE_USED (block) = 1;
12798 /* Expand code for an OpenMP master directive. */
12800 static void
12801 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
12803 tree block, lab = NULL, x, bfn_decl;
12804 gimple *stmt = gsi_stmt (*gsi_p);
12805 gbind *bind;
12806 location_t loc = gimple_location (stmt);
12807 gimple_seq tseq;
12809 push_gimplify_context ();
12811 block = make_node (BLOCK);
12812 bind = gimple_build_bind (NULL, NULL, block);
12813 gsi_replace (gsi_p, bind, true);
12814 gimple_bind_add_stmt (bind, stmt);
12816 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
12817 x = build_call_expr_loc (loc, bfn_decl, 0);
12818 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
12819 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
12820 tseq = NULL;
12821 gimplify_and_add (x, &tseq);
12822 gimple_bind_add_seq (bind, tseq);
12824 lower_omp (gimple_omp_body_ptr (stmt), ctx);
12825 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
12826 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
12827 gimple_omp_set_body (stmt, NULL);
12829 gimple_bind_add_stmt (bind, gimple_build_label (lab));
12831 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
12833 pop_gimplify_context (bind);
12835 gimple_bind_append_vars (bind, ctx->block_vars);
12836 BLOCK_VARS (block) = ctx->block_vars;
12840 /* Expand code for an OpenMP taskgroup directive. */
12842 static void
12843 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
12845 gimple *stmt = gsi_stmt (*gsi_p);
12846 gcall *x;
12847 gbind *bind;
12848 tree block = make_node (BLOCK);
12850 bind = gimple_build_bind (NULL, NULL, block);
12851 gsi_replace (gsi_p, bind, true);
12852 gimple_bind_add_stmt (bind, stmt);
12854 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
12856 gimple_bind_add_stmt (bind, x);
12858 lower_omp (gimple_omp_body_ptr (stmt), ctx);
12859 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
12860 gimple_omp_set_body (stmt, NULL);
12862 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
12864 gimple_bind_append_vars (bind, ctx->block_vars);
12865 BLOCK_VARS (block) = ctx->block_vars;
12869 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
12871 static void
12872 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
12873 omp_context *ctx)
12875 struct omp_for_data fd;
12876 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
12877 return;
12879 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
12880 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
12881 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
12882 if (!fd.ordered)
12883 return;
12885 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
12886 tree c = gimple_omp_ordered_clauses (ord_stmt);
12887 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
12888 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
12890 /* Merge depend clauses from multiple adjacent
12891 #pragma omp ordered depend(sink:...) constructs
12892 into one #pragma omp ordered depend(sink:...), so that
12893 we can optimize them together. */
12894 gimple_stmt_iterator gsi = *gsi_p;
12895 gsi_next (&gsi);
12896 while (!gsi_end_p (gsi))
12898 gimple *stmt = gsi_stmt (gsi);
12899 if (is_gimple_debug (stmt)
12900 || gimple_code (stmt) == GIMPLE_NOP)
12902 gsi_next (&gsi);
12903 continue;
12905 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
12906 break;
12907 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
12908 c = gimple_omp_ordered_clauses (ord_stmt2);
12909 if (c == NULL_TREE
12910 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
12911 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
12912 break;
12913 while (*list_p)
12914 list_p = &OMP_CLAUSE_CHAIN (*list_p);
12915 *list_p = c;
12916 gsi_remove (&gsi, true);
12920 /* Canonicalize sink dependence clauses into one folded clause if
12921 possible.
12923 The basic algorithm is to create a sink vector whose first
12924 element is the GCD of all the first elements, and whose remaining
12925 elements are the minimum of the subsequent columns.
12927 We ignore dependence vectors whose first element is zero because
12928 such dependencies are known to be executed by the same thread.
12930 We take into account the direction of the loop, so a minimum
12931 becomes a maximum if the loop is iterating forwards. We also
12932 ignore sink clauses where the loop direction is unknown, or where
12933 the offsets are clearly invalid because they are not a multiple
12934 of the loop increment.
12936 For example:
12938 #pragma omp for ordered(2)
12939 for (i=0; i < N; ++i)
12940 for (j=0; j < M; ++j)
12942 #pragma omp ordered \
12943 depend(sink:i-8,j-2) \
12944 depend(sink:i,j-1) \ // Completely ignored because i+0.
12945 depend(sink:i-4,j-3) \
12946 depend(sink:i-6,j-4)
12947 #pragma omp ordered depend(source)
12950 Folded clause is:
12952 depend(sink:-gcd(8,4,6),-min(2,3,4))
12953 -or-
12954 depend(sink:-2,-2)
12957 /* FIXME: Computing GCD's where the first element is zero is
12958 non-trivial in the presence of collapsed loops. Do this later. */
12959 if (fd.collapse > 1)
12960 return;
12962 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
12963 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
12964 tree folded_dep = NULL_TREE;
12965 /* TRUE if the first dimension's offset is negative. */
12966 bool neg_offset_p = false;
12968 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
12969 unsigned int i;
12970 while ((c = *list_p) != NULL)
12972 bool remove = false;
12974 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
12975 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
12976 goto next_ordered_clause;
12978 tree vec;
12979 for (vec = OMP_CLAUSE_DECL (c), i = 0;
12980 vec && TREE_CODE (vec) == TREE_LIST;
12981 vec = TREE_CHAIN (vec), ++i)
12983 gcc_assert (i < len);
12985 /* extract_omp_for_data has canonicalized the condition. */
12986 gcc_assert (fd.loops[i].cond_code == LT_EXPR
12987 || fd.loops[i].cond_code == GT_EXPR);
12988 bool forward = fd.loops[i].cond_code == LT_EXPR;
12989 bool maybe_lexically_later = true;
12991 /* While the committee makes up its mind, bail if we have any
12992 non-constant steps. */
12993 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
12994 goto lower_omp_ordered_ret;
12996 tree itype = TREE_TYPE (TREE_VALUE (vec));
12997 if (POINTER_TYPE_P (itype))
12998 itype = sizetype;
12999 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
13000 TYPE_PRECISION (itype),
13001 TYPE_SIGN (itype));
13003 /* Ignore invalid offsets that are not multiples of the step. */
13004 if (!wi::multiple_of_p
13005 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
13006 UNSIGNED))
13008 warning_at (OMP_CLAUSE_LOCATION (c), 0,
13009 "ignoring sink clause with offset that is not "
13010 "a multiple of the loop step");
13011 remove = true;
13012 goto next_ordered_clause;
13015 /* Calculate the first dimension. The first dimension of
13016 the folded dependency vector is the GCD of the first
13017 elements, while ignoring any first elements whose offset
13018 is 0. */
13019 if (i == 0)
13021 /* Ignore dependence vectors whose first dimension is 0. */
13022 if (offset == 0)
13024 remove = true;
13025 goto next_ordered_clause;
13027 else
13029 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
13031 error_at (OMP_CLAUSE_LOCATION (c),
13032 "first offset must be in opposite direction "
13033 "of loop iterations");
13034 goto lower_omp_ordered_ret;
13036 if (forward)
13037 offset = -offset;
13038 neg_offset_p = forward;
13039 /* Initialize the first time around. */
13040 if (folded_dep == NULL_TREE)
13042 folded_dep = c;
13043 folded_deps[0] = offset;
13045 else
13046 folded_deps[0] = wi::gcd (folded_deps[0],
13047 offset, UNSIGNED);
13050 /* Calculate minimum for the remaining dimensions. */
13051 else
13053 folded_deps[len + i - 1] = offset;
13054 if (folded_dep == c)
13055 folded_deps[i] = offset;
13056 else if (maybe_lexically_later
13057 && !wi::eq_p (folded_deps[i], offset))
13059 if (forward ^ wi::gts_p (folded_deps[i], offset))
13061 unsigned int j;
13062 folded_dep = c;
13063 for (j = 1; j <= i; j++)
13064 folded_deps[j] = folded_deps[len + j - 1];
13066 else
13067 maybe_lexically_later = false;
13071 gcc_assert (i == len);
13073 remove = true;
13075 next_ordered_clause:
13076 if (remove)
13077 *list_p = OMP_CLAUSE_CHAIN (c);
13078 else
13079 list_p = &OMP_CLAUSE_CHAIN (c);
13082 if (folded_dep)
13084 if (neg_offset_p)
13085 folded_deps[0] = -folded_deps[0];
13087 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
13088 if (POINTER_TYPE_P (itype))
13089 itype = sizetype;
13091 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
13092 = wide_int_to_tree (itype, folded_deps[0]);
13093 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
13094 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
13097 lower_omp_ordered_ret:
13099 /* Ordered without clauses is #pragma omp threads, while we want
13100 a nop instead if we remove all clauses. */
13101 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
13102 gsi_replace (gsi_p, gimple_build_nop (), true);
13106 /* Expand code for an OpenMP ordered directive. */
13108 static void
13109 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13111 tree block;
13112 gimple *stmt = gsi_stmt (*gsi_p);
13113 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
13114 gcall *x;
13115 gbind *bind;
13116 bool simd
13117 = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt), OMP_CLAUSE_SIMD);
13119 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13120 OMP_CLAUSE_DEPEND))
13122 /* FIXME: This is needs to be moved to the expansion to verify various
13123 conditions only testable on cfg with dominators computed, and also
13124 all the depend clauses to be merged still might need to be available
13125 for the runtime checks. */
13126 if (0)
13127 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
13128 return;
13131 push_gimplify_context ();
13133 block = make_node (BLOCK);
13134 bind = gimple_build_bind (NULL, NULL, block);
13135 gsi_replace (gsi_p, bind, true);
13136 gimple_bind_add_stmt (bind, stmt);
13138 if (simd)
13140 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 0);
13141 cfun->has_simduid_loops = true;
13143 else
13144 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
13146 gimple_bind_add_stmt (bind, x);
13148 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13149 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
13150 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13151 gimple_omp_set_body (stmt, NULL);
13153 if (simd)
13154 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 0);
13155 else
13156 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
13158 gimple_bind_add_stmt (bind, x);
13160 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13162 pop_gimplify_context (bind);
13164 gimple_bind_append_vars (bind, ctx->block_vars);
13165 BLOCK_VARS (block) = gimple_bind_vars (bind);
13169 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
13170 substitution of a couple of function calls. But in the NAMED case,
13171 requires that languages coordinate a symbol name. It is therefore
13172 best put here in common code. */
13174 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
13176 static void
13177 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13179 tree block;
13180 tree name, lock, unlock;
13181 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
13182 gbind *bind;
13183 location_t loc = gimple_location (stmt);
13184 gimple_seq tbody;
13186 name = gimple_omp_critical_name (stmt);
13187 if (name)
13189 tree decl;
13191 if (!critical_name_mutexes)
13192 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
13194 tree *n = critical_name_mutexes->get (name);
13195 if (n == NULL)
13197 char *new_str;
13199 decl = create_tmp_var_raw (ptr_type_node);
13201 new_str = ACONCAT ((".gomp_critical_user_",
13202 IDENTIFIER_POINTER (name), NULL));
13203 DECL_NAME (decl) = get_identifier (new_str);
13204 TREE_PUBLIC (decl) = 1;
13205 TREE_STATIC (decl) = 1;
13206 DECL_COMMON (decl) = 1;
13207 DECL_ARTIFICIAL (decl) = 1;
13208 DECL_IGNORED_P (decl) = 1;
13210 varpool_node::finalize_decl (decl);
13212 critical_name_mutexes->put (name, decl);
13214 else
13215 decl = *n;
13217 /* If '#pragma omp critical' is inside offloaded region or
13218 inside function marked as offloadable, the symbol must be
13219 marked as offloadable too. */
13220 omp_context *octx;
13221 if (cgraph_node::get (current_function_decl)->offloadable)
13222 varpool_node::get_create (decl)->offloadable = 1;
13223 else
13224 for (octx = ctx->outer; octx; octx = octx->outer)
13225 if (is_gimple_omp_offloaded (octx->stmt))
13227 varpool_node::get_create (decl)->offloadable = 1;
13228 break;
13231 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
13232 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
13234 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
13235 unlock = build_call_expr_loc (loc, unlock, 1,
13236 build_fold_addr_expr_loc (loc, decl));
13238 else
13240 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
13241 lock = build_call_expr_loc (loc, lock, 0);
13243 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
13244 unlock = build_call_expr_loc (loc, unlock, 0);
13247 push_gimplify_context ();
13249 block = make_node (BLOCK);
13250 bind = gimple_build_bind (NULL, NULL, block);
13251 gsi_replace (gsi_p, bind, true);
13252 gimple_bind_add_stmt (bind, stmt);
13254 tbody = gimple_bind_body (bind);
13255 gimplify_and_add (lock, &tbody);
13256 gimple_bind_set_body (bind, tbody);
13258 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13259 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
13260 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13261 gimple_omp_set_body (stmt, NULL);
13263 tbody = gimple_bind_body (bind);
13264 gimplify_and_add (unlock, &tbody);
13265 gimple_bind_set_body (bind, tbody);
13267 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13269 pop_gimplify_context (bind);
13270 gimple_bind_append_vars (bind, ctx->block_vars);
13271 BLOCK_VARS (block) = gimple_bind_vars (bind);
13275 /* A subroutine of lower_omp_for. Generate code to emit the predicate
13276 for a lastprivate clause. Given a loop control predicate of (V
13277 cond N2), we gate the clause on (!(V cond N2)). The lowered form
13278 is appended to *DLIST, iterator initialization is appended to
13279 *BODY_P. */
13281 static void
13282 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
13283 gimple_seq *dlist, struct omp_context *ctx)
13285 tree clauses, cond, vinit;
13286 enum tree_code cond_code;
13287 gimple_seq stmts;
13289 cond_code = fd->loop.cond_code;
13290 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
13292 /* When possible, use a strict equality expression. This can let VRP
13293 type optimizations deduce the value and remove a copy. */
13294 if (tree_fits_shwi_p (fd->loop.step))
13296 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
13297 if (step == 1 || step == -1)
13298 cond_code = EQ_EXPR;
13301 tree n2 = fd->loop.n2;
13302 if (fd->collapse > 1
13303 && TREE_CODE (n2) != INTEGER_CST
13304 && gimple_omp_for_combined_into_p (fd->for_stmt))
13306 struct omp_context *task_ctx = NULL;
13307 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
13309 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
13310 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
13312 struct omp_for_data outer_fd;
13313 extract_omp_for_data (gfor, &outer_fd, NULL);
13314 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
13316 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
13317 task_ctx = ctx->outer->outer;
13319 else if (is_task_ctx (ctx->outer))
13320 task_ctx = ctx->outer;
13321 if (task_ctx)
13323 int i;
13324 tree innerc
13325 = find_omp_clause (gimple_omp_task_clauses (task_ctx->stmt),
13326 OMP_CLAUSE__LOOPTEMP_);
13327 gcc_assert (innerc);
13328 for (i = 0; i < fd->collapse; i++)
13330 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
13331 OMP_CLAUSE__LOOPTEMP_);
13332 gcc_assert (innerc);
13334 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
13335 OMP_CLAUSE__LOOPTEMP_);
13336 if (innerc)
13337 n2 = fold_convert (TREE_TYPE (n2),
13338 lookup_decl (OMP_CLAUSE_DECL (innerc),
13339 task_ctx));
13342 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
13344 clauses = gimple_omp_for_clauses (fd->for_stmt);
13345 stmts = NULL;
13346 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
13347 if (!gimple_seq_empty_p (stmts))
13349 gimple_seq_add_seq (&stmts, *dlist);
13350 *dlist = stmts;
13352 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
13353 vinit = fd->loop.n1;
13354 if (cond_code == EQ_EXPR
13355 && tree_fits_shwi_p (fd->loop.n2)
13356 && ! integer_zerop (fd->loop.n2))
13357 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
13358 else
13359 vinit = unshare_expr (vinit);
13361 /* Initialize the iterator variable, so that threads that don't execute
13362 any iterations don't execute the lastprivate clauses by accident. */
13363 gimplify_assign (fd->loop.v, vinit, body_p);
13368 /* Lower code for an OMP loop directive. */
13370 static void
13371 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13373 tree *rhs_p, block;
13374 struct omp_for_data fd, *fdp = NULL;
13375 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
13376 gbind *new_stmt;
13377 gimple_seq omp_for_body, body, dlist;
13378 size_t i;
13380 push_gimplify_context ();
13382 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
13384 block = make_node (BLOCK);
13385 new_stmt = gimple_build_bind (NULL, NULL, block);
13386 /* Replace at gsi right away, so that 'stmt' is no member
13387 of a sequence anymore as we're going to add to a different
13388 one below. */
13389 gsi_replace (gsi_p, new_stmt, true);
13391 /* Move declaration of temporaries in the loop body before we make
13392 it go away. */
13393 omp_for_body = gimple_omp_body (stmt);
13394 if (!gimple_seq_empty_p (omp_for_body)
13395 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
13397 gbind *inner_bind
13398 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
13399 tree vars = gimple_bind_vars (inner_bind);
13400 gimple_bind_append_vars (new_stmt, vars);
13401 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
13402 keep them on the inner_bind and it's block. */
13403 gimple_bind_set_vars (inner_bind, NULL_TREE);
13404 if (gimple_bind_block (inner_bind))
13405 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
13408 if (gimple_omp_for_combined_into_p (stmt))
13410 extract_omp_for_data (stmt, &fd, NULL);
13411 fdp = &fd;
13413 /* We need two temporaries with fd.loop.v type (istart/iend)
13414 and then (fd.collapse - 1) temporaries with the same
13415 type for count2 ... countN-1 vars if not constant. */
13416 size_t count = 2;
13417 tree type = fd.iter_type;
13418 if (fd.collapse > 1
13419 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
13420 count += fd.collapse - 1;
13421 bool taskreg_for
13422 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
13423 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
13424 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
13425 tree clauses = *pc;
13426 if (taskreg_for)
13427 outerc
13428 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
13429 OMP_CLAUSE__LOOPTEMP_);
13430 for (i = 0; i < count; i++)
13432 tree temp;
13433 if (taskreg_for)
13435 gcc_assert (outerc);
13436 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
13437 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
13438 OMP_CLAUSE__LOOPTEMP_);
13440 else
13442 temp = create_tmp_var (type);
13443 insert_decl_map (&ctx->outer->cb, temp, temp);
13445 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
13446 OMP_CLAUSE_DECL (*pc) = temp;
13447 pc = &OMP_CLAUSE_CHAIN (*pc);
13449 *pc = clauses;
13452 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
13453 dlist = NULL;
13454 body = NULL;
13455 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
13456 fdp);
13457 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
13459 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13461 /* Lower the header expressions. At this point, we can assume that
13462 the header is of the form:
13464 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
13466 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
13467 using the .omp_data_s mapping, if needed. */
13468 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
13470 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
13471 if (!is_gimple_min_invariant (*rhs_p))
13472 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
13474 rhs_p = gimple_omp_for_final_ptr (stmt, i);
13475 if (!is_gimple_min_invariant (*rhs_p))
13476 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
13478 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
13479 if (!is_gimple_min_invariant (*rhs_p))
13480 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
13483 /* Once lowered, extract the bounds and clauses. */
13484 extract_omp_for_data (stmt, &fd, NULL);
13486 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
13488 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
13489 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
13490 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
13491 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
13493 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
13494 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
13495 OMP_CLAUSE_LINEAR_STEP (c)
13496 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
13497 ctx);
13500 gimple_seq_add_stmt (&body, stmt);
13501 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
13503 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
13504 fd.loop.v));
13506 /* After the loop, add exit clauses. */
13507 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
13509 if (ctx->cancellable)
13510 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
13512 gimple_seq_add_seq (&body, dlist);
13514 body = maybe_catch_exception (body);
13516 /* Region exit marker goes at the end of the loop body. */
13517 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
13518 maybe_add_implicit_barrier_cancel (ctx, &body);
13519 pop_gimplify_context (new_stmt);
13521 gimple_bind_append_vars (new_stmt, ctx->block_vars);
13522 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
13523 if (BLOCK_VARS (block))
13524 TREE_USED (block) = 1;
13526 gimple_bind_set_body (new_stmt, body);
13527 gimple_omp_set_body (stmt, NULL);
13528 gimple_omp_for_set_pre_body (stmt, NULL);
13531 /* Callback for walk_stmts. Check if the current statement only contains
13532 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
13534 static tree
13535 check_combined_parallel (gimple_stmt_iterator *gsi_p,
13536 bool *handled_ops_p,
13537 struct walk_stmt_info *wi)
13539 int *info = (int *) wi->info;
13540 gimple *stmt = gsi_stmt (*gsi_p);
13542 *handled_ops_p = true;
13543 switch (gimple_code (stmt))
13545 WALK_SUBSTMTS;
13547 case GIMPLE_OMP_FOR:
13548 case GIMPLE_OMP_SECTIONS:
13549 *info = *info == 0 ? 1 : -1;
13550 break;
13551 default:
13552 *info = -1;
13553 break;
13555 return NULL;
13558 struct omp_taskcopy_context
13560 /* This field must be at the beginning, as we do "inheritance": Some
13561 callback functions for tree-inline.c (e.g., omp_copy_decl)
13562 receive a copy_body_data pointer that is up-casted to an
13563 omp_context pointer. */
13564 copy_body_data cb;
13565 omp_context *ctx;
13568 static tree
13569 task_copyfn_copy_decl (tree var, copy_body_data *cb)
13571 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
13573 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
13574 return create_tmp_var (TREE_TYPE (var));
13576 return var;
13579 static tree
13580 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
13582 tree name, new_fields = NULL, type, f;
13584 type = lang_hooks.types.make_type (RECORD_TYPE);
13585 name = DECL_NAME (TYPE_NAME (orig_type));
13586 name = build_decl (gimple_location (tcctx->ctx->stmt),
13587 TYPE_DECL, name, type);
13588 TYPE_NAME (type) = name;
13590 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
13592 tree new_f = copy_node (f);
13593 DECL_CONTEXT (new_f) = type;
13594 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
13595 TREE_CHAIN (new_f) = new_fields;
13596 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
13597 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
13598 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
13599 &tcctx->cb, NULL);
13600 new_fields = new_f;
13601 tcctx->cb.decl_map->put (f, new_f);
13603 TYPE_FIELDS (type) = nreverse (new_fields);
13604 layout_type (type);
13605 return type;
13608 /* Create task copyfn. */
13610 static void
13611 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
13613 struct function *child_cfun;
13614 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
13615 tree record_type, srecord_type, bind, list;
13616 bool record_needs_remap = false, srecord_needs_remap = false;
13617 splay_tree_node n;
13618 struct omp_taskcopy_context tcctx;
13619 location_t loc = gimple_location (task_stmt);
13621 child_fn = gimple_omp_task_copy_fn (task_stmt);
13622 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
13623 gcc_assert (child_cfun->cfg == NULL);
13624 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
13626 /* Reset DECL_CONTEXT on function arguments. */
13627 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
13628 DECL_CONTEXT (t) = child_fn;
13630 /* Populate the function. */
13631 push_gimplify_context ();
13632 push_cfun (child_cfun);
13634 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
13635 TREE_SIDE_EFFECTS (bind) = 1;
13636 list = NULL;
13637 DECL_SAVED_TREE (child_fn) = bind;
13638 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
13640 /* Remap src and dst argument types if needed. */
13641 record_type = ctx->record_type;
13642 srecord_type = ctx->srecord_type;
13643 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
13644 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
13646 record_needs_remap = true;
13647 break;
13649 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
13650 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
13652 srecord_needs_remap = true;
13653 break;
13656 if (record_needs_remap || srecord_needs_remap)
13658 memset (&tcctx, '\0', sizeof (tcctx));
13659 tcctx.cb.src_fn = ctx->cb.src_fn;
13660 tcctx.cb.dst_fn = child_fn;
13661 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
13662 gcc_checking_assert (tcctx.cb.src_node);
13663 tcctx.cb.dst_node = tcctx.cb.src_node;
13664 tcctx.cb.src_cfun = ctx->cb.src_cfun;
13665 tcctx.cb.copy_decl = task_copyfn_copy_decl;
13666 tcctx.cb.eh_lp_nr = 0;
13667 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
13668 tcctx.cb.decl_map = new hash_map<tree, tree>;
13669 tcctx.ctx = ctx;
13671 if (record_needs_remap)
13672 record_type = task_copyfn_remap_type (&tcctx, record_type);
13673 if (srecord_needs_remap)
13674 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
13676 else
13677 tcctx.cb.decl_map = NULL;
13679 arg = DECL_ARGUMENTS (child_fn);
13680 TREE_TYPE (arg) = build_pointer_type (record_type);
13681 sarg = DECL_CHAIN (arg);
13682 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
13684 /* First pass: initialize temporaries used in record_type and srecord_type
13685 sizes and field offsets. */
13686 if (tcctx.cb.decl_map)
13687 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
13688 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
13690 tree *p;
13692 decl = OMP_CLAUSE_DECL (c);
13693 p = tcctx.cb.decl_map->get (decl);
13694 if (p == NULL)
13695 continue;
13696 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
13697 sf = (tree) n->value;
13698 sf = *tcctx.cb.decl_map->get (sf);
13699 src = build_simple_mem_ref_loc (loc, sarg);
13700 src = omp_build_component_ref (src, sf);
13701 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
13702 append_to_statement_list (t, &list);
13705 /* Second pass: copy shared var pointers and copy construct non-VLA
13706 firstprivate vars. */
13707 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
13708 switch (OMP_CLAUSE_CODE (c))
13710 splay_tree_key key;
13711 case OMP_CLAUSE_SHARED:
13712 decl = OMP_CLAUSE_DECL (c);
13713 key = (splay_tree_key) decl;
13714 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
13715 key = (splay_tree_key) &DECL_UID (decl);
13716 n = splay_tree_lookup (ctx->field_map, key);
13717 if (n == NULL)
13718 break;
13719 f = (tree) n->value;
13720 if (tcctx.cb.decl_map)
13721 f = *tcctx.cb.decl_map->get (f);
13722 n = splay_tree_lookup (ctx->sfield_map, key);
13723 sf = (tree) n->value;
13724 if (tcctx.cb.decl_map)
13725 sf = *tcctx.cb.decl_map->get (sf);
13726 src = build_simple_mem_ref_loc (loc, sarg);
13727 src = omp_build_component_ref (src, sf);
13728 dst = build_simple_mem_ref_loc (loc, arg);
13729 dst = omp_build_component_ref (dst, f);
13730 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
13731 append_to_statement_list (t, &list);
13732 break;
13733 case OMP_CLAUSE_FIRSTPRIVATE:
13734 decl = OMP_CLAUSE_DECL (c);
13735 if (is_variable_sized (decl))
13736 break;
13737 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
13738 if (n == NULL)
13739 break;
13740 f = (tree) n->value;
13741 if (tcctx.cb.decl_map)
13742 f = *tcctx.cb.decl_map->get (f);
13743 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
13744 if (n != NULL)
13746 sf = (tree) n->value;
13747 if (tcctx.cb.decl_map)
13748 sf = *tcctx.cb.decl_map->get (sf);
13749 src = build_simple_mem_ref_loc (loc, sarg);
13750 src = omp_build_component_ref (src, sf);
13751 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
13752 src = build_simple_mem_ref_loc (loc, src);
13754 else
13755 src = decl;
13756 dst = build_simple_mem_ref_loc (loc, arg);
13757 dst = omp_build_component_ref (dst, f);
13758 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
13759 append_to_statement_list (t, &list);
13760 break;
13761 case OMP_CLAUSE_PRIVATE:
13762 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
13763 break;
13764 decl = OMP_CLAUSE_DECL (c);
13765 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
13766 f = (tree) n->value;
13767 if (tcctx.cb.decl_map)
13768 f = *tcctx.cb.decl_map->get (f);
13769 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
13770 if (n != NULL)
13772 sf = (tree) n->value;
13773 if (tcctx.cb.decl_map)
13774 sf = *tcctx.cb.decl_map->get (sf);
13775 src = build_simple_mem_ref_loc (loc, sarg);
13776 src = omp_build_component_ref (src, sf);
13777 if (use_pointer_for_field (decl, NULL))
13778 src = build_simple_mem_ref_loc (loc, src);
13780 else
13781 src = decl;
13782 dst = build_simple_mem_ref_loc (loc, arg);
13783 dst = omp_build_component_ref (dst, f);
13784 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
13785 append_to_statement_list (t, &list);
13786 break;
13787 default:
13788 break;
13791 /* Last pass: handle VLA firstprivates. */
13792 if (tcctx.cb.decl_map)
13793 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
13794 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
13796 tree ind, ptr, df;
13798 decl = OMP_CLAUSE_DECL (c);
13799 if (!is_variable_sized (decl))
13800 continue;
13801 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
13802 if (n == NULL)
13803 continue;
13804 f = (tree) n->value;
13805 f = *tcctx.cb.decl_map->get (f);
13806 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
13807 ind = DECL_VALUE_EXPR (decl);
13808 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
13809 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
13810 n = splay_tree_lookup (ctx->sfield_map,
13811 (splay_tree_key) TREE_OPERAND (ind, 0));
13812 sf = (tree) n->value;
13813 sf = *tcctx.cb.decl_map->get (sf);
13814 src = build_simple_mem_ref_loc (loc, sarg);
13815 src = omp_build_component_ref (src, sf);
13816 src = build_simple_mem_ref_loc (loc, src);
13817 dst = build_simple_mem_ref_loc (loc, arg);
13818 dst = omp_build_component_ref (dst, f);
13819 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
13820 append_to_statement_list (t, &list);
13821 n = splay_tree_lookup (ctx->field_map,
13822 (splay_tree_key) TREE_OPERAND (ind, 0));
13823 df = (tree) n->value;
13824 df = *tcctx.cb.decl_map->get (df);
13825 ptr = build_simple_mem_ref_loc (loc, arg);
13826 ptr = omp_build_component_ref (ptr, df);
13827 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
13828 build_fold_addr_expr_loc (loc, dst));
13829 append_to_statement_list (t, &list);
13832 t = build1 (RETURN_EXPR, void_type_node, NULL);
13833 append_to_statement_list (t, &list);
13835 if (tcctx.cb.decl_map)
13836 delete tcctx.cb.decl_map;
13837 pop_gimplify_context (NULL);
13838 BIND_EXPR_BODY (bind) = list;
13839 pop_cfun ();
13842 static void
13843 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
13845 tree c, clauses;
13846 gimple *g;
13847 size_t n_in = 0, n_out = 0, idx = 2, i;
13849 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
13850 gcc_assert (clauses);
13851 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
13852 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
13853 switch (OMP_CLAUSE_DEPEND_KIND (c))
13855 case OMP_CLAUSE_DEPEND_IN:
13856 n_in++;
13857 break;
13858 case OMP_CLAUSE_DEPEND_OUT:
13859 case OMP_CLAUSE_DEPEND_INOUT:
13860 n_out++;
13861 break;
13862 case OMP_CLAUSE_DEPEND_SOURCE:
13863 case OMP_CLAUSE_DEPEND_SINK:
13864 /* FALLTHRU */
13865 default:
13866 gcc_unreachable ();
13868 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
13869 tree array = create_tmp_var (type);
13870 TREE_ADDRESSABLE (array) = 1;
13871 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
13872 NULL_TREE);
13873 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
13874 gimple_seq_add_stmt (iseq, g);
13875 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
13876 NULL_TREE);
13877 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
13878 gimple_seq_add_stmt (iseq, g);
13879 for (i = 0; i < 2; i++)
13881 if ((i ? n_in : n_out) == 0)
13882 continue;
13883 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
13884 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
13885 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
13887 tree t = OMP_CLAUSE_DECL (c);
13888 t = fold_convert (ptr_type_node, t);
13889 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
13890 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
13891 NULL_TREE, NULL_TREE);
13892 g = gimple_build_assign (r, t);
13893 gimple_seq_add_stmt (iseq, g);
13896 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
13897 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
13898 OMP_CLAUSE_CHAIN (c) = *pclauses;
13899 *pclauses = c;
13900 tree clobber = build_constructor (type, NULL);
13901 TREE_THIS_VOLATILE (clobber) = 1;
13902 g = gimple_build_assign (array, clobber);
13903 gimple_seq_add_stmt (oseq, g);
13906 /* Lower the OpenMP parallel or task directive in the current statement
13907 in GSI_P. CTX holds context information for the directive. */
13909 static void
13910 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13912 tree clauses;
13913 tree child_fn, t;
13914 gimple *stmt = gsi_stmt (*gsi_p);
13915 gbind *par_bind, *bind, *dep_bind = NULL;
13916 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
13917 location_t loc = gimple_location (stmt);
13919 clauses = gimple_omp_taskreg_clauses (stmt);
13920 par_bind
13921 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
13922 par_body = gimple_bind_body (par_bind);
13923 child_fn = ctx->cb.dst_fn;
13924 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
13925 && !gimple_omp_parallel_combined_p (stmt))
13927 struct walk_stmt_info wi;
13928 int ws_num = 0;
13930 memset (&wi, 0, sizeof (wi));
13931 wi.info = &ws_num;
13932 wi.val_only = true;
13933 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
13934 if (ws_num == 1)
13935 gimple_omp_parallel_set_combined_p (stmt, true);
13937 gimple_seq dep_ilist = NULL;
13938 gimple_seq dep_olist = NULL;
13939 if (gimple_code (stmt) == GIMPLE_OMP_TASK
13940 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
13942 push_gimplify_context ();
13943 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
13944 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
13945 &dep_ilist, &dep_olist);
13948 if (ctx->srecord_type)
13949 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
13951 push_gimplify_context ();
13953 par_olist = NULL;
13954 par_ilist = NULL;
13955 par_rlist = NULL;
13956 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
13957 lower_omp (&par_body, ctx);
13958 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
13959 lower_reduction_clauses (clauses, &par_rlist, ctx);
13961 /* Declare all the variables created by mapping and the variables
13962 declared in the scope of the parallel body. */
13963 record_vars_into (ctx->block_vars, child_fn);
13964 record_vars_into (gimple_bind_vars (par_bind), child_fn);
13966 if (ctx->record_type)
13968 ctx->sender_decl
13969 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
13970 : ctx->record_type, ".omp_data_o");
13971 DECL_NAMELESS (ctx->sender_decl) = 1;
13972 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
13973 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
13976 olist = NULL;
13977 ilist = NULL;
13978 lower_send_clauses (clauses, &ilist, &olist, ctx);
13979 lower_send_shared_vars (&ilist, &olist, ctx);
13981 if (ctx->record_type)
13983 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
13984 TREE_THIS_VOLATILE (clobber) = 1;
13985 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
13986 clobber));
13989 /* Once all the expansions are done, sequence all the different
13990 fragments inside gimple_omp_body. */
13992 new_body = NULL;
13994 if (ctx->record_type)
13996 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
13997 /* fixup_child_record_type might have changed receiver_decl's type. */
13998 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
13999 gimple_seq_add_stmt (&new_body,
14000 gimple_build_assign (ctx->receiver_decl, t));
14003 gimple_seq_add_seq (&new_body, par_ilist);
14004 gimple_seq_add_seq (&new_body, par_body);
14005 gimple_seq_add_seq (&new_body, par_rlist);
14006 if (ctx->cancellable)
14007 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
14008 gimple_seq_add_seq (&new_body, par_olist);
14009 new_body = maybe_catch_exception (new_body);
14010 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
14011 gimple_seq_add_stmt (&new_body,
14012 gimple_build_omp_continue (integer_zero_node,
14013 integer_zero_node));
14014 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
14015 gimple_omp_set_body (stmt, new_body);
14017 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
14018 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
14019 gimple_bind_add_seq (bind, ilist);
14020 gimple_bind_add_stmt (bind, stmt);
14021 gimple_bind_add_seq (bind, olist);
14023 pop_gimplify_context (NULL);
14025 if (dep_bind)
14027 gimple_bind_add_seq (dep_bind, dep_ilist);
14028 gimple_bind_add_stmt (dep_bind, bind);
14029 gimple_bind_add_seq (dep_bind, dep_olist);
14030 pop_gimplify_context (dep_bind);
14034 /* Lower the GIMPLE_OMP_TARGET in the current statement
14035 in GSI_P. CTX holds context information for the directive. */
14037 static void
14038 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14040 tree clauses;
14041 tree child_fn, t, c;
14042 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
14043 gbind *tgt_bind, *bind, *dep_bind = NULL;
14044 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
14045 location_t loc = gimple_location (stmt);
14046 bool offloaded, data_region;
14047 unsigned int map_cnt = 0;
14048 bool has_depend = false;
14050 offloaded = is_gimple_omp_offloaded (stmt);
14051 switch (gimple_omp_target_kind (stmt))
14053 case GF_OMP_TARGET_KIND_REGION:
14054 case GF_OMP_TARGET_KIND_UPDATE:
14055 case GF_OMP_TARGET_KIND_ENTER_DATA:
14056 case GF_OMP_TARGET_KIND_EXIT_DATA:
14057 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
14058 case GF_OMP_TARGET_KIND_OACC_KERNELS:
14059 case GF_OMP_TARGET_KIND_OACC_UPDATE:
14060 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
14061 data_region = false;
14062 break;
14063 case GF_OMP_TARGET_KIND_DATA:
14064 case GF_OMP_TARGET_KIND_OACC_DATA:
14065 data_region = true;
14066 break;
14067 default:
14068 gcc_unreachable ();
14071 clauses = gimple_omp_target_clauses (stmt);
14073 gimple_seq dep_ilist = NULL;
14074 gimple_seq dep_olist = NULL;
14075 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
14077 push_gimplify_context ();
14078 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
14079 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
14080 &dep_ilist, &dep_olist);
14081 has_depend = true;
14084 tgt_bind = NULL;
14085 tgt_body = NULL;
14086 if (offloaded)
14088 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
14089 tgt_body = gimple_bind_body (tgt_bind);
14091 else if (data_region)
14092 tgt_body = gimple_omp_body (stmt);
14093 child_fn = ctx->cb.dst_fn;
14095 push_gimplify_context ();
14097 irlist = NULL;
14098 orlist = NULL;
14099 if (offloaded
14100 && is_gimple_omp_oacc (stmt))
14101 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
14103 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
14104 switch (OMP_CLAUSE_CODE (c))
14106 tree var, x;
14108 default:
14109 break;
14110 case OMP_CLAUSE_MAP:
14111 #ifdef ENABLE_CHECKING
14112 /* First check what we're prepared to handle in the following. */
14113 switch (OMP_CLAUSE_MAP_KIND (c))
14115 case GOMP_MAP_ALLOC:
14116 case GOMP_MAP_TO:
14117 case GOMP_MAP_FROM:
14118 case GOMP_MAP_TOFROM:
14119 case GOMP_MAP_POINTER:
14120 case GOMP_MAP_TO_PSET:
14121 case GOMP_MAP_FORCE_DEALLOC:
14122 case GOMP_MAP_RELEASE:
14123 case GOMP_MAP_ALWAYS_TO:
14124 case GOMP_MAP_ALWAYS_FROM:
14125 case GOMP_MAP_ALWAYS_TOFROM:
14126 case GOMP_MAP_FIRSTPRIVATE_POINTER:
14127 case GOMP_MAP_STRUCT:
14128 break;
14129 case GOMP_MAP_FORCE_ALLOC:
14130 case GOMP_MAP_FORCE_TO:
14131 case GOMP_MAP_FORCE_FROM:
14132 case GOMP_MAP_FORCE_TOFROM:
14133 case GOMP_MAP_FORCE_PRESENT:
14134 case GOMP_MAP_FORCE_DEVICEPTR:
14135 gcc_assert (is_gimple_omp_oacc (stmt));
14136 break;
14137 default:
14138 gcc_unreachable ();
14140 #endif
14141 /* FALLTHRU */
14142 case OMP_CLAUSE_TO:
14143 case OMP_CLAUSE_FROM:
14144 var = OMP_CLAUSE_DECL (c);
14145 if (!DECL_P (var))
14147 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
14148 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
14149 && (OMP_CLAUSE_MAP_KIND (c)
14150 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
14151 map_cnt++;
14152 continue;
14155 if (DECL_SIZE (var)
14156 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
14158 tree var2 = DECL_VALUE_EXPR (var);
14159 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
14160 var2 = TREE_OPERAND (var2, 0);
14161 gcc_assert (DECL_P (var2));
14162 var = var2;
14165 if (offloaded
14166 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
14168 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
14170 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
14171 && varpool_node::get_create (var)->offloadable)
14172 continue;
14174 tree type = build_pointer_type (TREE_TYPE (var));
14175 tree new_var = lookup_decl (var, ctx);
14176 x = create_tmp_var_raw (type, get_name (new_var));
14177 gimple_add_tmp_var (x);
14178 x = build_simple_mem_ref (x);
14179 SET_DECL_VALUE_EXPR (new_var, x);
14180 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
14182 continue;
14185 if (offloaded && OMP_CLAUSE_MAP_PRIVATE (c))
14187 map_cnt++;
14188 continue;
14191 if (!maybe_lookup_field (var, ctx))
14192 continue;
14194 if (offloaded)
14196 x = build_receiver_ref (var, true, ctx);
14197 tree new_var = lookup_decl (var, ctx);
14199 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
14200 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
14201 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
14202 x = build_simple_mem_ref (x);
14203 SET_DECL_VALUE_EXPR (new_var, x);
14204 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
14206 map_cnt++;
14207 break;
14209 case OMP_CLAUSE_FIRSTPRIVATE:
14210 map_cnt++;
14211 var = OMP_CLAUSE_DECL (c);
14212 if (!is_reference (var)
14213 && !is_gimple_reg_type (TREE_TYPE (var)))
14215 tree new_var = lookup_decl (var, ctx);
14216 if (is_variable_sized (var))
14218 tree pvar = DECL_VALUE_EXPR (var);
14219 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
14220 pvar = TREE_OPERAND (pvar, 0);
14221 gcc_assert (DECL_P (pvar));
14222 tree new_pvar = lookup_decl (pvar, ctx);
14223 x = build_fold_indirect_ref (new_pvar);
14224 TREE_THIS_NOTRAP (x) = 1;
14226 else
14227 x = build_receiver_ref (var, true, ctx);
14228 SET_DECL_VALUE_EXPR (new_var, x);
14229 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
14231 break;
14233 case OMP_CLAUSE_PRIVATE:
14234 var = OMP_CLAUSE_DECL (c);
14235 if (is_variable_sized (var))
14237 tree new_var = lookup_decl (var, ctx);
14238 tree pvar = DECL_VALUE_EXPR (var);
14239 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
14240 pvar = TREE_OPERAND (pvar, 0);
14241 gcc_assert (DECL_P (pvar));
14242 tree new_pvar = lookup_decl (pvar, ctx);
14243 x = build_fold_indirect_ref (new_pvar);
14244 TREE_THIS_NOTRAP (x) = 1;
14245 SET_DECL_VALUE_EXPR (new_var, x);
14246 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
14248 break;
14250 case OMP_CLAUSE_USE_DEVICE_PTR:
14251 case OMP_CLAUSE_IS_DEVICE_PTR:
14252 var = OMP_CLAUSE_DECL (c);
14253 map_cnt++;
14254 if (is_variable_sized (var))
14256 tree new_var = lookup_decl (var, ctx);
14257 tree pvar = DECL_VALUE_EXPR (var);
14258 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
14259 pvar = TREE_OPERAND (pvar, 0);
14260 gcc_assert (DECL_P (pvar));
14261 tree new_pvar = lookup_decl (pvar, ctx);
14262 x = build_fold_indirect_ref (new_pvar);
14263 TREE_THIS_NOTRAP (x) = 1;
14264 SET_DECL_VALUE_EXPR (new_var, x);
14265 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
14267 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
14269 tree new_var = lookup_decl (var, ctx);
14270 tree type = build_pointer_type (TREE_TYPE (var));
14271 x = create_tmp_var_raw (type, get_name (new_var));
14272 gimple_add_tmp_var (x);
14273 x = build_simple_mem_ref (x);
14274 SET_DECL_VALUE_EXPR (new_var, x);
14275 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
14277 break;
14280 if (offloaded)
14282 target_nesting_level++;
14283 lower_omp (&tgt_body, ctx);
14284 target_nesting_level--;
14286 else if (data_region)
14287 lower_omp (&tgt_body, ctx);
14289 if (offloaded)
14291 /* Declare all the variables created by mapping and the variables
14292 declared in the scope of the target body. */
14293 record_vars_into (ctx->block_vars, child_fn);
14294 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
14297 olist = NULL;
14298 ilist = NULL;
14299 if (ctx->record_type)
14301 ctx->sender_decl
14302 = create_tmp_var (ctx->record_type, ".omp_data_arr");
14303 DECL_NAMELESS (ctx->sender_decl) = 1;
14304 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
14305 t = make_tree_vec (3);
14306 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
14307 TREE_VEC_ELT (t, 1)
14308 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
14309 ".omp_data_sizes");
14310 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
14311 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
14312 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
14313 tree tkind_type = short_unsigned_type_node;
14314 int talign_shift = 8;
14315 TREE_VEC_ELT (t, 2)
14316 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
14317 ".omp_data_kinds");
14318 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
14319 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
14320 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
14321 gimple_omp_target_set_data_arg (stmt, t);
14323 vec<constructor_elt, va_gc> *vsize;
14324 vec<constructor_elt, va_gc> *vkind;
14325 vec_alloc (vsize, map_cnt);
14326 vec_alloc (vkind, map_cnt);
14327 unsigned int map_idx = 0;
14329 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
14330 switch (OMP_CLAUSE_CODE (c))
14332 tree ovar, nc, s, purpose, var, x, type;
14333 unsigned int talign;
14335 default:
14336 break;
14337 case OMP_CLAUSE_MAP:
14338 case OMP_CLAUSE_TO:
14339 case OMP_CLAUSE_FROM:
14340 nc = c;
14341 ovar = OMP_CLAUSE_DECL (c);
14342 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
14343 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
14344 break;
14345 if (!DECL_P (ovar))
14347 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
14348 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
14350 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
14351 == get_base_address (ovar));
14352 nc = OMP_CLAUSE_CHAIN (c);
14353 ovar = OMP_CLAUSE_DECL (nc);
14355 else
14357 tree x = build_sender_ref (ovar, ctx);
14358 tree v
14359 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
14360 gimplify_assign (x, v, &ilist);
14361 nc = NULL_TREE;
14364 else
14366 if (DECL_SIZE (ovar)
14367 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
14369 tree ovar2 = DECL_VALUE_EXPR (ovar);
14370 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
14371 ovar2 = TREE_OPERAND (ovar2, 0);
14372 gcc_assert (DECL_P (ovar2));
14373 ovar = ovar2;
14375 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
14376 && OMP_CLAUSE_MAP_PRIVATE (c))
14378 if (!maybe_lookup_field ((splay_tree_key) &DECL_UID (ovar),
14379 ctx))
14380 continue;
14382 else if (!maybe_lookup_field (ovar, ctx))
14383 continue;
14386 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
14387 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
14388 talign = DECL_ALIGN_UNIT (ovar);
14389 if (nc)
14391 var = lookup_decl_in_outer_ctx (ovar, ctx);
14392 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
14393 && OMP_CLAUSE_MAP_PRIVATE (c))
14394 x = build_sender_ref ((splay_tree_key) &DECL_UID (ovar),
14395 ctx);
14396 else
14397 x = build_sender_ref (ovar, ctx);
14398 if (maybe_lookup_oacc_reduction (var, ctx))
14400 gcc_checking_assert (offloaded
14401 && is_gimple_omp_oacc (stmt));
14402 gimplify_assign (x, var, &ilist);
14404 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
14405 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
14406 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
14407 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
14409 gcc_assert (offloaded);
14410 tree avar
14411 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
14412 mark_addressable (avar);
14413 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
14414 talign = DECL_ALIGN_UNIT (avar);
14415 avar = build_fold_addr_expr (avar);
14416 gimplify_assign (x, avar, &ilist);
14418 else if (is_gimple_reg (var))
14420 gcc_assert (offloaded);
14421 tree avar = create_tmp_var (TREE_TYPE (var));
14422 mark_addressable (avar);
14423 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
14424 if (GOMP_MAP_COPY_TO_P (map_kind)
14425 || map_kind == GOMP_MAP_POINTER
14426 || map_kind == GOMP_MAP_TO_PSET
14427 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
14428 gimplify_assign (avar, var, &ilist);
14429 avar = build_fold_addr_expr (avar);
14430 gimplify_assign (x, avar, &ilist);
14431 if ((GOMP_MAP_COPY_FROM_P (map_kind)
14432 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
14433 && !TYPE_READONLY (TREE_TYPE (var)))
14435 x = unshare_expr (x);
14436 x = build_simple_mem_ref (x);
14437 gimplify_assign (var, x, &olist);
14440 else
14442 var = build_fold_addr_expr (var);
14443 gimplify_assign (x, var, &ilist);
14446 s = OMP_CLAUSE_SIZE (c);
14447 if (s == NULL_TREE)
14448 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
14449 s = fold_convert (size_type_node, s);
14450 purpose = size_int (map_idx++);
14451 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
14452 if (TREE_CODE (s) != INTEGER_CST)
14453 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
14455 unsigned HOST_WIDE_INT tkind, tkind_zero;
14456 switch (OMP_CLAUSE_CODE (c))
14458 case OMP_CLAUSE_MAP:
14459 tkind = OMP_CLAUSE_MAP_KIND (c);
14460 tkind_zero = tkind;
14461 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
14462 switch (tkind)
14464 case GOMP_MAP_ALLOC:
14465 case GOMP_MAP_TO:
14466 case GOMP_MAP_FROM:
14467 case GOMP_MAP_TOFROM:
14468 case GOMP_MAP_ALWAYS_TO:
14469 case GOMP_MAP_ALWAYS_FROM:
14470 case GOMP_MAP_ALWAYS_TOFROM:
14471 case GOMP_MAP_RELEASE:
14472 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
14473 break;
14474 case GOMP_MAP_DELETE:
14475 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
14476 default:
14477 break;
14479 if (tkind_zero != tkind)
14481 if (integer_zerop (s))
14482 tkind = tkind_zero;
14483 else if (integer_nonzerop (s))
14484 tkind_zero = tkind;
14486 break;
14487 case OMP_CLAUSE_TO:
14488 tkind = GOMP_MAP_TO;
14489 tkind_zero = tkind;
14490 break;
14491 case OMP_CLAUSE_FROM:
14492 tkind = GOMP_MAP_FROM;
14493 tkind_zero = tkind;
14494 break;
14495 default:
14496 gcc_unreachable ();
14498 gcc_checking_assert (tkind
14499 < (HOST_WIDE_INT_C (1U) << talign_shift));
14500 gcc_checking_assert (tkind_zero
14501 < (HOST_WIDE_INT_C (1U) << talign_shift));
14502 talign = ceil_log2 (talign);
14503 tkind |= talign << talign_shift;
14504 tkind_zero |= talign << talign_shift;
14505 gcc_checking_assert (tkind
14506 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
14507 gcc_checking_assert (tkind_zero
14508 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
14509 if (tkind == tkind_zero)
14510 x = build_int_cstu (tkind_type, tkind);
14511 else
14513 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
14514 x = build3 (COND_EXPR, tkind_type,
14515 fold_build2 (EQ_EXPR, boolean_type_node,
14516 unshare_expr (s), size_zero_node),
14517 build_int_cstu (tkind_type, tkind_zero),
14518 build_int_cstu (tkind_type, tkind));
14520 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
14521 if (nc && nc != c)
14522 c = nc;
14523 break;
14525 case OMP_CLAUSE_FIRSTPRIVATE:
14526 ovar = OMP_CLAUSE_DECL (c);
14527 if (is_reference (ovar))
14528 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
14529 else
14530 talign = DECL_ALIGN_UNIT (ovar);
14531 var = lookup_decl_in_outer_ctx (ovar, ctx);
14532 x = build_sender_ref (ovar, ctx);
14533 tkind = GOMP_MAP_FIRSTPRIVATE;
14534 type = TREE_TYPE (ovar);
14535 if (is_reference (ovar))
14536 type = TREE_TYPE (type);
14537 bool use_firstprivate_int, force_addr;
14538 use_firstprivate_int = false;
14539 force_addr = false;
14540 if ((INTEGRAL_TYPE_P (type)
14541 && TYPE_PRECISION (type) <= POINTER_SIZE)
14542 || TREE_CODE (type) == POINTER_TYPE)
14543 use_firstprivate_int = true;
14544 if (has_depend)
14546 if (is_reference (var))
14547 use_firstprivate_int = false;
14548 else if (is_gimple_reg (var))
14550 if (DECL_HAS_VALUE_EXPR_P (var))
14552 tree v = get_base_address (var);
14553 if (DECL_P (v) && TREE_ADDRESSABLE (v))
14555 use_firstprivate_int = false;
14556 force_addr = true;
14558 else
14559 switch (TREE_CODE (v))
14561 case INDIRECT_REF:
14562 case MEM_REF:
14563 use_firstprivate_int = false;
14564 force_addr = true;
14565 break;
14566 default:
14567 break;
14571 else
14572 use_firstprivate_int = false;
14574 if (use_firstprivate_int)
14576 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
14577 tree t = var;
14578 if (is_reference (var))
14579 t = build_simple_mem_ref (var);
14580 if (TREE_CODE (type) != POINTER_TYPE)
14581 t = fold_convert (pointer_sized_int_node, t);
14582 t = fold_convert (TREE_TYPE (x), t);
14583 gimplify_assign (x, t, &ilist);
14585 else if (is_reference (var))
14586 gimplify_assign (x, var, &ilist);
14587 else if (!force_addr && is_gimple_reg (var))
14589 tree avar = create_tmp_var (TREE_TYPE (var));
14590 mark_addressable (avar);
14591 gimplify_assign (avar, var, &ilist);
14592 avar = build_fold_addr_expr (avar);
14593 gimplify_assign (x, avar, &ilist);
14595 else
14597 var = build_fold_addr_expr (var);
14598 gimplify_assign (x, var, &ilist);
14600 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
14601 s = size_int (0);
14602 else if (is_reference (var))
14603 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
14604 else
14605 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
14606 s = fold_convert (size_type_node, s);
14607 purpose = size_int (map_idx++);
14608 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
14609 if (TREE_CODE (s) != INTEGER_CST)
14610 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
14612 gcc_checking_assert (tkind
14613 < (HOST_WIDE_INT_C (1U) << talign_shift));
14614 talign = ceil_log2 (talign);
14615 tkind |= talign << talign_shift;
14616 gcc_checking_assert (tkind
14617 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
14618 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
14619 build_int_cstu (tkind_type, tkind));
14620 break;
14622 case OMP_CLAUSE_USE_DEVICE_PTR:
14623 case OMP_CLAUSE_IS_DEVICE_PTR:
14624 ovar = OMP_CLAUSE_DECL (c);
14625 var = lookup_decl_in_outer_ctx (ovar, ctx);
14626 x = build_sender_ref (ovar, ctx);
14627 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
14628 tkind = GOMP_MAP_USE_DEVICE_PTR;
14629 else
14630 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
14631 type = TREE_TYPE (ovar);
14632 if (TREE_CODE (type) == ARRAY_TYPE)
14633 var = build_fold_addr_expr (var);
14634 else
14636 if (is_reference (ovar))
14638 type = TREE_TYPE (type);
14639 if (TREE_CODE (type) != ARRAY_TYPE)
14640 var = build_simple_mem_ref (var);
14641 var = fold_convert (TREE_TYPE (x), var);
14644 gimplify_assign (x, var, &ilist);
14645 s = size_int (0);
14646 purpose = size_int (map_idx++);
14647 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
14648 gcc_checking_assert (tkind
14649 < (HOST_WIDE_INT_C (1U) << talign_shift));
14650 gcc_checking_assert (tkind
14651 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
14652 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
14653 build_int_cstu (tkind_type, tkind));
14654 break;
14657 gcc_assert (map_idx == map_cnt);
14659 DECL_INITIAL (TREE_VEC_ELT (t, 1))
14660 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
14661 DECL_INITIAL (TREE_VEC_ELT (t, 2))
14662 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
14663 for (int i = 1; i <= 2; i++)
14664 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
14666 gimple_seq initlist = NULL;
14667 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
14668 TREE_VEC_ELT (t, i)),
14669 &initlist, true, NULL_TREE);
14670 gimple_seq_add_seq (&ilist, initlist);
14672 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
14673 NULL);
14674 TREE_THIS_VOLATILE (clobber) = 1;
14675 gimple_seq_add_stmt (&olist,
14676 gimple_build_assign (TREE_VEC_ELT (t, i),
14677 clobber));
14680 tree clobber = build_constructor (ctx->record_type, NULL);
14681 TREE_THIS_VOLATILE (clobber) = 1;
14682 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
14683 clobber));
14686 /* Once all the expansions are done, sequence all the different
14687 fragments inside gimple_omp_body. */
14689 new_body = NULL;
14691 if (offloaded
14692 && ctx->record_type)
14694 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
14695 /* fixup_child_record_type might have changed receiver_decl's type. */
14696 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
14697 gimple_seq_add_stmt (&new_body,
14698 gimple_build_assign (ctx->receiver_decl, t));
14701 if (offloaded || data_region)
14703 tree prev = NULL_TREE;
14704 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
14705 switch (OMP_CLAUSE_CODE (c))
14707 tree var, x;
14708 default:
14709 break;
14710 case OMP_CLAUSE_FIRSTPRIVATE:
14711 var = OMP_CLAUSE_DECL (c);
14712 if (is_reference (var)
14713 || is_gimple_reg_type (TREE_TYPE (var)))
14715 tree new_var = lookup_decl (var, ctx);
14716 tree type;
14717 type = TREE_TYPE (var);
14718 if (is_reference (var))
14719 type = TREE_TYPE (type);
14720 bool use_firstprivate_int;
14721 use_firstprivate_int = false;
14722 if ((INTEGRAL_TYPE_P (type)
14723 && TYPE_PRECISION (type) <= POINTER_SIZE)
14724 || TREE_CODE (type) == POINTER_TYPE)
14725 use_firstprivate_int = true;
14726 if (has_depend)
14728 tree v = lookup_decl_in_outer_ctx (var, ctx);
14729 if (is_reference (v))
14730 use_firstprivate_int = false;
14731 else if (is_gimple_reg (v))
14733 if (DECL_HAS_VALUE_EXPR_P (v))
14735 v = get_base_address (v);
14736 if (DECL_P (v) && TREE_ADDRESSABLE (v))
14737 use_firstprivate_int = false;
14738 else
14739 switch (TREE_CODE (v))
14741 case INDIRECT_REF:
14742 case MEM_REF:
14743 use_firstprivate_int = false;
14744 break;
14745 default:
14746 break;
14750 else
14751 use_firstprivate_int = false;
14753 if (use_firstprivate_int)
14755 x = build_receiver_ref (var, false, ctx);
14756 if (TREE_CODE (type) != POINTER_TYPE)
14757 x = fold_convert (pointer_sized_int_node, x);
14758 x = fold_convert (type, x);
14759 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
14760 fb_rvalue);
14761 if (is_reference (var))
14763 tree v = create_tmp_var_raw (type, get_name (var));
14764 gimple_add_tmp_var (v);
14765 TREE_ADDRESSABLE (v) = 1;
14766 gimple_seq_add_stmt (&new_body,
14767 gimple_build_assign (v, x));
14768 x = build_fold_addr_expr (v);
14770 gimple_seq_add_stmt (&new_body,
14771 gimple_build_assign (new_var, x));
14773 else
14775 x = build_receiver_ref (var, !is_reference (var), ctx);
14776 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
14777 fb_rvalue);
14778 gimple_seq_add_stmt (&new_body,
14779 gimple_build_assign (new_var, x));
14782 else if (is_variable_sized (var))
14784 tree pvar = DECL_VALUE_EXPR (var);
14785 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
14786 pvar = TREE_OPERAND (pvar, 0);
14787 gcc_assert (DECL_P (pvar));
14788 tree new_var = lookup_decl (pvar, ctx);
14789 x = build_receiver_ref (var, false, ctx);
14790 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
14791 gimple_seq_add_stmt (&new_body,
14792 gimple_build_assign (new_var, x));
14794 break;
14795 case OMP_CLAUSE_PRIVATE:
14796 var = OMP_CLAUSE_DECL (c);
14797 if (is_reference (var))
14799 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
14800 tree new_var = lookup_decl (var, ctx);
14801 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
14802 if (TREE_CONSTANT (x))
14804 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
14805 get_name (var));
14806 gimple_add_tmp_var (x);
14807 TREE_ADDRESSABLE (x) = 1;
14808 x = build_fold_addr_expr_loc (clause_loc, x);
14810 else
14812 tree atmp
14813 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
14814 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
14815 tree al = size_int (TYPE_ALIGN (rtype));
14816 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
14819 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
14820 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
14821 gimple_seq_add_stmt (&new_body,
14822 gimple_build_assign (new_var, x));
14824 break;
14825 case OMP_CLAUSE_USE_DEVICE_PTR:
14826 case OMP_CLAUSE_IS_DEVICE_PTR:
14827 var = OMP_CLAUSE_DECL (c);
14828 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
14829 x = build_sender_ref (var, ctx);
14830 else
14831 x = build_receiver_ref (var, false, ctx);
14832 if (is_variable_sized (var))
14834 tree pvar = DECL_VALUE_EXPR (var);
14835 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
14836 pvar = TREE_OPERAND (pvar, 0);
14837 gcc_assert (DECL_P (pvar));
14838 tree new_var = lookup_decl (pvar, ctx);
14839 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
14840 gimple_seq_add_stmt (&new_body,
14841 gimple_build_assign (new_var, x));
14843 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
14845 tree new_var = lookup_decl (var, ctx);
14846 new_var = DECL_VALUE_EXPR (new_var);
14847 gcc_assert (TREE_CODE (new_var) == MEM_REF);
14848 new_var = TREE_OPERAND (new_var, 0);
14849 gcc_assert (DECL_P (new_var));
14850 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
14851 gimple_seq_add_stmt (&new_body,
14852 gimple_build_assign (new_var, x));
14854 else
14856 tree type = TREE_TYPE (var);
14857 tree new_var = lookup_decl (var, ctx);
14858 if (is_reference (var))
14860 type = TREE_TYPE (type);
14861 if (TREE_CODE (type) != ARRAY_TYPE)
14863 tree v = create_tmp_var_raw (type, get_name (var));
14864 gimple_add_tmp_var (v);
14865 TREE_ADDRESSABLE (v) = 1;
14866 x = fold_convert (type, x);
14867 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
14868 fb_rvalue);
14869 gimple_seq_add_stmt (&new_body,
14870 gimple_build_assign (v, x));
14871 x = build_fold_addr_expr (v);
14874 x = fold_convert (TREE_TYPE (new_var), x);
14875 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
14876 gimple_seq_add_stmt (&new_body,
14877 gimple_build_assign (new_var, x));
14879 break;
14881 /* Handle GOMP_MAP_FIRSTPRIVATE_POINTER in second pass,
14882 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
14883 are already handled. */
14884 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
14885 switch (OMP_CLAUSE_CODE (c))
14887 tree var;
14888 default:
14889 break;
14890 case OMP_CLAUSE_MAP:
14891 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
14893 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
14894 HOST_WIDE_INT offset = 0;
14895 gcc_assert (prev);
14896 var = OMP_CLAUSE_DECL (c);
14897 if (DECL_P (var)
14898 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
14899 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
14900 ctx))
14901 && varpool_node::get_create (var)->offloadable)
14902 break;
14903 if (TREE_CODE (var) == INDIRECT_REF
14904 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
14905 var = TREE_OPERAND (var, 0);
14906 if (TREE_CODE (var) == COMPONENT_REF)
14908 var = get_addr_base_and_unit_offset (var, &offset);
14909 gcc_assert (var != NULL_TREE && DECL_P (var));
14911 else if (DECL_SIZE (var)
14912 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
14914 tree var2 = DECL_VALUE_EXPR (var);
14915 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
14916 var2 = TREE_OPERAND (var2, 0);
14917 gcc_assert (DECL_P (var2));
14918 var = var2;
14920 tree new_var = lookup_decl (var, ctx), x;
14921 tree type = TREE_TYPE (new_var);
14922 bool is_ref;
14923 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
14924 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
14925 == COMPONENT_REF))
14927 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
14928 is_ref = true;
14929 new_var = build2 (MEM_REF, type,
14930 build_fold_addr_expr (new_var),
14931 build_int_cst (build_pointer_type (type),
14932 offset));
14934 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
14936 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
14937 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
14938 new_var = build2 (MEM_REF, type,
14939 build_fold_addr_expr (new_var),
14940 build_int_cst (build_pointer_type (type),
14941 offset));
14943 else
14944 is_ref = is_reference (var);
14945 bool ref_to_array = false;
14946 if (is_ref)
14948 type = TREE_TYPE (type);
14949 if (TREE_CODE (type) == ARRAY_TYPE)
14951 type = build_pointer_type (type);
14952 ref_to_array = true;
14955 else if (TREE_CODE (type) == ARRAY_TYPE)
14957 tree decl2 = DECL_VALUE_EXPR (new_var);
14958 gcc_assert (TREE_CODE (decl2) == MEM_REF);
14959 decl2 = TREE_OPERAND (decl2, 0);
14960 gcc_assert (DECL_P (decl2));
14961 new_var = decl2;
14962 type = TREE_TYPE (new_var);
14964 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
14965 x = fold_convert_loc (clause_loc, type, x);
14966 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
14968 tree bias = OMP_CLAUSE_SIZE (c);
14969 if (DECL_P (bias))
14970 bias = lookup_decl (bias, ctx);
14971 bias = fold_convert_loc (clause_loc, sizetype, bias);
14972 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
14973 bias);
14974 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
14975 TREE_TYPE (x), x, bias);
14977 if (ref_to_array)
14978 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
14979 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
14980 if (is_ref && !ref_to_array)
14982 tree t = create_tmp_var_raw (type, get_name (var));
14983 gimple_add_tmp_var (t);
14984 TREE_ADDRESSABLE (t) = 1;
14985 gimple_seq_add_stmt (&new_body,
14986 gimple_build_assign (t, x));
14987 x = build_fold_addr_expr_loc (clause_loc, t);
14989 gimple_seq_add_stmt (&new_body,
14990 gimple_build_assign (new_var, x));
14991 prev = NULL_TREE;
14993 else if (OMP_CLAUSE_CHAIN (c)
14994 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
14995 == OMP_CLAUSE_MAP
14996 && OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
14997 == GOMP_MAP_FIRSTPRIVATE_POINTER)
14998 prev = c;
14999 break;
15000 case OMP_CLAUSE_PRIVATE:
15001 var = OMP_CLAUSE_DECL (c);
15002 if (is_variable_sized (var))
15004 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15005 tree new_var = lookup_decl (var, ctx);
15006 tree pvar = DECL_VALUE_EXPR (var);
15007 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15008 pvar = TREE_OPERAND (pvar, 0);
15009 gcc_assert (DECL_P (pvar));
15010 tree new_pvar = lookup_decl (pvar, ctx);
15011 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
15012 tree al = size_int (DECL_ALIGN (var));
15013 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
15014 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
15015 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
15016 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15017 gimple_seq_add_stmt (&new_body,
15018 gimple_build_assign (new_pvar, x));
15020 break;
15022 gimple_seq_add_seq (&new_body, tgt_body);
15023 if (offloaded)
15024 new_body = maybe_catch_exception (new_body);
15026 else if (data_region)
15027 new_body = tgt_body;
15028 if (offloaded || data_region)
15030 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15031 gimple_omp_set_body (stmt, new_body);
15034 bind = gimple_build_bind (NULL, NULL,
15035 tgt_bind ? gimple_bind_block (tgt_bind)
15036 : NULL_TREE);
15037 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15038 gimple_bind_add_seq (bind, irlist);
15039 gimple_bind_add_seq (bind, ilist);
15040 gimple_bind_add_stmt (bind, stmt);
15041 gimple_bind_add_seq (bind, olist);
15042 gimple_bind_add_seq (bind, orlist);
15044 pop_gimplify_context (NULL);
15046 if (dep_bind)
15048 gimple_bind_add_seq (dep_bind, dep_ilist);
15049 gimple_bind_add_stmt (dep_bind, bind);
15050 gimple_bind_add_seq (dep_bind, dep_olist);
15051 pop_gimplify_context (dep_bind);
15055 /* Expand code for an OpenMP teams directive. */
15057 static void
15058 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15060 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
15061 push_gimplify_context ();
15063 tree block = make_node (BLOCK);
15064 gbind *bind = gimple_build_bind (NULL, NULL, block);
15065 gsi_replace (gsi_p, bind, true);
15066 gimple_seq bind_body = NULL;
15067 gimple_seq dlist = NULL;
15068 gimple_seq olist = NULL;
15070 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
15071 OMP_CLAUSE_NUM_TEAMS);
15072 if (num_teams == NULL_TREE)
15073 num_teams = build_int_cst (unsigned_type_node, 0);
15074 else
15076 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
15077 num_teams = fold_convert (unsigned_type_node, num_teams);
15078 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
15080 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
15081 OMP_CLAUSE_THREAD_LIMIT);
15082 if (thread_limit == NULL_TREE)
15083 thread_limit = build_int_cst (unsigned_type_node, 0);
15084 else
15086 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
15087 thread_limit = fold_convert (unsigned_type_node, thread_limit);
15088 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
15089 fb_rvalue);
15092 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
15093 &bind_body, &dlist, ctx, NULL);
15094 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
15095 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
15096 gimple_seq_add_stmt (&bind_body, teams_stmt);
15098 location_t loc = gimple_location (teams_stmt);
15099 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
15100 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
15101 gimple_set_location (call, loc);
15102 gimple_seq_add_stmt (&bind_body, call);
15104 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
15105 gimple_omp_set_body (teams_stmt, NULL);
15106 gimple_seq_add_seq (&bind_body, olist);
15107 gimple_seq_add_seq (&bind_body, dlist);
15108 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
15109 gimple_bind_set_body (bind, bind_body);
15111 pop_gimplify_context (bind);
15113 gimple_bind_append_vars (bind, ctx->block_vars);
15114 BLOCK_VARS (block) = ctx->block_vars;
15115 if (BLOCK_VARS (block))
15116 TREE_USED (block) = 1;
15120 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
15121 regimplified. If DATA is non-NULL, lower_omp_1 is outside
15122 of OMP context, but with task_shared_vars set. */
15124 static tree
15125 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
15126 void *data)
15128 tree t = *tp;
15130 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
15131 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
15132 return t;
15134 if (task_shared_vars
15135 && DECL_P (t)
15136 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
15137 return t;
15139 /* If a global variable has been privatized, TREE_CONSTANT on
15140 ADDR_EXPR might be wrong. */
15141 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
15142 recompute_tree_invariant_for_addr_expr (t);
15144 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
15145 return NULL_TREE;
15148 /* Data to be communicated between lower_omp_regimplify_operands and
15149 lower_omp_regimplify_operands_p. */
15151 struct lower_omp_regimplify_operands_data
15153 omp_context *ctx;
15154 vec<tree> *decls;
15157 /* Helper function for lower_omp_regimplify_operands. Find
15158 omp_member_access_dummy_var vars and adjust temporarily their
15159 DECL_VALUE_EXPRs if needed. */
15161 static tree
15162 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
15163 void *data)
15165 tree t = omp_member_access_dummy_var (*tp);
15166 if (t)
15168 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
15169 lower_omp_regimplify_operands_data *ldata
15170 = (lower_omp_regimplify_operands_data *) wi->info;
15171 tree o = maybe_lookup_decl (t, ldata->ctx);
15172 if (o != t)
15174 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
15175 ldata->decls->safe_push (*tp);
15176 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
15177 SET_DECL_VALUE_EXPR (*tp, v);
15180 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
15181 return NULL_TREE;
15184 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
15185 of omp_member_access_dummy_var vars during regimplification. */
15187 static void
15188 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
15189 gimple_stmt_iterator *gsi_p)
15191 auto_vec<tree, 10> decls;
15192 if (ctx)
15194 struct walk_stmt_info wi;
15195 memset (&wi, '\0', sizeof (wi));
15196 struct lower_omp_regimplify_operands_data data;
15197 data.ctx = ctx;
15198 data.decls = &decls;
15199 wi.info = &data;
15200 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
15202 gimple_regimplify_operands (stmt, gsi_p);
15203 while (!decls.is_empty ())
15205 tree t = decls.pop ();
15206 tree v = decls.pop ();
15207 SET_DECL_VALUE_EXPR (t, v);
15211 static void
15212 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15214 gimple *stmt = gsi_stmt (*gsi_p);
15215 struct walk_stmt_info wi;
15216 gcall *call_stmt;
15218 if (gimple_has_location (stmt))
15219 input_location = gimple_location (stmt);
15221 if (task_shared_vars)
15222 memset (&wi, '\0', sizeof (wi));
15224 /* If we have issued syntax errors, avoid doing any heavy lifting.
15225 Just replace the OMP directives with a NOP to avoid
15226 confusing RTL expansion. */
15227 if (seen_error () && is_gimple_omp (stmt))
15229 gsi_replace (gsi_p, gimple_build_nop (), true);
15230 return;
15233 switch (gimple_code (stmt))
15235 case GIMPLE_COND:
15237 gcond *cond_stmt = as_a <gcond *> (stmt);
15238 if ((ctx || task_shared_vars)
15239 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
15240 lower_omp_regimplify_p,
15241 ctx ? NULL : &wi, NULL)
15242 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
15243 lower_omp_regimplify_p,
15244 ctx ? NULL : &wi, NULL)))
15245 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
15247 break;
15248 case GIMPLE_CATCH:
15249 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
15250 break;
15251 case GIMPLE_EH_FILTER:
15252 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
15253 break;
15254 case GIMPLE_TRY:
15255 lower_omp (gimple_try_eval_ptr (stmt), ctx);
15256 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
15257 break;
15258 case GIMPLE_TRANSACTION:
15259 lower_omp (gimple_transaction_body_ptr (
15260 as_a <gtransaction *> (stmt)),
15261 ctx);
15262 break;
15263 case GIMPLE_BIND:
15264 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
15265 break;
15266 case GIMPLE_OMP_PARALLEL:
15267 case GIMPLE_OMP_TASK:
15268 ctx = maybe_lookup_ctx (stmt);
15269 gcc_assert (ctx);
15270 if (ctx->cancellable)
15271 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
15272 lower_omp_taskreg (gsi_p, ctx);
15273 break;
15274 case GIMPLE_OMP_FOR:
15275 ctx = maybe_lookup_ctx (stmt);
15276 gcc_assert (ctx);
15277 if (ctx->cancellable)
15278 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
15279 lower_omp_for (gsi_p, ctx);
15280 break;
15281 case GIMPLE_OMP_SECTIONS:
15282 ctx = maybe_lookup_ctx (stmt);
15283 gcc_assert (ctx);
15284 if (ctx->cancellable)
15285 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
15286 lower_omp_sections (gsi_p, ctx);
15287 break;
15288 case GIMPLE_OMP_SINGLE:
15289 ctx = maybe_lookup_ctx (stmt);
15290 gcc_assert (ctx);
15291 lower_omp_single (gsi_p, ctx);
15292 break;
15293 case GIMPLE_OMP_MASTER:
15294 ctx = maybe_lookup_ctx (stmt);
15295 gcc_assert (ctx);
15296 lower_omp_master (gsi_p, ctx);
15297 break;
15298 case GIMPLE_OMP_TASKGROUP:
15299 ctx = maybe_lookup_ctx (stmt);
15300 gcc_assert (ctx);
15301 lower_omp_taskgroup (gsi_p, ctx);
15302 break;
15303 case GIMPLE_OMP_ORDERED:
15304 ctx = maybe_lookup_ctx (stmt);
15305 gcc_assert (ctx);
15306 lower_omp_ordered (gsi_p, ctx);
15307 break;
15308 case GIMPLE_OMP_CRITICAL:
15309 ctx = maybe_lookup_ctx (stmt);
15310 gcc_assert (ctx);
15311 lower_omp_critical (gsi_p, ctx);
15312 break;
15313 case GIMPLE_OMP_ATOMIC_LOAD:
15314 if ((ctx || task_shared_vars)
15315 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
15316 as_a <gomp_atomic_load *> (stmt)),
15317 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
15318 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
15319 break;
15320 case GIMPLE_OMP_TARGET:
15321 ctx = maybe_lookup_ctx (stmt);
15322 gcc_assert (ctx);
15323 lower_omp_target (gsi_p, ctx);
15324 break;
15325 case GIMPLE_OMP_TEAMS:
15326 ctx = maybe_lookup_ctx (stmt);
15327 gcc_assert (ctx);
15328 lower_omp_teams (gsi_p, ctx);
15329 break;
15330 case GIMPLE_CALL:
15331 tree fndecl;
15332 call_stmt = as_a <gcall *> (stmt);
15333 fndecl = gimple_call_fndecl (call_stmt);
15334 if (fndecl
15335 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
15336 switch (DECL_FUNCTION_CODE (fndecl))
15338 case BUILT_IN_GOMP_BARRIER:
15339 if (ctx == NULL)
15340 break;
15341 /* FALLTHRU */
15342 case BUILT_IN_GOMP_CANCEL:
15343 case BUILT_IN_GOMP_CANCELLATION_POINT:
15344 omp_context *cctx;
15345 cctx = ctx;
15346 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
15347 cctx = cctx->outer;
15348 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
15349 if (!cctx->cancellable)
15351 if (DECL_FUNCTION_CODE (fndecl)
15352 == BUILT_IN_GOMP_CANCELLATION_POINT)
15354 stmt = gimple_build_nop ();
15355 gsi_replace (gsi_p, stmt, false);
15357 break;
15359 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
15361 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
15362 gimple_call_set_fndecl (call_stmt, fndecl);
15363 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
15365 tree lhs;
15366 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
15367 gimple_call_set_lhs (call_stmt, lhs);
15368 tree fallthru_label;
15369 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
15370 gimple *g;
15371 g = gimple_build_label (fallthru_label);
15372 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15373 g = gimple_build_cond (NE_EXPR, lhs,
15374 fold_convert (TREE_TYPE (lhs),
15375 boolean_false_node),
15376 cctx->cancel_label, fallthru_label);
15377 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
15378 break;
15379 default:
15380 break;
15382 /* FALLTHRU */
15383 default:
15384 if ((ctx || task_shared_vars)
15385 && walk_gimple_op (stmt, lower_omp_regimplify_p,
15386 ctx ? NULL : &wi))
15388 /* Just remove clobbers, this should happen only if we have
15389 "privatized" local addressable variables in SIMD regions,
15390 the clobber isn't needed in that case and gimplifying address
15391 of the ARRAY_REF into a pointer and creating MEM_REF based
15392 clobber would create worse code than we get with the clobber
15393 dropped. */
15394 if (gimple_clobber_p (stmt))
15396 gsi_replace (gsi_p, gimple_build_nop (), true);
15397 break;
15399 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
15401 break;
15405 static void
15406 lower_omp (gimple_seq *body, omp_context *ctx)
15408 location_t saved_location = input_location;
15409 gimple_stmt_iterator gsi;
15410 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
15411 lower_omp_1 (&gsi, ctx);
15412 /* During gimplification, we haven't folded statments inside offloading
15413 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
15414 if (target_nesting_level || taskreg_nesting_level)
15415 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
15416 fold_stmt (&gsi);
15417 input_location = saved_location;
15420 /* Main entry point. */
15422 static unsigned int
15423 execute_lower_omp (void)
15425 gimple_seq body;
15426 int i;
15427 omp_context *ctx;
15429 /* This pass always runs, to provide PROP_gimple_lomp.
15430 But often, there is nothing to do. */
15431 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
15432 && flag_openmp_simd == 0)
15433 return 0;
15435 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
15436 delete_omp_context);
15438 body = gimple_body (current_function_decl);
15439 scan_omp (&body, NULL);
15440 gcc_assert (taskreg_nesting_level == 0);
15441 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
15442 finish_taskreg_scan (ctx);
15443 taskreg_contexts.release ();
15445 if (all_contexts->root)
15447 if (task_shared_vars)
15448 push_gimplify_context ();
15449 lower_omp (&body, NULL);
15450 if (task_shared_vars)
15451 pop_gimplify_context (NULL);
15454 if (all_contexts)
15456 splay_tree_delete (all_contexts);
15457 all_contexts = NULL;
15459 BITMAP_FREE (task_shared_vars);
15460 return 0;
15463 namespace {
15465 const pass_data pass_data_lower_omp =
15467 GIMPLE_PASS, /* type */
15468 "omplower", /* name */
15469 OPTGROUP_NONE, /* optinfo_flags */
15470 TV_NONE, /* tv_id */
15471 PROP_gimple_any, /* properties_required */
15472 PROP_gimple_lomp, /* properties_provided */
15473 0, /* properties_destroyed */
15474 0, /* todo_flags_start */
15475 0, /* todo_flags_finish */
15478 class pass_lower_omp : public gimple_opt_pass
15480 public:
15481 pass_lower_omp (gcc::context *ctxt)
15482 : gimple_opt_pass (pass_data_lower_omp, ctxt)
15485 /* opt_pass methods: */
15486 virtual unsigned int execute (function *) { return execute_lower_omp (); }
15488 }; // class pass_lower_omp
15490 } // anon namespace
15492 gimple_opt_pass *
15493 make_pass_lower_omp (gcc::context *ctxt)
15495 return new pass_lower_omp (ctxt);
15498 /* The following is a utility to diagnose structured block violations.
15499 It is not part of the "omplower" pass, as that's invoked too late. It
15500 should be invoked by the respective front ends after gimplification. */
15502 static splay_tree all_labels;
15504 /* Check for mismatched contexts and generate an error if needed. Return
15505 true if an error is detected. */
15507 static bool
15508 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
15509 gimple *branch_ctx, gimple *label_ctx)
15511 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
15512 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
15514 if (label_ctx == branch_ctx)
15515 return false;
15517 const char* kind = NULL;
15519 if (flag_cilkplus)
15521 if ((branch_ctx
15522 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
15523 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
15524 || (label_ctx
15525 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
15526 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
15527 kind = "Cilk Plus";
15529 if (flag_openacc)
15531 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
15532 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
15534 gcc_checking_assert (kind == NULL);
15535 kind = "OpenACC";
15538 if (kind == NULL)
15540 gcc_checking_assert (flag_openmp);
15541 kind = "OpenMP";
15545 Previously we kept track of the label's entire context in diagnose_sb_[12]
15546 so we could traverse it and issue a correct "exit" or "enter" error
15547 message upon a structured block violation.
15549 We built the context by building a list with tree_cons'ing, but there is
15550 no easy counterpart in gimple tuples. It seems like far too much work
15551 for issuing exit/enter error messages. If someone really misses the
15552 distinct error message... patches welcome.
15555 #if 0
15556 /* Try to avoid confusing the user by producing and error message
15557 with correct "exit" or "enter" verbiage. We prefer "exit"
15558 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
15559 if (branch_ctx == NULL)
15560 exit_p = false;
15561 else
15563 while (label_ctx)
15565 if (TREE_VALUE (label_ctx) == branch_ctx)
15567 exit_p = false;
15568 break;
15570 label_ctx = TREE_CHAIN (label_ctx);
15574 if (exit_p)
15575 error ("invalid exit from %s structured block", kind);
15576 else
15577 error ("invalid entry to %s structured block", kind);
15578 #endif
15580 /* If it's obvious we have an invalid entry, be specific about the error. */
15581 if (branch_ctx == NULL)
15582 error ("invalid entry to %s structured block", kind);
15583 else
15585 /* Otherwise, be vague and lazy, but efficient. */
15586 error ("invalid branch to/from %s structured block", kind);
15589 gsi_replace (gsi_p, gimple_build_nop (), false);
15590 return true;
15593 /* Pass 1: Create a minimal tree of structured blocks, and record
15594 where each label is found. */
15596 static tree
15597 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
15598 struct walk_stmt_info *wi)
15600 gimple *context = (gimple *) wi->info;
15601 gimple *inner_context;
15602 gimple *stmt = gsi_stmt (*gsi_p);
15604 *handled_ops_p = true;
15606 switch (gimple_code (stmt))
15608 WALK_SUBSTMTS;
15610 case GIMPLE_OMP_PARALLEL:
15611 case GIMPLE_OMP_TASK:
15612 case GIMPLE_OMP_SECTIONS:
15613 case GIMPLE_OMP_SINGLE:
15614 case GIMPLE_OMP_SECTION:
15615 case GIMPLE_OMP_MASTER:
15616 case GIMPLE_OMP_ORDERED:
15617 case GIMPLE_OMP_CRITICAL:
15618 case GIMPLE_OMP_TARGET:
15619 case GIMPLE_OMP_TEAMS:
15620 case GIMPLE_OMP_TASKGROUP:
15621 /* The minimal context here is just the current OMP construct. */
15622 inner_context = stmt;
15623 wi->info = inner_context;
15624 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
15625 wi->info = context;
15626 break;
15628 case GIMPLE_OMP_FOR:
15629 inner_context = stmt;
15630 wi->info = inner_context;
15631 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
15632 walk them. */
15633 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
15634 diagnose_sb_1, NULL, wi);
15635 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
15636 wi->info = context;
15637 break;
15639 case GIMPLE_LABEL:
15640 splay_tree_insert (all_labels,
15641 (splay_tree_key) gimple_label_label (
15642 as_a <glabel *> (stmt)),
15643 (splay_tree_value) context);
15644 break;
15646 default:
15647 break;
15650 return NULL_TREE;
15653 /* Pass 2: Check each branch and see if its context differs from that of
15654 the destination label's context. */
15656 static tree
15657 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
15658 struct walk_stmt_info *wi)
15660 gimple *context = (gimple *) wi->info;
15661 splay_tree_node n;
15662 gimple *stmt = gsi_stmt (*gsi_p);
15664 *handled_ops_p = true;
15666 switch (gimple_code (stmt))
15668 WALK_SUBSTMTS;
15670 case GIMPLE_OMP_PARALLEL:
15671 case GIMPLE_OMP_TASK:
15672 case GIMPLE_OMP_SECTIONS:
15673 case GIMPLE_OMP_SINGLE:
15674 case GIMPLE_OMP_SECTION:
15675 case GIMPLE_OMP_MASTER:
15676 case GIMPLE_OMP_ORDERED:
15677 case GIMPLE_OMP_CRITICAL:
15678 case GIMPLE_OMP_TARGET:
15679 case GIMPLE_OMP_TEAMS:
15680 case GIMPLE_OMP_TASKGROUP:
15681 wi->info = stmt;
15682 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
15683 wi->info = context;
15684 break;
15686 case GIMPLE_OMP_FOR:
15687 wi->info = stmt;
15688 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
15689 walk them. */
15690 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
15691 diagnose_sb_2, NULL, wi);
15692 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
15693 wi->info = context;
15694 break;
15696 case GIMPLE_COND:
15698 gcond *cond_stmt = as_a <gcond *> (stmt);
15699 tree lab = gimple_cond_true_label (cond_stmt);
15700 if (lab)
15702 n = splay_tree_lookup (all_labels,
15703 (splay_tree_key) lab);
15704 diagnose_sb_0 (gsi_p, context,
15705 n ? (gimple *) n->value : NULL);
15707 lab = gimple_cond_false_label (cond_stmt);
15708 if (lab)
15710 n = splay_tree_lookup (all_labels,
15711 (splay_tree_key) lab);
15712 diagnose_sb_0 (gsi_p, context,
15713 n ? (gimple *) n->value : NULL);
15716 break;
15718 case GIMPLE_GOTO:
15720 tree lab = gimple_goto_dest (stmt);
15721 if (TREE_CODE (lab) != LABEL_DECL)
15722 break;
15724 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
15725 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
15727 break;
15729 case GIMPLE_SWITCH:
15731 gswitch *switch_stmt = as_a <gswitch *> (stmt);
15732 unsigned int i;
15733 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
15735 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
15736 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
15737 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
15738 break;
15741 break;
15743 case GIMPLE_RETURN:
15744 diagnose_sb_0 (gsi_p, context, NULL);
15745 break;
15747 default:
15748 break;
15751 return NULL_TREE;
15754 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
15755 GIMPLE_* codes. */
15756 bool
15757 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
15758 int *region_idx)
15760 gimple *last = last_stmt (bb);
15761 enum gimple_code code = gimple_code (last);
15762 struct omp_region *cur_region = *region;
15763 bool fallthru = false;
15765 switch (code)
15767 case GIMPLE_OMP_PARALLEL:
15768 case GIMPLE_OMP_TASK:
15769 case GIMPLE_OMP_FOR:
15770 case GIMPLE_OMP_SINGLE:
15771 case GIMPLE_OMP_TEAMS:
15772 case GIMPLE_OMP_MASTER:
15773 case GIMPLE_OMP_TASKGROUP:
15774 case GIMPLE_OMP_CRITICAL:
15775 case GIMPLE_OMP_SECTION:
15776 cur_region = new_omp_region (bb, code, cur_region);
15777 fallthru = true;
15778 break;
15780 case GIMPLE_OMP_ORDERED:
15781 cur_region = new_omp_region (bb, code, cur_region);
15782 fallthru = true;
15783 if (find_omp_clause (gimple_omp_ordered_clauses
15784 (as_a <gomp_ordered *> (last)),
15785 OMP_CLAUSE_DEPEND))
15786 cur_region = cur_region->outer;
15787 break;
15789 case GIMPLE_OMP_TARGET:
15790 cur_region = new_omp_region (bb, code, cur_region);
15791 fallthru = true;
15792 switch (gimple_omp_target_kind (last))
15794 case GF_OMP_TARGET_KIND_REGION:
15795 case GF_OMP_TARGET_KIND_DATA:
15796 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15797 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15798 case GF_OMP_TARGET_KIND_OACC_DATA:
15799 break;
15800 case GF_OMP_TARGET_KIND_UPDATE:
15801 case GF_OMP_TARGET_KIND_ENTER_DATA:
15802 case GF_OMP_TARGET_KIND_EXIT_DATA:
15803 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15804 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
15805 cur_region = cur_region->outer;
15806 break;
15807 default:
15808 gcc_unreachable ();
15810 break;
15812 case GIMPLE_OMP_SECTIONS:
15813 cur_region = new_omp_region (bb, code, cur_region);
15814 fallthru = true;
15815 break;
15817 case GIMPLE_OMP_SECTIONS_SWITCH:
15818 fallthru = false;
15819 break;
15821 case GIMPLE_OMP_ATOMIC_LOAD:
15822 case GIMPLE_OMP_ATOMIC_STORE:
15823 fallthru = true;
15824 break;
15826 case GIMPLE_OMP_RETURN:
15827 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
15828 somewhere other than the next block. This will be
15829 created later. */
15830 cur_region->exit = bb;
15831 if (cur_region->type == GIMPLE_OMP_TASK)
15832 /* Add an edge corresponding to not scheduling the task
15833 immediately. */
15834 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
15835 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
15836 cur_region = cur_region->outer;
15837 break;
15839 case GIMPLE_OMP_CONTINUE:
15840 cur_region->cont = bb;
15841 switch (cur_region->type)
15843 case GIMPLE_OMP_FOR:
15844 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
15845 succs edges as abnormal to prevent splitting
15846 them. */
15847 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
15848 /* Make the loopback edge. */
15849 make_edge (bb, single_succ (cur_region->entry),
15850 EDGE_ABNORMAL);
15852 /* Create an edge from GIMPLE_OMP_FOR to exit, which
15853 corresponds to the case that the body of the loop
15854 is not executed at all. */
15855 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
15856 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
15857 fallthru = false;
15858 break;
15860 case GIMPLE_OMP_SECTIONS:
15861 /* Wire up the edges into and out of the nested sections. */
15863 basic_block switch_bb = single_succ (cur_region->entry);
15865 struct omp_region *i;
15866 for (i = cur_region->inner; i ; i = i->next)
15868 gcc_assert (i->type == GIMPLE_OMP_SECTION);
15869 make_edge (switch_bb, i->entry, 0);
15870 make_edge (i->exit, bb, EDGE_FALLTHRU);
15873 /* Make the loopback edge to the block with
15874 GIMPLE_OMP_SECTIONS_SWITCH. */
15875 make_edge (bb, switch_bb, 0);
15877 /* Make the edge from the switch to exit. */
15878 make_edge (switch_bb, bb->next_bb, 0);
15879 fallthru = false;
15881 break;
15883 case GIMPLE_OMP_TASK:
15884 fallthru = true;
15885 break;
15887 default:
15888 gcc_unreachable ();
15890 break;
15892 default:
15893 gcc_unreachable ();
15896 if (*region != cur_region)
15898 *region = cur_region;
15899 if (cur_region)
15900 *region_idx = cur_region->entry->index;
15901 else
15902 *region_idx = 0;
15905 return fallthru;
15908 static unsigned int
15909 diagnose_omp_structured_block_errors (void)
15911 struct walk_stmt_info wi;
15912 gimple_seq body = gimple_body (current_function_decl);
15914 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
15916 memset (&wi, 0, sizeof (wi));
15917 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
15919 memset (&wi, 0, sizeof (wi));
15920 wi.want_locations = true;
15921 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
15923 gimple_set_body (current_function_decl, body);
15925 splay_tree_delete (all_labels);
15926 all_labels = NULL;
15928 return 0;
15931 namespace {
15933 const pass_data pass_data_diagnose_omp_blocks =
15935 GIMPLE_PASS, /* type */
15936 "*diagnose_omp_blocks", /* name */
15937 OPTGROUP_NONE, /* optinfo_flags */
15938 TV_NONE, /* tv_id */
15939 PROP_gimple_any, /* properties_required */
15940 0, /* properties_provided */
15941 0, /* properties_destroyed */
15942 0, /* todo_flags_start */
15943 0, /* todo_flags_finish */
15946 class pass_diagnose_omp_blocks : public gimple_opt_pass
15948 public:
15949 pass_diagnose_omp_blocks (gcc::context *ctxt)
15950 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
15953 /* opt_pass methods: */
15954 virtual bool gate (function *)
15956 return flag_cilkplus || flag_openacc || flag_openmp;
15958 virtual unsigned int execute (function *)
15960 return diagnose_omp_structured_block_errors ();
15963 }; // class pass_diagnose_omp_blocks
15965 } // anon namespace
15967 gimple_opt_pass *
15968 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
15970 return new pass_diagnose_omp_blocks (ctxt);
15973 /* SIMD clone supporting code. */
15975 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
15976 of arguments to reserve space for. */
15978 static struct cgraph_simd_clone *
15979 simd_clone_struct_alloc (int nargs)
15981 struct cgraph_simd_clone *clone_info;
15982 size_t len = (sizeof (struct cgraph_simd_clone)
15983 + nargs * sizeof (struct cgraph_simd_clone_arg));
15984 clone_info = (struct cgraph_simd_clone *)
15985 ggc_internal_cleared_alloc (len);
15986 return clone_info;
15989 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
15991 static inline void
15992 simd_clone_struct_copy (struct cgraph_simd_clone *to,
15993 struct cgraph_simd_clone *from)
15995 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
15996 + ((from->nargs - from->inbranch)
15997 * sizeof (struct cgraph_simd_clone_arg))));
16000 /* Return vector of parameter types of function FNDECL. This uses
16001 TYPE_ARG_TYPES if available, otherwise falls back to types of
16002 DECL_ARGUMENTS types. */
16004 vec<tree>
16005 simd_clone_vector_of_formal_parm_types (tree fndecl)
16007 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
16008 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
16009 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
16010 unsigned int i;
16011 tree arg;
16012 FOR_EACH_VEC_ELT (args, i, arg)
16013 args[i] = TREE_TYPE (args[i]);
16014 return args;
16017 /* Given a simd function in NODE, extract the simd specific
16018 information from the OMP clauses passed in CLAUSES, and return
16019 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
16020 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
16021 otherwise set to FALSE. */
16023 static struct cgraph_simd_clone *
16024 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
16025 bool *inbranch_specified)
16027 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
16028 tree t;
16029 int n;
16030 *inbranch_specified = false;
16032 n = args.length ();
16033 if (n > 0 && args.last () == void_type_node)
16034 n--;
16036 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
16037 be cloned have a distinctive artificial label in addition to "omp
16038 declare simd". */
16039 bool cilk_clone
16040 = (flag_cilkplus
16041 && lookup_attribute ("cilk simd function",
16042 DECL_ATTRIBUTES (node->decl)));
16044 /* Allocate one more than needed just in case this is an in-branch
16045 clone which will require a mask argument. */
16046 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
16047 clone_info->nargs = n;
16048 clone_info->cilk_elemental = cilk_clone;
16050 if (!clauses)
16052 args.release ();
16053 return clone_info;
16055 clauses = TREE_VALUE (clauses);
16056 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
16057 return clone_info;
16059 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
16061 switch (OMP_CLAUSE_CODE (t))
16063 case OMP_CLAUSE_INBRANCH:
16064 clone_info->inbranch = 1;
16065 *inbranch_specified = true;
16066 break;
16067 case OMP_CLAUSE_NOTINBRANCH:
16068 clone_info->inbranch = 0;
16069 *inbranch_specified = true;
16070 break;
16071 case OMP_CLAUSE_SIMDLEN:
16072 clone_info->simdlen
16073 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
16074 break;
16075 case OMP_CLAUSE_LINEAR:
16077 tree decl = OMP_CLAUSE_DECL (t);
16078 tree step = OMP_CLAUSE_LINEAR_STEP (t);
16079 int argno = TREE_INT_CST_LOW (decl);
16080 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
16082 clone_info->args[argno].arg_type
16083 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
16084 clone_info->args[argno].linear_step = tree_to_shwi (step);
16085 gcc_assert (clone_info->args[argno].linear_step >= 0
16086 && clone_info->args[argno].linear_step < n);
16088 else
16090 if (POINTER_TYPE_P (args[argno]))
16091 step = fold_convert (ssizetype, step);
16092 if (!tree_fits_shwi_p (step))
16094 warning_at (OMP_CLAUSE_LOCATION (t), 0,
16095 "ignoring large linear step");
16096 args.release ();
16097 return NULL;
16099 else if (integer_zerop (step))
16101 warning_at (OMP_CLAUSE_LOCATION (t), 0,
16102 "ignoring zero linear step");
16103 args.release ();
16104 return NULL;
16106 else
16108 enum cgraph_simd_clone_arg_type arg_type;
16109 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
16110 switch (OMP_CLAUSE_LINEAR_KIND (t))
16112 case OMP_CLAUSE_LINEAR_REF:
16113 arg_type
16114 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
16115 break;
16116 case OMP_CLAUSE_LINEAR_UVAL:
16117 arg_type
16118 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
16119 break;
16120 case OMP_CLAUSE_LINEAR_VAL:
16121 case OMP_CLAUSE_LINEAR_DEFAULT:
16122 arg_type
16123 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
16124 break;
16125 default:
16126 gcc_unreachable ();
16128 else
16129 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
16130 clone_info->args[argno].arg_type = arg_type;
16131 clone_info->args[argno].linear_step = tree_to_shwi (step);
16134 break;
16136 case OMP_CLAUSE_UNIFORM:
16138 tree decl = OMP_CLAUSE_DECL (t);
16139 int argno = tree_to_uhwi (decl);
16140 clone_info->args[argno].arg_type
16141 = SIMD_CLONE_ARG_TYPE_UNIFORM;
16142 break;
16144 case OMP_CLAUSE_ALIGNED:
16146 tree decl = OMP_CLAUSE_DECL (t);
16147 int argno = tree_to_uhwi (decl);
16148 clone_info->args[argno].alignment
16149 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
16150 break;
16152 default:
16153 break;
16156 args.release ();
16157 return clone_info;
16160 /* Given a SIMD clone in NODE, calculate the characteristic data
16161 type and return the coresponding type. The characteristic data
16162 type is computed as described in the Intel Vector ABI. */
16164 static tree
16165 simd_clone_compute_base_data_type (struct cgraph_node *node,
16166 struct cgraph_simd_clone *clone_info)
16168 tree type = integer_type_node;
16169 tree fndecl = node->decl;
16171 /* a) For non-void function, the characteristic data type is the
16172 return type. */
16173 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
16174 type = TREE_TYPE (TREE_TYPE (fndecl));
16176 /* b) If the function has any non-uniform, non-linear parameters,
16177 then the characteristic data type is the type of the first
16178 such parameter. */
16179 else
16181 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
16182 for (unsigned int i = 0; i < clone_info->nargs; ++i)
16183 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
16185 type = map[i];
16186 break;
16188 map.release ();
16191 /* c) If the characteristic data type determined by a) or b) above
16192 is struct, union, or class type which is pass-by-value (except
16193 for the type that maps to the built-in complex data type), the
16194 characteristic data type is int. */
16195 if (RECORD_OR_UNION_TYPE_P (type)
16196 && !aggregate_value_p (type, NULL)
16197 && TREE_CODE (type) != COMPLEX_TYPE)
16198 return integer_type_node;
16200 /* d) If none of the above three classes is applicable, the
16201 characteristic data type is int. */
16203 return type;
16205 /* e) For Intel Xeon Phi native and offload compilation, if the
16206 resulting characteristic data type is 8-bit or 16-bit integer
16207 data type, the characteristic data type is int. */
16208 /* Well, we don't handle Xeon Phi yet. */
16211 static tree
16212 simd_clone_mangle (struct cgraph_node *node,
16213 struct cgraph_simd_clone *clone_info)
16215 char vecsize_mangle = clone_info->vecsize_mangle;
16216 char mask = clone_info->inbranch ? 'M' : 'N';
16217 unsigned int simdlen = clone_info->simdlen;
16218 unsigned int n;
16219 pretty_printer pp;
16221 gcc_assert (vecsize_mangle && simdlen);
16223 pp_string (&pp, "_ZGV");
16224 pp_character (&pp, vecsize_mangle);
16225 pp_character (&pp, mask);
16226 pp_decimal_int (&pp, simdlen);
16228 for (n = 0; n < clone_info->nargs; ++n)
16230 struct cgraph_simd_clone_arg arg = clone_info->args[n];
16232 switch (arg.arg_type)
16234 case SIMD_CLONE_ARG_TYPE_UNIFORM:
16235 pp_character (&pp, 'u');
16236 break;
16237 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
16238 pp_character (&pp, 'l');
16239 goto mangle_linear;
16240 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
16241 pp_character (&pp, 'R');
16242 goto mangle_linear;
16243 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
16244 pp_character (&pp, 'L');
16245 goto mangle_linear;
16246 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
16247 pp_character (&pp, 'U');
16248 goto mangle_linear;
16249 mangle_linear:
16250 gcc_assert (arg.linear_step != 0);
16251 if (arg.linear_step > 1)
16252 pp_unsigned_wide_integer (&pp, arg.linear_step);
16253 else if (arg.linear_step < 0)
16255 pp_character (&pp, 'n');
16256 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
16257 arg.linear_step));
16259 break;
16260 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
16261 pp_character (&pp, 's');
16262 pp_unsigned_wide_integer (&pp, arg.linear_step);
16263 break;
16264 default:
16265 pp_character (&pp, 'v');
16267 if (arg.alignment)
16269 pp_character (&pp, 'a');
16270 pp_decimal_int (&pp, arg.alignment);
16274 pp_underscore (&pp);
16275 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
16276 if (*str == '*')
16277 ++str;
16278 pp_string (&pp, str);
16279 str = pp_formatted_text (&pp);
16281 /* If there already is a SIMD clone with the same mangled name, don't
16282 add another one. This can happen e.g. for
16283 #pragma omp declare simd
16284 #pragma omp declare simd simdlen(8)
16285 int foo (int, int);
16286 if the simdlen is assumed to be 8 for the first one, etc. */
16287 for (struct cgraph_node *clone = node->simd_clones; clone;
16288 clone = clone->simdclone->next_clone)
16289 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
16290 str) == 0)
16291 return NULL_TREE;
16293 return get_identifier (str);
16296 /* Create a simd clone of OLD_NODE and return it. */
16298 static struct cgraph_node *
16299 simd_clone_create (struct cgraph_node *old_node)
16301 struct cgraph_node *new_node;
16302 if (old_node->definition)
16304 if (!old_node->has_gimple_body_p ())
16305 return NULL;
16306 old_node->get_body ();
16307 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
16308 false, NULL, NULL,
16309 "simdclone");
16311 else
16313 tree old_decl = old_node->decl;
16314 tree new_decl = copy_node (old_node->decl);
16315 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
16316 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
16317 SET_DECL_RTL (new_decl, NULL);
16318 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
16319 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
16320 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
16321 symtab->call_cgraph_insertion_hooks (new_node);
16323 if (new_node == NULL)
16324 return new_node;
16326 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
16328 /* The function cgraph_function_versioning () will force the new
16329 symbol local. Undo this, and inherit external visability from
16330 the old node. */
16331 new_node->local.local = old_node->local.local;
16332 new_node->externally_visible = old_node->externally_visible;
16334 return new_node;
16337 /* Adjust the return type of the given function to its appropriate
16338 vector counterpart. Returns a simd array to be used throughout the
16339 function as a return value. */
16341 static tree
16342 simd_clone_adjust_return_type (struct cgraph_node *node)
16344 tree fndecl = node->decl;
16345 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
16346 unsigned int veclen;
16347 tree t;
16349 /* Adjust the function return type. */
16350 if (orig_rettype == void_type_node)
16351 return NULL_TREE;
16352 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
16353 t = TREE_TYPE (TREE_TYPE (fndecl));
16354 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
16355 veclen = node->simdclone->vecsize_int;
16356 else
16357 veclen = node->simdclone->vecsize_float;
16358 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
16359 if (veclen > node->simdclone->simdlen)
16360 veclen = node->simdclone->simdlen;
16361 if (POINTER_TYPE_P (t))
16362 t = pointer_sized_int_node;
16363 if (veclen == node->simdclone->simdlen)
16364 t = build_vector_type (t, node->simdclone->simdlen);
16365 else
16367 t = build_vector_type (t, veclen);
16368 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
16370 TREE_TYPE (TREE_TYPE (fndecl)) = t;
16371 if (!node->definition)
16372 return NULL_TREE;
16374 t = DECL_RESULT (fndecl);
16375 /* Adjust the DECL_RESULT. */
16376 gcc_assert (TREE_TYPE (t) != void_type_node);
16377 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
16378 relayout_decl (t);
16380 tree atype = build_array_type_nelts (orig_rettype,
16381 node->simdclone->simdlen);
16382 if (veclen != node->simdclone->simdlen)
16383 return build1 (VIEW_CONVERT_EXPR, atype, t);
16385 /* Set up a SIMD array to use as the return value. */
16386 tree retval = create_tmp_var_raw (atype, "retval");
16387 gimple_add_tmp_var (retval);
16388 return retval;
16391 /* Each vector argument has a corresponding array to be used locally
16392 as part of the eventual loop. Create such temporary array and
16393 return it.
16395 PREFIX is the prefix to be used for the temporary.
16397 TYPE is the inner element type.
16399 SIMDLEN is the number of elements. */
16401 static tree
16402 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
16404 tree atype = build_array_type_nelts (type, simdlen);
16405 tree avar = create_tmp_var_raw (atype, prefix);
16406 gimple_add_tmp_var (avar);
16407 return avar;
16410 /* Modify the function argument types to their corresponding vector
16411 counterparts if appropriate. Also, create one array for each simd
16412 argument to be used locally when using the function arguments as
16413 part of the loop.
16415 NODE is the function whose arguments are to be adjusted.
16417 Returns an adjustment vector that will be filled describing how the
16418 argument types will be adjusted. */
16420 static ipa_parm_adjustment_vec
16421 simd_clone_adjust_argument_types (struct cgraph_node *node)
16423 vec<tree> args;
16424 ipa_parm_adjustment_vec adjustments;
16426 if (node->definition)
16427 args = ipa_get_vector_of_formal_parms (node->decl);
16428 else
16429 args = simd_clone_vector_of_formal_parm_types (node->decl);
16430 adjustments.create (args.length ());
16431 unsigned i, j, veclen;
16432 struct ipa_parm_adjustment adj;
16433 for (i = 0; i < node->simdclone->nargs; ++i)
16435 memset (&adj, 0, sizeof (adj));
16436 tree parm = args[i];
16437 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
16438 adj.base_index = i;
16439 adj.base = parm;
16441 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
16442 node->simdclone->args[i].orig_type = parm_type;
16444 switch (node->simdclone->args[i].arg_type)
16446 default:
16447 /* No adjustment necessary for scalar arguments. */
16448 adj.op = IPA_PARM_OP_COPY;
16449 break;
16450 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
16451 if (node->definition)
16452 node->simdclone->args[i].simd_array
16453 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
16454 TREE_TYPE (parm_type),
16455 node->simdclone->simdlen);
16456 adj.op = IPA_PARM_OP_COPY;
16457 break;
16458 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
16459 case SIMD_CLONE_ARG_TYPE_VECTOR:
16460 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
16461 veclen = node->simdclone->vecsize_int;
16462 else
16463 veclen = node->simdclone->vecsize_float;
16464 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
16465 if (veclen > node->simdclone->simdlen)
16466 veclen = node->simdclone->simdlen;
16467 adj.arg_prefix = "simd";
16468 if (POINTER_TYPE_P (parm_type))
16469 adj.type = build_vector_type (pointer_sized_int_node, veclen);
16470 else
16471 adj.type = build_vector_type (parm_type, veclen);
16472 node->simdclone->args[i].vector_type = adj.type;
16473 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
16475 adjustments.safe_push (adj);
16476 if (j == veclen)
16478 memset (&adj, 0, sizeof (adj));
16479 adj.op = IPA_PARM_OP_NEW;
16480 adj.arg_prefix = "simd";
16481 adj.base_index = i;
16482 adj.type = node->simdclone->args[i].vector_type;
16486 if (node->definition)
16487 node->simdclone->args[i].simd_array
16488 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
16489 parm_type, node->simdclone->simdlen);
16491 adjustments.safe_push (adj);
16494 if (node->simdclone->inbranch)
16496 tree base_type
16497 = simd_clone_compute_base_data_type (node->simdclone->origin,
16498 node->simdclone);
16500 memset (&adj, 0, sizeof (adj));
16501 adj.op = IPA_PARM_OP_NEW;
16502 adj.arg_prefix = "mask";
16504 adj.base_index = i;
16505 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
16506 veclen = node->simdclone->vecsize_int;
16507 else
16508 veclen = node->simdclone->vecsize_float;
16509 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
16510 if (veclen > node->simdclone->simdlen)
16511 veclen = node->simdclone->simdlen;
16512 if (POINTER_TYPE_P (base_type))
16513 adj.type = build_vector_type (pointer_sized_int_node, veclen);
16514 else
16515 adj.type = build_vector_type (base_type, veclen);
16516 adjustments.safe_push (adj);
16518 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
16519 adjustments.safe_push (adj);
16521 /* We have previously allocated one extra entry for the mask. Use
16522 it and fill it. */
16523 struct cgraph_simd_clone *sc = node->simdclone;
16524 sc->nargs++;
16525 if (node->definition)
16527 sc->args[i].orig_arg
16528 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
16529 sc->args[i].simd_array
16530 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
16532 sc->args[i].orig_type = base_type;
16533 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
16536 if (node->definition)
16537 ipa_modify_formal_parameters (node->decl, adjustments);
16538 else
16540 tree new_arg_types = NULL_TREE, new_reversed;
16541 bool last_parm_void = false;
16542 if (args.length () > 0 && args.last () == void_type_node)
16543 last_parm_void = true;
16545 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
16546 j = adjustments.length ();
16547 for (i = 0; i < j; i++)
16549 struct ipa_parm_adjustment *adj = &adjustments[i];
16550 tree ptype;
16551 if (adj->op == IPA_PARM_OP_COPY)
16552 ptype = args[adj->base_index];
16553 else
16554 ptype = adj->type;
16555 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
16557 new_reversed = nreverse (new_arg_types);
16558 if (last_parm_void)
16560 if (new_reversed)
16561 TREE_CHAIN (new_arg_types) = void_list_node;
16562 else
16563 new_reversed = void_list_node;
16566 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
16567 TYPE_ARG_TYPES (new_type) = new_reversed;
16568 TREE_TYPE (node->decl) = new_type;
16570 adjustments.release ();
16572 args.release ();
16573 return adjustments;
16576 /* Initialize and copy the function arguments in NODE to their
16577 corresponding local simd arrays. Returns a fresh gimple_seq with
16578 the instruction sequence generated. */
16580 static gimple_seq
16581 simd_clone_init_simd_arrays (struct cgraph_node *node,
16582 ipa_parm_adjustment_vec adjustments)
16584 gimple_seq seq = NULL;
16585 unsigned i = 0, j = 0, k;
16587 for (tree arg = DECL_ARGUMENTS (node->decl);
16588 arg;
16589 arg = DECL_CHAIN (arg), i++, j++)
16591 if (adjustments[j].op == IPA_PARM_OP_COPY
16592 || POINTER_TYPE_P (TREE_TYPE (arg)))
16593 continue;
16595 node->simdclone->args[i].vector_arg = arg;
16597 tree array = node->simdclone->args[i].simd_array;
16598 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
16600 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
16601 tree ptr = build_fold_addr_expr (array);
16602 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
16603 build_int_cst (ptype, 0));
16604 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
16605 gimplify_and_add (t, &seq);
16607 else
16609 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
16610 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
16611 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
16613 tree ptr = build_fold_addr_expr (array);
16614 int elemsize;
16615 if (k)
16617 arg = DECL_CHAIN (arg);
16618 j++;
16620 elemsize
16621 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
16622 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
16623 build_int_cst (ptype, k * elemsize));
16624 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
16625 gimplify_and_add (t, &seq);
16629 return seq;
16632 /* Callback info for ipa_simd_modify_stmt_ops below. */
16634 struct modify_stmt_info {
16635 ipa_parm_adjustment_vec adjustments;
16636 gimple *stmt;
16637 /* True if the parent statement was modified by
16638 ipa_simd_modify_stmt_ops. */
16639 bool modified;
16642 /* Callback for walk_gimple_op.
16644 Adjust operands from a given statement as specified in the
16645 adjustments vector in the callback data. */
16647 static tree
16648 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
16650 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16651 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
16652 tree *orig_tp = tp;
16653 if (TREE_CODE (*tp) == ADDR_EXPR)
16654 tp = &TREE_OPERAND (*tp, 0);
16655 struct ipa_parm_adjustment *cand = NULL;
16656 if (TREE_CODE (*tp) == PARM_DECL)
16657 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
16658 else
16660 if (TYPE_P (*tp))
16661 *walk_subtrees = 0;
16664 tree repl = NULL_TREE;
16665 if (cand)
16666 repl = unshare_expr (cand->new_decl);
16667 else
16669 if (tp != orig_tp)
16671 *walk_subtrees = 0;
16672 bool modified = info->modified;
16673 info->modified = false;
16674 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
16675 if (!info->modified)
16677 info->modified = modified;
16678 return NULL_TREE;
16680 info->modified = modified;
16681 repl = *tp;
16683 else
16684 return NULL_TREE;
16687 if (tp != orig_tp)
16689 repl = build_fold_addr_expr (repl);
16690 gimple *stmt;
16691 if (is_gimple_debug (info->stmt))
16693 tree vexpr = make_node (DEBUG_EXPR_DECL);
16694 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
16695 DECL_ARTIFICIAL (vexpr) = 1;
16696 TREE_TYPE (vexpr) = TREE_TYPE (repl);
16697 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
16698 repl = vexpr;
16700 else
16702 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
16703 repl = gimple_assign_lhs (stmt);
16705 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
16706 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
16707 *orig_tp = repl;
16709 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
16711 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
16712 *tp = vce;
16714 else
16715 *tp = repl;
16717 info->modified = true;
16718 return NULL_TREE;
16721 /* Traverse the function body and perform all modifications as
16722 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
16723 modified such that the replacement/reduction value will now be an
16724 offset into the corresponding simd_array.
16726 This function will replace all function argument uses with their
16727 corresponding simd array elements, and ajust the return values
16728 accordingly. */
16730 static void
16731 ipa_simd_modify_function_body (struct cgraph_node *node,
16732 ipa_parm_adjustment_vec adjustments,
16733 tree retval_array, tree iter)
16735 basic_block bb;
16736 unsigned int i, j, l;
16738 /* Re-use the adjustments array, but this time use it to replace
16739 every function argument use to an offset into the corresponding
16740 simd_array. */
16741 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
16743 if (!node->simdclone->args[i].vector_arg)
16744 continue;
16746 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
16747 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
16748 adjustments[j].new_decl
16749 = build4 (ARRAY_REF,
16750 basetype,
16751 node->simdclone->args[i].simd_array,
16752 iter,
16753 NULL_TREE, NULL_TREE);
16754 if (adjustments[j].op == IPA_PARM_OP_NONE
16755 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
16756 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
16759 l = adjustments.length ();
16760 for (i = 1; i < num_ssa_names; i++)
16762 tree name = ssa_name (i);
16763 if (name
16764 && SSA_NAME_VAR (name)
16765 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
16767 for (j = 0; j < l; j++)
16768 if (SSA_NAME_VAR (name) == adjustments[j].base
16769 && adjustments[j].new_decl)
16771 tree base_var;
16772 if (adjustments[j].new_ssa_base == NULL_TREE)
16774 base_var
16775 = copy_var_decl (adjustments[j].base,
16776 DECL_NAME (adjustments[j].base),
16777 TREE_TYPE (adjustments[j].base));
16778 adjustments[j].new_ssa_base = base_var;
16780 else
16781 base_var = adjustments[j].new_ssa_base;
16782 if (SSA_NAME_IS_DEFAULT_DEF (name))
16784 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
16785 gimple_stmt_iterator gsi = gsi_after_labels (bb);
16786 tree new_decl = unshare_expr (adjustments[j].new_decl);
16787 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
16788 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
16789 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
16790 gimple *stmt = gimple_build_assign (name, new_decl);
16791 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
16793 else
16794 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
16799 struct modify_stmt_info info;
16800 info.adjustments = adjustments;
16802 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
16804 gimple_stmt_iterator gsi;
16806 gsi = gsi_start_bb (bb);
16807 while (!gsi_end_p (gsi))
16809 gimple *stmt = gsi_stmt (gsi);
16810 info.stmt = stmt;
16811 struct walk_stmt_info wi;
16813 memset (&wi, 0, sizeof (wi));
16814 info.modified = false;
16815 wi.info = &info;
16816 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
16818 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
16820 tree retval = gimple_return_retval (return_stmt);
16821 if (!retval)
16823 gsi_remove (&gsi, true);
16824 continue;
16827 /* Replace `return foo' with `retval_array[iter] = foo'. */
16828 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
16829 retval_array, iter, NULL, NULL);
16830 stmt = gimple_build_assign (ref, retval);
16831 gsi_replace (&gsi, stmt, true);
16832 info.modified = true;
16835 if (info.modified)
16837 update_stmt (stmt);
16838 if (maybe_clean_eh_stmt (stmt))
16839 gimple_purge_dead_eh_edges (gimple_bb (stmt));
16841 gsi_next (&gsi);
16846 /* Adjust the argument types in NODE to their appropriate vector
16847 counterparts. */
16849 static void
16850 simd_clone_adjust (struct cgraph_node *node)
16852 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
16854 targetm.simd_clone.adjust (node);
16856 tree retval = simd_clone_adjust_return_type (node);
16857 ipa_parm_adjustment_vec adjustments
16858 = simd_clone_adjust_argument_types (node);
16860 push_gimplify_context ();
16862 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
16864 /* Adjust all uses of vector arguments accordingly. Adjust all
16865 return values accordingly. */
16866 tree iter = create_tmp_var (unsigned_type_node, "iter");
16867 tree iter1 = make_ssa_name (iter);
16868 tree iter2 = make_ssa_name (iter);
16869 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
16871 /* Initialize the iteration variable. */
16872 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
16873 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
16874 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
16875 /* Insert the SIMD array and iv initialization at function
16876 entry. */
16877 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
16879 pop_gimplify_context (NULL);
16881 /* Create a new BB right before the original exit BB, to hold the
16882 iteration increment and the condition/branch. */
16883 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
16884 basic_block incr_bb = create_empty_bb (orig_exit);
16885 add_bb_to_loop (incr_bb, body_bb->loop_father);
16886 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
16887 flag. Set it now to be a FALLTHRU_EDGE. */
16888 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
16889 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
16890 for (unsigned i = 0;
16891 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
16893 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
16894 redirect_edge_succ (e, incr_bb);
16896 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
16897 e->probability = REG_BR_PROB_BASE;
16898 gsi = gsi_last_bb (incr_bb);
16899 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
16900 build_int_cst (unsigned_type_node, 1));
16901 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
16903 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
16904 struct loop *loop = alloc_loop ();
16905 cfun->has_force_vectorize_loops = true;
16906 loop->safelen = node->simdclone->simdlen;
16907 loop->force_vectorize = true;
16908 loop->header = body_bb;
16910 /* Branch around the body if the mask applies. */
16911 if (node->simdclone->inbranch)
16913 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
16914 tree mask_array
16915 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
16916 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
16917 tree aref = build4 (ARRAY_REF,
16918 TREE_TYPE (TREE_TYPE (mask_array)),
16919 mask_array, iter1,
16920 NULL, NULL);
16921 g = gimple_build_assign (mask, aref);
16922 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
16923 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
16924 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
16926 aref = build1 (VIEW_CONVERT_EXPR,
16927 build_nonstandard_integer_type (bitsize, 0), mask);
16928 mask = make_ssa_name (TREE_TYPE (aref));
16929 g = gimple_build_assign (mask, aref);
16930 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
16933 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
16934 NULL, NULL);
16935 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
16936 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
16937 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
16940 /* Generate the condition. */
16941 g = gimple_build_cond (LT_EXPR,
16942 iter2,
16943 build_int_cst (unsigned_type_node,
16944 node->simdclone->simdlen),
16945 NULL, NULL);
16946 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
16947 e = split_block (incr_bb, gsi_stmt (gsi));
16948 basic_block latch_bb = e->dest;
16949 basic_block new_exit_bb;
16950 new_exit_bb = split_block_after_labels (latch_bb)->dest;
16951 loop->latch = latch_bb;
16953 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
16955 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
16956 /* The successor of incr_bb is already pointing to latch_bb; just
16957 change the flags.
16958 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
16959 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
16961 gphi *phi = create_phi_node (iter1, body_bb);
16962 edge preheader_edge = find_edge (entry_bb, body_bb);
16963 edge latch_edge = single_succ_edge (latch_bb);
16964 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
16965 UNKNOWN_LOCATION);
16966 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
16968 /* Generate the new return. */
16969 gsi = gsi_last_bb (new_exit_bb);
16970 if (retval
16971 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
16972 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
16973 retval = TREE_OPERAND (retval, 0);
16974 else if (retval)
16976 retval = build1 (VIEW_CONVERT_EXPR,
16977 TREE_TYPE (TREE_TYPE (node->decl)),
16978 retval);
16979 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
16980 false, GSI_CONTINUE_LINKING);
16982 g = gimple_build_return (retval);
16983 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
16985 /* Handle aligned clauses by replacing default defs of the aligned
16986 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
16987 lhs. Handle linear by adding PHIs. */
16988 for (unsigned i = 0; i < node->simdclone->nargs; i++)
16989 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
16990 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
16991 || !is_gimple_reg_type
16992 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
16994 tree orig_arg = node->simdclone->args[i].orig_arg;
16995 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
16996 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
16997 else
16999 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
17000 gimple_add_tmp_var (iter1);
17002 gsi = gsi_after_labels (entry_bb);
17003 g = gimple_build_assign (iter1, orig_arg);
17004 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
17005 gsi = gsi_after_labels (body_bb);
17006 g = gimple_build_assign (orig_arg, iter1);
17007 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
17009 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
17010 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
17011 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
17012 == REFERENCE_TYPE
17013 && TREE_ADDRESSABLE
17014 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
17016 tree orig_arg = node->simdclone->args[i].orig_arg;
17017 tree def = ssa_default_def (cfun, orig_arg);
17018 if (def && !has_zero_uses (def))
17020 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
17021 gimple_add_tmp_var (iter1);
17022 gsi = gsi_after_labels (entry_bb);
17023 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
17024 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
17025 gsi = gsi_after_labels (body_bb);
17026 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
17027 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
17030 else if (node->simdclone->args[i].alignment
17031 && node->simdclone->args[i].arg_type
17032 == SIMD_CLONE_ARG_TYPE_UNIFORM
17033 && (node->simdclone->args[i].alignment
17034 & (node->simdclone->args[i].alignment - 1)) == 0
17035 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
17036 == POINTER_TYPE)
17038 unsigned int alignment = node->simdclone->args[i].alignment;
17039 tree orig_arg = node->simdclone->args[i].orig_arg;
17040 tree def = ssa_default_def (cfun, orig_arg);
17041 if (def && !has_zero_uses (def))
17043 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
17044 gimple_seq seq = NULL;
17045 bool need_cvt = false;
17046 gcall *call
17047 = gimple_build_call (fn, 2, def, size_int (alignment));
17048 g = call;
17049 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
17050 ptr_type_node))
17051 need_cvt = true;
17052 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
17053 gimple_call_set_lhs (g, t);
17054 gimple_seq_add_stmt_without_update (&seq, g);
17055 if (need_cvt)
17057 t = make_ssa_name (orig_arg);
17058 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
17059 gimple_seq_add_stmt_without_update (&seq, g);
17061 gsi_insert_seq_on_edge_immediate
17062 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
17064 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17065 int freq = compute_call_stmt_bb_frequency (current_function_decl,
17066 entry_bb);
17067 node->create_edge (cgraph_node::get_create (fn),
17068 call, entry_bb->count, freq);
17070 imm_use_iterator iter;
17071 use_operand_p use_p;
17072 gimple *use_stmt;
17073 tree repl = gimple_get_lhs (g);
17074 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
17075 if (is_gimple_debug (use_stmt) || use_stmt == call)
17076 continue;
17077 else
17078 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
17079 SET_USE (use_p, repl);
17082 else if ((node->simdclone->args[i].arg_type
17083 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
17084 || (node->simdclone->args[i].arg_type
17085 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP))
17087 tree orig_arg = node->simdclone->args[i].orig_arg;
17088 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
17089 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
17090 tree def = NULL_TREE;
17091 if (TREE_ADDRESSABLE (orig_arg))
17093 def = make_ssa_name (TREE_TYPE (orig_arg));
17094 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
17095 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
17096 gsi = gsi_after_labels (entry_bb);
17097 g = gimple_build_assign (def, orig_arg);
17098 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
17100 else
17102 def = ssa_default_def (cfun, orig_arg);
17103 if (!def || has_zero_uses (def))
17104 def = NULL_TREE;
17105 else
17107 iter1 = make_ssa_name (orig_arg);
17108 iter2 = make_ssa_name (orig_arg);
17111 if (def)
17113 phi = create_phi_node (iter1, body_bb);
17114 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
17115 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
17116 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
17117 ? PLUS_EXPR : POINTER_PLUS_EXPR;
17118 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
17119 ? TREE_TYPE (orig_arg) : sizetype;
17120 tree addcst
17121 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
17122 g = gimple_build_assign (iter2, code, iter1, addcst);
17123 gsi = gsi_last_bb (incr_bb);
17124 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17126 imm_use_iterator iter;
17127 use_operand_p use_p;
17128 gimple *use_stmt;
17129 if (TREE_ADDRESSABLE (orig_arg))
17131 gsi = gsi_after_labels (body_bb);
17132 g = gimple_build_assign (orig_arg, iter1);
17133 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
17135 else
17136 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
17137 if (use_stmt == phi)
17138 continue;
17139 else
17140 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
17141 SET_USE (use_p, iter1);
17144 else if (node->simdclone->args[i].arg_type
17145 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP)
17147 tree orig_arg = node->simdclone->args[i].orig_arg;
17148 tree def = ssa_default_def (cfun, orig_arg);
17149 gcc_assert (!TREE_ADDRESSABLE (orig_arg)
17150 && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
17151 if (def && !has_zero_uses (def))
17153 tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
17154 iter1 = make_ssa_name (orig_arg);
17155 iter2 = make_ssa_name (orig_arg);
17156 tree iter3 = make_ssa_name (rtype);
17157 tree iter4 = make_ssa_name (rtype);
17158 tree iter5 = make_ssa_name (rtype);
17159 gsi = gsi_after_labels (entry_bb);
17160 gimple *load
17161 = gimple_build_assign (iter3, build_simple_mem_ref (def));
17162 gsi_insert_before (&gsi, load, GSI_NEW_STMT);
17164 tree array = node->simdclone->args[i].simd_array;
17165 TREE_ADDRESSABLE (array) = 1;
17166 tree ptr = build_fold_addr_expr (array);
17167 phi = create_phi_node (iter1, body_bb);
17168 add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
17169 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
17170 g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
17171 TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
17172 gsi = gsi_last_bb (incr_bb);
17173 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17175 phi = create_phi_node (iter4, body_bb);
17176 add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
17177 add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
17178 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
17179 ? PLUS_EXPR : POINTER_PLUS_EXPR;
17180 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
17181 ? TREE_TYPE (iter3) : sizetype;
17182 tree addcst
17183 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
17184 g = gimple_build_assign (iter5, code, iter4, addcst);
17185 gsi = gsi_last_bb (incr_bb);
17186 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17188 g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
17189 gsi = gsi_after_labels (body_bb);
17190 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17192 imm_use_iterator iter;
17193 use_operand_p use_p;
17194 gimple *use_stmt;
17195 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
17196 if (use_stmt == load)
17197 continue;
17198 else
17199 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
17200 SET_USE (use_p, iter1);
17202 if (!TYPE_READONLY (rtype))
17204 tree v = make_ssa_name (rtype);
17205 tree aref = build4 (ARRAY_REF, rtype, array,
17206 size_zero_node, NULL_TREE,
17207 NULL_TREE);
17208 gsi = gsi_after_labels (new_exit_bb);
17209 g = gimple_build_assign (v, aref);
17210 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17211 g = gimple_build_assign (build_simple_mem_ref (def), v);
17212 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17217 calculate_dominance_info (CDI_DOMINATORS);
17218 add_loop (loop, loop->header->loop_father);
17219 update_ssa (TODO_update_ssa);
17221 pop_cfun ();
17224 /* If the function in NODE is tagged as an elemental SIMD function,
17225 create the appropriate SIMD clones. */
17227 static void
17228 expand_simd_clones (struct cgraph_node *node)
17230 tree attr = lookup_attribute ("omp declare simd",
17231 DECL_ATTRIBUTES (node->decl));
17232 if (attr == NULL_TREE
17233 || node->global.inlined_to
17234 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
17235 return;
17237 /* Ignore
17238 #pragma omp declare simd
17239 extern int foo ();
17240 in C, there we don't know the argument types at all. */
17241 if (!node->definition
17242 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
17243 return;
17247 /* Start with parsing the "omp declare simd" attribute(s). */
17248 bool inbranch_clause_specified;
17249 struct cgraph_simd_clone *clone_info
17250 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
17251 &inbranch_clause_specified);
17252 if (clone_info == NULL)
17253 continue;
17255 int orig_simdlen = clone_info->simdlen;
17256 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
17257 /* The target can return 0 (no simd clones should be created),
17258 1 (just one ISA of simd clones should be created) or higher
17259 count of ISA variants. In that case, clone_info is initialized
17260 for the first ISA variant. */
17261 int count
17262 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
17263 base_type, 0);
17264 if (count == 0)
17265 continue;
17267 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
17268 also create one inbranch and one !inbranch clone of it. */
17269 for (int i = 0; i < count * 2; i++)
17271 struct cgraph_simd_clone *clone = clone_info;
17272 if (inbranch_clause_specified && (i & 1) != 0)
17273 continue;
17275 if (i != 0)
17277 clone = simd_clone_struct_alloc (clone_info->nargs
17278 + ((i & 1) != 0));
17279 simd_clone_struct_copy (clone, clone_info);
17280 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
17281 and simd_clone_adjust_argument_types did to the first
17282 clone's info. */
17283 clone->nargs -= clone_info->inbranch;
17284 clone->simdlen = orig_simdlen;
17285 /* And call the target hook again to get the right ISA. */
17286 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
17287 base_type,
17288 i / 2);
17289 if ((i & 1) != 0)
17290 clone->inbranch = 1;
17293 /* simd_clone_mangle might fail if such a clone has been created
17294 already. */
17295 tree id = simd_clone_mangle (node, clone);
17296 if (id == NULL_TREE)
17297 continue;
17299 /* Only when we are sure we want to create the clone actually
17300 clone the function (or definitions) or create another
17301 extern FUNCTION_DECL (for prototypes without definitions). */
17302 struct cgraph_node *n = simd_clone_create (node);
17303 if (n == NULL)
17304 continue;
17306 n->simdclone = clone;
17307 clone->origin = node;
17308 clone->next_clone = NULL;
17309 if (node->simd_clones == NULL)
17311 clone->prev_clone = n;
17312 node->simd_clones = n;
17314 else
17316 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
17317 clone->prev_clone->simdclone->next_clone = n;
17318 node->simd_clones->simdclone->prev_clone = n;
17320 symtab->change_decl_assembler_name (n->decl, id);
17321 /* And finally adjust the return type, parameters and for
17322 definitions also function body. */
17323 if (node->definition)
17324 simd_clone_adjust (n);
17325 else
17327 simd_clone_adjust_return_type (n);
17328 simd_clone_adjust_argument_types (n);
17332 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
17335 /* Entry point for IPA simd clone creation pass. */
17337 static unsigned int
17338 ipa_omp_simd_clone (void)
17340 struct cgraph_node *node;
17341 FOR_EACH_FUNCTION (node)
17342 expand_simd_clones (node);
17343 return 0;
17346 namespace {
17348 const pass_data pass_data_omp_simd_clone =
17350 SIMPLE_IPA_PASS, /* type */
17351 "simdclone", /* name */
17352 OPTGROUP_NONE, /* optinfo_flags */
17353 TV_NONE, /* tv_id */
17354 ( PROP_ssa | PROP_cfg ), /* properties_required */
17355 0, /* properties_provided */
17356 0, /* properties_destroyed */
17357 0, /* todo_flags_start */
17358 0, /* todo_flags_finish */
17361 class pass_omp_simd_clone : public simple_ipa_opt_pass
17363 public:
17364 pass_omp_simd_clone(gcc::context *ctxt)
17365 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
17368 /* opt_pass methods: */
17369 virtual bool gate (function *);
17370 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
17373 bool
17374 pass_omp_simd_clone::gate (function *)
17376 return ((flag_openmp || flag_openmp_simd
17377 || flag_cilkplus
17378 || (in_lto_p && !flag_wpa))
17379 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
17382 } // anon namespace
17384 simple_ipa_opt_pass *
17385 make_pass_omp_simd_clone (gcc::context *ctxt)
17387 return new pass_omp_simd_clone (ctxt);
17390 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
17391 adds their addresses and sizes to constructor-vector V_CTOR. */
17392 static void
17393 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
17394 vec<constructor_elt, va_gc> *v_ctor)
17396 unsigned len = vec_safe_length (v_decls);
17397 for (unsigned i = 0; i < len; i++)
17399 tree it = (*v_decls)[i];
17400 bool is_function = TREE_CODE (it) != VAR_DECL;
17402 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
17403 if (!is_function)
17404 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
17405 fold_convert (const_ptr_type_node,
17406 DECL_SIZE_UNIT (it)));
17410 /* Create new symbols containing (address, size) pairs for global variables,
17411 marked with "omp declare target" attribute, as well as addresses for the
17412 functions, which are outlined offloading regions. */
17413 void
17414 omp_finish_file (void)
17416 unsigned num_funcs = vec_safe_length (offload_funcs);
17417 unsigned num_vars = vec_safe_length (offload_vars);
17419 if (num_funcs == 0 && num_vars == 0)
17420 return;
17422 if (targetm_common.have_named_sections)
17424 vec<constructor_elt, va_gc> *v_f, *v_v;
17425 vec_alloc (v_f, num_funcs);
17426 vec_alloc (v_v, num_vars * 2);
17428 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
17429 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
17431 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
17432 num_vars * 2);
17433 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
17434 num_funcs);
17435 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
17436 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
17437 tree ctor_v = build_constructor (vars_decl_type, v_v);
17438 tree ctor_f = build_constructor (funcs_decl_type, v_f);
17439 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
17440 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
17441 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
17442 get_identifier (".offload_func_table"),
17443 funcs_decl_type);
17444 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
17445 get_identifier (".offload_var_table"),
17446 vars_decl_type);
17447 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
17448 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
17449 otherwise a joint table in a binary will contain padding between
17450 tables from multiple object files. */
17451 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
17452 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
17453 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
17454 DECL_INITIAL (funcs_decl) = ctor_f;
17455 DECL_INITIAL (vars_decl) = ctor_v;
17456 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
17457 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
17459 varpool_node::finalize_decl (vars_decl);
17460 varpool_node::finalize_decl (funcs_decl);
17462 else
17464 for (unsigned i = 0; i < num_funcs; i++)
17466 tree it = (*offload_funcs)[i];
17467 targetm.record_offload_symbol (it);
17469 for (unsigned i = 0; i < num_vars; i++)
17471 tree it = (*offload_vars)[i];
17472 targetm.record_offload_symbol (it);
17477 /* Validate and update the dimensions for offloaded FN. ATTRS is the
17478 raw attribute. DIMS is an array of dimensions, which is returned.
17479 Returns the function level dimensionality -- the level at which an
17480 offload routine wishes to partition a loop. */
17482 static int
17483 oacc_validate_dims (tree fn, tree attrs, int *dims)
17485 tree purpose[GOMP_DIM_MAX];
17486 unsigned ix;
17487 tree pos = TREE_VALUE (attrs);
17488 int fn_level = -1;
17490 /* Make sure the attribute creator attached the dimension
17491 information. */
17492 gcc_assert (pos);
17494 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
17496 purpose[ix] = TREE_PURPOSE (pos);
17498 if (purpose[ix])
17500 if (integer_zerop (purpose[ix]))
17501 fn_level = ix + 1;
17502 else if (fn_level < 0)
17503 fn_level = ix;
17506 tree val = TREE_VALUE (pos);
17507 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
17508 pos = TREE_CHAIN (pos);
17511 bool changed = targetm.goacc.validate_dims (fn, dims, fn_level);
17513 /* Default anything left to 1. */
17514 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
17515 if (dims[ix] < 0)
17517 dims[ix] = 1;
17518 changed = true;
17521 if (changed)
17523 /* Replace the attribute with new values. */
17524 pos = NULL_TREE;
17525 for (ix = GOMP_DIM_MAX; ix--;)
17526 pos = tree_cons (purpose[ix],
17527 build_int_cst (integer_type_node, dims[ix]),
17528 pos);
17529 replace_oacc_fn_attrib (fn, pos);
17532 return fn_level;
17535 /* Main entry point for oacc transformations which run on the device
17536 compiler after LTO, so we know what the target device is at this
17537 point (including the host fallback). */
17539 static unsigned int
17540 execute_oacc_device_lower ()
17542 tree attrs = get_oacc_fn_attrib (current_function_decl);
17543 int dims[GOMP_DIM_MAX];
17545 if (!attrs)
17546 /* Not an offloaded function. */
17547 return 0;
17549 oacc_validate_dims (current_function_decl, attrs, dims);
17551 return 0;
17554 /* Default launch dimension validator. Force everything to 1. A
17555 backend that wants to provide larger dimensions must override this
17556 hook. */
17558 bool
17559 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
17560 int ARG_UNUSED (fn_level))
17562 bool changed = false;
17564 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
17566 if (dims[ix] != 1)
17568 dims[ix] = 1;
17569 changed = true;
17573 return changed;
17576 namespace {
17578 const pass_data pass_data_oacc_device_lower =
17580 GIMPLE_PASS, /* type */
17581 "oaccdevlow", /* name */
17582 OPTGROUP_NONE, /* optinfo_flags */
17583 TV_NONE, /* tv_id */
17584 PROP_cfg, /* properties_required */
17585 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
17586 0, /* properties_destroyed */
17587 0, /* todo_flags_start */
17588 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
17591 class pass_oacc_device_lower : public gimple_opt_pass
17593 public:
17594 pass_oacc_device_lower (gcc::context *ctxt)
17595 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
17598 /* opt_pass methods: */
17599 virtual unsigned int execute (function *)
17601 bool gate = (flag_openacc != 0 && !seen_error ());
17603 if (!gate)
17604 return 0;
17606 return execute_oacc_device_lower ();
17609 }; // class pass_oacc_transform
17611 } // anon namespace
17613 gimple_opt_pass *
17614 make_pass_oacc_device_lower (gcc::context *ctxt)
17616 return new pass_oacc_device_lower (ctxt);
17619 #include "gt-omp-low.h"