2015-06-11 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / omp-low.c
blob72c431e3e9f4c6bdb3a0ca9aa0a45f4a50f517fd
1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "input.h"
30 #include "alias.h"
31 #include "symtab.h"
32 #include "tree.h"
33 #include "fold-const.h"
34 #include "stringpool.h"
35 #include "stor-layout.h"
36 #include "rtl.h"
37 #include "predict.h"
38 #include "hard-reg-set.h"
39 #include "function.h"
40 #include "dominance.h"
41 #include "cfg.h"
42 #include "cfganal.h"
43 #include "basic-block.h"
44 #include "tree-ssa-alias.h"
45 #include "internal-fn.h"
46 #include "gimple-fold.h"
47 #include "gimple-expr.h"
48 #include "is-a.h"
49 #include "gimple.h"
50 #include "gimplify.h"
51 #include "gimple-iterator.h"
52 #include "gimplify-me.h"
53 #include "gimple-walk.h"
54 #include "tree-iterator.h"
55 #include "tree-inline.h"
56 #include "langhooks.h"
57 #include "diagnostic-core.h"
58 #include "gimple-ssa.h"
59 #include "plugin-api.h"
60 #include "ipa-ref.h"
61 #include "cgraph.h"
62 #include "tree-cfg.h"
63 #include "tree-phinodes.h"
64 #include "ssa-iterators.h"
65 #include "tree-ssanames.h"
66 #include "tree-into-ssa.h"
67 #include "flags.h"
68 #include "insn-config.h"
69 #include "expmed.h"
70 #include "dojump.h"
71 #include "explow.h"
72 #include "calls.h"
73 #include "emit-rtl.h"
74 #include "varasm.h"
75 #include "stmt.h"
76 #include "expr.h"
77 #include "tree-dfa.h"
78 #include "tree-ssa.h"
79 #include "tree-pass.h"
80 #include "except.h"
81 #include "splay-tree.h"
82 #include "insn-codes.h"
83 #include "optabs.h"
84 #include "cfgloop.h"
85 #include "target.h"
86 #include "common/common-target.h"
87 #include "omp-low.h"
88 #include "gimple-low.h"
89 #include "tree-cfgcleanup.h"
90 #include "pretty-print.h"
91 #include "alloc-pool.h"
92 #include "symbol-summary.h"
93 #include "ipa-prop.h"
94 #include "tree-nested.h"
95 #include "tree-eh.h"
96 #include "cilk.h"
97 #include "context.h"
98 #include "lto-section-names.h"
99 #include "gomp-constants.h"
102 /* Lowering of OMP parallel and workshare constructs proceeds in two
103 phases. The first phase scans the function looking for OMP statements
104 and then for variables that must be replaced to satisfy data sharing
105 clauses. The second phase expands code for the constructs, as well as
106 re-gimplifying things when variables have been replaced with complex
107 expressions.
109 Final code generation is done by pass_expand_omp. The flowgraph is
110 scanned for regions which are then moved to a new
111 function, to be invoked by the thread library, or offloaded. */
113 /* OMP region information. Every parallel and workshare
114 directive is enclosed between two markers, the OMP_* directive
115 and a corresponding OMP_RETURN statement. */
117 struct omp_region
119 /* The enclosing region. */
120 struct omp_region *outer;
122 /* First child region. */
123 struct omp_region *inner;
125 /* Next peer region. */
126 struct omp_region *next;
128 /* Block containing the omp directive as its last stmt. */
129 basic_block entry;
131 /* Block containing the OMP_RETURN as its last stmt. */
132 basic_block exit;
134 /* Block containing the OMP_CONTINUE as its last stmt. */
135 basic_block cont;
137 /* If this is a combined parallel+workshare region, this is a list
138 of additional arguments needed by the combined parallel+workshare
139 library call. */
140 vec<tree, va_gc> *ws_args;
142 /* The code for the omp directive of this region. */
143 enum gimple_code type;
145 /* Schedule kind, only used for OMP_FOR type regions. */
146 enum omp_clause_schedule_kind sched_kind;
148 /* True if this is a combined parallel+workshare region. */
149 bool is_combined_parallel;
152 /* Levels of parallelism as defined by OpenACC. Increasing numbers
153 correspond to deeper loop nesting levels. */
154 #define MASK_GANG 1
155 #define MASK_WORKER 2
156 #define MASK_VECTOR 4
158 /* Context structure. Used to store information about each parallel
159 directive in the code. */
161 typedef struct omp_context
163 /* This field must be at the beginning, as we do "inheritance": Some
164 callback functions for tree-inline.c (e.g., omp_copy_decl)
165 receive a copy_body_data pointer that is up-casted to an
166 omp_context pointer. */
167 copy_body_data cb;
169 /* The tree of contexts corresponding to the encountered constructs. */
170 struct omp_context *outer;
171 gimple stmt;
173 /* Map variables to fields in a structure that allows communication
174 between sending and receiving threads. */
175 splay_tree field_map;
176 tree record_type;
177 tree sender_decl;
178 tree receiver_decl;
180 /* These are used just by task contexts, if task firstprivate fn is
181 needed. srecord_type is used to communicate from the thread
182 that encountered the task construct to task firstprivate fn,
183 record_type is allocated by GOMP_task, initialized by task firstprivate
184 fn and passed to the task body fn. */
185 splay_tree sfield_map;
186 tree srecord_type;
188 /* A chain of variables to add to the top-level block surrounding the
189 construct. In the case of a parallel, this is in the child function. */
190 tree block_vars;
192 /* A map of reduction pointer variables. For accelerators, each
193 reduction variable is replaced with an array. Each thread, in turn,
194 is assigned to a slot on that array. */
195 splay_tree reduction_map;
197 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
198 barriers should jump to during omplower pass. */
199 tree cancel_label;
201 /* What to do with variables with implicitly determined sharing
202 attributes. */
203 enum omp_clause_default_kind default_kind;
205 /* Nesting depth of this context. Used to beautify error messages re
206 invalid gotos. The outermost ctx is depth 1, with depth 0 being
207 reserved for the main body of the function. */
208 int depth;
210 /* True if this parallel directive is nested within another. */
211 bool is_nested;
213 /* True if this construct can be cancelled. */
214 bool cancellable;
216 /* For OpenACC loops, a mask of gang, worker and vector used at
217 levels below this one. */
218 int gwv_below;
219 /* For OpenACC loops, a mask of gang, worker and vector used at
220 this level and above. For parallel and kernels clauses, a mask
221 indicating which of num_gangs/num_workers/num_vectors was used. */
222 int gwv_this;
223 } omp_context;
225 /* A structure holding the elements of:
226 for (V = N1; V cond N2; V += STEP) [...] */
228 struct omp_for_data_loop
230 tree v, n1, n2, step;
231 enum tree_code cond_code;
234 /* A structure describing the main elements of a parallel loop. */
236 struct omp_for_data
238 struct omp_for_data_loop loop;
239 tree chunk_size;
240 gomp_for *for_stmt;
241 tree pre, iter_type;
242 int collapse;
243 bool have_nowait, have_ordered;
244 enum omp_clause_schedule_kind sched_kind;
245 struct omp_for_data_loop *loops;
249 static splay_tree all_contexts;
250 static int taskreg_nesting_level;
251 static int target_nesting_level;
252 static struct omp_region *root_omp_region;
253 static bitmap task_shared_vars;
254 static vec<omp_context *> taskreg_contexts;
256 static void scan_omp (gimple_seq *, omp_context *);
257 static tree scan_omp_1_op (tree *, int *, void *);
259 #define WALK_SUBSTMTS \
260 case GIMPLE_BIND: \
261 case GIMPLE_TRY: \
262 case GIMPLE_CATCH: \
263 case GIMPLE_EH_FILTER: \
264 case GIMPLE_TRANSACTION: \
265 /* The sub-statements for these should be walked. */ \
266 *handled_ops_p = false; \
267 break;
269 /* Helper function to get the name of the array containing the partial
270 reductions for OpenACC reductions. */
271 static const char *
272 oacc_get_reduction_array_id (tree node)
274 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
275 int len = strlen ("OACC") + strlen (id);
276 char *temp_name = XALLOCAVEC (char, len + 1);
277 snprintf (temp_name, len + 1, "OACC%s", id);
278 return IDENTIFIER_POINTER (get_identifier (temp_name));
281 /* Determine the number of threads OpenACC threads used to determine the
282 size of the array of partial reductions. Currently, this is num_gangs
283 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
284 because it is independed of the device used. */
286 static tree
287 oacc_max_threads (omp_context *ctx)
289 tree nthreads, vector_length, gangs, clauses;
291 gangs = fold_convert (sizetype, integer_one_node);
292 vector_length = gangs;
294 /* The reduction clause may be nested inside a loop directive.
295 Scan for the innermost vector_length clause. */
296 for (omp_context *oc = ctx; oc; oc = oc->outer)
298 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
299 || (gimple_omp_target_kind (oc->stmt)
300 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
301 continue;
303 clauses = gimple_omp_target_clauses (oc->stmt);
305 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
306 if (vector_length)
307 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
308 sizetype,
309 OMP_CLAUSE_VECTOR_LENGTH_EXPR
310 (vector_length));
311 else
312 vector_length = fold_convert (sizetype, integer_one_node);
314 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
315 if (gangs)
316 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
317 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
318 else
319 gangs = fold_convert (sizetype, integer_one_node);
321 break;
324 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
326 return nthreads;
329 /* Holds offload tables with decls. */
330 vec<tree, va_gc> *offload_funcs, *offload_vars;
332 /* Convenience function for calling scan_omp_1_op on tree operands. */
334 static inline tree
335 scan_omp_op (tree *tp, omp_context *ctx)
337 struct walk_stmt_info wi;
339 memset (&wi, 0, sizeof (wi));
340 wi.info = ctx;
341 wi.want_locations = true;
343 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
346 static void lower_omp (gimple_seq *, omp_context *);
347 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
348 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
350 /* Find an OMP clause of type KIND within CLAUSES. */
352 tree
353 find_omp_clause (tree clauses, enum omp_clause_code kind)
355 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
356 if (OMP_CLAUSE_CODE (clauses) == kind)
357 return clauses;
359 return NULL_TREE;
362 /* Return true if CTX is for an omp parallel. */
364 static inline bool
365 is_parallel_ctx (omp_context *ctx)
367 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
371 /* Return true if CTX is for an omp task. */
373 static inline bool
374 is_task_ctx (omp_context *ctx)
376 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
380 /* Return true if CTX is for an omp parallel or omp task. */
382 static inline bool
383 is_taskreg_ctx (omp_context *ctx)
385 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
386 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
390 /* Return true if REGION is a combined parallel+workshare region. */
392 static inline bool
393 is_combined_parallel (struct omp_region *region)
395 return region->is_combined_parallel;
399 /* Extract the header elements of parallel loop FOR_STMT and store
400 them into *FD. */
402 static void
403 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
404 struct omp_for_data_loop *loops)
406 tree t, var, *collapse_iter, *collapse_count;
407 tree count = NULL_TREE, iter_type = long_integer_type_node;
408 struct omp_for_data_loop *loop;
409 int i;
410 struct omp_for_data_loop dummy_loop;
411 location_t loc = gimple_location (for_stmt);
412 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
413 bool distribute = gimple_omp_for_kind (for_stmt)
414 == GF_OMP_FOR_KIND_DISTRIBUTE;
416 fd->for_stmt = for_stmt;
417 fd->pre = NULL;
418 fd->collapse = gimple_omp_for_collapse (for_stmt);
419 if (fd->collapse > 1)
420 fd->loops = loops;
421 else
422 fd->loops = &fd->loop;
424 fd->have_nowait = distribute || simd;
425 fd->have_ordered = false;
426 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
427 fd->chunk_size = NULL_TREE;
428 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
429 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
430 collapse_iter = NULL;
431 collapse_count = NULL;
433 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
434 switch (OMP_CLAUSE_CODE (t))
436 case OMP_CLAUSE_NOWAIT:
437 fd->have_nowait = true;
438 break;
439 case OMP_CLAUSE_ORDERED:
440 fd->have_ordered = true;
441 break;
442 case OMP_CLAUSE_SCHEDULE:
443 gcc_assert (!distribute);
444 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
445 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
446 break;
447 case OMP_CLAUSE_DIST_SCHEDULE:
448 gcc_assert (distribute);
449 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
450 break;
451 case OMP_CLAUSE_COLLAPSE:
452 if (fd->collapse > 1)
454 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
455 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
457 break;
458 default:
459 break;
462 /* FIXME: for now map schedule(auto) to schedule(static).
463 There should be analysis to determine whether all iterations
464 are approximately the same amount of work (then schedule(static)
465 is best) or if it varies (then schedule(dynamic,N) is better). */
466 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
468 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
469 gcc_assert (fd->chunk_size == NULL);
471 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
472 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
473 gcc_assert (fd->chunk_size == NULL);
474 else if (fd->chunk_size == NULL)
476 /* We only need to compute a default chunk size for ordered
477 static loops and dynamic loops. */
478 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
479 || fd->have_ordered)
480 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
481 ? integer_zero_node : integer_one_node;
484 for (i = 0; i < fd->collapse; i++)
486 if (fd->collapse == 1)
487 loop = &fd->loop;
488 else if (loops != NULL)
489 loop = loops + i;
490 else
491 loop = &dummy_loop;
493 loop->v = gimple_omp_for_index (for_stmt, i);
494 gcc_assert (SSA_VAR_P (loop->v));
495 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
496 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
497 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
498 loop->n1 = gimple_omp_for_initial (for_stmt, i);
500 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
501 loop->n2 = gimple_omp_for_final (for_stmt, i);
502 switch (loop->cond_code)
504 case LT_EXPR:
505 case GT_EXPR:
506 break;
507 case NE_EXPR:
508 gcc_assert (gimple_omp_for_kind (for_stmt)
509 == GF_OMP_FOR_KIND_CILKSIMD
510 || (gimple_omp_for_kind (for_stmt)
511 == GF_OMP_FOR_KIND_CILKFOR));
512 break;
513 case LE_EXPR:
514 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
515 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
516 else
517 loop->n2 = fold_build2_loc (loc,
518 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
519 build_int_cst (TREE_TYPE (loop->n2), 1));
520 loop->cond_code = LT_EXPR;
521 break;
522 case GE_EXPR:
523 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
524 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
525 else
526 loop->n2 = fold_build2_loc (loc,
527 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
528 build_int_cst (TREE_TYPE (loop->n2), 1));
529 loop->cond_code = GT_EXPR;
530 break;
531 default:
532 gcc_unreachable ();
535 t = gimple_omp_for_incr (for_stmt, i);
536 gcc_assert (TREE_OPERAND (t, 0) == var);
537 switch (TREE_CODE (t))
539 case PLUS_EXPR:
540 loop->step = TREE_OPERAND (t, 1);
541 break;
542 case POINTER_PLUS_EXPR:
543 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
544 break;
545 case MINUS_EXPR:
546 loop->step = TREE_OPERAND (t, 1);
547 loop->step = fold_build1_loc (loc,
548 NEGATE_EXPR, TREE_TYPE (loop->step),
549 loop->step);
550 break;
551 default:
552 gcc_unreachable ();
555 if (simd
556 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
557 && !fd->have_ordered))
559 if (fd->collapse == 1)
560 iter_type = TREE_TYPE (loop->v);
561 else if (i == 0
562 || TYPE_PRECISION (iter_type)
563 < TYPE_PRECISION (TREE_TYPE (loop->v)))
564 iter_type
565 = build_nonstandard_integer_type
566 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
568 else if (iter_type != long_long_unsigned_type_node)
570 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
571 iter_type = long_long_unsigned_type_node;
572 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
573 && TYPE_PRECISION (TREE_TYPE (loop->v))
574 >= TYPE_PRECISION (iter_type))
576 tree n;
578 if (loop->cond_code == LT_EXPR)
579 n = fold_build2_loc (loc,
580 PLUS_EXPR, TREE_TYPE (loop->v),
581 loop->n2, loop->step);
582 else
583 n = loop->n1;
584 if (TREE_CODE (n) != INTEGER_CST
585 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
586 iter_type = long_long_unsigned_type_node;
588 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
589 > TYPE_PRECISION (iter_type))
591 tree n1, n2;
593 if (loop->cond_code == LT_EXPR)
595 n1 = loop->n1;
596 n2 = fold_build2_loc (loc,
597 PLUS_EXPR, TREE_TYPE (loop->v),
598 loop->n2, loop->step);
600 else
602 n1 = fold_build2_loc (loc,
603 MINUS_EXPR, TREE_TYPE (loop->v),
604 loop->n2, loop->step);
605 n2 = loop->n1;
607 if (TREE_CODE (n1) != INTEGER_CST
608 || TREE_CODE (n2) != INTEGER_CST
609 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
610 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
611 iter_type = long_long_unsigned_type_node;
615 if (collapse_count && *collapse_count == NULL)
617 t = fold_binary (loop->cond_code, boolean_type_node,
618 fold_convert (TREE_TYPE (loop->v), loop->n1),
619 fold_convert (TREE_TYPE (loop->v), loop->n2));
620 if (t && integer_zerop (t))
621 count = build_zero_cst (long_long_unsigned_type_node);
622 else if ((i == 0 || count != NULL_TREE)
623 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
624 && TREE_CONSTANT (loop->n1)
625 && TREE_CONSTANT (loop->n2)
626 && TREE_CODE (loop->step) == INTEGER_CST)
628 tree itype = TREE_TYPE (loop->v);
630 if (POINTER_TYPE_P (itype))
631 itype = signed_type_for (itype);
632 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
633 t = fold_build2_loc (loc,
634 PLUS_EXPR, itype,
635 fold_convert_loc (loc, itype, loop->step), t);
636 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
637 fold_convert_loc (loc, itype, loop->n2));
638 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
639 fold_convert_loc (loc, itype, loop->n1));
640 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
641 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
642 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
643 fold_build1_loc (loc, NEGATE_EXPR, itype,
644 fold_convert_loc (loc, itype,
645 loop->step)));
646 else
647 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
648 fold_convert_loc (loc, itype, loop->step));
649 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
650 if (count != NULL_TREE)
651 count = fold_build2_loc (loc,
652 MULT_EXPR, long_long_unsigned_type_node,
653 count, t);
654 else
655 count = t;
656 if (TREE_CODE (count) != INTEGER_CST)
657 count = NULL_TREE;
659 else if (count && !integer_zerop (count))
660 count = NULL_TREE;
664 if (count
665 && !simd
666 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
667 || fd->have_ordered))
669 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
670 iter_type = long_long_unsigned_type_node;
671 else
672 iter_type = long_integer_type_node;
674 else if (collapse_iter && *collapse_iter != NULL)
675 iter_type = TREE_TYPE (*collapse_iter);
676 fd->iter_type = iter_type;
677 if (collapse_iter && *collapse_iter == NULL)
678 *collapse_iter = create_tmp_var (iter_type, ".iter");
679 if (collapse_count && *collapse_count == NULL)
681 if (count)
682 *collapse_count = fold_convert_loc (loc, iter_type, count);
683 else
684 *collapse_count = create_tmp_var (iter_type, ".count");
687 if (fd->collapse > 1)
689 fd->loop.v = *collapse_iter;
690 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
691 fd->loop.n2 = *collapse_count;
692 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
693 fd->loop.cond_code = LT_EXPR;
696 /* For OpenACC loops, force a chunk size of one, as this avoids the default
697 scheduling where several subsequent iterations are being executed by the
698 same thread. */
699 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
701 gcc_assert (fd->chunk_size == NULL_TREE);
702 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
707 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
708 is the immediate dominator of PAR_ENTRY_BB, return true if there
709 are no data dependencies that would prevent expanding the parallel
710 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
712 When expanding a combined parallel+workshare region, the call to
713 the child function may need additional arguments in the case of
714 GIMPLE_OMP_FOR regions. In some cases, these arguments are
715 computed out of variables passed in from the parent to the child
716 via 'struct .omp_data_s'. For instance:
718 #pragma omp parallel for schedule (guided, i * 4)
719 for (j ...)
721 Is lowered into:
723 # BLOCK 2 (PAR_ENTRY_BB)
724 .omp_data_o.i = i;
725 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
727 # BLOCK 3 (WS_ENTRY_BB)
728 .omp_data_i = &.omp_data_o;
729 D.1667 = .omp_data_i->i;
730 D.1598 = D.1667 * 4;
731 #pragma omp for schedule (guided, D.1598)
733 When we outline the parallel region, the call to the child function
734 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
735 that value is computed *after* the call site. So, in principle we
736 cannot do the transformation.
738 To see whether the code in WS_ENTRY_BB blocks the combined
739 parallel+workshare call, we collect all the variables used in the
740 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
741 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
742 call.
744 FIXME. If we had the SSA form built at this point, we could merely
745 hoist the code in block 3 into block 2 and be done with it. But at
746 this point we don't have dataflow information and though we could
747 hack something up here, it is really not worth the aggravation. */
749 static bool
750 workshare_safe_to_combine_p (basic_block ws_entry_bb)
752 struct omp_for_data fd;
753 gimple ws_stmt = last_stmt (ws_entry_bb);
755 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
756 return true;
758 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
760 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
762 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
763 return false;
764 if (fd.iter_type != long_integer_type_node)
765 return false;
767 /* FIXME. We give up too easily here. If any of these arguments
768 are not constants, they will likely involve variables that have
769 been mapped into fields of .omp_data_s for sharing with the child
770 function. With appropriate data flow, it would be possible to
771 see through this. */
772 if (!is_gimple_min_invariant (fd.loop.n1)
773 || !is_gimple_min_invariant (fd.loop.n2)
774 || !is_gimple_min_invariant (fd.loop.step)
775 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
776 return false;
778 return true;
782 /* Collect additional arguments needed to emit a combined
783 parallel+workshare call. WS_STMT is the workshare directive being
784 expanded. */
786 static vec<tree, va_gc> *
787 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
789 tree t;
790 location_t loc = gimple_location (ws_stmt);
791 vec<tree, va_gc> *ws_args;
793 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
795 struct omp_for_data fd;
796 tree n1, n2;
798 extract_omp_for_data (for_stmt, &fd, NULL);
799 n1 = fd.loop.n1;
800 n2 = fd.loop.n2;
802 if (gimple_omp_for_combined_into_p (for_stmt))
804 tree innerc
805 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
806 OMP_CLAUSE__LOOPTEMP_);
807 gcc_assert (innerc);
808 n1 = OMP_CLAUSE_DECL (innerc);
809 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
810 OMP_CLAUSE__LOOPTEMP_);
811 gcc_assert (innerc);
812 n2 = OMP_CLAUSE_DECL (innerc);
815 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
817 t = fold_convert_loc (loc, long_integer_type_node, n1);
818 ws_args->quick_push (t);
820 t = fold_convert_loc (loc, long_integer_type_node, n2);
821 ws_args->quick_push (t);
823 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
824 ws_args->quick_push (t);
826 if (fd.chunk_size)
828 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
829 ws_args->quick_push (t);
832 return ws_args;
834 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
836 /* Number of sections is equal to the number of edges from the
837 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
838 the exit of the sections region. */
839 basic_block bb = single_succ (gimple_bb (ws_stmt));
840 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
841 vec_alloc (ws_args, 1);
842 ws_args->quick_push (t);
843 return ws_args;
846 gcc_unreachable ();
850 /* Discover whether REGION is a combined parallel+workshare region. */
852 static void
853 determine_parallel_type (struct omp_region *region)
855 basic_block par_entry_bb, par_exit_bb;
856 basic_block ws_entry_bb, ws_exit_bb;
858 if (region == NULL || region->inner == NULL
859 || region->exit == NULL || region->inner->exit == NULL
860 || region->inner->cont == NULL)
861 return;
863 /* We only support parallel+for and parallel+sections. */
864 if (region->type != GIMPLE_OMP_PARALLEL
865 || (region->inner->type != GIMPLE_OMP_FOR
866 && region->inner->type != GIMPLE_OMP_SECTIONS))
867 return;
869 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
870 WS_EXIT_BB -> PAR_EXIT_BB. */
871 par_entry_bb = region->entry;
872 par_exit_bb = region->exit;
873 ws_entry_bb = region->inner->entry;
874 ws_exit_bb = region->inner->exit;
876 if (single_succ (par_entry_bb) == ws_entry_bb
877 && single_succ (ws_exit_bb) == par_exit_bb
878 && workshare_safe_to_combine_p (ws_entry_bb)
879 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
880 || (last_and_only_stmt (ws_entry_bb)
881 && last_and_only_stmt (par_exit_bb))))
883 gimple par_stmt = last_stmt (par_entry_bb);
884 gimple ws_stmt = last_stmt (ws_entry_bb);
886 if (region->inner->type == GIMPLE_OMP_FOR)
888 /* If this is a combined parallel loop, we need to determine
889 whether or not to use the combined library calls. There
890 are two cases where we do not apply the transformation:
891 static loops and any kind of ordered loop. In the first
892 case, we already open code the loop so there is no need
893 to do anything else. In the latter case, the combined
894 parallel loop call would still need extra synchronization
895 to implement ordered semantics, so there would not be any
896 gain in using the combined call. */
897 tree clauses = gimple_omp_for_clauses (ws_stmt);
898 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
899 if (c == NULL
900 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
901 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
903 region->is_combined_parallel = false;
904 region->inner->is_combined_parallel = false;
905 return;
909 region->is_combined_parallel = true;
910 region->inner->is_combined_parallel = true;
911 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
916 /* Return true if EXPR is variable sized. */
918 static inline bool
919 is_variable_sized (const_tree expr)
921 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
924 /* Return true if DECL is a reference type. */
926 static inline bool
927 is_reference (tree decl)
929 return lang_hooks.decls.omp_privatize_by_reference (decl);
932 /* Return the type of a decl. If the decl is reference type,
933 return its base type. */
934 static inline tree
935 get_base_type (tree decl)
937 tree type = TREE_TYPE (decl);
938 if (is_reference (decl))
939 type = TREE_TYPE (type);
940 return type;
943 /* Lookup variables. The "maybe" form
944 allows for the variable form to not have been entered, otherwise we
945 assert that the variable must have been entered. */
947 static inline tree
948 lookup_decl (tree var, omp_context *ctx)
950 tree *n = ctx->cb.decl_map->get (var);
951 return *n;
954 static inline tree
955 maybe_lookup_decl (const_tree var, omp_context *ctx)
957 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
958 return n ? *n : NULL_TREE;
961 static inline tree
962 lookup_field (tree var, omp_context *ctx)
964 splay_tree_node n;
965 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
966 return (tree) n->value;
969 static inline tree
970 lookup_sfield (tree var, omp_context *ctx)
972 splay_tree_node n;
973 n = splay_tree_lookup (ctx->sfield_map
974 ? ctx->sfield_map : ctx->field_map,
975 (splay_tree_key) var);
976 return (tree) n->value;
979 static inline tree
980 maybe_lookup_field (tree var, omp_context *ctx)
982 splay_tree_node n;
983 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
984 return n ? (tree) n->value : NULL_TREE;
987 static inline tree
988 lookup_oacc_reduction (const char *id, omp_context *ctx)
990 splay_tree_node n;
991 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
992 return (tree) n->value;
995 static inline tree
996 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
998 splay_tree_node n = NULL;
999 if (ctx->reduction_map)
1000 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
1001 return n ? (tree) n->value : NULL_TREE;
1004 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1005 the parallel context if DECL is to be shared. */
1007 static bool
1008 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1010 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1011 return true;
1013 /* We can only use copy-in/copy-out semantics for shared variables
1014 when we know the value is not accessible from an outer scope. */
1015 if (shared_ctx)
1017 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1019 /* ??? Trivially accessible from anywhere. But why would we even
1020 be passing an address in this case? Should we simply assert
1021 this to be false, or should we have a cleanup pass that removes
1022 these from the list of mappings? */
1023 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1024 return true;
1026 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1027 without analyzing the expression whether or not its location
1028 is accessible to anyone else. In the case of nested parallel
1029 regions it certainly may be. */
1030 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1031 return true;
1033 /* Do not use copy-in/copy-out for variables that have their
1034 address taken. */
1035 if (TREE_ADDRESSABLE (decl))
1036 return true;
1038 /* lower_send_shared_vars only uses copy-in, but not copy-out
1039 for these. */
1040 if (TREE_READONLY (decl)
1041 || ((TREE_CODE (decl) == RESULT_DECL
1042 || TREE_CODE (decl) == PARM_DECL)
1043 && DECL_BY_REFERENCE (decl)))
1044 return false;
1046 /* Disallow copy-in/out in nested parallel if
1047 decl is shared in outer parallel, otherwise
1048 each thread could store the shared variable
1049 in its own copy-in location, making the
1050 variable no longer really shared. */
1051 if (shared_ctx->is_nested)
1053 omp_context *up;
1055 for (up = shared_ctx->outer; up; up = up->outer)
1056 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1057 break;
1059 if (up)
1061 tree c;
1063 for (c = gimple_omp_taskreg_clauses (up->stmt);
1064 c; c = OMP_CLAUSE_CHAIN (c))
1065 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1066 && OMP_CLAUSE_DECL (c) == decl)
1067 break;
1069 if (c)
1070 goto maybe_mark_addressable_and_ret;
1074 /* For tasks avoid using copy-in/out. As tasks can be
1075 deferred or executed in different thread, when GOMP_task
1076 returns, the task hasn't necessarily terminated. */
1077 if (is_task_ctx (shared_ctx))
1079 tree outer;
1080 maybe_mark_addressable_and_ret:
1081 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1082 if (is_gimple_reg (outer))
1084 /* Taking address of OUTER in lower_send_shared_vars
1085 might need regimplification of everything that uses the
1086 variable. */
1087 if (!task_shared_vars)
1088 task_shared_vars = BITMAP_ALLOC (NULL);
1089 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1090 TREE_ADDRESSABLE (outer) = 1;
1092 return true;
1096 return false;
1099 /* Construct a new automatic decl similar to VAR. */
1101 static tree
1102 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1104 tree copy = copy_var_decl (var, name, type);
1106 DECL_CONTEXT (copy) = current_function_decl;
1107 DECL_CHAIN (copy) = ctx->block_vars;
1108 ctx->block_vars = copy;
1110 return copy;
1113 static tree
1114 omp_copy_decl_1 (tree var, omp_context *ctx)
1116 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1119 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1120 as appropriate. */
1121 static tree
1122 omp_build_component_ref (tree obj, tree field)
1124 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1125 if (TREE_THIS_VOLATILE (field))
1126 TREE_THIS_VOLATILE (ret) |= 1;
1127 if (TREE_READONLY (field))
1128 TREE_READONLY (ret) |= 1;
1129 return ret;
1132 /* Build tree nodes to access the field for VAR on the receiver side. */
1134 static tree
1135 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1137 tree x, field = lookup_field (var, ctx);
1139 /* If the receiver record type was remapped in the child function,
1140 remap the field into the new record type. */
1141 x = maybe_lookup_field (field, ctx);
1142 if (x != NULL)
1143 field = x;
1145 x = build_simple_mem_ref (ctx->receiver_decl);
1146 x = omp_build_component_ref (x, field);
1147 if (by_ref)
1148 x = build_simple_mem_ref (x);
1150 return x;
1153 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1154 of a parallel, this is a component reference; for workshare constructs
1155 this is some variable. */
1157 static tree
1158 build_outer_var_ref (tree var, omp_context *ctx)
1160 tree x;
1162 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1163 x = var;
1164 else if (is_variable_sized (var))
1166 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1167 x = build_outer_var_ref (x, ctx);
1168 x = build_simple_mem_ref (x);
1170 else if (is_taskreg_ctx (ctx))
1172 bool by_ref = use_pointer_for_field (var, NULL);
1173 x = build_receiver_ref (var, by_ref, ctx);
1175 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1176 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1178 /* #pragma omp simd isn't a worksharing construct, and can reference even
1179 private vars in its linear etc. clauses. */
1180 x = NULL_TREE;
1181 if (ctx->outer && is_taskreg_ctx (ctx))
1182 x = lookup_decl (var, ctx->outer);
1183 else if (ctx->outer)
1184 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1185 if (x == NULL_TREE)
1186 x = var;
1188 else if (ctx->outer)
1189 x = lookup_decl (var, ctx->outer);
1190 else if (is_reference (var))
1191 /* This can happen with orphaned constructs. If var is reference, it is
1192 possible it is shared and as such valid. */
1193 x = var;
1194 else
1195 gcc_unreachable ();
1197 if (is_reference (var))
1198 x = build_simple_mem_ref (x);
1200 return x;
1203 /* Build tree nodes to access the field for VAR on the sender side. */
1205 static tree
1206 build_sender_ref (tree var, omp_context *ctx)
1208 tree field = lookup_sfield (var, ctx);
1209 return omp_build_component_ref (ctx->sender_decl, field);
1212 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1214 static void
1215 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1217 tree field, type, sfield = NULL_TREE;
1219 gcc_assert ((mask & 1) == 0
1220 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1221 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1222 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1223 gcc_assert ((mask & 3) == 3
1224 || !is_gimple_omp_oacc (ctx->stmt));
1226 type = TREE_TYPE (var);
1227 if (mask & 4)
1229 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1230 type = build_pointer_type (build_pointer_type (type));
1232 else if (by_ref)
1233 type = build_pointer_type (type);
1234 else if ((mask & 3) == 1 && is_reference (var))
1235 type = TREE_TYPE (type);
1237 field = build_decl (DECL_SOURCE_LOCATION (var),
1238 FIELD_DECL, DECL_NAME (var), type);
1240 /* Remember what variable this field was created for. This does have a
1241 side effect of making dwarf2out ignore this member, so for helpful
1242 debugging we clear it later in delete_omp_context. */
1243 DECL_ABSTRACT_ORIGIN (field) = var;
1244 if (type == TREE_TYPE (var))
1246 DECL_ALIGN (field) = DECL_ALIGN (var);
1247 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1248 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1250 else
1251 DECL_ALIGN (field) = TYPE_ALIGN (type);
1253 if ((mask & 3) == 3)
1255 insert_field_into_struct (ctx->record_type, field);
1256 if (ctx->srecord_type)
1258 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1259 FIELD_DECL, DECL_NAME (var), type);
1260 DECL_ABSTRACT_ORIGIN (sfield) = var;
1261 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1262 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1263 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1264 insert_field_into_struct (ctx->srecord_type, sfield);
1267 else
1269 if (ctx->srecord_type == NULL_TREE)
1271 tree t;
1273 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1274 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1275 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1277 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1278 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1279 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1280 insert_field_into_struct (ctx->srecord_type, sfield);
1281 splay_tree_insert (ctx->sfield_map,
1282 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1283 (splay_tree_value) sfield);
1286 sfield = field;
1287 insert_field_into_struct ((mask & 1) ? ctx->record_type
1288 : ctx->srecord_type, field);
1291 if (mask & 1)
1292 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1293 (splay_tree_value) field);
1294 if ((mask & 2) && ctx->sfield_map)
1295 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1296 (splay_tree_value) sfield);
1299 static tree
1300 install_var_local (tree var, omp_context *ctx)
1302 tree new_var = omp_copy_decl_1 (var, ctx);
1303 insert_decl_map (&ctx->cb, var, new_var);
1304 return new_var;
1307 /* Adjust the replacement for DECL in CTX for the new context. This means
1308 copying the DECL_VALUE_EXPR, and fixing up the type. */
1310 static void
1311 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1313 tree new_decl, size;
1315 new_decl = lookup_decl (decl, ctx);
1317 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1319 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1320 && DECL_HAS_VALUE_EXPR_P (decl))
1322 tree ve = DECL_VALUE_EXPR (decl);
1323 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1324 SET_DECL_VALUE_EXPR (new_decl, ve);
1325 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1328 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1330 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1331 if (size == error_mark_node)
1332 size = TYPE_SIZE (TREE_TYPE (new_decl));
1333 DECL_SIZE (new_decl) = size;
1335 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1336 if (size == error_mark_node)
1337 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1338 DECL_SIZE_UNIT (new_decl) = size;
1342 /* The callback for remap_decl. Search all containing contexts for a
1343 mapping of the variable; this avoids having to duplicate the splay
1344 tree ahead of time. We know a mapping doesn't already exist in the
1345 given context. Create new mappings to implement default semantics. */
1347 static tree
1348 omp_copy_decl (tree var, copy_body_data *cb)
1350 omp_context *ctx = (omp_context *) cb;
1351 tree new_var;
1353 if (TREE_CODE (var) == LABEL_DECL)
1355 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1356 DECL_CONTEXT (new_var) = current_function_decl;
1357 insert_decl_map (&ctx->cb, var, new_var);
1358 return new_var;
1361 while (!is_taskreg_ctx (ctx))
1363 ctx = ctx->outer;
1364 if (ctx == NULL)
1365 return var;
1366 new_var = maybe_lookup_decl (var, ctx);
1367 if (new_var)
1368 return new_var;
1371 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1372 return var;
1374 return error_mark_node;
1378 /* Debugging dumps for parallel regions. */
1379 void dump_omp_region (FILE *, struct omp_region *, int);
1380 void debug_omp_region (struct omp_region *);
1381 void debug_all_omp_regions (void);
1383 /* Dump the parallel region tree rooted at REGION. */
1385 void
1386 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1388 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1389 gimple_code_name[region->type]);
1391 if (region->inner)
1392 dump_omp_region (file, region->inner, indent + 4);
1394 if (region->cont)
1396 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1397 region->cont->index);
1400 if (region->exit)
1401 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1402 region->exit->index);
1403 else
1404 fprintf (file, "%*s[no exit marker]\n", indent, "");
1406 if (region->next)
1407 dump_omp_region (file, region->next, indent);
1410 DEBUG_FUNCTION void
1411 debug_omp_region (struct omp_region *region)
1413 dump_omp_region (stderr, region, 0);
1416 DEBUG_FUNCTION void
1417 debug_all_omp_regions (void)
1419 dump_omp_region (stderr, root_omp_region, 0);
1423 /* Create a new parallel region starting at STMT inside region PARENT. */
1425 static struct omp_region *
1426 new_omp_region (basic_block bb, enum gimple_code type,
1427 struct omp_region *parent)
1429 struct omp_region *region = XCNEW (struct omp_region);
1431 region->outer = parent;
1432 region->entry = bb;
1433 region->type = type;
1435 if (parent)
1437 /* This is a nested region. Add it to the list of inner
1438 regions in PARENT. */
1439 region->next = parent->inner;
1440 parent->inner = region;
1442 else
1444 /* This is a toplevel region. Add it to the list of toplevel
1445 regions in ROOT_OMP_REGION. */
1446 region->next = root_omp_region;
1447 root_omp_region = region;
1450 return region;
1453 /* Release the memory associated with the region tree rooted at REGION. */
1455 static void
1456 free_omp_region_1 (struct omp_region *region)
1458 struct omp_region *i, *n;
1460 for (i = region->inner; i ; i = n)
1462 n = i->next;
1463 free_omp_region_1 (i);
1466 free (region);
1469 /* Release the memory for the entire omp region tree. */
1471 void
1472 free_omp_regions (void)
1474 struct omp_region *r, *n;
1475 for (r = root_omp_region; r ; r = n)
1477 n = r->next;
1478 free_omp_region_1 (r);
1480 root_omp_region = NULL;
1484 /* Create a new context, with OUTER_CTX being the surrounding context. */
1486 static omp_context *
1487 new_omp_context (gimple stmt, omp_context *outer_ctx)
1489 omp_context *ctx = XCNEW (omp_context);
1491 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1492 (splay_tree_value) ctx);
1493 ctx->stmt = stmt;
1495 if (outer_ctx)
1497 ctx->outer = outer_ctx;
1498 ctx->cb = outer_ctx->cb;
1499 ctx->cb.block = NULL;
1500 ctx->depth = outer_ctx->depth + 1;
1501 ctx->reduction_map = outer_ctx->reduction_map;
1503 else
1505 ctx->cb.src_fn = current_function_decl;
1506 ctx->cb.dst_fn = current_function_decl;
1507 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1508 gcc_checking_assert (ctx->cb.src_node);
1509 ctx->cb.dst_node = ctx->cb.src_node;
1510 ctx->cb.src_cfun = cfun;
1511 ctx->cb.copy_decl = omp_copy_decl;
1512 ctx->cb.eh_lp_nr = 0;
1513 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1514 ctx->depth = 1;
1517 ctx->cb.decl_map = new hash_map<tree, tree>;
1519 return ctx;
1522 static gimple_seq maybe_catch_exception (gimple_seq);
1524 /* Finalize task copyfn. */
1526 static void
1527 finalize_task_copyfn (gomp_task *task_stmt)
1529 struct function *child_cfun;
1530 tree child_fn;
1531 gimple_seq seq = NULL, new_seq;
1532 gbind *bind;
1534 child_fn = gimple_omp_task_copy_fn (task_stmt);
1535 if (child_fn == NULL_TREE)
1536 return;
1538 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1539 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1541 push_cfun (child_cfun);
1542 bind = gimplify_body (child_fn, false);
1543 gimple_seq_add_stmt (&seq, bind);
1544 new_seq = maybe_catch_exception (seq);
1545 if (new_seq != seq)
1547 bind = gimple_build_bind (NULL, new_seq, NULL);
1548 seq = NULL;
1549 gimple_seq_add_stmt (&seq, bind);
1551 gimple_set_body (child_fn, seq);
1552 pop_cfun ();
1554 /* Inform the callgraph about the new function. */
1555 cgraph_node *node = cgraph_node::get_create (child_fn);
1556 node->parallelized_function = 1;
1557 cgraph_node::add_new_function (child_fn, false);
1560 /* Destroy a omp_context data structures. Called through the splay tree
1561 value delete callback. */
1563 static void
1564 delete_omp_context (splay_tree_value value)
1566 omp_context *ctx = (omp_context *) value;
1568 delete ctx->cb.decl_map;
1570 if (ctx->field_map)
1571 splay_tree_delete (ctx->field_map);
1572 if (ctx->sfield_map)
1573 splay_tree_delete (ctx->sfield_map);
1574 /* Reduction map is copied to nested contexts, so only delete it in the
1575 owner. */
1576 if (ctx->reduction_map
1577 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1578 && is_gimple_omp_offloaded (ctx->stmt)
1579 && is_gimple_omp_oacc (ctx->stmt))
1580 splay_tree_delete (ctx->reduction_map);
1582 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1583 it produces corrupt debug information. */
1584 if (ctx->record_type)
1586 tree t;
1587 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1588 DECL_ABSTRACT_ORIGIN (t) = NULL;
1590 if (ctx->srecord_type)
1592 tree t;
1593 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1594 DECL_ABSTRACT_ORIGIN (t) = NULL;
1597 if (is_task_ctx (ctx))
1598 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1600 XDELETE (ctx);
1603 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1604 context. */
1606 static void
1607 fixup_child_record_type (omp_context *ctx)
1609 tree f, type = ctx->record_type;
1611 /* ??? It isn't sufficient to just call remap_type here, because
1612 variably_modified_type_p doesn't work the way we expect for
1613 record types. Testing each field for whether it needs remapping
1614 and creating a new record by hand works, however. */
1615 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1616 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1617 break;
1618 if (f)
1620 tree name, new_fields = NULL;
1622 type = lang_hooks.types.make_type (RECORD_TYPE);
1623 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1624 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1625 TYPE_DECL, name, type);
1626 TYPE_NAME (type) = name;
1628 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1630 tree new_f = copy_node (f);
1631 DECL_CONTEXT (new_f) = type;
1632 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1633 DECL_CHAIN (new_f) = new_fields;
1634 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1635 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1636 &ctx->cb, NULL);
1637 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1638 &ctx->cb, NULL);
1639 new_fields = new_f;
1641 /* Arrange to be able to look up the receiver field
1642 given the sender field. */
1643 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1644 (splay_tree_value) new_f);
1646 TYPE_FIELDS (type) = nreverse (new_fields);
1647 layout_type (type);
1650 TREE_TYPE (ctx->receiver_decl)
1651 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1654 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1655 specified by CLAUSES. */
1657 static void
1658 scan_sharing_clauses (tree clauses, omp_context *ctx)
1660 tree c, decl;
1661 bool scan_array_reductions = false;
1663 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1665 bool by_ref;
1667 switch (OMP_CLAUSE_CODE (c))
1669 case OMP_CLAUSE_PRIVATE:
1670 decl = OMP_CLAUSE_DECL (c);
1671 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1672 goto do_private;
1673 else if (!is_variable_sized (decl))
1674 install_var_local (decl, ctx);
1675 break;
1677 case OMP_CLAUSE_SHARED:
1678 decl = OMP_CLAUSE_DECL (c);
1679 /* Ignore shared directives in teams construct. */
1680 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1682 /* Global variables don't need to be copied,
1683 the receiver side will use them directly. */
1684 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1685 if (is_global_var (odecl))
1686 break;
1687 insert_decl_map (&ctx->cb, decl, odecl);
1688 break;
1690 gcc_assert (is_taskreg_ctx (ctx));
1691 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1692 || !is_variable_sized (decl));
1693 /* Global variables don't need to be copied,
1694 the receiver side will use them directly. */
1695 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1696 break;
1697 by_ref = use_pointer_for_field (decl, ctx);
1698 if (! TREE_READONLY (decl)
1699 || TREE_ADDRESSABLE (decl)
1700 || by_ref
1701 || is_reference (decl))
1703 install_var_field (decl, by_ref, 3, ctx);
1704 install_var_local (decl, ctx);
1705 break;
1707 /* We don't need to copy const scalar vars back. */
1708 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1709 goto do_private;
1711 case OMP_CLAUSE_LASTPRIVATE:
1712 /* Let the corresponding firstprivate clause create
1713 the variable. */
1714 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1715 break;
1716 /* FALLTHRU */
1718 case OMP_CLAUSE_FIRSTPRIVATE:
1719 if (is_gimple_omp_oacc (ctx->stmt))
1721 sorry ("clause not supported yet");
1722 break;
1724 /* FALLTHRU */
1725 case OMP_CLAUSE_REDUCTION:
1726 case OMP_CLAUSE_LINEAR:
1727 decl = OMP_CLAUSE_DECL (c);
1728 do_private:
1729 if (is_variable_sized (decl))
1731 if (is_task_ctx (ctx))
1732 install_var_field (decl, false, 1, ctx);
1733 break;
1735 else if (is_taskreg_ctx (ctx))
1737 bool global
1738 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1739 by_ref = use_pointer_for_field (decl, NULL);
1741 if (is_task_ctx (ctx)
1742 && (global || by_ref || is_reference (decl)))
1744 install_var_field (decl, false, 1, ctx);
1745 if (!global)
1746 install_var_field (decl, by_ref, 2, ctx);
1748 else if (!global)
1749 install_var_field (decl, by_ref, 3, ctx);
1751 install_var_local (decl, ctx);
1752 if (is_gimple_omp_oacc (ctx->stmt)
1753 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1755 /* Create a decl for the reduction array. */
1756 tree var = OMP_CLAUSE_DECL (c);
1757 tree type = get_base_type (var);
1758 tree ptype = build_pointer_type (type);
1759 tree array = create_tmp_var (ptype,
1760 oacc_get_reduction_array_id (var));
1761 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1762 install_var_field (array, true, 3, c);
1763 install_var_local (array, c);
1765 /* Insert it into the current context. */
1766 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1767 oacc_get_reduction_array_id (var),
1768 (splay_tree_value) array);
1769 splay_tree_insert (ctx->reduction_map,
1770 (splay_tree_key) array,
1771 (splay_tree_value) array);
1773 break;
1775 case OMP_CLAUSE__LOOPTEMP_:
1776 gcc_assert (is_parallel_ctx (ctx));
1777 decl = OMP_CLAUSE_DECL (c);
1778 install_var_field (decl, false, 3, ctx);
1779 install_var_local (decl, ctx);
1780 break;
1782 case OMP_CLAUSE_COPYPRIVATE:
1783 case OMP_CLAUSE_COPYIN:
1784 decl = OMP_CLAUSE_DECL (c);
1785 by_ref = use_pointer_for_field (decl, NULL);
1786 install_var_field (decl, by_ref, 3, ctx);
1787 break;
1789 case OMP_CLAUSE_DEFAULT:
1790 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1791 break;
1793 case OMP_CLAUSE_FINAL:
1794 case OMP_CLAUSE_IF:
1795 case OMP_CLAUSE_NUM_THREADS:
1796 case OMP_CLAUSE_NUM_TEAMS:
1797 case OMP_CLAUSE_THREAD_LIMIT:
1798 case OMP_CLAUSE_DEVICE:
1799 case OMP_CLAUSE_SCHEDULE:
1800 case OMP_CLAUSE_DIST_SCHEDULE:
1801 case OMP_CLAUSE_DEPEND:
1802 case OMP_CLAUSE__CILK_FOR_COUNT_:
1803 case OMP_CLAUSE_NUM_GANGS:
1804 case OMP_CLAUSE_NUM_WORKERS:
1805 case OMP_CLAUSE_VECTOR_LENGTH:
1806 if (ctx->outer)
1807 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1808 break;
1810 case OMP_CLAUSE_TO:
1811 case OMP_CLAUSE_FROM:
1812 case OMP_CLAUSE_MAP:
1813 if (ctx->outer)
1814 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1815 decl = OMP_CLAUSE_DECL (c);
1816 /* Global variables with "omp declare target" attribute
1817 don't need to be copied, the receiver side will use them
1818 directly. */
1819 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1820 && DECL_P (decl)
1821 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1822 && varpool_node::get_create (decl)->offloadable)
1823 break;
1824 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1825 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
1827 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1828 not offloaded; there is nothing to map for those. */
1829 if (!is_gimple_omp_offloaded (ctx->stmt)
1830 && !POINTER_TYPE_P (TREE_TYPE (decl))
1831 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
1832 break;
1834 if (DECL_P (decl))
1836 if (DECL_SIZE (decl)
1837 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1839 tree decl2 = DECL_VALUE_EXPR (decl);
1840 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1841 decl2 = TREE_OPERAND (decl2, 0);
1842 gcc_assert (DECL_P (decl2));
1843 install_var_field (decl2, true, 3, ctx);
1844 install_var_local (decl2, ctx);
1845 install_var_local (decl, ctx);
1847 else
1849 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1850 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1851 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1852 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1853 install_var_field (decl, true, 7, ctx);
1854 else
1855 install_var_field (decl, true, 3, ctx);
1856 if (is_gimple_omp_offloaded (ctx->stmt))
1857 install_var_local (decl, ctx);
1860 else
1862 tree base = get_base_address (decl);
1863 tree nc = OMP_CLAUSE_CHAIN (c);
1864 if (DECL_P (base)
1865 && nc != NULL_TREE
1866 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1867 && OMP_CLAUSE_DECL (nc) == base
1868 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1869 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1871 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1872 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1874 else
1876 if (ctx->outer)
1878 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1879 decl = OMP_CLAUSE_DECL (c);
1881 gcc_assert (!splay_tree_lookup (ctx->field_map,
1882 (splay_tree_key) decl));
1883 tree field
1884 = build_decl (OMP_CLAUSE_LOCATION (c),
1885 FIELD_DECL, NULL_TREE, ptr_type_node);
1886 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1887 insert_field_into_struct (ctx->record_type, field);
1888 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1889 (splay_tree_value) field);
1892 break;
1894 case OMP_CLAUSE_NOWAIT:
1895 case OMP_CLAUSE_ORDERED:
1896 case OMP_CLAUSE_COLLAPSE:
1897 case OMP_CLAUSE_UNTIED:
1898 case OMP_CLAUSE_MERGEABLE:
1899 case OMP_CLAUSE_PROC_BIND:
1900 case OMP_CLAUSE_SAFELEN:
1901 case OMP_CLAUSE_ASYNC:
1902 case OMP_CLAUSE_WAIT:
1903 case OMP_CLAUSE_GANG:
1904 case OMP_CLAUSE_WORKER:
1905 case OMP_CLAUSE_VECTOR:
1906 break;
1908 case OMP_CLAUSE_ALIGNED:
1909 decl = OMP_CLAUSE_DECL (c);
1910 if (is_global_var (decl)
1911 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1912 install_var_local (decl, ctx);
1913 break;
1915 case OMP_CLAUSE_DEVICE_RESIDENT:
1916 case OMP_CLAUSE_USE_DEVICE:
1917 case OMP_CLAUSE__CACHE_:
1918 case OMP_CLAUSE_INDEPENDENT:
1919 case OMP_CLAUSE_AUTO:
1920 case OMP_CLAUSE_SEQ:
1921 sorry ("Clause not supported yet");
1922 break;
1924 default:
1925 gcc_unreachable ();
1929 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1931 switch (OMP_CLAUSE_CODE (c))
1933 case OMP_CLAUSE_LASTPRIVATE:
1934 /* Let the corresponding firstprivate clause create
1935 the variable. */
1936 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1937 scan_array_reductions = true;
1938 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1939 break;
1940 /* FALLTHRU */
1942 case OMP_CLAUSE_FIRSTPRIVATE:
1943 if (is_gimple_omp_oacc (ctx->stmt))
1945 sorry ("clause not supported yet");
1946 break;
1948 /* FALLTHRU */
1949 case OMP_CLAUSE_PRIVATE:
1950 case OMP_CLAUSE_REDUCTION:
1951 case OMP_CLAUSE_LINEAR:
1952 decl = OMP_CLAUSE_DECL (c);
1953 if (is_variable_sized (decl))
1954 install_var_local (decl, ctx);
1955 fixup_remapped_decl (decl, ctx,
1956 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1957 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1958 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1959 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1960 scan_array_reductions = true;
1961 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1962 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1963 scan_array_reductions = true;
1964 break;
1966 case OMP_CLAUSE_SHARED:
1967 /* Ignore shared directives in teams construct. */
1968 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1969 break;
1970 decl = OMP_CLAUSE_DECL (c);
1971 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1972 fixup_remapped_decl (decl, ctx, false);
1973 break;
1975 case OMP_CLAUSE_MAP:
1976 if (!is_gimple_omp_offloaded (ctx->stmt))
1977 break;
1978 decl = OMP_CLAUSE_DECL (c);
1979 if (DECL_P (decl)
1980 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1981 && varpool_node::get_create (decl)->offloadable)
1982 break;
1983 if (DECL_P (decl))
1985 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1986 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1987 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1989 tree new_decl = lookup_decl (decl, ctx);
1990 TREE_TYPE (new_decl)
1991 = remap_type (TREE_TYPE (decl), &ctx->cb);
1993 else if (DECL_SIZE (decl)
1994 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1996 tree decl2 = DECL_VALUE_EXPR (decl);
1997 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1998 decl2 = TREE_OPERAND (decl2, 0);
1999 gcc_assert (DECL_P (decl2));
2000 fixup_remapped_decl (decl2, ctx, false);
2001 fixup_remapped_decl (decl, ctx, true);
2003 else
2004 fixup_remapped_decl (decl, ctx, false);
2006 break;
2008 case OMP_CLAUSE_COPYPRIVATE:
2009 case OMP_CLAUSE_COPYIN:
2010 case OMP_CLAUSE_DEFAULT:
2011 case OMP_CLAUSE_IF:
2012 case OMP_CLAUSE_NUM_THREADS:
2013 case OMP_CLAUSE_NUM_TEAMS:
2014 case OMP_CLAUSE_THREAD_LIMIT:
2015 case OMP_CLAUSE_DEVICE:
2016 case OMP_CLAUSE_SCHEDULE:
2017 case OMP_CLAUSE_DIST_SCHEDULE:
2018 case OMP_CLAUSE_NOWAIT:
2019 case OMP_CLAUSE_ORDERED:
2020 case OMP_CLAUSE_COLLAPSE:
2021 case OMP_CLAUSE_UNTIED:
2022 case OMP_CLAUSE_FINAL:
2023 case OMP_CLAUSE_MERGEABLE:
2024 case OMP_CLAUSE_PROC_BIND:
2025 case OMP_CLAUSE_SAFELEN:
2026 case OMP_CLAUSE_ALIGNED:
2027 case OMP_CLAUSE_DEPEND:
2028 case OMP_CLAUSE__LOOPTEMP_:
2029 case OMP_CLAUSE_TO:
2030 case OMP_CLAUSE_FROM:
2031 case OMP_CLAUSE__CILK_FOR_COUNT_:
2032 case OMP_CLAUSE_ASYNC:
2033 case OMP_CLAUSE_WAIT:
2034 case OMP_CLAUSE_NUM_GANGS:
2035 case OMP_CLAUSE_NUM_WORKERS:
2036 case OMP_CLAUSE_VECTOR_LENGTH:
2037 case OMP_CLAUSE_GANG:
2038 case OMP_CLAUSE_WORKER:
2039 case OMP_CLAUSE_VECTOR:
2040 break;
2042 case OMP_CLAUSE_DEVICE_RESIDENT:
2043 case OMP_CLAUSE_USE_DEVICE:
2044 case OMP_CLAUSE__CACHE_:
2045 case OMP_CLAUSE_INDEPENDENT:
2046 case OMP_CLAUSE_AUTO:
2047 case OMP_CLAUSE_SEQ:
2048 sorry ("Clause not supported yet");
2049 break;
2051 default:
2052 gcc_unreachable ();
2056 gcc_checking_assert (!scan_array_reductions
2057 || !is_gimple_omp_oacc (ctx->stmt));
2058 if (scan_array_reductions)
2059 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2060 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2061 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2063 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2064 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2066 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2067 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2068 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2069 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2070 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2071 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2074 /* Create a new name for omp child function. Returns an identifier. If
2075 IS_CILK_FOR is true then the suffix for the child function is
2076 "_cilk_for_fn." */
2078 static tree
2079 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2081 if (is_cilk_for)
2082 return clone_function_name (current_function_decl, "_cilk_for_fn");
2083 return clone_function_name (current_function_decl,
2084 task_copy ? "_omp_cpyfn" : "_omp_fn");
2087 /* Returns the type of the induction variable for the child function for
2088 _Cilk_for and the types for _high and _low variables based on TYPE. */
2090 static tree
2091 cilk_for_check_loop_diff_type (tree type)
2093 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2095 if (TYPE_UNSIGNED (type))
2096 return uint32_type_node;
2097 else
2098 return integer_type_node;
2100 else
2102 if (TYPE_UNSIGNED (type))
2103 return uint64_type_node;
2104 else
2105 return long_long_integer_type_node;
2109 /* Build a decl for the omp child function. It'll not contain a body
2110 yet, just the bare decl. */
2112 static void
2113 create_omp_child_function (omp_context *ctx, bool task_copy)
2115 tree decl, type, name, t;
2117 tree cilk_for_count
2118 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2119 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2120 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2121 tree cilk_var_type = NULL_TREE;
2123 name = create_omp_child_function_name (task_copy,
2124 cilk_for_count != NULL_TREE);
2125 if (task_copy)
2126 type = build_function_type_list (void_type_node, ptr_type_node,
2127 ptr_type_node, NULL_TREE);
2128 else if (cilk_for_count)
2130 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2131 cilk_var_type = cilk_for_check_loop_diff_type (type);
2132 type = build_function_type_list (void_type_node, ptr_type_node,
2133 cilk_var_type, cilk_var_type, NULL_TREE);
2135 else
2136 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2138 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2140 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2141 || !task_copy);
2142 if (!task_copy)
2143 ctx->cb.dst_fn = decl;
2144 else
2145 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2147 TREE_STATIC (decl) = 1;
2148 TREE_USED (decl) = 1;
2149 DECL_ARTIFICIAL (decl) = 1;
2150 DECL_IGNORED_P (decl) = 0;
2151 TREE_PUBLIC (decl) = 0;
2152 DECL_UNINLINABLE (decl) = 1;
2153 DECL_EXTERNAL (decl) = 0;
2154 DECL_CONTEXT (decl) = NULL_TREE;
2155 DECL_INITIAL (decl) = make_node (BLOCK);
2156 if (cgraph_node::get (current_function_decl)->offloadable)
2157 cgraph_node::get_create (decl)->offloadable = 1;
2158 else
2160 omp_context *octx;
2161 for (octx = ctx; octx; octx = octx->outer)
2162 if (is_gimple_omp_offloaded (octx->stmt))
2164 cgraph_node::get_create (decl)->offloadable = 1;
2165 #ifdef ENABLE_OFFLOADING
2166 g->have_offload = true;
2167 #endif
2168 break;
2172 if (cgraph_node::get_create (decl)->offloadable
2173 && !lookup_attribute ("omp declare target",
2174 DECL_ATTRIBUTES (current_function_decl)))
2175 DECL_ATTRIBUTES (decl)
2176 = tree_cons (get_identifier ("omp target entrypoint"),
2177 NULL_TREE, DECL_ATTRIBUTES (decl));
2179 t = build_decl (DECL_SOURCE_LOCATION (decl),
2180 RESULT_DECL, NULL_TREE, void_type_node);
2181 DECL_ARTIFICIAL (t) = 1;
2182 DECL_IGNORED_P (t) = 1;
2183 DECL_CONTEXT (t) = decl;
2184 DECL_RESULT (decl) = t;
2186 /* _Cilk_for's child function requires two extra parameters called
2187 __low and __high that are set the by Cilk runtime when it calls this
2188 function. */
2189 if (cilk_for_count)
2191 t = build_decl (DECL_SOURCE_LOCATION (decl),
2192 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2193 DECL_ARTIFICIAL (t) = 1;
2194 DECL_NAMELESS (t) = 1;
2195 DECL_ARG_TYPE (t) = ptr_type_node;
2196 DECL_CONTEXT (t) = current_function_decl;
2197 TREE_USED (t) = 1;
2198 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2199 DECL_ARGUMENTS (decl) = t;
2201 t = build_decl (DECL_SOURCE_LOCATION (decl),
2202 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2203 DECL_ARTIFICIAL (t) = 1;
2204 DECL_NAMELESS (t) = 1;
2205 DECL_ARG_TYPE (t) = ptr_type_node;
2206 DECL_CONTEXT (t) = current_function_decl;
2207 TREE_USED (t) = 1;
2208 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2209 DECL_ARGUMENTS (decl) = t;
2212 tree data_name = get_identifier (".omp_data_i");
2213 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2214 ptr_type_node);
2215 DECL_ARTIFICIAL (t) = 1;
2216 DECL_NAMELESS (t) = 1;
2217 DECL_ARG_TYPE (t) = ptr_type_node;
2218 DECL_CONTEXT (t) = current_function_decl;
2219 TREE_USED (t) = 1;
2220 if (cilk_for_count)
2221 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2222 DECL_ARGUMENTS (decl) = t;
2223 if (!task_copy)
2224 ctx->receiver_decl = t;
2225 else
2227 t = build_decl (DECL_SOURCE_LOCATION (decl),
2228 PARM_DECL, get_identifier (".omp_data_o"),
2229 ptr_type_node);
2230 DECL_ARTIFICIAL (t) = 1;
2231 DECL_NAMELESS (t) = 1;
2232 DECL_ARG_TYPE (t) = ptr_type_node;
2233 DECL_CONTEXT (t) = current_function_decl;
2234 TREE_USED (t) = 1;
2235 TREE_ADDRESSABLE (t) = 1;
2236 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2237 DECL_ARGUMENTS (decl) = t;
2240 /* Allocate memory for the function structure. The call to
2241 allocate_struct_function clobbers CFUN, so we need to restore
2242 it afterward. */
2243 push_struct_function (decl);
2244 cfun->function_end_locus = gimple_location (ctx->stmt);
2245 pop_cfun ();
2248 /* Callback for walk_gimple_seq. Check if combined parallel
2249 contains gimple_omp_for_combined_into_p OMP_FOR. */
2251 static tree
2252 find_combined_for (gimple_stmt_iterator *gsi_p,
2253 bool *handled_ops_p,
2254 struct walk_stmt_info *wi)
2256 gimple stmt = gsi_stmt (*gsi_p);
2258 *handled_ops_p = true;
2259 switch (gimple_code (stmt))
2261 WALK_SUBSTMTS;
2263 case GIMPLE_OMP_FOR:
2264 if (gimple_omp_for_combined_into_p (stmt)
2265 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2267 wi->info = stmt;
2268 return integer_zero_node;
2270 break;
2271 default:
2272 break;
2274 return NULL;
2277 /* Scan an OpenMP parallel directive. */
2279 static void
2280 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2282 omp_context *ctx;
2283 tree name;
2284 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2286 /* Ignore parallel directives with empty bodies, unless there
2287 are copyin clauses. */
2288 if (optimize > 0
2289 && empty_body_p (gimple_omp_body (stmt))
2290 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2291 OMP_CLAUSE_COPYIN) == NULL)
2293 gsi_replace (gsi, gimple_build_nop (), false);
2294 return;
2297 if (gimple_omp_parallel_combined_p (stmt))
2299 struct walk_stmt_info wi;
2301 memset (&wi, 0, sizeof (wi));
2302 wi.val_only = true;
2303 walk_gimple_seq (gimple_omp_body (stmt),
2304 find_combined_for, NULL, &wi);
2305 if (wi.info)
2307 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2308 struct omp_for_data fd;
2309 extract_omp_for_data (for_stmt, &fd, NULL);
2310 /* We need two temporaries with fd.loop.v type (istart/iend)
2311 and then (fd.collapse - 1) temporaries with the same
2312 type for count2 ... countN-1 vars if not constant. */
2313 size_t count = 2, i;
2314 tree type = fd.iter_type;
2315 if (fd.collapse > 1
2316 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2317 count += fd.collapse - 1;
2318 for (i = 0; i < count; i++)
2320 tree temp = create_tmp_var (type);
2321 tree c = build_omp_clause (UNKNOWN_LOCATION,
2322 OMP_CLAUSE__LOOPTEMP_);
2323 insert_decl_map (&outer_ctx->cb, temp, temp);
2324 OMP_CLAUSE_DECL (c) = temp;
2325 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2326 gimple_omp_parallel_set_clauses (stmt, c);
2331 ctx = new_omp_context (stmt, outer_ctx);
2332 taskreg_contexts.safe_push (ctx);
2333 if (taskreg_nesting_level > 1)
2334 ctx->is_nested = true;
2335 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2336 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2337 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2338 name = create_tmp_var_name (".omp_data_s");
2339 name = build_decl (gimple_location (stmt),
2340 TYPE_DECL, name, ctx->record_type);
2341 DECL_ARTIFICIAL (name) = 1;
2342 DECL_NAMELESS (name) = 1;
2343 TYPE_NAME (ctx->record_type) = name;
2344 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2345 create_omp_child_function (ctx, false);
2346 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2348 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2349 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2351 if (TYPE_FIELDS (ctx->record_type) == NULL)
2352 ctx->record_type = ctx->receiver_decl = NULL;
2355 /* Scan an OpenMP task directive. */
2357 static void
2358 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2360 omp_context *ctx;
2361 tree name, t;
2362 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2364 /* Ignore task directives with empty bodies. */
2365 if (optimize > 0
2366 && empty_body_p (gimple_omp_body (stmt)))
2368 gsi_replace (gsi, gimple_build_nop (), false);
2369 return;
2372 ctx = new_omp_context (stmt, outer_ctx);
2373 taskreg_contexts.safe_push (ctx);
2374 if (taskreg_nesting_level > 1)
2375 ctx->is_nested = true;
2376 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2377 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2378 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2379 name = create_tmp_var_name (".omp_data_s");
2380 name = build_decl (gimple_location (stmt),
2381 TYPE_DECL, name, ctx->record_type);
2382 DECL_ARTIFICIAL (name) = 1;
2383 DECL_NAMELESS (name) = 1;
2384 TYPE_NAME (ctx->record_type) = name;
2385 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2386 create_omp_child_function (ctx, false);
2387 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2389 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2391 if (ctx->srecord_type)
2393 name = create_tmp_var_name (".omp_data_a");
2394 name = build_decl (gimple_location (stmt),
2395 TYPE_DECL, name, ctx->srecord_type);
2396 DECL_ARTIFICIAL (name) = 1;
2397 DECL_NAMELESS (name) = 1;
2398 TYPE_NAME (ctx->srecord_type) = name;
2399 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2400 create_omp_child_function (ctx, true);
2403 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2405 if (TYPE_FIELDS (ctx->record_type) == NULL)
2407 ctx->record_type = ctx->receiver_decl = NULL;
2408 t = build_int_cst (long_integer_type_node, 0);
2409 gimple_omp_task_set_arg_size (stmt, t);
2410 t = build_int_cst (long_integer_type_node, 1);
2411 gimple_omp_task_set_arg_align (stmt, t);
2416 /* If any decls have been made addressable during scan_omp,
2417 adjust their fields if needed, and layout record types
2418 of parallel/task constructs. */
2420 static void
2421 finish_taskreg_scan (omp_context *ctx)
2423 if (ctx->record_type == NULL_TREE)
2424 return;
2426 /* If any task_shared_vars were needed, verify all
2427 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2428 statements if use_pointer_for_field hasn't changed
2429 because of that. If it did, update field types now. */
2430 if (task_shared_vars)
2432 tree c;
2434 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2435 c; c = OMP_CLAUSE_CHAIN (c))
2436 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2438 tree decl = OMP_CLAUSE_DECL (c);
2440 /* Global variables don't need to be copied,
2441 the receiver side will use them directly. */
2442 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2443 continue;
2444 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2445 || !use_pointer_for_field (decl, ctx))
2446 continue;
2447 tree field = lookup_field (decl, ctx);
2448 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2449 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2450 continue;
2451 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2452 TREE_THIS_VOLATILE (field) = 0;
2453 DECL_USER_ALIGN (field) = 0;
2454 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2455 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2456 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2457 if (ctx->srecord_type)
2459 tree sfield = lookup_sfield (decl, ctx);
2460 TREE_TYPE (sfield) = TREE_TYPE (field);
2461 TREE_THIS_VOLATILE (sfield) = 0;
2462 DECL_USER_ALIGN (sfield) = 0;
2463 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2464 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2465 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2470 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2472 layout_type (ctx->record_type);
2473 fixup_child_record_type (ctx);
2475 else
2477 location_t loc = gimple_location (ctx->stmt);
2478 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2479 /* Move VLA fields to the end. */
2480 p = &TYPE_FIELDS (ctx->record_type);
2481 while (*p)
2482 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2483 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2485 *q = *p;
2486 *p = TREE_CHAIN (*p);
2487 TREE_CHAIN (*q) = NULL_TREE;
2488 q = &TREE_CHAIN (*q);
2490 else
2491 p = &DECL_CHAIN (*p);
2492 *p = vla_fields;
2493 layout_type (ctx->record_type);
2494 fixup_child_record_type (ctx);
2495 if (ctx->srecord_type)
2496 layout_type (ctx->srecord_type);
2497 tree t = fold_convert_loc (loc, long_integer_type_node,
2498 TYPE_SIZE_UNIT (ctx->record_type));
2499 gimple_omp_task_set_arg_size (ctx->stmt, t);
2500 t = build_int_cst (long_integer_type_node,
2501 TYPE_ALIGN_UNIT (ctx->record_type));
2502 gimple_omp_task_set_arg_align (ctx->stmt, t);
2507 static omp_context *
2508 enclosing_target_ctx (omp_context *ctx)
2510 while (ctx != NULL
2511 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2512 ctx = ctx->outer;
2513 gcc_assert (ctx != NULL);
2514 return ctx;
2517 static bool
2518 oacc_loop_or_target_p (gimple stmt)
2520 enum gimple_code outer_type = gimple_code (stmt);
2521 return ((outer_type == GIMPLE_OMP_TARGET
2522 && ((gimple_omp_target_kind (stmt)
2523 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2524 || (gimple_omp_target_kind (stmt)
2525 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2526 || (outer_type == GIMPLE_OMP_FOR
2527 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2530 /* Scan a GIMPLE_OMP_FOR. */
2532 static void
2533 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2535 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
2536 omp_context *ctx;
2537 size_t i;
2538 tree clauses = gimple_omp_for_clauses (stmt);
2540 if (outer_ctx)
2541 outer_type = gimple_code (outer_ctx->stmt);
2543 ctx = new_omp_context (stmt, outer_ctx);
2545 if (is_gimple_omp_oacc (stmt))
2547 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2548 ctx->gwv_this = outer_ctx->gwv_this;
2549 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2551 int val;
2552 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2553 val = MASK_GANG;
2554 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2555 val = MASK_WORKER;
2556 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2557 val = MASK_VECTOR;
2558 else
2559 continue;
2560 ctx->gwv_this |= val;
2561 if (!outer_ctx)
2563 /* Skip; not nested inside a region. */
2564 continue;
2566 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2568 /* Skip; not nested inside an OpenACC region. */
2569 continue;
2571 if (outer_type == GIMPLE_OMP_FOR)
2572 outer_ctx->gwv_below |= val;
2573 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2575 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2576 if (gimple_omp_target_kind (enclosing->stmt)
2577 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2578 error_at (gimple_location (stmt),
2579 "no arguments allowed to gang, worker and vector clauses inside parallel");
2584 scan_sharing_clauses (clauses, ctx);
2586 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2587 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2589 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2590 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2591 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2592 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2594 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2596 if (is_gimple_omp_oacc (stmt))
2598 if (ctx->gwv_this & ctx->gwv_below)
2599 error_at (gimple_location (stmt),
2600 "gang, worker and vector may occur only once in a loop nest");
2601 else if (ctx->gwv_below != 0
2602 && ctx->gwv_this > ctx->gwv_below)
2603 error_at (gimple_location (stmt),
2604 "gang, worker and vector must occur in this order in a loop nest");
2605 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2606 outer_ctx->gwv_below |= ctx->gwv_below;
2610 /* Scan an OpenMP sections directive. */
2612 static void
2613 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2615 omp_context *ctx;
2617 ctx = new_omp_context (stmt, outer_ctx);
2618 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2619 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2622 /* Scan an OpenMP single directive. */
2624 static void
2625 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2627 omp_context *ctx;
2628 tree name;
2630 ctx = new_omp_context (stmt, outer_ctx);
2631 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2632 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2633 name = create_tmp_var_name (".omp_copy_s");
2634 name = build_decl (gimple_location (stmt),
2635 TYPE_DECL, name, ctx->record_type);
2636 TYPE_NAME (ctx->record_type) = name;
2638 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2639 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2641 if (TYPE_FIELDS (ctx->record_type) == NULL)
2642 ctx->record_type = NULL;
2643 else
2644 layout_type (ctx->record_type);
2647 /* Scan a GIMPLE_OMP_TARGET. */
2649 static void
2650 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2652 omp_context *ctx;
2653 tree name;
2654 bool offloaded = is_gimple_omp_offloaded (stmt);
2655 tree clauses = gimple_omp_target_clauses (stmt);
2657 ctx = new_omp_context (stmt, outer_ctx);
2658 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2659 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2660 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2661 name = create_tmp_var_name (".omp_data_t");
2662 name = build_decl (gimple_location (stmt),
2663 TYPE_DECL, name, ctx->record_type);
2664 DECL_ARTIFICIAL (name) = 1;
2665 DECL_NAMELESS (name) = 1;
2666 TYPE_NAME (ctx->record_type) = name;
2667 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2668 if (offloaded)
2670 if (is_gimple_omp_oacc (stmt))
2671 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2672 0, 0);
2674 create_omp_child_function (ctx, false);
2675 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2678 if (is_gimple_omp_oacc (stmt))
2680 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2682 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2683 ctx->gwv_this |= MASK_GANG;
2684 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2685 ctx->gwv_this |= MASK_WORKER;
2686 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2687 ctx->gwv_this |= MASK_VECTOR;
2691 scan_sharing_clauses (clauses, ctx);
2692 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2694 if (TYPE_FIELDS (ctx->record_type) == NULL)
2695 ctx->record_type = ctx->receiver_decl = NULL;
2696 else
2698 TYPE_FIELDS (ctx->record_type)
2699 = nreverse (TYPE_FIELDS (ctx->record_type));
2700 #ifdef ENABLE_CHECKING
2701 tree field;
2702 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2703 for (field = TYPE_FIELDS (ctx->record_type);
2704 field;
2705 field = DECL_CHAIN (field))
2706 gcc_assert (DECL_ALIGN (field) == align);
2707 #endif
2708 layout_type (ctx->record_type);
2709 if (offloaded)
2710 fixup_child_record_type (ctx);
2714 /* Scan an OpenMP teams directive. */
2716 static void
2717 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2719 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2720 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2721 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2724 /* Check nesting restrictions. */
2725 static bool
2726 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2728 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2729 inside an OpenACC CTX. */
2730 if (!(is_gimple_omp (stmt)
2731 && is_gimple_omp_oacc (stmt)))
2733 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2734 if (is_gimple_omp (ctx_->stmt)
2735 && is_gimple_omp_oacc (ctx_->stmt))
2737 error_at (gimple_location (stmt),
2738 "non-OpenACC construct inside of OpenACC region");
2739 return false;
2743 if (ctx != NULL)
2745 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2746 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2748 error_at (gimple_location (stmt),
2749 "OpenMP constructs may not be nested inside simd region");
2750 return false;
2752 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2754 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2755 || (gimple_omp_for_kind (stmt)
2756 != GF_OMP_FOR_KIND_DISTRIBUTE))
2757 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2759 error_at (gimple_location (stmt),
2760 "only distribute or parallel constructs are allowed to "
2761 "be closely nested inside teams construct");
2762 return false;
2766 switch (gimple_code (stmt))
2768 case GIMPLE_OMP_FOR:
2769 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2770 return true;
2771 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2773 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2775 error_at (gimple_location (stmt),
2776 "distribute construct must be closely nested inside "
2777 "teams construct");
2778 return false;
2780 return true;
2782 /* FALLTHRU */
2783 case GIMPLE_CALL:
2784 if (is_gimple_call (stmt)
2785 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2786 == BUILT_IN_GOMP_CANCEL
2787 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2788 == BUILT_IN_GOMP_CANCELLATION_POINT))
2790 const char *bad = NULL;
2791 const char *kind = NULL;
2792 if (ctx == NULL)
2794 error_at (gimple_location (stmt), "orphaned %qs construct",
2795 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2796 == BUILT_IN_GOMP_CANCEL
2797 ? "#pragma omp cancel"
2798 : "#pragma omp cancellation point");
2799 return false;
2801 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2802 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2803 : 0)
2805 case 1:
2806 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2807 bad = "#pragma omp parallel";
2808 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2809 == BUILT_IN_GOMP_CANCEL
2810 && !integer_zerop (gimple_call_arg (stmt, 1)))
2811 ctx->cancellable = true;
2812 kind = "parallel";
2813 break;
2814 case 2:
2815 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2816 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2817 bad = "#pragma omp for";
2818 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2819 == BUILT_IN_GOMP_CANCEL
2820 && !integer_zerop (gimple_call_arg (stmt, 1)))
2822 ctx->cancellable = true;
2823 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2824 OMP_CLAUSE_NOWAIT))
2825 warning_at (gimple_location (stmt), 0,
2826 "%<#pragma omp cancel for%> inside "
2827 "%<nowait%> for construct");
2828 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2829 OMP_CLAUSE_ORDERED))
2830 warning_at (gimple_location (stmt), 0,
2831 "%<#pragma omp cancel for%> inside "
2832 "%<ordered%> for construct");
2834 kind = "for";
2835 break;
2836 case 4:
2837 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2838 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2839 bad = "#pragma omp sections";
2840 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2841 == BUILT_IN_GOMP_CANCEL
2842 && !integer_zerop (gimple_call_arg (stmt, 1)))
2844 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2846 ctx->cancellable = true;
2847 if (find_omp_clause (gimple_omp_sections_clauses
2848 (ctx->stmt),
2849 OMP_CLAUSE_NOWAIT))
2850 warning_at (gimple_location (stmt), 0,
2851 "%<#pragma omp cancel sections%> inside "
2852 "%<nowait%> sections construct");
2854 else
2856 gcc_assert (ctx->outer
2857 && gimple_code (ctx->outer->stmt)
2858 == GIMPLE_OMP_SECTIONS);
2859 ctx->outer->cancellable = true;
2860 if (find_omp_clause (gimple_omp_sections_clauses
2861 (ctx->outer->stmt),
2862 OMP_CLAUSE_NOWAIT))
2863 warning_at (gimple_location (stmt), 0,
2864 "%<#pragma omp cancel sections%> inside "
2865 "%<nowait%> sections construct");
2868 kind = "sections";
2869 break;
2870 case 8:
2871 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2872 bad = "#pragma omp task";
2873 else
2874 ctx->cancellable = true;
2875 kind = "taskgroup";
2876 break;
2877 default:
2878 error_at (gimple_location (stmt), "invalid arguments");
2879 return false;
2881 if (bad)
2883 error_at (gimple_location (stmt),
2884 "%<%s %s%> construct not closely nested inside of %qs",
2885 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2886 == BUILT_IN_GOMP_CANCEL
2887 ? "#pragma omp cancel"
2888 : "#pragma omp cancellation point", kind, bad);
2889 return false;
2892 /* FALLTHRU */
2893 case GIMPLE_OMP_SECTIONS:
2894 case GIMPLE_OMP_SINGLE:
2895 for (; ctx != NULL; ctx = ctx->outer)
2896 switch (gimple_code (ctx->stmt))
2898 case GIMPLE_OMP_FOR:
2899 case GIMPLE_OMP_SECTIONS:
2900 case GIMPLE_OMP_SINGLE:
2901 case GIMPLE_OMP_ORDERED:
2902 case GIMPLE_OMP_MASTER:
2903 case GIMPLE_OMP_TASK:
2904 case GIMPLE_OMP_CRITICAL:
2905 if (is_gimple_call (stmt))
2907 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2908 != BUILT_IN_GOMP_BARRIER)
2909 return true;
2910 error_at (gimple_location (stmt),
2911 "barrier region may not be closely nested inside "
2912 "of work-sharing, critical, ordered, master or "
2913 "explicit task region");
2914 return false;
2916 error_at (gimple_location (stmt),
2917 "work-sharing region may not be closely nested inside "
2918 "of work-sharing, critical, ordered, master or explicit "
2919 "task region");
2920 return false;
2921 case GIMPLE_OMP_PARALLEL:
2922 return true;
2923 default:
2924 break;
2926 break;
2927 case GIMPLE_OMP_MASTER:
2928 for (; ctx != NULL; ctx = ctx->outer)
2929 switch (gimple_code (ctx->stmt))
2931 case GIMPLE_OMP_FOR:
2932 case GIMPLE_OMP_SECTIONS:
2933 case GIMPLE_OMP_SINGLE:
2934 case GIMPLE_OMP_TASK:
2935 error_at (gimple_location (stmt),
2936 "master region may not be closely nested inside "
2937 "of work-sharing or explicit task region");
2938 return false;
2939 case GIMPLE_OMP_PARALLEL:
2940 return true;
2941 default:
2942 break;
2944 break;
2945 case GIMPLE_OMP_ORDERED:
2946 for (; ctx != NULL; ctx = ctx->outer)
2947 switch (gimple_code (ctx->stmt))
2949 case GIMPLE_OMP_CRITICAL:
2950 case GIMPLE_OMP_TASK:
2951 error_at (gimple_location (stmt),
2952 "ordered region may not be closely nested inside "
2953 "of critical or explicit task region");
2954 return false;
2955 case GIMPLE_OMP_FOR:
2956 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2957 OMP_CLAUSE_ORDERED) == NULL)
2959 error_at (gimple_location (stmt),
2960 "ordered region must be closely nested inside "
2961 "a loop region with an ordered clause");
2962 return false;
2964 return true;
2965 case GIMPLE_OMP_PARALLEL:
2966 error_at (gimple_location (stmt),
2967 "ordered region must be closely nested inside "
2968 "a loop region with an ordered clause");
2969 return false;
2970 default:
2971 break;
2973 break;
2974 case GIMPLE_OMP_CRITICAL:
2976 tree this_stmt_name
2977 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2978 for (; ctx != NULL; ctx = ctx->outer)
2979 if (gomp_critical *other_crit
2980 = dyn_cast <gomp_critical *> (ctx->stmt))
2981 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2983 error_at (gimple_location (stmt),
2984 "critical region may not be nested inside a critical "
2985 "region with the same name");
2986 return false;
2989 break;
2990 case GIMPLE_OMP_TEAMS:
2991 if (ctx == NULL
2992 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2993 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2995 error_at (gimple_location (stmt),
2996 "teams construct not closely nested inside of target "
2997 "region");
2998 return false;
3000 break;
3001 case GIMPLE_OMP_TARGET:
3002 for (; ctx != NULL; ctx = ctx->outer)
3004 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3006 if (is_gimple_omp (stmt)
3007 && is_gimple_omp_oacc (stmt)
3008 && is_gimple_omp (ctx->stmt))
3010 error_at (gimple_location (stmt),
3011 "OpenACC construct inside of non-OpenACC region");
3012 return false;
3014 continue;
3017 const char *stmt_name, *ctx_stmt_name;
3018 switch (gimple_omp_target_kind (stmt))
3020 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3021 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3022 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3023 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3024 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3025 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3026 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3027 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3028 default: gcc_unreachable ();
3030 switch (gimple_omp_target_kind (ctx->stmt))
3032 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3033 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3034 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3035 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3036 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3037 default: gcc_unreachable ();
3040 /* OpenACC/OpenMP mismatch? */
3041 if (is_gimple_omp_oacc (stmt)
3042 != is_gimple_omp_oacc (ctx->stmt))
3044 error_at (gimple_location (stmt),
3045 "%s %s construct inside of %s %s region",
3046 (is_gimple_omp_oacc (stmt)
3047 ? "OpenACC" : "OpenMP"), stmt_name,
3048 (is_gimple_omp_oacc (ctx->stmt)
3049 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3050 return false;
3052 if (is_gimple_omp_offloaded (ctx->stmt))
3054 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3055 if (is_gimple_omp_oacc (ctx->stmt))
3057 error_at (gimple_location (stmt),
3058 "%s construct inside of %s region",
3059 stmt_name, ctx_stmt_name);
3060 return false;
3062 else
3064 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3065 warning_at (gimple_location (stmt), 0,
3066 "%s construct inside of %s region",
3067 stmt_name, ctx_stmt_name);
3071 break;
3072 default:
3073 break;
3075 return true;
3079 /* Helper function scan_omp.
3081 Callback for walk_tree or operators in walk_gimple_stmt used to
3082 scan for OMP directives in TP. */
3084 static tree
3085 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3087 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3088 omp_context *ctx = (omp_context *) wi->info;
3089 tree t = *tp;
3091 switch (TREE_CODE (t))
3093 case VAR_DECL:
3094 case PARM_DECL:
3095 case LABEL_DECL:
3096 case RESULT_DECL:
3097 if (ctx)
3098 *tp = remap_decl (t, &ctx->cb);
3099 break;
3101 default:
3102 if (ctx && TYPE_P (t))
3103 *tp = remap_type (t, &ctx->cb);
3104 else if (!DECL_P (t))
3106 *walk_subtrees = 1;
3107 if (ctx)
3109 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3110 if (tem != TREE_TYPE (t))
3112 if (TREE_CODE (t) == INTEGER_CST)
3113 *tp = wide_int_to_tree (tem, t);
3114 else
3115 TREE_TYPE (t) = tem;
3119 break;
3122 return NULL_TREE;
3125 /* Return true if FNDECL is a setjmp or a longjmp. */
3127 static bool
3128 setjmp_or_longjmp_p (const_tree fndecl)
3130 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3131 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3132 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3133 return true;
3135 tree declname = DECL_NAME (fndecl);
3136 if (!declname)
3137 return false;
3138 const char *name = IDENTIFIER_POINTER (declname);
3139 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3143 /* Helper function for scan_omp.
3145 Callback for walk_gimple_stmt used to scan for OMP directives in
3146 the current statement in GSI. */
3148 static tree
3149 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3150 struct walk_stmt_info *wi)
3152 gimple stmt = gsi_stmt (*gsi);
3153 omp_context *ctx = (omp_context *) wi->info;
3155 if (gimple_has_location (stmt))
3156 input_location = gimple_location (stmt);
3158 /* Check the nesting restrictions. */
3159 bool remove = false;
3160 if (is_gimple_omp (stmt))
3161 remove = !check_omp_nesting_restrictions (stmt, ctx);
3162 else if (is_gimple_call (stmt))
3164 tree fndecl = gimple_call_fndecl (stmt);
3165 if (fndecl)
3167 if (setjmp_or_longjmp_p (fndecl)
3168 && ctx
3169 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3170 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3172 remove = true;
3173 error_at (gimple_location (stmt),
3174 "setjmp/longjmp inside simd construct");
3176 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3177 switch (DECL_FUNCTION_CODE (fndecl))
3179 case BUILT_IN_GOMP_BARRIER:
3180 case BUILT_IN_GOMP_CANCEL:
3181 case BUILT_IN_GOMP_CANCELLATION_POINT:
3182 case BUILT_IN_GOMP_TASKYIELD:
3183 case BUILT_IN_GOMP_TASKWAIT:
3184 case BUILT_IN_GOMP_TASKGROUP_START:
3185 case BUILT_IN_GOMP_TASKGROUP_END:
3186 remove = !check_omp_nesting_restrictions (stmt, ctx);
3187 break;
3188 default:
3189 break;
3193 if (remove)
3195 stmt = gimple_build_nop ();
3196 gsi_replace (gsi, stmt, false);
3199 *handled_ops_p = true;
3201 switch (gimple_code (stmt))
3203 case GIMPLE_OMP_PARALLEL:
3204 taskreg_nesting_level++;
3205 scan_omp_parallel (gsi, ctx);
3206 taskreg_nesting_level--;
3207 break;
3209 case GIMPLE_OMP_TASK:
3210 taskreg_nesting_level++;
3211 scan_omp_task (gsi, ctx);
3212 taskreg_nesting_level--;
3213 break;
3215 case GIMPLE_OMP_FOR:
3216 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3217 break;
3219 case GIMPLE_OMP_SECTIONS:
3220 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3221 break;
3223 case GIMPLE_OMP_SINGLE:
3224 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3225 break;
3227 case GIMPLE_OMP_SECTION:
3228 case GIMPLE_OMP_MASTER:
3229 case GIMPLE_OMP_TASKGROUP:
3230 case GIMPLE_OMP_ORDERED:
3231 case GIMPLE_OMP_CRITICAL:
3232 ctx = new_omp_context (stmt, ctx);
3233 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3234 break;
3236 case GIMPLE_OMP_TARGET:
3237 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3238 break;
3240 case GIMPLE_OMP_TEAMS:
3241 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3242 break;
3244 case GIMPLE_BIND:
3246 tree var;
3248 *handled_ops_p = false;
3249 if (ctx)
3250 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3251 var ;
3252 var = DECL_CHAIN (var))
3253 insert_decl_map (&ctx->cb, var, var);
3255 break;
3256 default:
3257 *handled_ops_p = false;
3258 break;
3261 return NULL_TREE;
3265 /* Scan all the statements starting at the current statement. CTX
3266 contains context information about the OMP directives and
3267 clauses found during the scan. */
3269 static void
3270 scan_omp (gimple_seq *body_p, omp_context *ctx)
3272 location_t saved_location;
3273 struct walk_stmt_info wi;
3275 memset (&wi, 0, sizeof (wi));
3276 wi.info = ctx;
3277 wi.want_locations = true;
3279 saved_location = input_location;
3280 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3281 input_location = saved_location;
3284 /* Re-gimplification and code generation routines. */
3286 /* Build a call to GOMP_barrier. */
3288 static gimple
3289 build_omp_barrier (tree lhs)
3291 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3292 : BUILT_IN_GOMP_BARRIER);
3293 gcall *g = gimple_build_call (fndecl, 0);
3294 if (lhs)
3295 gimple_call_set_lhs (g, lhs);
3296 return g;
3299 /* If a context was created for STMT when it was scanned, return it. */
3301 static omp_context *
3302 maybe_lookup_ctx (gimple stmt)
3304 splay_tree_node n;
3305 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3306 return n ? (omp_context *) n->value : NULL;
3310 /* Find the mapping for DECL in CTX or the immediately enclosing
3311 context that has a mapping for DECL.
3313 If CTX is a nested parallel directive, we may have to use the decl
3314 mappings created in CTX's parent context. Suppose that we have the
3315 following parallel nesting (variable UIDs showed for clarity):
3317 iD.1562 = 0;
3318 #omp parallel shared(iD.1562) -> outer parallel
3319 iD.1562 = iD.1562 + 1;
3321 #omp parallel shared (iD.1562) -> inner parallel
3322 iD.1562 = iD.1562 - 1;
3324 Each parallel structure will create a distinct .omp_data_s structure
3325 for copying iD.1562 in/out of the directive:
3327 outer parallel .omp_data_s.1.i -> iD.1562
3328 inner parallel .omp_data_s.2.i -> iD.1562
3330 A shared variable mapping will produce a copy-out operation before
3331 the parallel directive and a copy-in operation after it. So, in
3332 this case we would have:
3334 iD.1562 = 0;
3335 .omp_data_o.1.i = iD.1562;
3336 #omp parallel shared(iD.1562) -> outer parallel
3337 .omp_data_i.1 = &.omp_data_o.1
3338 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3340 .omp_data_o.2.i = iD.1562; -> **
3341 #omp parallel shared(iD.1562) -> inner parallel
3342 .omp_data_i.2 = &.omp_data_o.2
3343 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3346 ** This is a problem. The symbol iD.1562 cannot be referenced
3347 inside the body of the outer parallel region. But since we are
3348 emitting this copy operation while expanding the inner parallel
3349 directive, we need to access the CTX structure of the outer
3350 parallel directive to get the correct mapping:
3352 .omp_data_o.2.i = .omp_data_i.1->i
3354 Since there may be other workshare or parallel directives enclosing
3355 the parallel directive, it may be necessary to walk up the context
3356 parent chain. This is not a problem in general because nested
3357 parallelism happens only rarely. */
3359 static tree
3360 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3362 tree t;
3363 omp_context *up;
3365 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3366 t = maybe_lookup_decl (decl, up);
3368 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3370 return t ? t : decl;
3374 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3375 in outer contexts. */
3377 static tree
3378 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3380 tree t = NULL;
3381 omp_context *up;
3383 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3384 t = maybe_lookup_decl (decl, up);
3386 return t ? t : decl;
3390 /* Construct the initialization value for reduction CLAUSE. */
3392 tree
3393 omp_reduction_init (tree clause, tree type)
3395 location_t loc = OMP_CLAUSE_LOCATION (clause);
3396 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3398 case PLUS_EXPR:
3399 case MINUS_EXPR:
3400 case BIT_IOR_EXPR:
3401 case BIT_XOR_EXPR:
3402 case TRUTH_OR_EXPR:
3403 case TRUTH_ORIF_EXPR:
3404 case TRUTH_XOR_EXPR:
3405 case NE_EXPR:
3406 return build_zero_cst (type);
3408 case MULT_EXPR:
3409 case TRUTH_AND_EXPR:
3410 case TRUTH_ANDIF_EXPR:
3411 case EQ_EXPR:
3412 return fold_convert_loc (loc, type, integer_one_node);
3414 case BIT_AND_EXPR:
3415 return fold_convert_loc (loc, type, integer_minus_one_node);
3417 case MAX_EXPR:
3418 if (SCALAR_FLOAT_TYPE_P (type))
3420 REAL_VALUE_TYPE max, min;
3421 if (HONOR_INFINITIES (type))
3423 real_inf (&max);
3424 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3426 else
3427 real_maxval (&min, 1, TYPE_MODE (type));
3428 return build_real (type, min);
3430 else
3432 gcc_assert (INTEGRAL_TYPE_P (type));
3433 return TYPE_MIN_VALUE (type);
3436 case MIN_EXPR:
3437 if (SCALAR_FLOAT_TYPE_P (type))
3439 REAL_VALUE_TYPE max;
3440 if (HONOR_INFINITIES (type))
3441 real_inf (&max);
3442 else
3443 real_maxval (&max, 0, TYPE_MODE (type));
3444 return build_real (type, max);
3446 else
3448 gcc_assert (INTEGRAL_TYPE_P (type));
3449 return TYPE_MAX_VALUE (type);
3452 default:
3453 gcc_unreachable ();
3457 /* Return alignment to be assumed for var in CLAUSE, which should be
3458 OMP_CLAUSE_ALIGNED. */
3460 static tree
3461 omp_clause_aligned_alignment (tree clause)
3463 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3464 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3466 /* Otherwise return implementation defined alignment. */
3467 unsigned int al = 1;
3468 machine_mode mode, vmode;
3469 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3470 if (vs)
3471 vs = 1 << floor_log2 (vs);
3472 static enum mode_class classes[]
3473 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3474 for (int i = 0; i < 4; i += 2)
3475 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3476 mode != VOIDmode;
3477 mode = GET_MODE_WIDER_MODE (mode))
3479 vmode = targetm.vectorize.preferred_simd_mode (mode);
3480 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3481 continue;
3482 while (vs
3483 && GET_MODE_SIZE (vmode) < vs
3484 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3485 vmode = GET_MODE_2XWIDER_MODE (vmode);
3487 tree type = lang_hooks.types.type_for_mode (mode, 1);
3488 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3489 continue;
3490 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3491 / GET_MODE_SIZE (mode));
3492 if (TYPE_MODE (type) != vmode)
3493 continue;
3494 if (TYPE_ALIGN_UNIT (type) > al)
3495 al = TYPE_ALIGN_UNIT (type);
3497 return build_int_cst (integer_type_node, al);
3500 /* Return maximum possible vectorization factor for the target. */
3502 static int
3503 omp_max_vf (void)
3505 if (!optimize
3506 || optimize_debug
3507 || !flag_tree_loop_optimize
3508 || (!flag_tree_loop_vectorize
3509 && (global_options_set.x_flag_tree_loop_vectorize
3510 || global_options_set.x_flag_tree_vectorize)))
3511 return 1;
3513 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3514 if (vs)
3516 vs = 1 << floor_log2 (vs);
3517 return vs;
3519 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3520 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3521 return GET_MODE_NUNITS (vqimode);
3522 return 1;
3525 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3526 privatization. */
3528 static bool
3529 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3530 tree &idx, tree &lane, tree &ivar, tree &lvar)
3532 if (max_vf == 0)
3534 max_vf = omp_max_vf ();
3535 if (max_vf > 1)
3537 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3538 OMP_CLAUSE_SAFELEN);
3539 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3540 max_vf = 1;
3541 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3542 max_vf) == -1)
3543 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3545 if (max_vf > 1)
3547 idx = create_tmp_var (unsigned_type_node);
3548 lane = create_tmp_var (unsigned_type_node);
3551 if (max_vf == 1)
3552 return false;
3554 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3555 tree avar = create_tmp_var_raw (atype);
3556 if (TREE_ADDRESSABLE (new_var))
3557 TREE_ADDRESSABLE (avar) = 1;
3558 DECL_ATTRIBUTES (avar)
3559 = tree_cons (get_identifier ("omp simd array"), NULL,
3560 DECL_ATTRIBUTES (avar));
3561 gimple_add_tmp_var (avar);
3562 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3563 NULL_TREE, NULL_TREE);
3564 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3565 NULL_TREE, NULL_TREE);
3566 if (DECL_P (new_var))
3568 SET_DECL_VALUE_EXPR (new_var, lvar);
3569 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3571 return true;
3574 /* Helper function of lower_rec_input_clauses. For a reference
3575 in simd reduction, add an underlying variable it will reference. */
3577 static void
3578 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3580 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3581 if (TREE_CONSTANT (z))
3583 const char *name = NULL;
3584 if (DECL_NAME (new_vard))
3585 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3587 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3588 gimple_add_tmp_var (z);
3589 TREE_ADDRESSABLE (z) = 1;
3590 z = build_fold_addr_expr_loc (loc, z);
3591 gimplify_assign (new_vard, z, ilist);
3595 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3596 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3597 private variables. Initialization statements go in ILIST, while calls
3598 to destructors go in DLIST. */
3600 static void
3601 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3602 omp_context *ctx, struct omp_for_data *fd)
3604 tree c, dtor, copyin_seq, x, ptr;
3605 bool copyin_by_ref = false;
3606 bool lastprivate_firstprivate = false;
3607 bool reduction_omp_orig_ref = false;
3608 int pass;
3609 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3610 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3611 int max_vf = 0;
3612 tree lane = NULL_TREE, idx = NULL_TREE;
3613 tree ivar = NULL_TREE, lvar = NULL_TREE;
3614 gimple_seq llist[2] = { NULL, NULL };
3616 copyin_seq = NULL;
3618 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3619 with data sharing clauses referencing variable sized vars. That
3620 is unnecessarily hard to support and very unlikely to result in
3621 vectorized code anyway. */
3622 if (is_simd)
3623 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3624 switch (OMP_CLAUSE_CODE (c))
3626 case OMP_CLAUSE_LINEAR:
3627 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3628 max_vf = 1;
3629 /* FALLTHRU */
3630 case OMP_CLAUSE_REDUCTION:
3631 case OMP_CLAUSE_PRIVATE:
3632 case OMP_CLAUSE_FIRSTPRIVATE:
3633 case OMP_CLAUSE_LASTPRIVATE:
3634 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3635 max_vf = 1;
3636 break;
3637 default:
3638 continue;
3641 /* Do all the fixed sized types in the first pass, and the variable sized
3642 types in the second pass. This makes sure that the scalar arguments to
3643 the variable sized types are processed before we use them in the
3644 variable sized operations. */
3645 for (pass = 0; pass < 2; ++pass)
3647 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3649 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3650 tree var, new_var;
3651 bool by_ref;
3652 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3654 switch (c_kind)
3656 case OMP_CLAUSE_PRIVATE:
3657 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3658 continue;
3659 break;
3660 case OMP_CLAUSE_SHARED:
3661 /* Ignore shared directives in teams construct. */
3662 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3663 continue;
3664 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3666 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3667 continue;
3669 case OMP_CLAUSE_FIRSTPRIVATE:
3670 case OMP_CLAUSE_COPYIN:
3671 case OMP_CLAUSE_LINEAR:
3672 break;
3673 case OMP_CLAUSE_REDUCTION:
3674 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3675 reduction_omp_orig_ref = true;
3676 break;
3677 case OMP_CLAUSE__LOOPTEMP_:
3678 /* Handle _looptemp_ clauses only on parallel. */
3679 if (fd)
3680 continue;
3681 break;
3682 case OMP_CLAUSE_LASTPRIVATE:
3683 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3685 lastprivate_firstprivate = true;
3686 if (pass != 0)
3687 continue;
3689 /* Even without corresponding firstprivate, if
3690 decl is Fortran allocatable, it needs outer var
3691 reference. */
3692 else if (pass == 0
3693 && lang_hooks.decls.omp_private_outer_ref
3694 (OMP_CLAUSE_DECL (c)))
3695 lastprivate_firstprivate = true;
3696 break;
3697 case OMP_CLAUSE_ALIGNED:
3698 if (pass == 0)
3699 continue;
3700 var = OMP_CLAUSE_DECL (c);
3701 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3702 && !is_global_var (var))
3704 new_var = maybe_lookup_decl (var, ctx);
3705 if (new_var == NULL_TREE)
3706 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3707 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3708 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3709 omp_clause_aligned_alignment (c));
3710 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3711 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3712 gimplify_and_add (x, ilist);
3714 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3715 && is_global_var (var))
3717 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3718 new_var = lookup_decl (var, ctx);
3719 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3720 t = build_fold_addr_expr_loc (clause_loc, t);
3721 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3722 t = build_call_expr_loc (clause_loc, t2, 2, t,
3723 omp_clause_aligned_alignment (c));
3724 t = fold_convert_loc (clause_loc, ptype, t);
3725 x = create_tmp_var (ptype);
3726 t = build2 (MODIFY_EXPR, ptype, x, t);
3727 gimplify_and_add (t, ilist);
3728 t = build_simple_mem_ref_loc (clause_loc, x);
3729 SET_DECL_VALUE_EXPR (new_var, t);
3730 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3732 continue;
3733 default:
3734 continue;
3737 new_var = var = OMP_CLAUSE_DECL (c);
3738 if (c_kind != OMP_CLAUSE_COPYIN)
3739 new_var = lookup_decl (var, ctx);
3741 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3743 if (pass != 0)
3744 continue;
3746 else if (is_variable_sized (var))
3748 /* For variable sized types, we need to allocate the
3749 actual storage here. Call alloca and store the
3750 result in the pointer decl that we created elsewhere. */
3751 if (pass == 0)
3752 continue;
3754 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3756 gcall *stmt;
3757 tree tmp, atmp;
3759 ptr = DECL_VALUE_EXPR (new_var);
3760 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3761 ptr = TREE_OPERAND (ptr, 0);
3762 gcc_assert (DECL_P (ptr));
3763 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3765 /* void *tmp = __builtin_alloca */
3766 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3767 stmt = gimple_build_call (atmp, 1, x);
3768 tmp = create_tmp_var_raw (ptr_type_node);
3769 gimple_add_tmp_var (tmp);
3770 gimple_call_set_lhs (stmt, tmp);
3772 gimple_seq_add_stmt (ilist, stmt);
3774 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3775 gimplify_assign (ptr, x, ilist);
3778 else if (is_reference (var))
3780 /* For references that are being privatized for Fortran,
3781 allocate new backing storage for the new pointer
3782 variable. This allows us to avoid changing all the
3783 code that expects a pointer to something that expects
3784 a direct variable. */
3785 if (pass == 0)
3786 continue;
3788 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3789 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3791 x = build_receiver_ref (var, false, ctx);
3792 x = build_fold_addr_expr_loc (clause_loc, x);
3794 else if (TREE_CONSTANT (x))
3796 /* For reduction in SIMD loop, defer adding the
3797 initialization of the reference, because if we decide
3798 to use SIMD array for it, the initilization could cause
3799 expansion ICE. */
3800 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3801 x = NULL_TREE;
3802 else
3804 const char *name = NULL;
3805 if (DECL_NAME (var))
3806 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3808 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3809 name);
3810 gimple_add_tmp_var (x);
3811 TREE_ADDRESSABLE (x) = 1;
3812 x = build_fold_addr_expr_loc (clause_loc, x);
3815 else
3817 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3818 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3821 if (x)
3823 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3824 gimplify_assign (new_var, x, ilist);
3827 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3829 else if (c_kind == OMP_CLAUSE_REDUCTION
3830 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3832 if (pass == 0)
3833 continue;
3835 else if (pass != 0)
3836 continue;
3838 switch (OMP_CLAUSE_CODE (c))
3840 case OMP_CLAUSE_SHARED:
3841 /* Ignore shared directives in teams construct. */
3842 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3843 continue;
3844 /* Shared global vars are just accessed directly. */
3845 if (is_global_var (new_var))
3846 break;
3847 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3848 needs to be delayed until after fixup_child_record_type so
3849 that we get the correct type during the dereference. */
3850 by_ref = use_pointer_for_field (var, ctx);
3851 x = build_receiver_ref (var, by_ref, ctx);
3852 SET_DECL_VALUE_EXPR (new_var, x);
3853 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3855 /* ??? If VAR is not passed by reference, and the variable
3856 hasn't been initialized yet, then we'll get a warning for
3857 the store into the omp_data_s structure. Ideally, we'd be
3858 able to notice this and not store anything at all, but
3859 we're generating code too early. Suppress the warning. */
3860 if (!by_ref)
3861 TREE_NO_WARNING (var) = 1;
3862 break;
3864 case OMP_CLAUSE_LASTPRIVATE:
3865 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3866 break;
3867 /* FALLTHRU */
3869 case OMP_CLAUSE_PRIVATE:
3870 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3871 x = build_outer_var_ref (var, ctx);
3872 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3874 if (is_task_ctx (ctx))
3875 x = build_receiver_ref (var, false, ctx);
3876 else
3877 x = build_outer_var_ref (var, ctx);
3879 else
3880 x = NULL;
3881 do_private:
3882 tree nx;
3883 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3884 if (is_simd)
3886 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3887 if ((TREE_ADDRESSABLE (new_var) || nx || y
3888 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3889 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3890 idx, lane, ivar, lvar))
3892 if (nx)
3893 x = lang_hooks.decls.omp_clause_default_ctor
3894 (c, unshare_expr (ivar), x);
3895 if (nx && x)
3896 gimplify_and_add (x, &llist[0]);
3897 if (y)
3899 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3900 if (y)
3902 gimple_seq tseq = NULL;
3904 dtor = y;
3905 gimplify_stmt (&dtor, &tseq);
3906 gimple_seq_add_seq (&llist[1], tseq);
3909 break;
3912 if (nx)
3913 gimplify_and_add (nx, ilist);
3914 /* FALLTHRU */
3916 do_dtor:
3917 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3918 if (x)
3920 gimple_seq tseq = NULL;
3922 dtor = x;
3923 gimplify_stmt (&dtor, &tseq);
3924 gimple_seq_add_seq (dlist, tseq);
3926 break;
3928 case OMP_CLAUSE_LINEAR:
3929 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3930 goto do_firstprivate;
3931 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3932 x = NULL;
3933 else
3934 x = build_outer_var_ref (var, ctx);
3935 goto do_private;
3937 case OMP_CLAUSE_FIRSTPRIVATE:
3938 if (is_task_ctx (ctx))
3940 if (is_reference (var) || is_variable_sized (var))
3941 goto do_dtor;
3942 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3943 ctx))
3944 || use_pointer_for_field (var, NULL))
3946 x = build_receiver_ref (var, false, ctx);
3947 SET_DECL_VALUE_EXPR (new_var, x);
3948 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3949 goto do_dtor;
3952 do_firstprivate:
3953 x = build_outer_var_ref (var, ctx);
3954 if (is_simd)
3956 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3957 && gimple_omp_for_combined_into_p (ctx->stmt))
3959 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3960 tree stept = TREE_TYPE (t);
3961 tree ct = find_omp_clause (clauses,
3962 OMP_CLAUSE__LOOPTEMP_);
3963 gcc_assert (ct);
3964 tree l = OMP_CLAUSE_DECL (ct);
3965 tree n1 = fd->loop.n1;
3966 tree step = fd->loop.step;
3967 tree itype = TREE_TYPE (l);
3968 if (POINTER_TYPE_P (itype))
3969 itype = signed_type_for (itype);
3970 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3971 if (TYPE_UNSIGNED (itype)
3972 && fd->loop.cond_code == GT_EXPR)
3973 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3974 fold_build1 (NEGATE_EXPR, itype, l),
3975 fold_build1 (NEGATE_EXPR,
3976 itype, step));
3977 else
3978 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3979 t = fold_build2 (MULT_EXPR, stept,
3980 fold_convert (stept, l), t);
3982 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3984 x = lang_hooks.decls.omp_clause_linear_ctor
3985 (c, new_var, x, t);
3986 gimplify_and_add (x, ilist);
3987 goto do_dtor;
3990 if (POINTER_TYPE_P (TREE_TYPE (x)))
3991 x = fold_build2 (POINTER_PLUS_EXPR,
3992 TREE_TYPE (x), x, t);
3993 else
3994 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3997 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3998 || TREE_ADDRESSABLE (new_var))
3999 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4000 idx, lane, ivar, lvar))
4002 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4004 tree iv = create_tmp_var (TREE_TYPE (new_var));
4005 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4006 gimplify_and_add (x, ilist);
4007 gimple_stmt_iterator gsi
4008 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4009 gassign *g
4010 = gimple_build_assign (unshare_expr (lvar), iv);
4011 gsi_insert_before_without_update (&gsi, g,
4012 GSI_SAME_STMT);
4013 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4014 enum tree_code code = PLUS_EXPR;
4015 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4016 code = POINTER_PLUS_EXPR;
4017 g = gimple_build_assign (iv, code, iv, t);
4018 gsi_insert_before_without_update (&gsi, g,
4019 GSI_SAME_STMT);
4020 break;
4022 x = lang_hooks.decls.omp_clause_copy_ctor
4023 (c, unshare_expr (ivar), x);
4024 gimplify_and_add (x, &llist[0]);
4025 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4026 if (x)
4028 gimple_seq tseq = NULL;
4030 dtor = x;
4031 gimplify_stmt (&dtor, &tseq);
4032 gimple_seq_add_seq (&llist[1], tseq);
4034 break;
4037 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4038 gimplify_and_add (x, ilist);
4039 goto do_dtor;
4041 case OMP_CLAUSE__LOOPTEMP_:
4042 gcc_assert (is_parallel_ctx (ctx));
4043 x = build_outer_var_ref (var, ctx);
4044 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4045 gimplify_and_add (x, ilist);
4046 break;
4048 case OMP_CLAUSE_COPYIN:
4049 by_ref = use_pointer_for_field (var, NULL);
4050 x = build_receiver_ref (var, by_ref, ctx);
4051 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4052 append_to_statement_list (x, &copyin_seq);
4053 copyin_by_ref |= by_ref;
4054 break;
4056 case OMP_CLAUSE_REDUCTION:
4057 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4059 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4060 gimple tseq;
4061 x = build_outer_var_ref (var, ctx);
4063 if (is_reference (var)
4064 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4065 TREE_TYPE (x)))
4066 x = build_fold_addr_expr_loc (clause_loc, x);
4067 SET_DECL_VALUE_EXPR (placeholder, x);
4068 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4069 tree new_vard = new_var;
4070 if (is_reference (var))
4072 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4073 new_vard = TREE_OPERAND (new_var, 0);
4074 gcc_assert (DECL_P (new_vard));
4076 if (is_simd
4077 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4078 idx, lane, ivar, lvar))
4080 if (new_vard == new_var)
4082 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4083 SET_DECL_VALUE_EXPR (new_var, ivar);
4085 else
4087 SET_DECL_VALUE_EXPR (new_vard,
4088 build_fold_addr_expr (ivar));
4089 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4091 x = lang_hooks.decls.omp_clause_default_ctor
4092 (c, unshare_expr (ivar),
4093 build_outer_var_ref (var, ctx));
4094 if (x)
4095 gimplify_and_add (x, &llist[0]);
4096 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4098 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4099 lower_omp (&tseq, ctx);
4100 gimple_seq_add_seq (&llist[0], tseq);
4102 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4103 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4104 lower_omp (&tseq, ctx);
4105 gimple_seq_add_seq (&llist[1], tseq);
4106 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4107 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4108 if (new_vard == new_var)
4109 SET_DECL_VALUE_EXPR (new_var, lvar);
4110 else
4111 SET_DECL_VALUE_EXPR (new_vard,
4112 build_fold_addr_expr (lvar));
4113 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4114 if (x)
4116 tseq = NULL;
4117 dtor = x;
4118 gimplify_stmt (&dtor, &tseq);
4119 gimple_seq_add_seq (&llist[1], tseq);
4121 break;
4123 /* If this is a reference to constant size reduction var
4124 with placeholder, we haven't emitted the initializer
4125 for it because it is undesirable if SIMD arrays are used.
4126 But if they aren't used, we need to emit the deferred
4127 initialization now. */
4128 else if (is_reference (var) && is_simd)
4129 handle_simd_reference (clause_loc, new_vard, ilist);
4130 x = lang_hooks.decls.omp_clause_default_ctor
4131 (c, unshare_expr (new_var),
4132 build_outer_var_ref (var, ctx));
4133 if (x)
4134 gimplify_and_add (x, ilist);
4135 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4137 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4138 lower_omp (&tseq, ctx);
4139 gimple_seq_add_seq (ilist, tseq);
4141 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4142 if (is_simd)
4144 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4145 lower_omp (&tseq, ctx);
4146 gimple_seq_add_seq (dlist, tseq);
4147 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4149 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4150 goto do_dtor;
4152 else
4154 x = omp_reduction_init (c, TREE_TYPE (new_var));
4155 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4156 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4158 /* reduction(-:var) sums up the partial results, so it
4159 acts identically to reduction(+:var). */
4160 if (code == MINUS_EXPR)
4161 code = PLUS_EXPR;
4163 tree new_vard = new_var;
4164 if (is_simd && is_reference (var))
4166 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4167 new_vard = TREE_OPERAND (new_var, 0);
4168 gcc_assert (DECL_P (new_vard));
4170 if (is_simd
4171 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4172 idx, lane, ivar, lvar))
4174 tree ref = build_outer_var_ref (var, ctx);
4176 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4178 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4179 ref = build_outer_var_ref (var, ctx);
4180 gimplify_assign (ref, x, &llist[1]);
4182 if (new_vard != new_var)
4184 SET_DECL_VALUE_EXPR (new_vard,
4185 build_fold_addr_expr (lvar));
4186 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4189 else
4191 if (is_reference (var) && is_simd)
4192 handle_simd_reference (clause_loc, new_vard, ilist);
4193 gimplify_assign (new_var, x, ilist);
4194 if (is_simd)
4196 tree ref = build_outer_var_ref (var, ctx);
4198 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4199 ref = build_outer_var_ref (var, ctx);
4200 gimplify_assign (ref, x, dlist);
4204 break;
4206 default:
4207 gcc_unreachable ();
4212 if (lane)
4214 tree uid = create_tmp_var (ptr_type_node, "simduid");
4215 /* Don't want uninit warnings on simduid, it is always uninitialized,
4216 but we use it not for the value, but for the DECL_UID only. */
4217 TREE_NO_WARNING (uid) = 1;
4218 gimple g
4219 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4220 gimple_call_set_lhs (g, lane);
4221 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4222 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4223 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4224 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4225 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4226 gimple_omp_for_set_clauses (ctx->stmt, c);
4227 g = gimple_build_assign (lane, INTEGER_CST,
4228 build_int_cst (unsigned_type_node, 0));
4229 gimple_seq_add_stmt (ilist, g);
4230 for (int i = 0; i < 2; i++)
4231 if (llist[i])
4233 tree vf = create_tmp_var (unsigned_type_node);
4234 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4235 gimple_call_set_lhs (g, vf);
4236 gimple_seq *seq = i == 0 ? ilist : dlist;
4237 gimple_seq_add_stmt (seq, g);
4238 tree t = build_int_cst (unsigned_type_node, 0);
4239 g = gimple_build_assign (idx, INTEGER_CST, t);
4240 gimple_seq_add_stmt (seq, g);
4241 tree body = create_artificial_label (UNKNOWN_LOCATION);
4242 tree header = create_artificial_label (UNKNOWN_LOCATION);
4243 tree end = create_artificial_label (UNKNOWN_LOCATION);
4244 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4245 gimple_seq_add_stmt (seq, gimple_build_label (body));
4246 gimple_seq_add_seq (seq, llist[i]);
4247 t = build_int_cst (unsigned_type_node, 1);
4248 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4249 gimple_seq_add_stmt (seq, g);
4250 gimple_seq_add_stmt (seq, gimple_build_label (header));
4251 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4252 gimple_seq_add_stmt (seq, g);
4253 gimple_seq_add_stmt (seq, gimple_build_label (end));
4257 /* The copyin sequence is not to be executed by the main thread, since
4258 that would result in self-copies. Perhaps not visible to scalars,
4259 but it certainly is to C++ operator=. */
4260 if (copyin_seq)
4262 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4264 x = build2 (NE_EXPR, boolean_type_node, x,
4265 build_int_cst (TREE_TYPE (x), 0));
4266 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4267 gimplify_and_add (x, ilist);
4270 /* If any copyin variable is passed by reference, we must ensure the
4271 master thread doesn't modify it before it is copied over in all
4272 threads. Similarly for variables in both firstprivate and
4273 lastprivate clauses we need to ensure the lastprivate copying
4274 happens after firstprivate copying in all threads. And similarly
4275 for UDRs if initializer expression refers to omp_orig. */
4276 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4278 /* Don't add any barrier for #pragma omp simd or
4279 #pragma omp distribute. */
4280 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4281 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4282 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4285 /* If max_vf is non-zero, then we can use only a vectorization factor
4286 up to the max_vf we chose. So stick it into the safelen clause. */
4287 if (max_vf)
4289 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4290 OMP_CLAUSE_SAFELEN);
4291 if (c == NULL_TREE
4292 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4293 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4294 max_vf) == 1))
4296 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4297 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4298 max_vf);
4299 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4300 gimple_omp_for_set_clauses (ctx->stmt, c);
4306 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4307 both parallel and workshare constructs. PREDICATE may be NULL if it's
4308 always true. */
4310 static void
4311 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4312 omp_context *ctx)
4314 tree x, c, label = NULL, orig_clauses = clauses;
4315 bool par_clauses = false;
4316 tree simduid = NULL, lastlane = NULL;
4318 /* Early exit if there are no lastprivate or linear clauses. */
4319 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4320 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4321 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4322 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4323 break;
4324 if (clauses == NULL)
4326 /* If this was a workshare clause, see if it had been combined
4327 with its parallel. In that case, look for the clauses on the
4328 parallel statement itself. */
4329 if (is_parallel_ctx (ctx))
4330 return;
4332 ctx = ctx->outer;
4333 if (ctx == NULL || !is_parallel_ctx (ctx))
4334 return;
4336 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4337 OMP_CLAUSE_LASTPRIVATE);
4338 if (clauses == NULL)
4339 return;
4340 par_clauses = true;
4343 if (predicate)
4345 gcond *stmt;
4346 tree label_true, arm1, arm2;
4348 label = create_artificial_label (UNKNOWN_LOCATION);
4349 label_true = create_artificial_label (UNKNOWN_LOCATION);
4350 arm1 = TREE_OPERAND (predicate, 0);
4351 arm2 = TREE_OPERAND (predicate, 1);
4352 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4353 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4354 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4355 label_true, label);
4356 gimple_seq_add_stmt (stmt_list, stmt);
4357 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4360 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4361 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4363 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4364 if (simduid)
4365 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4368 for (c = clauses; c ;)
4370 tree var, new_var;
4371 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4373 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4374 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4375 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4377 var = OMP_CLAUSE_DECL (c);
4378 new_var = lookup_decl (var, ctx);
4380 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4382 tree val = DECL_VALUE_EXPR (new_var);
4383 if (TREE_CODE (val) == ARRAY_REF
4384 && VAR_P (TREE_OPERAND (val, 0))
4385 && lookup_attribute ("omp simd array",
4386 DECL_ATTRIBUTES (TREE_OPERAND (val,
4387 0))))
4389 if (lastlane == NULL)
4391 lastlane = create_tmp_var (unsigned_type_node);
4392 gcall *g
4393 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4394 2, simduid,
4395 TREE_OPERAND (val, 1));
4396 gimple_call_set_lhs (g, lastlane);
4397 gimple_seq_add_stmt (stmt_list, g);
4399 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4400 TREE_OPERAND (val, 0), lastlane,
4401 NULL_TREE, NULL_TREE);
4405 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4406 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4408 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4409 gimple_seq_add_seq (stmt_list,
4410 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4411 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4413 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4414 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4416 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4417 gimple_seq_add_seq (stmt_list,
4418 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4419 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4422 x = build_outer_var_ref (var, ctx);
4423 if (is_reference (var))
4424 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4425 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4426 gimplify_and_add (x, stmt_list);
4428 c = OMP_CLAUSE_CHAIN (c);
4429 if (c == NULL && !par_clauses)
4431 /* If this was a workshare clause, see if it had been combined
4432 with its parallel. In that case, continue looking for the
4433 clauses also on the parallel statement itself. */
4434 if (is_parallel_ctx (ctx))
4435 break;
4437 ctx = ctx->outer;
4438 if (ctx == NULL || !is_parallel_ctx (ctx))
4439 break;
4441 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4442 OMP_CLAUSE_LASTPRIVATE);
4443 par_clauses = true;
4447 if (label)
4448 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4451 static void
4452 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4453 tree tid, tree var, tree new_var)
4455 /* The atomic add at the end of the sum creates unnecessary
4456 write contention on accelerators. To work around this,
4457 create an array to store the partial reductions. Later, in
4458 lower_omp_for (for openacc), the values of array will be
4459 combined. */
4461 tree t = NULL_TREE, array, x;
4462 tree type = get_base_type (var);
4463 gimple stmt;
4465 /* Now insert the partial reductions into the array. */
4467 /* Find the reduction array. */
4469 tree ptype = build_pointer_type (type);
4471 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4472 t = build_receiver_ref (t, false, ctx->outer);
4474 array = create_tmp_var (ptype);
4475 gimplify_assign (array, t, stmt_seqp);
4477 tree ptr = create_tmp_var (TREE_TYPE (array));
4479 /* Find the reduction array. */
4481 /* testing a unary conversion. */
4482 tree offset = create_tmp_var (sizetype);
4483 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4484 stmt_seqp);
4485 t = create_tmp_var (sizetype);
4486 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4487 stmt_seqp);
4488 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4489 gimple_seq_add_stmt (stmt_seqp, stmt);
4491 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4492 of adding sizeof(var) to the array? */
4493 ptr = create_tmp_var (ptype);
4494 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4495 offset);
4496 gimple_seq_add_stmt (stmt_seqp, stmt);
4498 /* Move the local sum to gfc$sum[i]. */
4499 x = unshare_expr (build_simple_mem_ref (ptr));
4500 stmt = gimplify_assign (x, new_var, stmt_seqp);
4503 /* Generate code to implement the REDUCTION clauses. */
4505 static void
4506 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4508 gimple_seq sub_seq = NULL;
4509 gimple stmt;
4510 tree x, c, tid = NULL_TREE;
4511 int count = 0;
4513 /* SIMD reductions are handled in lower_rec_input_clauses. */
4514 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4515 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4516 return;
4518 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4519 update in that case, otherwise use a lock. */
4520 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4521 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4523 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4525 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4526 count = -1;
4527 break;
4529 count++;
4532 if (count == 0)
4533 return;
4535 /* Initialize thread info for OpenACC. */
4536 if (is_gimple_omp_oacc (ctx->stmt))
4538 /* Get the current thread id. */
4539 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4540 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4541 gimple stmt = gimple_build_call (call, 0);
4542 gimple_call_set_lhs (stmt, tid);
4543 gimple_seq_add_stmt (stmt_seqp, stmt);
4546 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4548 tree var, ref, new_var;
4549 enum tree_code code;
4550 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4552 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4553 continue;
4555 var = OMP_CLAUSE_DECL (c);
4556 new_var = lookup_decl (var, ctx);
4557 if (is_reference (var))
4558 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4559 ref = build_outer_var_ref (var, ctx);
4560 code = OMP_CLAUSE_REDUCTION_CODE (c);
4562 /* reduction(-:var) sums up the partial results, so it acts
4563 identically to reduction(+:var). */
4564 if (code == MINUS_EXPR)
4565 code = PLUS_EXPR;
4567 if (is_gimple_omp_oacc (ctx->stmt))
4569 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4571 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4573 else if (count == 1)
4575 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4577 addr = save_expr (addr);
4578 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4579 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4580 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4581 gimplify_and_add (x, stmt_seqp);
4582 return;
4584 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4586 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4588 if (is_reference (var)
4589 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4590 TREE_TYPE (ref)))
4591 ref = build_fold_addr_expr_loc (clause_loc, ref);
4592 SET_DECL_VALUE_EXPR (placeholder, ref);
4593 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4594 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4595 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4596 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4597 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4599 else
4601 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4602 ref = build_outer_var_ref (var, ctx);
4603 gimplify_assign (ref, x, &sub_seq);
4607 if (is_gimple_omp_oacc (ctx->stmt))
4608 return;
4610 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4612 gimple_seq_add_stmt (stmt_seqp, stmt);
4614 gimple_seq_add_seq (stmt_seqp, sub_seq);
4616 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4618 gimple_seq_add_stmt (stmt_seqp, stmt);
4622 /* Generate code to implement the COPYPRIVATE clauses. */
4624 static void
4625 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4626 omp_context *ctx)
4628 tree c;
4630 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4632 tree var, new_var, ref, x;
4633 bool by_ref;
4634 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4636 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4637 continue;
4639 var = OMP_CLAUSE_DECL (c);
4640 by_ref = use_pointer_for_field (var, NULL);
4642 ref = build_sender_ref (var, ctx);
4643 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4644 if (by_ref)
4646 x = build_fold_addr_expr_loc (clause_loc, new_var);
4647 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4649 gimplify_assign (ref, x, slist);
4651 ref = build_receiver_ref (var, false, ctx);
4652 if (by_ref)
4654 ref = fold_convert_loc (clause_loc,
4655 build_pointer_type (TREE_TYPE (new_var)),
4656 ref);
4657 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4659 if (is_reference (var))
4661 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4662 ref = build_simple_mem_ref_loc (clause_loc, ref);
4663 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4665 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4666 gimplify_and_add (x, rlist);
4671 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4672 and REDUCTION from the sender (aka parent) side. */
4674 static void
4675 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4676 omp_context *ctx)
4678 tree c;
4680 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4682 tree val, ref, x, var;
4683 bool by_ref, do_in = false, do_out = false;
4684 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4686 switch (OMP_CLAUSE_CODE (c))
4688 case OMP_CLAUSE_PRIVATE:
4689 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4690 break;
4691 continue;
4692 case OMP_CLAUSE_FIRSTPRIVATE:
4693 case OMP_CLAUSE_COPYIN:
4694 case OMP_CLAUSE_LASTPRIVATE:
4695 case OMP_CLAUSE_REDUCTION:
4696 case OMP_CLAUSE__LOOPTEMP_:
4697 break;
4698 default:
4699 continue;
4702 val = OMP_CLAUSE_DECL (c);
4703 var = lookup_decl_in_outer_ctx (val, ctx);
4705 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4706 && is_global_var (var))
4707 continue;
4708 if (is_variable_sized (val))
4709 continue;
4710 by_ref = use_pointer_for_field (val, NULL);
4712 switch (OMP_CLAUSE_CODE (c))
4714 case OMP_CLAUSE_PRIVATE:
4715 case OMP_CLAUSE_FIRSTPRIVATE:
4716 case OMP_CLAUSE_COPYIN:
4717 case OMP_CLAUSE__LOOPTEMP_:
4718 do_in = true;
4719 break;
4721 case OMP_CLAUSE_LASTPRIVATE:
4722 if (by_ref || is_reference (val))
4724 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4725 continue;
4726 do_in = true;
4728 else
4730 do_out = true;
4731 if (lang_hooks.decls.omp_private_outer_ref (val))
4732 do_in = true;
4734 break;
4736 case OMP_CLAUSE_REDUCTION:
4737 do_in = true;
4738 do_out = !(by_ref || is_reference (val));
4739 break;
4741 default:
4742 gcc_unreachable ();
4745 if (do_in)
4747 ref = build_sender_ref (val, ctx);
4748 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4749 gimplify_assign (ref, x, ilist);
4750 if (is_task_ctx (ctx))
4751 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4754 if (do_out)
4756 ref = build_sender_ref (val, ctx);
4757 gimplify_assign (var, ref, olist);
4762 /* Generate code to implement SHARED from the sender (aka parent)
4763 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4764 list things that got automatically shared. */
4766 static void
4767 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4769 tree var, ovar, nvar, f, x, record_type;
4771 if (ctx->record_type == NULL)
4772 return;
4774 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4775 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4777 ovar = DECL_ABSTRACT_ORIGIN (f);
4778 nvar = maybe_lookup_decl (ovar, ctx);
4779 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4780 continue;
4782 /* If CTX is a nested parallel directive. Find the immediately
4783 enclosing parallel or workshare construct that contains a
4784 mapping for OVAR. */
4785 var = lookup_decl_in_outer_ctx (ovar, ctx);
4787 if (use_pointer_for_field (ovar, ctx))
4789 x = build_sender_ref (ovar, ctx);
4790 var = build_fold_addr_expr (var);
4791 gimplify_assign (x, var, ilist);
4793 else
4795 x = build_sender_ref (ovar, ctx);
4796 gimplify_assign (x, var, ilist);
4798 if (!TREE_READONLY (var)
4799 /* We don't need to receive a new reference to a result
4800 or parm decl. In fact we may not store to it as we will
4801 invalidate any pending RSO and generate wrong gimple
4802 during inlining. */
4803 && !((TREE_CODE (var) == RESULT_DECL
4804 || TREE_CODE (var) == PARM_DECL)
4805 && DECL_BY_REFERENCE (var)))
4807 x = build_sender_ref (ovar, ctx);
4808 gimplify_assign (var, x, olist);
4815 /* A convenience function to build an empty GIMPLE_COND with just the
4816 condition. */
4818 static gcond *
4819 gimple_build_cond_empty (tree cond)
4821 enum tree_code pred_code;
4822 tree lhs, rhs;
4824 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4825 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4829 /* Build the function calls to GOMP_parallel_start etc to actually
4830 generate the parallel operation. REGION is the parallel region
4831 being expanded. BB is the block where to insert the code. WS_ARGS
4832 will be set if this is a call to a combined parallel+workshare
4833 construct, it contains the list of additional arguments needed by
4834 the workshare construct. */
4836 static void
4837 expand_parallel_call (struct omp_region *region, basic_block bb,
4838 gomp_parallel *entry_stmt,
4839 vec<tree, va_gc> *ws_args)
4841 tree t, t1, t2, val, cond, c, clauses, flags;
4842 gimple_stmt_iterator gsi;
4843 gimple stmt;
4844 enum built_in_function start_ix;
4845 int start_ix2;
4846 location_t clause_loc;
4847 vec<tree, va_gc> *args;
4849 clauses = gimple_omp_parallel_clauses (entry_stmt);
4851 /* Determine what flavor of GOMP_parallel we will be
4852 emitting. */
4853 start_ix = BUILT_IN_GOMP_PARALLEL;
4854 if (is_combined_parallel (region))
4856 switch (region->inner->type)
4858 case GIMPLE_OMP_FOR:
4859 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4860 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4861 + (region->inner->sched_kind
4862 == OMP_CLAUSE_SCHEDULE_RUNTIME
4863 ? 3 : region->inner->sched_kind));
4864 start_ix = (enum built_in_function)start_ix2;
4865 break;
4866 case GIMPLE_OMP_SECTIONS:
4867 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4868 break;
4869 default:
4870 gcc_unreachable ();
4874 /* By default, the value of NUM_THREADS is zero (selected at run time)
4875 and there is no conditional. */
4876 cond = NULL_TREE;
4877 val = build_int_cst (unsigned_type_node, 0);
4878 flags = build_int_cst (unsigned_type_node, 0);
4880 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4881 if (c)
4882 cond = OMP_CLAUSE_IF_EXPR (c);
4884 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4885 if (c)
4887 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4888 clause_loc = OMP_CLAUSE_LOCATION (c);
4890 else
4891 clause_loc = gimple_location (entry_stmt);
4893 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4894 if (c)
4895 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4897 /* Ensure 'val' is of the correct type. */
4898 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4900 /* If we found the clause 'if (cond)', build either
4901 (cond != 0) or (cond ? val : 1u). */
4902 if (cond)
4904 cond = gimple_boolify (cond);
4906 if (integer_zerop (val))
4907 val = fold_build2_loc (clause_loc,
4908 EQ_EXPR, unsigned_type_node, cond,
4909 build_int_cst (TREE_TYPE (cond), 0));
4910 else
4912 basic_block cond_bb, then_bb, else_bb;
4913 edge e, e_then, e_else;
4914 tree tmp_then, tmp_else, tmp_join, tmp_var;
4916 tmp_var = create_tmp_var (TREE_TYPE (val));
4917 if (gimple_in_ssa_p (cfun))
4919 tmp_then = make_ssa_name (tmp_var);
4920 tmp_else = make_ssa_name (tmp_var);
4921 tmp_join = make_ssa_name (tmp_var);
4923 else
4925 tmp_then = tmp_var;
4926 tmp_else = tmp_var;
4927 tmp_join = tmp_var;
4930 e = split_block_after_labels (bb);
4931 cond_bb = e->src;
4932 bb = e->dest;
4933 remove_edge (e);
4935 then_bb = create_empty_bb (cond_bb);
4936 else_bb = create_empty_bb (then_bb);
4937 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4938 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4940 stmt = gimple_build_cond_empty (cond);
4941 gsi = gsi_start_bb (cond_bb);
4942 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4944 gsi = gsi_start_bb (then_bb);
4945 stmt = gimple_build_assign (tmp_then, val);
4946 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4948 gsi = gsi_start_bb (else_bb);
4949 stmt = gimple_build_assign
4950 (tmp_else, build_int_cst (unsigned_type_node, 1));
4951 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4953 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4954 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4955 add_bb_to_loop (then_bb, cond_bb->loop_father);
4956 add_bb_to_loop (else_bb, cond_bb->loop_father);
4957 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4958 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4960 if (gimple_in_ssa_p (cfun))
4962 gphi *phi = create_phi_node (tmp_join, bb);
4963 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4964 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4967 val = tmp_join;
4970 gsi = gsi_start_bb (bb);
4971 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4972 false, GSI_CONTINUE_LINKING);
4975 gsi = gsi_last_bb (bb);
4976 t = gimple_omp_parallel_data_arg (entry_stmt);
4977 if (t == NULL)
4978 t1 = null_pointer_node;
4979 else
4980 t1 = build_fold_addr_expr (t);
4981 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4983 vec_alloc (args, 4 + vec_safe_length (ws_args));
4984 args->quick_push (t2);
4985 args->quick_push (t1);
4986 args->quick_push (val);
4987 if (ws_args)
4988 args->splice (*ws_args);
4989 args->quick_push (flags);
4991 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4992 builtin_decl_explicit (start_ix), args);
4994 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4995 false, GSI_CONTINUE_LINKING);
4998 /* Insert a function call whose name is FUNC_NAME with the information from
4999 ENTRY_STMT into the basic_block BB. */
5001 static void
5002 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
5003 vec <tree, va_gc> *ws_args)
5005 tree t, t1, t2;
5006 gimple_stmt_iterator gsi;
5007 vec <tree, va_gc> *args;
5009 gcc_assert (vec_safe_length (ws_args) == 2);
5010 tree func_name = (*ws_args)[0];
5011 tree grain = (*ws_args)[1];
5013 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5014 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5015 gcc_assert (count != NULL_TREE);
5016 count = OMP_CLAUSE_OPERAND (count, 0);
5018 gsi = gsi_last_bb (bb);
5019 t = gimple_omp_parallel_data_arg (entry_stmt);
5020 if (t == NULL)
5021 t1 = null_pointer_node;
5022 else
5023 t1 = build_fold_addr_expr (t);
5024 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5026 vec_alloc (args, 4);
5027 args->quick_push (t2);
5028 args->quick_push (t1);
5029 args->quick_push (count);
5030 args->quick_push (grain);
5031 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5033 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5034 GSI_CONTINUE_LINKING);
5037 /* Build the function call to GOMP_task to actually
5038 generate the task operation. BB is the block where to insert the code. */
5040 static void
5041 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5043 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5044 gimple_stmt_iterator gsi;
5045 location_t loc = gimple_location (entry_stmt);
5047 clauses = gimple_omp_task_clauses (entry_stmt);
5049 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5050 if (c)
5051 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5052 else
5053 cond = boolean_true_node;
5055 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5056 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5057 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5058 flags = build_int_cst (unsigned_type_node,
5059 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5061 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5062 if (c)
5064 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5065 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5066 build_int_cst (unsigned_type_node, 2),
5067 build_int_cst (unsigned_type_node, 0));
5068 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5070 if (depend)
5071 depend = OMP_CLAUSE_DECL (depend);
5072 else
5073 depend = build_int_cst (ptr_type_node, 0);
5075 gsi = gsi_last_bb (bb);
5076 t = gimple_omp_task_data_arg (entry_stmt);
5077 if (t == NULL)
5078 t2 = null_pointer_node;
5079 else
5080 t2 = build_fold_addr_expr_loc (loc, t);
5081 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5082 t = gimple_omp_task_copy_fn (entry_stmt);
5083 if (t == NULL)
5084 t3 = null_pointer_node;
5085 else
5086 t3 = build_fold_addr_expr_loc (loc, t);
5088 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5089 8, t1, t2, t3,
5090 gimple_omp_task_arg_size (entry_stmt),
5091 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5092 depend);
5094 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5095 false, GSI_CONTINUE_LINKING);
5099 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5100 catch handler and return it. This prevents programs from violating the
5101 structured block semantics with throws. */
5103 static gimple_seq
5104 maybe_catch_exception (gimple_seq body)
5106 gimple g;
5107 tree decl;
5109 if (!flag_exceptions)
5110 return body;
5112 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5113 decl = lang_hooks.eh_protect_cleanup_actions ();
5114 else
5115 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5117 g = gimple_build_eh_must_not_throw (decl);
5118 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5119 GIMPLE_TRY_CATCH);
5121 return gimple_seq_alloc_with_stmt (g);
5124 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5126 static tree
5127 vec2chain (vec<tree, va_gc> *v)
5129 tree chain = NULL_TREE, t;
5130 unsigned ix;
5132 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5134 DECL_CHAIN (t) = chain;
5135 chain = t;
5138 return chain;
5142 /* Remove barriers in REGION->EXIT's block. Note that this is only
5143 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5144 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5145 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5146 removed. */
5148 static void
5149 remove_exit_barrier (struct omp_region *region)
5151 gimple_stmt_iterator gsi;
5152 basic_block exit_bb;
5153 edge_iterator ei;
5154 edge e;
5155 gimple stmt;
5156 int any_addressable_vars = -1;
5158 exit_bb = region->exit;
5160 /* If the parallel region doesn't return, we don't have REGION->EXIT
5161 block at all. */
5162 if (! exit_bb)
5163 return;
5165 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5166 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5167 statements that can appear in between are extremely limited -- no
5168 memory operations at all. Here, we allow nothing at all, so the
5169 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5170 gsi = gsi_last_bb (exit_bb);
5171 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5172 gsi_prev (&gsi);
5173 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5174 return;
5176 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5178 gsi = gsi_last_bb (e->src);
5179 if (gsi_end_p (gsi))
5180 continue;
5181 stmt = gsi_stmt (gsi);
5182 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5183 && !gimple_omp_return_nowait_p (stmt))
5185 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5186 in many cases. If there could be tasks queued, the barrier
5187 might be needed to let the tasks run before some local
5188 variable of the parallel that the task uses as shared
5189 runs out of scope. The task can be spawned either
5190 from within current function (this would be easy to check)
5191 or from some function it calls and gets passed an address
5192 of such a variable. */
5193 if (any_addressable_vars < 0)
5195 gomp_parallel *parallel_stmt
5196 = as_a <gomp_parallel *> (last_stmt (region->entry));
5197 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5198 tree local_decls, block, decl;
5199 unsigned ix;
5201 any_addressable_vars = 0;
5202 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5203 if (TREE_ADDRESSABLE (decl))
5205 any_addressable_vars = 1;
5206 break;
5208 for (block = gimple_block (stmt);
5209 !any_addressable_vars
5210 && block
5211 && TREE_CODE (block) == BLOCK;
5212 block = BLOCK_SUPERCONTEXT (block))
5214 for (local_decls = BLOCK_VARS (block);
5215 local_decls;
5216 local_decls = DECL_CHAIN (local_decls))
5217 if (TREE_ADDRESSABLE (local_decls))
5219 any_addressable_vars = 1;
5220 break;
5222 if (block == gimple_block (parallel_stmt))
5223 break;
5226 if (!any_addressable_vars)
5227 gimple_omp_return_set_nowait (stmt);
5232 static void
5233 remove_exit_barriers (struct omp_region *region)
5235 if (region->type == GIMPLE_OMP_PARALLEL)
5236 remove_exit_barrier (region);
5238 if (region->inner)
5240 region = region->inner;
5241 remove_exit_barriers (region);
5242 while (region->next)
5244 region = region->next;
5245 remove_exit_barriers (region);
5250 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5251 calls. These can't be declared as const functions, but
5252 within one parallel body they are constant, so they can be
5253 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5254 which are declared const. Similarly for task body, except
5255 that in untied task omp_get_thread_num () can change at any task
5256 scheduling point. */
5258 static void
5259 optimize_omp_library_calls (gimple entry_stmt)
5261 basic_block bb;
5262 gimple_stmt_iterator gsi;
5263 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5264 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5265 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5266 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5267 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5268 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5269 OMP_CLAUSE_UNTIED) != NULL);
5271 FOR_EACH_BB_FN (bb, cfun)
5272 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5274 gimple call = gsi_stmt (gsi);
5275 tree decl;
5277 if (is_gimple_call (call)
5278 && (decl = gimple_call_fndecl (call))
5279 && DECL_EXTERNAL (decl)
5280 && TREE_PUBLIC (decl)
5281 && DECL_INITIAL (decl) == NULL)
5283 tree built_in;
5285 if (DECL_NAME (decl) == thr_num_id)
5287 /* In #pragma omp task untied omp_get_thread_num () can change
5288 during the execution of the task region. */
5289 if (untied_task)
5290 continue;
5291 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5293 else if (DECL_NAME (decl) == num_thr_id)
5294 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5295 else
5296 continue;
5298 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5299 || gimple_call_num_args (call) != 0)
5300 continue;
5302 if (flag_exceptions && !TREE_NOTHROW (decl))
5303 continue;
5305 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5306 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5307 TREE_TYPE (TREE_TYPE (built_in))))
5308 continue;
5310 gimple_call_set_fndecl (call, built_in);
5315 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5316 regimplified. */
5318 static tree
5319 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5321 tree t = *tp;
5323 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5324 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5325 return t;
5327 if (TREE_CODE (t) == ADDR_EXPR)
5328 recompute_tree_invariant_for_addr_expr (t);
5330 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5331 return NULL_TREE;
5334 /* Prepend TO = FROM assignment before *GSI_P. */
5336 static void
5337 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5339 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5340 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5341 true, GSI_SAME_STMT);
5342 gimple stmt = gimple_build_assign (to, from);
5343 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5344 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5345 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5347 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5348 gimple_regimplify_operands (stmt, &gsi);
5352 /* Expand the OpenMP parallel or task directive starting at REGION. */
5354 static void
5355 expand_omp_taskreg (struct omp_region *region)
5357 basic_block entry_bb, exit_bb, new_bb;
5358 struct function *child_cfun;
5359 tree child_fn, block, t;
5360 gimple_stmt_iterator gsi;
5361 gimple entry_stmt, stmt;
5362 edge e;
5363 vec<tree, va_gc> *ws_args;
5365 entry_stmt = last_stmt (region->entry);
5366 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5367 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5369 entry_bb = region->entry;
5370 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
5371 exit_bb = region->cont;
5372 else
5373 exit_bb = region->exit;
5375 bool is_cilk_for
5376 = (flag_cilkplus
5377 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5378 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5379 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5381 if (is_cilk_for)
5382 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5383 and the inner statement contains the name of the built-in function
5384 and grain. */
5385 ws_args = region->inner->ws_args;
5386 else if (is_combined_parallel (region))
5387 ws_args = region->ws_args;
5388 else
5389 ws_args = NULL;
5391 if (child_cfun->cfg)
5393 /* Due to inlining, it may happen that we have already outlined
5394 the region, in which case all we need to do is make the
5395 sub-graph unreachable and emit the parallel call. */
5396 edge entry_succ_e, exit_succ_e;
5398 entry_succ_e = single_succ_edge (entry_bb);
5400 gsi = gsi_last_bb (entry_bb);
5401 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5402 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5403 gsi_remove (&gsi, true);
5405 new_bb = entry_bb;
5406 if (exit_bb)
5408 exit_succ_e = single_succ_edge (exit_bb);
5409 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5411 remove_edge_and_dominated_blocks (entry_succ_e);
5413 else
5415 unsigned srcidx, dstidx, num;
5417 /* If the parallel region needs data sent from the parent
5418 function, then the very first statement (except possible
5419 tree profile counter updates) of the parallel body
5420 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5421 &.OMP_DATA_O is passed as an argument to the child function,
5422 we need to replace it with the argument as seen by the child
5423 function.
5425 In most cases, this will end up being the identity assignment
5426 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5427 a function call that has been inlined, the original PARM_DECL
5428 .OMP_DATA_I may have been converted into a different local
5429 variable. In which case, we need to keep the assignment. */
5430 if (gimple_omp_taskreg_data_arg (entry_stmt))
5432 basic_block entry_succ_bb
5433 = single_succ_p (entry_bb) ? single_succ (entry_bb)
5434 : FALLTHRU_EDGE (entry_bb)->dest;
5435 tree arg, narg;
5436 gimple parcopy_stmt = NULL;
5438 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5440 gimple stmt;
5442 gcc_assert (!gsi_end_p (gsi));
5443 stmt = gsi_stmt (gsi);
5444 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5445 continue;
5447 if (gimple_num_ops (stmt) == 2)
5449 tree arg = gimple_assign_rhs1 (stmt);
5451 /* We're ignore the subcode because we're
5452 effectively doing a STRIP_NOPS. */
5454 if (TREE_CODE (arg) == ADDR_EXPR
5455 && TREE_OPERAND (arg, 0)
5456 == gimple_omp_taskreg_data_arg (entry_stmt))
5458 parcopy_stmt = stmt;
5459 break;
5464 gcc_assert (parcopy_stmt != NULL);
5465 arg = DECL_ARGUMENTS (child_fn);
5467 if (!gimple_in_ssa_p (cfun))
5469 if (gimple_assign_lhs (parcopy_stmt) == arg)
5470 gsi_remove (&gsi, true);
5471 else
5473 /* ?? Is setting the subcode really necessary ?? */
5474 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5475 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5478 else
5480 /* If we are in ssa form, we must load the value from the default
5481 definition of the argument. That should not be defined now,
5482 since the argument is not used uninitialized. */
5483 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5484 narg = make_ssa_name (arg, gimple_build_nop ());
5485 set_ssa_default_def (cfun, arg, narg);
5486 /* ?? Is setting the subcode really necessary ?? */
5487 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5488 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5489 update_stmt (parcopy_stmt);
5493 /* Declare local variables needed in CHILD_CFUN. */
5494 block = DECL_INITIAL (child_fn);
5495 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5496 /* The gimplifier could record temporaries in parallel/task block
5497 rather than in containing function's local_decls chain,
5498 which would mean cgraph missed finalizing them. Do it now. */
5499 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5500 if (TREE_CODE (t) == VAR_DECL
5501 && TREE_STATIC (t)
5502 && !DECL_EXTERNAL (t))
5503 varpool_node::finalize_decl (t);
5504 DECL_SAVED_TREE (child_fn) = NULL;
5505 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5506 gimple_set_body (child_fn, NULL);
5507 TREE_USED (block) = 1;
5509 /* Reset DECL_CONTEXT on function arguments. */
5510 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5511 DECL_CONTEXT (t) = child_fn;
5513 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5514 so that it can be moved to the child function. */
5515 gsi = gsi_last_bb (entry_bb);
5516 stmt = gsi_stmt (gsi);
5517 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5518 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5519 e = split_block (entry_bb, stmt);
5520 gsi_remove (&gsi, true);
5521 entry_bb = e->dest;
5522 edge e2 = NULL;
5523 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5524 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5525 else
5527 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
5528 gcc_assert (e2->dest == region->exit);
5529 remove_edge (BRANCH_EDGE (entry_bb));
5530 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
5531 gsi = gsi_last_bb (region->exit);
5532 gcc_assert (!gsi_end_p (gsi)
5533 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5534 gsi_remove (&gsi, true);
5537 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5538 if (exit_bb)
5540 gsi = gsi_last_bb (exit_bb);
5541 gcc_assert (!gsi_end_p (gsi)
5542 && (gimple_code (gsi_stmt (gsi))
5543 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
5544 stmt = gimple_build_return (NULL);
5545 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5546 gsi_remove (&gsi, true);
5549 /* Move the parallel region into CHILD_CFUN. */
5551 if (gimple_in_ssa_p (cfun))
5553 init_tree_ssa (child_cfun);
5554 init_ssa_operands (child_cfun);
5555 child_cfun->gimple_df->in_ssa_p = true;
5556 block = NULL_TREE;
5558 else
5559 block = gimple_block (entry_stmt);
5561 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5562 if (exit_bb)
5563 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5564 if (e2)
5566 basic_block dest_bb = e2->dest;
5567 if (!exit_bb)
5568 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
5569 remove_edge (e2);
5570 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
5572 /* When the OMP expansion process cannot guarantee an up-to-date
5573 loop tree arrange for the child function to fixup loops. */
5574 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5575 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5577 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5578 num = vec_safe_length (child_cfun->local_decls);
5579 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5581 t = (*child_cfun->local_decls)[srcidx];
5582 if (DECL_CONTEXT (t) == cfun->decl)
5583 continue;
5584 if (srcidx != dstidx)
5585 (*child_cfun->local_decls)[dstidx] = t;
5586 dstidx++;
5588 if (dstidx != num)
5589 vec_safe_truncate (child_cfun->local_decls, dstidx);
5591 /* Inform the callgraph about the new function. */
5592 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5593 cgraph_node *node = cgraph_node::get_create (child_fn);
5594 node->parallelized_function = 1;
5595 cgraph_node::add_new_function (child_fn, true);
5597 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5598 fixed in a following pass. */
5599 push_cfun (child_cfun);
5600 if (optimize)
5601 optimize_omp_library_calls (entry_stmt);
5602 cgraph_edge::rebuild_edges ();
5604 /* Some EH regions might become dead, see PR34608. If
5605 pass_cleanup_cfg isn't the first pass to happen with the
5606 new child, these dead EH edges might cause problems.
5607 Clean them up now. */
5608 if (flag_exceptions)
5610 basic_block bb;
5611 bool changed = false;
5613 FOR_EACH_BB_FN (bb, cfun)
5614 changed |= gimple_purge_dead_eh_edges (bb);
5615 if (changed)
5616 cleanup_tree_cfg ();
5618 if (gimple_in_ssa_p (cfun))
5619 update_ssa (TODO_update_ssa);
5620 pop_cfun ();
5623 /* Emit a library call to launch the children threads. */
5624 if (is_cilk_for)
5625 expand_cilk_for_call (new_bb,
5626 as_a <gomp_parallel *> (entry_stmt), ws_args);
5627 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5628 expand_parallel_call (region, new_bb,
5629 as_a <gomp_parallel *> (entry_stmt), ws_args);
5630 else
5631 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5632 if (gimple_in_ssa_p (cfun))
5633 update_ssa (TODO_update_ssa_only_virtuals);
5637 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5638 of the combined collapse > 1 loop constructs, generate code like:
5639 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5640 if (cond3 is <)
5641 adj = STEP3 - 1;
5642 else
5643 adj = STEP3 + 1;
5644 count3 = (adj + N32 - N31) / STEP3;
5645 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5646 if (cond2 is <)
5647 adj = STEP2 - 1;
5648 else
5649 adj = STEP2 + 1;
5650 count2 = (adj + N22 - N21) / STEP2;
5651 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5652 if (cond1 is <)
5653 adj = STEP1 - 1;
5654 else
5655 adj = STEP1 + 1;
5656 count1 = (adj + N12 - N11) / STEP1;
5657 count = count1 * count2 * count3;
5658 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5659 count = 0;
5660 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5661 of the combined loop constructs, just initialize COUNTS array
5662 from the _looptemp_ clauses. */
5664 /* NOTE: It *could* be better to moosh all of the BBs together,
5665 creating one larger BB with all the computation and the unexpected
5666 jump at the end. I.e.
5668 bool zero3, zero2, zero1, zero;
5670 zero3 = N32 c3 N31;
5671 count3 = (N32 - N31) /[cl] STEP3;
5672 zero2 = N22 c2 N21;
5673 count2 = (N22 - N21) /[cl] STEP2;
5674 zero1 = N12 c1 N11;
5675 count1 = (N12 - N11) /[cl] STEP1;
5676 zero = zero3 || zero2 || zero1;
5677 count = count1 * count2 * count3;
5678 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5680 After all, we expect the zero=false, and thus we expect to have to
5681 evaluate all of the comparison expressions, so short-circuiting
5682 oughtn't be a win. Since the condition isn't protecting a
5683 denominator, we're not concerned about divide-by-zero, so we can
5684 fully evaluate count even if a numerator turned out to be wrong.
5686 It seems like putting this all together would create much better
5687 scheduling opportunities, and less pressure on the chip's branch
5688 predictor. */
5690 static void
5691 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5692 basic_block &entry_bb, tree *counts,
5693 basic_block &zero_iter_bb, int &first_zero_iter,
5694 basic_block &l2_dom_bb)
5696 tree t, type = TREE_TYPE (fd->loop.v);
5697 edge e, ne;
5698 int i;
5700 /* Collapsed loops need work for expansion into SSA form. */
5701 gcc_assert (!gimple_in_ssa_p (cfun));
5703 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5704 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5706 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5707 isn't supposed to be handled, as the inner loop doesn't
5708 use it. */
5709 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5710 OMP_CLAUSE__LOOPTEMP_);
5711 gcc_assert (innerc);
5712 for (i = 0; i < fd->collapse; i++)
5714 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5715 OMP_CLAUSE__LOOPTEMP_);
5716 gcc_assert (innerc);
5717 if (i)
5718 counts[i] = OMP_CLAUSE_DECL (innerc);
5719 else
5720 counts[0] = NULL_TREE;
5722 return;
5725 for (i = 0; i < fd->collapse; i++)
5727 tree itype = TREE_TYPE (fd->loops[i].v);
5729 if (SSA_VAR_P (fd->loop.n2)
5730 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5731 fold_convert (itype, fd->loops[i].n1),
5732 fold_convert (itype, fd->loops[i].n2)))
5733 == NULL_TREE || !integer_onep (t)))
5735 gcond *cond_stmt;
5736 tree n1, n2;
5737 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5738 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5739 true, GSI_SAME_STMT);
5740 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5741 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5742 true, GSI_SAME_STMT);
5743 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5744 NULL_TREE, NULL_TREE);
5745 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5746 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5747 expand_omp_regimplify_p, NULL, NULL)
5748 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5749 expand_omp_regimplify_p, NULL, NULL))
5751 *gsi = gsi_for_stmt (cond_stmt);
5752 gimple_regimplify_operands (cond_stmt, gsi);
5754 e = split_block (entry_bb, cond_stmt);
5755 if (zero_iter_bb == NULL)
5757 gassign *assign_stmt;
5758 first_zero_iter = i;
5759 zero_iter_bb = create_empty_bb (entry_bb);
5760 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5761 *gsi = gsi_after_labels (zero_iter_bb);
5762 assign_stmt = gimple_build_assign (fd->loop.n2,
5763 build_zero_cst (type));
5764 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5765 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5766 entry_bb);
5768 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5769 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5770 e->flags = EDGE_TRUE_VALUE;
5771 e->probability = REG_BR_PROB_BASE - ne->probability;
5772 if (l2_dom_bb == NULL)
5773 l2_dom_bb = entry_bb;
5774 entry_bb = e->dest;
5775 *gsi = gsi_last_bb (entry_bb);
5778 if (POINTER_TYPE_P (itype))
5779 itype = signed_type_for (itype);
5780 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5781 ? -1 : 1));
5782 t = fold_build2 (PLUS_EXPR, itype,
5783 fold_convert (itype, fd->loops[i].step), t);
5784 t = fold_build2 (PLUS_EXPR, itype, t,
5785 fold_convert (itype, fd->loops[i].n2));
5786 t = fold_build2 (MINUS_EXPR, itype, t,
5787 fold_convert (itype, fd->loops[i].n1));
5788 /* ?? We could probably use CEIL_DIV_EXPR instead of
5789 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5790 generate the same code in the end because generically we
5791 don't know that the values involved must be negative for
5792 GT?? */
5793 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5794 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5795 fold_build1 (NEGATE_EXPR, itype, t),
5796 fold_build1 (NEGATE_EXPR, itype,
5797 fold_convert (itype,
5798 fd->loops[i].step)));
5799 else
5800 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5801 fold_convert (itype, fd->loops[i].step));
5802 t = fold_convert (type, t);
5803 if (TREE_CODE (t) == INTEGER_CST)
5804 counts[i] = t;
5805 else
5807 counts[i] = create_tmp_reg (type, ".count");
5808 expand_omp_build_assign (gsi, counts[i], t);
5810 if (SSA_VAR_P (fd->loop.n2))
5812 if (i == 0)
5813 t = counts[0];
5814 else
5815 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5816 expand_omp_build_assign (gsi, fd->loop.n2, t);
5822 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5823 T = V;
5824 V3 = N31 + (T % count3) * STEP3;
5825 T = T / count3;
5826 V2 = N21 + (T % count2) * STEP2;
5827 T = T / count2;
5828 V1 = N11 + T * STEP1;
5829 if this loop doesn't have an inner loop construct combined with it.
5830 If it does have an inner loop construct combined with it and the
5831 iteration count isn't known constant, store values from counts array
5832 into its _looptemp_ temporaries instead. */
5834 static void
5835 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5836 tree *counts, gimple inner_stmt, tree startvar)
5838 int i;
5839 if (gimple_omp_for_combined_p (fd->for_stmt))
5841 /* If fd->loop.n2 is constant, then no propagation of the counts
5842 is needed, they are constant. */
5843 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5844 return;
5846 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5847 ? gimple_omp_parallel_clauses (inner_stmt)
5848 : gimple_omp_for_clauses (inner_stmt);
5849 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5850 isn't supposed to be handled, as the inner loop doesn't
5851 use it. */
5852 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5853 gcc_assert (innerc);
5854 for (i = 0; i < fd->collapse; i++)
5856 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5857 OMP_CLAUSE__LOOPTEMP_);
5858 gcc_assert (innerc);
5859 if (i)
5861 tree tem = OMP_CLAUSE_DECL (innerc);
5862 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5863 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5864 false, GSI_CONTINUE_LINKING);
5865 gassign *stmt = gimple_build_assign (tem, t);
5866 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5869 return;
5872 tree type = TREE_TYPE (fd->loop.v);
5873 tree tem = create_tmp_reg (type, ".tem");
5874 gassign *stmt = gimple_build_assign (tem, startvar);
5875 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5877 for (i = fd->collapse - 1; i >= 0; i--)
5879 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5880 itype = vtype;
5881 if (POINTER_TYPE_P (vtype))
5882 itype = signed_type_for (vtype);
5883 if (i != 0)
5884 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5885 else
5886 t = tem;
5887 t = fold_convert (itype, t);
5888 t = fold_build2 (MULT_EXPR, itype, t,
5889 fold_convert (itype, fd->loops[i].step));
5890 if (POINTER_TYPE_P (vtype))
5891 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5892 else
5893 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5894 t = force_gimple_operand_gsi (gsi, t,
5895 DECL_P (fd->loops[i].v)
5896 && TREE_ADDRESSABLE (fd->loops[i].v),
5897 NULL_TREE, false,
5898 GSI_CONTINUE_LINKING);
5899 stmt = gimple_build_assign (fd->loops[i].v, t);
5900 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5901 if (i != 0)
5903 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5904 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5905 false, GSI_CONTINUE_LINKING);
5906 stmt = gimple_build_assign (tem, t);
5907 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5913 /* Helper function for expand_omp_for_*. Generate code like:
5914 L10:
5915 V3 += STEP3;
5916 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5917 L11:
5918 V3 = N31;
5919 V2 += STEP2;
5920 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5921 L12:
5922 V2 = N21;
5923 V1 += STEP1;
5924 goto BODY_BB; */
5926 static basic_block
5927 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5928 basic_block body_bb)
5930 basic_block last_bb, bb, collapse_bb = NULL;
5931 int i;
5932 gimple_stmt_iterator gsi;
5933 edge e;
5934 tree t;
5935 gimple stmt;
5937 last_bb = cont_bb;
5938 for (i = fd->collapse - 1; i >= 0; i--)
5940 tree vtype = TREE_TYPE (fd->loops[i].v);
5942 bb = create_empty_bb (last_bb);
5943 add_bb_to_loop (bb, last_bb->loop_father);
5944 gsi = gsi_start_bb (bb);
5946 if (i < fd->collapse - 1)
5948 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5949 e->probability = REG_BR_PROB_BASE / 8;
5951 t = fd->loops[i + 1].n1;
5952 t = force_gimple_operand_gsi (&gsi, t,
5953 DECL_P (fd->loops[i + 1].v)
5954 && TREE_ADDRESSABLE (fd->loops[i
5955 + 1].v),
5956 NULL_TREE, false,
5957 GSI_CONTINUE_LINKING);
5958 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5959 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5961 else
5962 collapse_bb = bb;
5964 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5966 if (POINTER_TYPE_P (vtype))
5967 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5968 else
5969 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5970 t = force_gimple_operand_gsi (&gsi, t,
5971 DECL_P (fd->loops[i].v)
5972 && TREE_ADDRESSABLE (fd->loops[i].v),
5973 NULL_TREE, false, GSI_CONTINUE_LINKING);
5974 stmt = gimple_build_assign (fd->loops[i].v, t);
5975 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5977 if (i > 0)
5979 t = fd->loops[i].n2;
5980 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5981 false, GSI_CONTINUE_LINKING);
5982 tree v = fd->loops[i].v;
5983 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5984 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5985 false, GSI_CONTINUE_LINKING);
5986 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5987 stmt = gimple_build_cond_empty (t);
5988 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5989 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5990 e->probability = REG_BR_PROB_BASE * 7 / 8;
5992 else
5993 make_edge (bb, body_bb, EDGE_FALLTHRU);
5994 last_bb = bb;
5997 return collapse_bb;
6001 /* A subroutine of expand_omp_for. Generate code for a parallel
6002 loop with any schedule. Given parameters:
6004 for (V = N1; V cond N2; V += STEP) BODY;
6006 where COND is "<" or ">", we generate pseudocode
6008 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
6009 if (more) goto L0; else goto L3;
6011 V = istart0;
6012 iend = iend0;
6014 BODY;
6015 V += STEP;
6016 if (V cond iend) goto L1; else goto L2;
6018 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6021 If this is a combined omp parallel loop, instead of the call to
6022 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6023 If this is gimple_omp_for_combined_p loop, then instead of assigning
6024 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6025 inner GIMPLE_OMP_FOR and V += STEP; and
6026 if (V cond iend) goto L1; else goto L2; are removed.
6028 For collapsed loops, given parameters:
6029 collapse(3)
6030 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6031 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6032 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6033 BODY;
6035 we generate pseudocode
6037 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6038 if (cond3 is <)
6039 adj = STEP3 - 1;
6040 else
6041 adj = STEP3 + 1;
6042 count3 = (adj + N32 - N31) / STEP3;
6043 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6044 if (cond2 is <)
6045 adj = STEP2 - 1;
6046 else
6047 adj = STEP2 + 1;
6048 count2 = (adj + N22 - N21) / STEP2;
6049 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6050 if (cond1 is <)
6051 adj = STEP1 - 1;
6052 else
6053 adj = STEP1 + 1;
6054 count1 = (adj + N12 - N11) / STEP1;
6055 count = count1 * count2 * count3;
6056 goto Z1;
6058 count = 0;
6060 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6061 if (more) goto L0; else goto L3;
6063 V = istart0;
6064 T = V;
6065 V3 = N31 + (T % count3) * STEP3;
6066 T = T / count3;
6067 V2 = N21 + (T % count2) * STEP2;
6068 T = T / count2;
6069 V1 = N11 + T * STEP1;
6070 iend = iend0;
6072 BODY;
6073 V += 1;
6074 if (V < iend) goto L10; else goto L2;
6075 L10:
6076 V3 += STEP3;
6077 if (V3 cond3 N32) goto L1; else goto L11;
6078 L11:
6079 V3 = N31;
6080 V2 += STEP2;
6081 if (V2 cond2 N22) goto L1; else goto L12;
6082 L12:
6083 V2 = N21;
6084 V1 += STEP1;
6085 goto L1;
6087 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6092 static void
6093 expand_omp_for_generic (struct omp_region *region,
6094 struct omp_for_data *fd,
6095 enum built_in_function start_fn,
6096 enum built_in_function next_fn,
6097 gimple inner_stmt)
6099 tree type, istart0, iend0, iend;
6100 tree t, vmain, vback, bias = NULL_TREE;
6101 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6102 basic_block l2_bb = NULL, l3_bb = NULL;
6103 gimple_stmt_iterator gsi;
6104 gassign *assign_stmt;
6105 bool in_combined_parallel = is_combined_parallel (region);
6106 bool broken_loop = region->cont == NULL;
6107 edge e, ne;
6108 tree *counts = NULL;
6109 int i;
6111 gcc_assert (!broken_loop || !in_combined_parallel);
6112 gcc_assert (fd->iter_type == long_integer_type_node
6113 || !in_combined_parallel);
6115 type = TREE_TYPE (fd->loop.v);
6116 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6117 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6118 TREE_ADDRESSABLE (istart0) = 1;
6119 TREE_ADDRESSABLE (iend0) = 1;
6121 /* See if we need to bias by LLONG_MIN. */
6122 if (fd->iter_type == long_long_unsigned_type_node
6123 && TREE_CODE (type) == INTEGER_TYPE
6124 && !TYPE_UNSIGNED (type))
6126 tree n1, n2;
6128 if (fd->loop.cond_code == LT_EXPR)
6130 n1 = fd->loop.n1;
6131 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6133 else
6135 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6136 n2 = fd->loop.n1;
6138 if (TREE_CODE (n1) != INTEGER_CST
6139 || TREE_CODE (n2) != INTEGER_CST
6140 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6141 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6144 entry_bb = region->entry;
6145 cont_bb = region->cont;
6146 collapse_bb = NULL;
6147 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6148 gcc_assert (broken_loop
6149 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6150 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6151 l1_bb = single_succ (l0_bb);
6152 if (!broken_loop)
6154 l2_bb = create_empty_bb (cont_bb);
6155 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6156 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6158 else
6159 l2_bb = NULL;
6160 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6161 exit_bb = region->exit;
6163 gsi = gsi_last_bb (entry_bb);
6165 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6166 if (fd->collapse > 1)
6168 int first_zero_iter = -1;
6169 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6171 counts = XALLOCAVEC (tree, fd->collapse);
6172 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6173 zero_iter_bb, first_zero_iter,
6174 l2_dom_bb);
6176 if (zero_iter_bb)
6178 /* Some counts[i] vars might be uninitialized if
6179 some loop has zero iterations. But the body shouldn't
6180 be executed in that case, so just avoid uninit warnings. */
6181 for (i = first_zero_iter; i < fd->collapse; i++)
6182 if (SSA_VAR_P (counts[i]))
6183 TREE_NO_WARNING (counts[i]) = 1;
6184 gsi_prev (&gsi);
6185 e = split_block (entry_bb, gsi_stmt (gsi));
6186 entry_bb = e->dest;
6187 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6188 gsi = gsi_last_bb (entry_bb);
6189 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6190 get_immediate_dominator (CDI_DOMINATORS,
6191 zero_iter_bb));
6194 if (in_combined_parallel)
6196 /* In a combined parallel loop, emit a call to
6197 GOMP_loop_foo_next. */
6198 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6199 build_fold_addr_expr (istart0),
6200 build_fold_addr_expr (iend0));
6202 else
6204 tree t0, t1, t2, t3, t4;
6205 /* If this is not a combined parallel loop, emit a call to
6206 GOMP_loop_foo_start in ENTRY_BB. */
6207 t4 = build_fold_addr_expr (iend0);
6208 t3 = build_fold_addr_expr (istart0);
6209 t2 = fold_convert (fd->iter_type, fd->loop.step);
6210 t1 = fd->loop.n2;
6211 t0 = fd->loop.n1;
6212 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6214 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6215 OMP_CLAUSE__LOOPTEMP_);
6216 gcc_assert (innerc);
6217 t0 = OMP_CLAUSE_DECL (innerc);
6218 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6219 OMP_CLAUSE__LOOPTEMP_);
6220 gcc_assert (innerc);
6221 t1 = OMP_CLAUSE_DECL (innerc);
6223 if (POINTER_TYPE_P (TREE_TYPE (t0))
6224 && TYPE_PRECISION (TREE_TYPE (t0))
6225 != TYPE_PRECISION (fd->iter_type))
6227 /* Avoid casting pointers to integer of a different size. */
6228 tree itype = signed_type_for (type);
6229 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6230 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6232 else
6234 t1 = fold_convert (fd->iter_type, t1);
6235 t0 = fold_convert (fd->iter_type, t0);
6237 if (bias)
6239 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6240 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6242 if (fd->iter_type == long_integer_type_node)
6244 if (fd->chunk_size)
6246 t = fold_convert (fd->iter_type, fd->chunk_size);
6247 t = build_call_expr (builtin_decl_explicit (start_fn),
6248 6, t0, t1, t2, t, t3, t4);
6250 else
6251 t = build_call_expr (builtin_decl_explicit (start_fn),
6252 5, t0, t1, t2, t3, t4);
6254 else
6256 tree t5;
6257 tree c_bool_type;
6258 tree bfn_decl;
6260 /* The GOMP_loop_ull_*start functions have additional boolean
6261 argument, true for < loops and false for > loops.
6262 In Fortran, the C bool type can be different from
6263 boolean_type_node. */
6264 bfn_decl = builtin_decl_explicit (start_fn);
6265 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6266 t5 = build_int_cst (c_bool_type,
6267 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6268 if (fd->chunk_size)
6270 tree bfn_decl = builtin_decl_explicit (start_fn);
6271 t = fold_convert (fd->iter_type, fd->chunk_size);
6272 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6274 else
6275 t = build_call_expr (builtin_decl_explicit (start_fn),
6276 6, t5, t0, t1, t2, t3, t4);
6279 if (TREE_TYPE (t) != boolean_type_node)
6280 t = fold_build2 (NE_EXPR, boolean_type_node,
6281 t, build_int_cst (TREE_TYPE (t), 0));
6282 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6283 true, GSI_SAME_STMT);
6284 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6286 /* Remove the GIMPLE_OMP_FOR statement. */
6287 gsi_remove (&gsi, true);
6289 /* Iteration setup for sequential loop goes in L0_BB. */
6290 tree startvar = fd->loop.v;
6291 tree endvar = NULL_TREE;
6293 if (gimple_omp_for_combined_p (fd->for_stmt))
6295 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6296 && gimple_omp_for_kind (inner_stmt)
6297 == GF_OMP_FOR_KIND_SIMD);
6298 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6299 OMP_CLAUSE__LOOPTEMP_);
6300 gcc_assert (innerc);
6301 startvar = OMP_CLAUSE_DECL (innerc);
6302 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6303 OMP_CLAUSE__LOOPTEMP_);
6304 gcc_assert (innerc);
6305 endvar = OMP_CLAUSE_DECL (innerc);
6308 gsi = gsi_start_bb (l0_bb);
6309 t = istart0;
6310 if (bias)
6311 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6312 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6313 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6314 t = fold_convert (TREE_TYPE (startvar), t);
6315 t = force_gimple_operand_gsi (&gsi, t,
6316 DECL_P (startvar)
6317 && TREE_ADDRESSABLE (startvar),
6318 NULL_TREE, false, GSI_CONTINUE_LINKING);
6319 assign_stmt = gimple_build_assign (startvar, t);
6320 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6322 t = iend0;
6323 if (bias)
6324 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6325 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6326 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6327 t = fold_convert (TREE_TYPE (startvar), t);
6328 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6329 false, GSI_CONTINUE_LINKING);
6330 if (endvar)
6332 assign_stmt = gimple_build_assign (endvar, iend);
6333 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6334 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6335 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6336 else
6337 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6338 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6340 if (fd->collapse > 1)
6341 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6343 if (!broken_loop)
6345 /* Code to control the increment and predicate for the sequential
6346 loop goes in the CONT_BB. */
6347 gsi = gsi_last_bb (cont_bb);
6348 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6349 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6350 vmain = gimple_omp_continue_control_use (cont_stmt);
6351 vback = gimple_omp_continue_control_def (cont_stmt);
6353 if (!gimple_omp_for_combined_p (fd->for_stmt))
6355 if (POINTER_TYPE_P (type))
6356 t = fold_build_pointer_plus (vmain, fd->loop.step);
6357 else
6358 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6359 t = force_gimple_operand_gsi (&gsi, t,
6360 DECL_P (vback)
6361 && TREE_ADDRESSABLE (vback),
6362 NULL_TREE, true, GSI_SAME_STMT);
6363 assign_stmt = gimple_build_assign (vback, t);
6364 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6366 t = build2 (fd->loop.cond_code, boolean_type_node,
6367 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6368 iend);
6369 gcond *cond_stmt = gimple_build_cond_empty (t);
6370 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6373 /* Remove GIMPLE_OMP_CONTINUE. */
6374 gsi_remove (&gsi, true);
6376 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6377 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6379 /* Emit code to get the next parallel iteration in L2_BB. */
6380 gsi = gsi_start_bb (l2_bb);
6382 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6383 build_fold_addr_expr (istart0),
6384 build_fold_addr_expr (iend0));
6385 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6386 false, GSI_CONTINUE_LINKING);
6387 if (TREE_TYPE (t) != boolean_type_node)
6388 t = fold_build2 (NE_EXPR, boolean_type_node,
6389 t, build_int_cst (TREE_TYPE (t), 0));
6390 gcond *cond_stmt = gimple_build_cond_empty (t);
6391 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6394 /* Add the loop cleanup function. */
6395 gsi = gsi_last_bb (exit_bb);
6396 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6397 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6398 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6399 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6400 else
6401 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6402 gcall *call_stmt = gimple_build_call (t, 0);
6403 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6404 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6405 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6406 gsi_remove (&gsi, true);
6408 /* Connect the new blocks. */
6409 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6410 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6412 if (!broken_loop)
6414 gimple_seq phis;
6416 e = find_edge (cont_bb, l3_bb);
6417 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6419 phis = phi_nodes (l3_bb);
6420 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6422 gimple phi = gsi_stmt (gsi);
6423 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6424 PHI_ARG_DEF_FROM_EDGE (phi, e));
6426 remove_edge (e);
6428 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6429 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6430 e = find_edge (cont_bb, l1_bb);
6431 if (gimple_omp_for_combined_p (fd->for_stmt))
6433 remove_edge (e);
6434 e = NULL;
6436 else if (fd->collapse > 1)
6438 remove_edge (e);
6439 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6441 else
6442 e->flags = EDGE_TRUE_VALUE;
6443 if (e)
6445 e->probability = REG_BR_PROB_BASE * 7 / 8;
6446 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6448 else
6450 e = find_edge (cont_bb, l2_bb);
6451 e->flags = EDGE_FALLTHRU;
6453 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6455 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6456 recompute_dominator (CDI_DOMINATORS, l2_bb));
6457 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6458 recompute_dominator (CDI_DOMINATORS, l3_bb));
6459 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6460 recompute_dominator (CDI_DOMINATORS, l0_bb));
6461 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6462 recompute_dominator (CDI_DOMINATORS, l1_bb));
6464 struct loop *outer_loop = alloc_loop ();
6465 outer_loop->header = l0_bb;
6466 outer_loop->latch = l2_bb;
6467 add_loop (outer_loop, l0_bb->loop_father);
6469 if (!gimple_omp_for_combined_p (fd->for_stmt))
6471 struct loop *loop = alloc_loop ();
6472 loop->header = l1_bb;
6473 /* The loop may have multiple latches. */
6474 add_loop (loop, outer_loop);
6480 /* A subroutine of expand_omp_for. Generate code for a parallel
6481 loop with static schedule and no specified chunk size. Given
6482 parameters:
6484 for (V = N1; V cond N2; V += STEP) BODY;
6486 where COND is "<" or ">", we generate pseudocode
6488 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6489 if (cond is <)
6490 adj = STEP - 1;
6491 else
6492 adj = STEP + 1;
6493 if ((__typeof (V)) -1 > 0 && cond is >)
6494 n = -(adj + N2 - N1) / -STEP;
6495 else
6496 n = (adj + N2 - N1) / STEP;
6497 q = n / nthreads;
6498 tt = n % nthreads;
6499 if (threadid < tt) goto L3; else goto L4;
6501 tt = 0;
6502 q = q + 1;
6504 s0 = q * threadid + tt;
6505 e0 = s0 + q;
6506 V = s0 * STEP + N1;
6507 if (s0 >= e0) goto L2; else goto L0;
6509 e = e0 * STEP + N1;
6511 BODY;
6512 V += STEP;
6513 if (V cond e) goto L1;
6517 static void
6518 expand_omp_for_static_nochunk (struct omp_region *region,
6519 struct omp_for_data *fd,
6520 gimple inner_stmt)
6522 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6523 tree type, itype, vmain, vback;
6524 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6525 basic_block body_bb, cont_bb, collapse_bb = NULL;
6526 basic_block fin_bb;
6527 gimple_stmt_iterator gsi;
6528 edge ep;
6529 bool broken_loop = region->cont == NULL;
6530 tree *counts = NULL;
6531 tree n1, n2, step;
6533 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6534 != GF_OMP_FOR_KIND_OACC_LOOP)
6535 || !inner_stmt);
6537 itype = type = TREE_TYPE (fd->loop.v);
6538 if (POINTER_TYPE_P (type))
6539 itype = signed_type_for (type);
6541 entry_bb = region->entry;
6542 cont_bb = region->cont;
6543 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6544 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6545 gcc_assert (broken_loop
6546 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6547 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6548 body_bb = single_succ (seq_start_bb);
6549 if (!broken_loop)
6551 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6552 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6554 exit_bb = region->exit;
6556 /* Iteration space partitioning goes in ENTRY_BB. */
6557 gsi = gsi_last_bb (entry_bb);
6558 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6560 if (fd->collapse > 1)
6562 int first_zero_iter = -1;
6563 basic_block l2_dom_bb = NULL;
6565 counts = XALLOCAVEC (tree, fd->collapse);
6566 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6567 fin_bb, first_zero_iter,
6568 l2_dom_bb);
6569 t = NULL_TREE;
6571 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6572 t = integer_one_node;
6573 else
6574 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6575 fold_convert (type, fd->loop.n1),
6576 fold_convert (type, fd->loop.n2));
6577 if (fd->collapse == 1
6578 && TYPE_UNSIGNED (type)
6579 && (t == NULL_TREE || !integer_onep (t)))
6581 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6582 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6583 true, GSI_SAME_STMT);
6584 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6585 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6586 true, GSI_SAME_STMT);
6587 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6588 NULL_TREE, NULL_TREE);
6589 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6590 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6591 expand_omp_regimplify_p, NULL, NULL)
6592 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6593 expand_omp_regimplify_p, NULL, NULL))
6595 gsi = gsi_for_stmt (cond_stmt);
6596 gimple_regimplify_operands (cond_stmt, &gsi);
6598 ep = split_block (entry_bb, cond_stmt);
6599 ep->flags = EDGE_TRUE_VALUE;
6600 entry_bb = ep->dest;
6601 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6602 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6603 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6604 if (gimple_in_ssa_p (cfun))
6606 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6607 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6608 !gsi_end_p (gpi); gsi_next (&gpi))
6610 gphi *phi = gpi.phi ();
6611 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6612 ep, UNKNOWN_LOCATION);
6615 gsi = gsi_last_bb (entry_bb);
6618 switch (gimple_omp_for_kind (fd->for_stmt))
6620 case GF_OMP_FOR_KIND_FOR:
6621 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6622 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6623 break;
6624 case GF_OMP_FOR_KIND_DISTRIBUTE:
6625 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6626 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6627 break;
6628 case GF_OMP_FOR_KIND_OACC_LOOP:
6629 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6630 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6631 break;
6632 default:
6633 gcc_unreachable ();
6635 nthreads = build_call_expr (nthreads, 0);
6636 nthreads = fold_convert (itype, nthreads);
6637 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6638 true, GSI_SAME_STMT);
6639 threadid = build_call_expr (threadid, 0);
6640 threadid = fold_convert (itype, threadid);
6641 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6642 true, GSI_SAME_STMT);
6644 n1 = fd->loop.n1;
6645 n2 = fd->loop.n2;
6646 step = fd->loop.step;
6647 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6649 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6650 OMP_CLAUSE__LOOPTEMP_);
6651 gcc_assert (innerc);
6652 n1 = OMP_CLAUSE_DECL (innerc);
6653 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6654 OMP_CLAUSE__LOOPTEMP_);
6655 gcc_assert (innerc);
6656 n2 = OMP_CLAUSE_DECL (innerc);
6658 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6659 true, NULL_TREE, true, GSI_SAME_STMT);
6660 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6661 true, NULL_TREE, true, GSI_SAME_STMT);
6662 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6663 true, NULL_TREE, true, GSI_SAME_STMT);
6665 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6666 t = fold_build2 (PLUS_EXPR, itype, step, t);
6667 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6668 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6669 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6670 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6671 fold_build1 (NEGATE_EXPR, itype, t),
6672 fold_build1 (NEGATE_EXPR, itype, step));
6673 else
6674 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6675 t = fold_convert (itype, t);
6676 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6678 q = create_tmp_reg (itype, "q");
6679 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6680 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6681 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6683 tt = create_tmp_reg (itype, "tt");
6684 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6685 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6686 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6688 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6689 gcond *cond_stmt = gimple_build_cond_empty (t);
6690 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6692 second_bb = split_block (entry_bb, cond_stmt)->dest;
6693 gsi = gsi_last_bb (second_bb);
6694 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6696 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6697 GSI_SAME_STMT);
6698 gassign *assign_stmt
6699 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6700 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6702 third_bb = split_block (second_bb, assign_stmt)->dest;
6703 gsi = gsi_last_bb (third_bb);
6704 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6706 t = build2 (MULT_EXPR, itype, q, threadid);
6707 t = build2 (PLUS_EXPR, itype, t, tt);
6708 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6710 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6711 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6713 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6714 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6716 /* Remove the GIMPLE_OMP_FOR statement. */
6717 gsi_remove (&gsi, true);
6719 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6720 gsi = gsi_start_bb (seq_start_bb);
6722 tree startvar = fd->loop.v;
6723 tree endvar = NULL_TREE;
6725 if (gimple_omp_for_combined_p (fd->for_stmt))
6727 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6728 ? gimple_omp_parallel_clauses (inner_stmt)
6729 : gimple_omp_for_clauses (inner_stmt);
6730 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6731 gcc_assert (innerc);
6732 startvar = OMP_CLAUSE_DECL (innerc);
6733 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6734 OMP_CLAUSE__LOOPTEMP_);
6735 gcc_assert (innerc);
6736 endvar = OMP_CLAUSE_DECL (innerc);
6738 t = fold_convert (itype, s0);
6739 t = fold_build2 (MULT_EXPR, itype, t, step);
6740 if (POINTER_TYPE_P (type))
6741 t = fold_build_pointer_plus (n1, t);
6742 else
6743 t = fold_build2 (PLUS_EXPR, type, t, n1);
6744 t = fold_convert (TREE_TYPE (startvar), t);
6745 t = force_gimple_operand_gsi (&gsi, t,
6746 DECL_P (startvar)
6747 && TREE_ADDRESSABLE (startvar),
6748 NULL_TREE, false, GSI_CONTINUE_LINKING);
6749 assign_stmt = gimple_build_assign (startvar, t);
6750 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6752 t = fold_convert (itype, e0);
6753 t = fold_build2 (MULT_EXPR, itype, t, step);
6754 if (POINTER_TYPE_P (type))
6755 t = fold_build_pointer_plus (n1, t);
6756 else
6757 t = fold_build2 (PLUS_EXPR, type, t, n1);
6758 t = fold_convert (TREE_TYPE (startvar), t);
6759 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6760 false, GSI_CONTINUE_LINKING);
6761 if (endvar)
6763 assign_stmt = gimple_build_assign (endvar, e);
6764 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6765 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6766 assign_stmt = gimple_build_assign (fd->loop.v, e);
6767 else
6768 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6769 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6771 if (fd->collapse > 1)
6772 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6774 if (!broken_loop)
6776 /* The code controlling the sequential loop replaces the
6777 GIMPLE_OMP_CONTINUE. */
6778 gsi = gsi_last_bb (cont_bb);
6779 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6780 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6781 vmain = gimple_omp_continue_control_use (cont_stmt);
6782 vback = gimple_omp_continue_control_def (cont_stmt);
6784 if (!gimple_omp_for_combined_p (fd->for_stmt))
6786 if (POINTER_TYPE_P (type))
6787 t = fold_build_pointer_plus (vmain, step);
6788 else
6789 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6790 t = force_gimple_operand_gsi (&gsi, t,
6791 DECL_P (vback)
6792 && TREE_ADDRESSABLE (vback),
6793 NULL_TREE, true, GSI_SAME_STMT);
6794 assign_stmt = gimple_build_assign (vback, t);
6795 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6797 t = build2 (fd->loop.cond_code, boolean_type_node,
6798 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6799 ? t : vback, e);
6800 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6803 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6804 gsi_remove (&gsi, true);
6806 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6807 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6810 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6811 gsi = gsi_last_bb (exit_bb);
6812 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6814 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6815 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6816 gcc_checking_assert (t == NULL_TREE);
6817 else
6818 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6820 gsi_remove (&gsi, true);
6822 /* Connect all the blocks. */
6823 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6824 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6825 ep = find_edge (entry_bb, second_bb);
6826 ep->flags = EDGE_TRUE_VALUE;
6827 ep->probability = REG_BR_PROB_BASE / 4;
6828 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6829 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6831 if (!broken_loop)
6833 ep = find_edge (cont_bb, body_bb);
6834 if (gimple_omp_for_combined_p (fd->for_stmt))
6836 remove_edge (ep);
6837 ep = NULL;
6839 else if (fd->collapse > 1)
6841 remove_edge (ep);
6842 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6844 else
6845 ep->flags = EDGE_TRUE_VALUE;
6846 find_edge (cont_bb, fin_bb)->flags
6847 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6850 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6851 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6852 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6854 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6855 recompute_dominator (CDI_DOMINATORS, body_bb));
6856 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6857 recompute_dominator (CDI_DOMINATORS, fin_bb));
6859 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6861 struct loop *loop = alloc_loop ();
6862 loop->header = body_bb;
6863 if (collapse_bb == NULL)
6864 loop->latch = cont_bb;
6865 add_loop (loop, body_bb->loop_father);
6870 /* A subroutine of expand_omp_for. Generate code for a parallel
6871 loop with static schedule and a specified chunk size. Given
6872 parameters:
6874 for (V = N1; V cond N2; V += STEP) BODY;
6876 where COND is "<" or ">", we generate pseudocode
6878 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6879 if (cond is <)
6880 adj = STEP - 1;
6881 else
6882 adj = STEP + 1;
6883 if ((__typeof (V)) -1 > 0 && cond is >)
6884 n = -(adj + N2 - N1) / -STEP;
6885 else
6886 n = (adj + N2 - N1) / STEP;
6887 trip = 0;
6888 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6889 here so that V is defined
6890 if the loop is not entered
6892 s0 = (trip * nthreads + threadid) * CHUNK;
6893 e0 = min(s0 + CHUNK, n);
6894 if (s0 < n) goto L1; else goto L4;
6896 V = s0 * STEP + N1;
6897 e = e0 * STEP + N1;
6899 BODY;
6900 V += STEP;
6901 if (V cond e) goto L2; else goto L3;
6903 trip += 1;
6904 goto L0;
6908 static void
6909 expand_omp_for_static_chunk (struct omp_region *region,
6910 struct omp_for_data *fd, gimple inner_stmt)
6912 tree n, s0, e0, e, t;
6913 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6914 tree type, itype, vmain, vback, vextra;
6915 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6916 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6917 gimple_stmt_iterator gsi;
6918 edge se;
6919 bool broken_loop = region->cont == NULL;
6920 tree *counts = NULL;
6921 tree n1, n2, step;
6923 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6924 != GF_OMP_FOR_KIND_OACC_LOOP)
6925 || !inner_stmt);
6927 itype = type = TREE_TYPE (fd->loop.v);
6928 if (POINTER_TYPE_P (type))
6929 itype = signed_type_for (type);
6931 entry_bb = region->entry;
6932 se = split_block (entry_bb, last_stmt (entry_bb));
6933 entry_bb = se->src;
6934 iter_part_bb = se->dest;
6935 cont_bb = region->cont;
6936 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6937 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6938 gcc_assert (broken_loop
6939 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6940 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6941 body_bb = single_succ (seq_start_bb);
6942 if (!broken_loop)
6944 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6945 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6946 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6948 exit_bb = region->exit;
6950 /* Trip and adjustment setup goes in ENTRY_BB. */
6951 gsi = gsi_last_bb (entry_bb);
6952 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6954 if (fd->collapse > 1)
6956 int first_zero_iter = -1;
6957 basic_block l2_dom_bb = NULL;
6959 counts = XALLOCAVEC (tree, fd->collapse);
6960 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6961 fin_bb, first_zero_iter,
6962 l2_dom_bb);
6963 t = NULL_TREE;
6965 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6966 t = integer_one_node;
6967 else
6968 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6969 fold_convert (type, fd->loop.n1),
6970 fold_convert (type, fd->loop.n2));
6971 if (fd->collapse == 1
6972 && TYPE_UNSIGNED (type)
6973 && (t == NULL_TREE || !integer_onep (t)))
6975 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6976 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6977 true, GSI_SAME_STMT);
6978 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6979 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6980 true, GSI_SAME_STMT);
6981 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6982 NULL_TREE, NULL_TREE);
6983 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6984 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6985 expand_omp_regimplify_p, NULL, NULL)
6986 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6987 expand_omp_regimplify_p, NULL, NULL))
6989 gsi = gsi_for_stmt (cond_stmt);
6990 gimple_regimplify_operands (cond_stmt, &gsi);
6992 se = split_block (entry_bb, cond_stmt);
6993 se->flags = EDGE_TRUE_VALUE;
6994 entry_bb = se->dest;
6995 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6996 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6997 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6998 if (gimple_in_ssa_p (cfun))
7000 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
7001 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
7002 !gsi_end_p (gpi); gsi_next (&gpi))
7004 gphi *phi = gpi.phi ();
7005 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
7006 se, UNKNOWN_LOCATION);
7009 gsi = gsi_last_bb (entry_bb);
7012 switch (gimple_omp_for_kind (fd->for_stmt))
7014 case GF_OMP_FOR_KIND_FOR:
7015 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7016 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7017 break;
7018 case GF_OMP_FOR_KIND_DISTRIBUTE:
7019 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7020 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7021 break;
7022 case GF_OMP_FOR_KIND_OACC_LOOP:
7023 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7024 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7025 break;
7026 default:
7027 gcc_unreachable ();
7029 nthreads = build_call_expr (nthreads, 0);
7030 nthreads = fold_convert (itype, nthreads);
7031 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7032 true, GSI_SAME_STMT);
7033 threadid = build_call_expr (threadid, 0);
7034 threadid = fold_convert (itype, threadid);
7035 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7036 true, GSI_SAME_STMT);
7038 n1 = fd->loop.n1;
7039 n2 = fd->loop.n2;
7040 step = fd->loop.step;
7041 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7043 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7044 OMP_CLAUSE__LOOPTEMP_);
7045 gcc_assert (innerc);
7046 n1 = OMP_CLAUSE_DECL (innerc);
7047 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7048 OMP_CLAUSE__LOOPTEMP_);
7049 gcc_assert (innerc);
7050 n2 = OMP_CLAUSE_DECL (innerc);
7052 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7053 true, NULL_TREE, true, GSI_SAME_STMT);
7054 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7055 true, NULL_TREE, true, GSI_SAME_STMT);
7056 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7057 true, NULL_TREE, true, GSI_SAME_STMT);
7058 fd->chunk_size
7059 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7060 true, NULL_TREE, true, GSI_SAME_STMT);
7062 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7063 t = fold_build2 (PLUS_EXPR, itype, step, t);
7064 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7065 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7066 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7067 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7068 fold_build1 (NEGATE_EXPR, itype, t),
7069 fold_build1 (NEGATE_EXPR, itype, step));
7070 else
7071 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7072 t = fold_convert (itype, t);
7073 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7074 true, GSI_SAME_STMT);
7076 trip_var = create_tmp_reg (itype, ".trip");
7077 if (gimple_in_ssa_p (cfun))
7079 trip_init = make_ssa_name (trip_var);
7080 trip_main = make_ssa_name (trip_var);
7081 trip_back = make_ssa_name (trip_var);
7083 else
7085 trip_init = trip_var;
7086 trip_main = trip_var;
7087 trip_back = trip_var;
7090 gassign *assign_stmt
7091 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7092 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7094 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7095 t = fold_build2 (MULT_EXPR, itype, t, step);
7096 if (POINTER_TYPE_P (type))
7097 t = fold_build_pointer_plus (n1, t);
7098 else
7099 t = fold_build2 (PLUS_EXPR, type, t, n1);
7100 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7101 true, GSI_SAME_STMT);
7103 /* Remove the GIMPLE_OMP_FOR. */
7104 gsi_remove (&gsi, true);
7106 /* Iteration space partitioning goes in ITER_PART_BB. */
7107 gsi = gsi_last_bb (iter_part_bb);
7109 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7110 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7111 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7112 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7113 false, GSI_CONTINUE_LINKING);
7115 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7116 t = fold_build2 (MIN_EXPR, itype, t, n);
7117 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7118 false, GSI_CONTINUE_LINKING);
7120 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7121 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7123 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7124 gsi = gsi_start_bb (seq_start_bb);
7126 tree startvar = fd->loop.v;
7127 tree endvar = NULL_TREE;
7129 if (gimple_omp_for_combined_p (fd->for_stmt))
7131 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7132 ? gimple_omp_parallel_clauses (inner_stmt)
7133 : gimple_omp_for_clauses (inner_stmt);
7134 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7135 gcc_assert (innerc);
7136 startvar = OMP_CLAUSE_DECL (innerc);
7137 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7138 OMP_CLAUSE__LOOPTEMP_);
7139 gcc_assert (innerc);
7140 endvar = OMP_CLAUSE_DECL (innerc);
7143 t = fold_convert (itype, s0);
7144 t = fold_build2 (MULT_EXPR, itype, t, step);
7145 if (POINTER_TYPE_P (type))
7146 t = fold_build_pointer_plus (n1, t);
7147 else
7148 t = fold_build2 (PLUS_EXPR, type, t, n1);
7149 t = fold_convert (TREE_TYPE (startvar), t);
7150 t = force_gimple_operand_gsi (&gsi, t,
7151 DECL_P (startvar)
7152 && TREE_ADDRESSABLE (startvar),
7153 NULL_TREE, false, GSI_CONTINUE_LINKING);
7154 assign_stmt = gimple_build_assign (startvar, t);
7155 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7157 t = fold_convert (itype, e0);
7158 t = fold_build2 (MULT_EXPR, itype, t, step);
7159 if (POINTER_TYPE_P (type))
7160 t = fold_build_pointer_plus (n1, t);
7161 else
7162 t = fold_build2 (PLUS_EXPR, type, t, n1);
7163 t = fold_convert (TREE_TYPE (startvar), t);
7164 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7165 false, GSI_CONTINUE_LINKING);
7166 if (endvar)
7168 assign_stmt = gimple_build_assign (endvar, e);
7169 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7170 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7171 assign_stmt = gimple_build_assign (fd->loop.v, e);
7172 else
7173 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7174 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7176 if (fd->collapse > 1)
7177 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7179 if (!broken_loop)
7181 /* The code controlling the sequential loop goes in CONT_BB,
7182 replacing the GIMPLE_OMP_CONTINUE. */
7183 gsi = gsi_last_bb (cont_bb);
7184 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7185 vmain = gimple_omp_continue_control_use (cont_stmt);
7186 vback = gimple_omp_continue_control_def (cont_stmt);
7188 if (!gimple_omp_for_combined_p (fd->for_stmt))
7190 if (POINTER_TYPE_P (type))
7191 t = fold_build_pointer_plus (vmain, step);
7192 else
7193 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7194 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7195 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7196 true, GSI_SAME_STMT);
7197 assign_stmt = gimple_build_assign (vback, t);
7198 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7200 t = build2 (fd->loop.cond_code, boolean_type_node,
7201 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7202 ? t : vback, e);
7203 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7206 /* Remove GIMPLE_OMP_CONTINUE. */
7207 gsi_remove (&gsi, true);
7209 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7210 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7212 /* Trip update code goes into TRIP_UPDATE_BB. */
7213 gsi = gsi_start_bb (trip_update_bb);
7215 t = build_int_cst (itype, 1);
7216 t = build2 (PLUS_EXPR, itype, trip_main, t);
7217 assign_stmt = gimple_build_assign (trip_back, t);
7218 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7221 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7222 gsi = gsi_last_bb (exit_bb);
7223 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7225 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7226 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7227 gcc_checking_assert (t == NULL_TREE);
7228 else
7229 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7231 gsi_remove (&gsi, true);
7233 /* Connect the new blocks. */
7234 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7235 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7237 if (!broken_loop)
7239 se = find_edge (cont_bb, body_bb);
7240 if (gimple_omp_for_combined_p (fd->for_stmt))
7242 remove_edge (se);
7243 se = NULL;
7245 else if (fd->collapse > 1)
7247 remove_edge (se);
7248 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7250 else
7251 se->flags = EDGE_TRUE_VALUE;
7252 find_edge (cont_bb, trip_update_bb)->flags
7253 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7255 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7258 if (gimple_in_ssa_p (cfun))
7260 gphi_iterator psi;
7261 gphi *phi;
7262 edge re, ene;
7263 edge_var_map *vm;
7264 size_t i;
7266 gcc_assert (fd->collapse == 1 && !broken_loop);
7268 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7269 remove arguments of the phi nodes in fin_bb. We need to create
7270 appropriate phi nodes in iter_part_bb instead. */
7271 se = single_pred_edge (fin_bb);
7272 re = single_succ_edge (trip_update_bb);
7273 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7274 ene = single_succ_edge (entry_bb);
7276 psi = gsi_start_phis (fin_bb);
7277 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7278 gsi_next (&psi), ++i)
7280 gphi *nphi;
7281 source_location locus;
7283 phi = psi.phi ();
7284 t = gimple_phi_result (phi);
7285 gcc_assert (t == redirect_edge_var_map_result (vm));
7286 nphi = create_phi_node (t, iter_part_bb);
7288 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7289 locus = gimple_phi_arg_location_from_edge (phi, se);
7291 /* A special case -- fd->loop.v is not yet computed in
7292 iter_part_bb, we need to use vextra instead. */
7293 if (t == fd->loop.v)
7294 t = vextra;
7295 add_phi_arg (nphi, t, ene, locus);
7296 locus = redirect_edge_var_map_location (vm);
7297 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7299 gcc_assert (gsi_end_p (psi) && i == head->length ());
7300 redirect_edge_var_map_clear (re);
7301 while (1)
7303 psi = gsi_start_phis (fin_bb);
7304 if (gsi_end_p (psi))
7305 break;
7306 remove_phi_node (&psi, false);
7309 /* Make phi node for trip. */
7310 phi = create_phi_node (trip_main, iter_part_bb);
7311 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7312 UNKNOWN_LOCATION);
7313 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7314 UNKNOWN_LOCATION);
7317 if (!broken_loop)
7318 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7319 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7320 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7321 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7322 recompute_dominator (CDI_DOMINATORS, fin_bb));
7323 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7324 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7325 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7326 recompute_dominator (CDI_DOMINATORS, body_bb));
7328 if (!broken_loop)
7330 struct loop *trip_loop = alloc_loop ();
7331 trip_loop->header = iter_part_bb;
7332 trip_loop->latch = trip_update_bb;
7333 add_loop (trip_loop, iter_part_bb->loop_father);
7335 if (!gimple_omp_for_combined_p (fd->for_stmt))
7337 struct loop *loop = alloc_loop ();
7338 loop->header = body_bb;
7339 if (collapse_bb == NULL)
7340 loop->latch = cont_bb;
7341 add_loop (loop, trip_loop);
7346 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7347 Given parameters:
7348 for (V = N1; V cond N2; V += STEP) BODY;
7350 where COND is "<" or ">" or "!=", we generate pseudocode
7352 for (ind_var = low; ind_var < high; ind_var++)
7354 V = n1 + (ind_var * STEP)
7356 <BODY>
7359 In the above pseudocode, low and high are function parameters of the
7360 child function. In the function below, we are inserting a temp.
7361 variable that will be making a call to two OMP functions that will not be
7362 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7363 with _Cilk_for). These functions are replaced with low and high
7364 by the function that handles taskreg. */
7367 static void
7368 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7370 bool broken_loop = region->cont == NULL;
7371 basic_block entry_bb = region->entry;
7372 basic_block cont_bb = region->cont;
7374 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7375 gcc_assert (broken_loop
7376 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7377 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7378 basic_block l1_bb, l2_bb;
7380 if (!broken_loop)
7382 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7383 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7384 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7385 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7387 else
7389 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7390 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7391 l2_bb = single_succ (l1_bb);
7393 basic_block exit_bb = region->exit;
7394 basic_block l2_dom_bb = NULL;
7396 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7398 /* Below statements until the "tree high_val = ..." are pseudo statements
7399 used to pass information to be used by expand_omp_taskreg.
7400 low_val and high_val will be replaced by the __low and __high
7401 parameter from the child function.
7403 The call_exprs part is a place-holder, it is mainly used
7404 to distinctly identify to the top-level part that this is
7405 where we should put low and high (reasoning given in header
7406 comment). */
7408 tree child_fndecl
7409 = gimple_omp_parallel_child_fn (
7410 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7411 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7412 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7414 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7415 high_val = t;
7416 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7417 low_val = t;
7419 gcc_assert (low_val && high_val);
7421 tree type = TREE_TYPE (low_val);
7422 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7423 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7425 /* Not needed in SSA form right now. */
7426 gcc_assert (!gimple_in_ssa_p (cfun));
7427 if (l2_dom_bb == NULL)
7428 l2_dom_bb = l1_bb;
7430 tree n1 = low_val;
7431 tree n2 = high_val;
7433 gimple stmt = gimple_build_assign (ind_var, n1);
7435 /* Replace the GIMPLE_OMP_FOR statement. */
7436 gsi_replace (&gsi, stmt, true);
7438 if (!broken_loop)
7440 /* Code to control the increment goes in the CONT_BB. */
7441 gsi = gsi_last_bb (cont_bb);
7442 stmt = gsi_stmt (gsi);
7443 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7444 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7445 build_one_cst (type));
7447 /* Replace GIMPLE_OMP_CONTINUE. */
7448 gsi_replace (&gsi, stmt, true);
7451 /* Emit the condition in L1_BB. */
7452 gsi = gsi_after_labels (l1_bb);
7453 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7454 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7455 fd->loop.step);
7456 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7457 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7458 fd->loop.n1, fold_convert (sizetype, t));
7459 else
7460 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7461 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7462 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7463 expand_omp_build_assign (&gsi, fd->loop.v, t);
7465 /* The condition is always '<' since the runtime will fill in the low
7466 and high values. */
7467 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7468 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7470 /* Remove GIMPLE_OMP_RETURN. */
7471 gsi = gsi_last_bb (exit_bb);
7472 gsi_remove (&gsi, true);
7474 /* Connect the new blocks. */
7475 remove_edge (FALLTHRU_EDGE (entry_bb));
7477 edge e, ne;
7478 if (!broken_loop)
7480 remove_edge (BRANCH_EDGE (entry_bb));
7481 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7483 e = BRANCH_EDGE (l1_bb);
7484 ne = FALLTHRU_EDGE (l1_bb);
7485 e->flags = EDGE_TRUE_VALUE;
7487 else
7489 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7491 ne = single_succ_edge (l1_bb);
7492 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7495 ne->flags = EDGE_FALSE_VALUE;
7496 e->probability = REG_BR_PROB_BASE * 7 / 8;
7497 ne->probability = REG_BR_PROB_BASE / 8;
7499 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7500 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7501 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7503 if (!broken_loop)
7505 struct loop *loop = alloc_loop ();
7506 loop->header = l1_bb;
7507 loop->latch = cont_bb;
7508 add_loop (loop, l1_bb->loop_father);
7509 loop->safelen = INT_MAX;
7512 /* Pick the correct library function based on the precision of the
7513 induction variable type. */
7514 tree lib_fun = NULL_TREE;
7515 if (TYPE_PRECISION (type) == 32)
7516 lib_fun = cilk_for_32_fndecl;
7517 else if (TYPE_PRECISION (type) == 64)
7518 lib_fun = cilk_for_64_fndecl;
7519 else
7520 gcc_unreachable ();
7522 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7524 /* WS_ARGS contains the library function flavor to call:
7525 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7526 user-defined grain value. If the user does not define one, then zero
7527 is passed in by the parser. */
7528 vec_alloc (region->ws_args, 2);
7529 region->ws_args->quick_push (lib_fun);
7530 region->ws_args->quick_push (fd->chunk_size);
7533 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7534 loop. Given parameters:
7536 for (V = N1; V cond N2; V += STEP) BODY;
7538 where COND is "<" or ">", we generate pseudocode
7540 V = N1;
7541 goto L1;
7543 BODY;
7544 V += STEP;
7546 if (V cond N2) goto L0; else goto L2;
7549 For collapsed loops, given parameters:
7550 collapse(3)
7551 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7552 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7553 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7554 BODY;
7556 we generate pseudocode
7558 if (cond3 is <)
7559 adj = STEP3 - 1;
7560 else
7561 adj = STEP3 + 1;
7562 count3 = (adj + N32 - N31) / STEP3;
7563 if (cond2 is <)
7564 adj = STEP2 - 1;
7565 else
7566 adj = STEP2 + 1;
7567 count2 = (adj + N22 - N21) / STEP2;
7568 if (cond1 is <)
7569 adj = STEP1 - 1;
7570 else
7571 adj = STEP1 + 1;
7572 count1 = (adj + N12 - N11) / STEP1;
7573 count = count1 * count2 * count3;
7574 V = 0;
7575 V1 = N11;
7576 V2 = N21;
7577 V3 = N31;
7578 goto L1;
7580 BODY;
7581 V += 1;
7582 V3 += STEP3;
7583 V2 += (V3 cond3 N32) ? 0 : STEP2;
7584 V3 = (V3 cond3 N32) ? V3 : N31;
7585 V1 += (V2 cond2 N22) ? 0 : STEP1;
7586 V2 = (V2 cond2 N22) ? V2 : N21;
7588 if (V < count) goto L0; else goto L2;
7593 static void
7594 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7596 tree type, t;
7597 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7598 gimple_stmt_iterator gsi;
7599 gimple stmt;
7600 gcond *cond_stmt;
7601 bool broken_loop = region->cont == NULL;
7602 edge e, ne;
7603 tree *counts = NULL;
7604 int i;
7605 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7606 OMP_CLAUSE_SAFELEN);
7607 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7608 OMP_CLAUSE__SIMDUID_);
7609 tree n1, n2;
7611 type = TREE_TYPE (fd->loop.v);
7612 entry_bb = region->entry;
7613 cont_bb = region->cont;
7614 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7615 gcc_assert (broken_loop
7616 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7617 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7618 if (!broken_loop)
7620 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7621 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7622 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7623 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7625 else
7627 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7628 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7629 l2_bb = single_succ (l1_bb);
7631 exit_bb = region->exit;
7632 l2_dom_bb = NULL;
7634 gsi = gsi_last_bb (entry_bb);
7636 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7637 /* Not needed in SSA form right now. */
7638 gcc_assert (!gimple_in_ssa_p (cfun));
7639 if (fd->collapse > 1)
7641 int first_zero_iter = -1;
7642 basic_block zero_iter_bb = l2_bb;
7644 counts = XALLOCAVEC (tree, fd->collapse);
7645 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7646 zero_iter_bb, first_zero_iter,
7647 l2_dom_bb);
7649 if (l2_dom_bb == NULL)
7650 l2_dom_bb = l1_bb;
7652 n1 = fd->loop.n1;
7653 n2 = fd->loop.n2;
7654 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7656 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7657 OMP_CLAUSE__LOOPTEMP_);
7658 gcc_assert (innerc);
7659 n1 = OMP_CLAUSE_DECL (innerc);
7660 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7661 OMP_CLAUSE__LOOPTEMP_);
7662 gcc_assert (innerc);
7663 n2 = OMP_CLAUSE_DECL (innerc);
7664 expand_omp_build_assign (&gsi, fd->loop.v,
7665 fold_convert (type, n1));
7666 if (fd->collapse > 1)
7668 gsi_prev (&gsi);
7669 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7670 gsi_next (&gsi);
7673 else
7675 expand_omp_build_assign (&gsi, fd->loop.v,
7676 fold_convert (type, fd->loop.n1));
7677 if (fd->collapse > 1)
7678 for (i = 0; i < fd->collapse; i++)
7680 tree itype = TREE_TYPE (fd->loops[i].v);
7681 if (POINTER_TYPE_P (itype))
7682 itype = signed_type_for (itype);
7683 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7684 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7688 /* Remove the GIMPLE_OMP_FOR statement. */
7689 gsi_remove (&gsi, true);
7691 if (!broken_loop)
7693 /* Code to control the increment goes in the CONT_BB. */
7694 gsi = gsi_last_bb (cont_bb);
7695 stmt = gsi_stmt (gsi);
7696 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7698 if (POINTER_TYPE_P (type))
7699 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7700 else
7701 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7702 expand_omp_build_assign (&gsi, fd->loop.v, t);
7704 if (fd->collapse > 1)
7706 i = fd->collapse - 1;
7707 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7709 t = fold_convert (sizetype, fd->loops[i].step);
7710 t = fold_build_pointer_plus (fd->loops[i].v, t);
7712 else
7714 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7715 fd->loops[i].step);
7716 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7717 fd->loops[i].v, t);
7719 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7721 for (i = fd->collapse - 1; i > 0; i--)
7723 tree itype = TREE_TYPE (fd->loops[i].v);
7724 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7725 if (POINTER_TYPE_P (itype2))
7726 itype2 = signed_type_for (itype2);
7727 t = build3 (COND_EXPR, itype2,
7728 build2 (fd->loops[i].cond_code, boolean_type_node,
7729 fd->loops[i].v,
7730 fold_convert (itype, fd->loops[i].n2)),
7731 build_int_cst (itype2, 0),
7732 fold_convert (itype2, fd->loops[i - 1].step));
7733 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7734 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7735 else
7736 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7737 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7739 t = build3 (COND_EXPR, itype,
7740 build2 (fd->loops[i].cond_code, boolean_type_node,
7741 fd->loops[i].v,
7742 fold_convert (itype, fd->loops[i].n2)),
7743 fd->loops[i].v,
7744 fold_convert (itype, fd->loops[i].n1));
7745 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7749 /* Remove GIMPLE_OMP_CONTINUE. */
7750 gsi_remove (&gsi, true);
7753 /* Emit the condition in L1_BB. */
7754 gsi = gsi_start_bb (l1_bb);
7756 t = fold_convert (type, n2);
7757 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7758 false, GSI_CONTINUE_LINKING);
7759 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7760 cond_stmt = gimple_build_cond_empty (t);
7761 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7762 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7763 NULL, NULL)
7764 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7765 NULL, NULL))
7767 gsi = gsi_for_stmt (cond_stmt);
7768 gimple_regimplify_operands (cond_stmt, &gsi);
7771 /* Remove GIMPLE_OMP_RETURN. */
7772 gsi = gsi_last_bb (exit_bb);
7773 gsi_remove (&gsi, true);
7775 /* Connect the new blocks. */
7776 remove_edge (FALLTHRU_EDGE (entry_bb));
7778 if (!broken_loop)
7780 remove_edge (BRANCH_EDGE (entry_bb));
7781 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7783 e = BRANCH_EDGE (l1_bb);
7784 ne = FALLTHRU_EDGE (l1_bb);
7785 e->flags = EDGE_TRUE_VALUE;
7787 else
7789 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7791 ne = single_succ_edge (l1_bb);
7792 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7795 ne->flags = EDGE_FALSE_VALUE;
7796 e->probability = REG_BR_PROB_BASE * 7 / 8;
7797 ne->probability = REG_BR_PROB_BASE / 8;
7799 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7800 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7801 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7803 if (!broken_loop)
7805 struct loop *loop = alloc_loop ();
7806 loop->header = l1_bb;
7807 loop->latch = cont_bb;
7808 add_loop (loop, l1_bb->loop_father);
7809 if (safelen == NULL_TREE)
7810 loop->safelen = INT_MAX;
7811 else
7813 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7814 if (TREE_CODE (safelen) != INTEGER_CST)
7815 loop->safelen = 0;
7816 else if (!tree_fits_uhwi_p (safelen)
7817 || tree_to_uhwi (safelen) > INT_MAX)
7818 loop->safelen = INT_MAX;
7819 else
7820 loop->safelen = tree_to_uhwi (safelen);
7821 if (loop->safelen == 1)
7822 loop->safelen = 0;
7824 if (simduid)
7826 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7827 cfun->has_simduid_loops = true;
7829 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7830 the loop. */
7831 if ((flag_tree_loop_vectorize
7832 || (!global_options_set.x_flag_tree_loop_vectorize
7833 && !global_options_set.x_flag_tree_vectorize))
7834 && flag_tree_loop_optimize
7835 && loop->safelen > 1)
7837 loop->force_vectorize = true;
7838 cfun->has_force_vectorize_loops = true;
7844 /* Expand the OMP loop defined by REGION. */
7846 static void
7847 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7849 struct omp_for_data fd;
7850 struct omp_for_data_loop *loops;
7852 loops
7853 = (struct omp_for_data_loop *)
7854 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7855 * sizeof (struct omp_for_data_loop));
7856 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7857 &fd, loops);
7858 region->sched_kind = fd.sched_kind;
7860 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7861 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7862 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7863 if (region->cont)
7865 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7866 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7867 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7869 else
7870 /* If there isn't a continue then this is a degerate case where
7871 the introduction of abnormal edges during lowering will prevent
7872 original loops from being detected. Fix that up. */
7873 loops_state_set (LOOPS_NEED_FIXUP);
7875 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7876 expand_omp_simd (region, &fd);
7877 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7878 expand_cilk_for (region, &fd);
7879 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7880 && !fd.have_ordered)
7882 if (fd.chunk_size == NULL)
7883 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7884 else
7885 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7887 else
7889 int fn_index, start_ix, next_ix;
7891 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7892 == GF_OMP_FOR_KIND_FOR);
7893 if (fd.chunk_size == NULL
7894 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7895 fd.chunk_size = integer_zero_node;
7896 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7897 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7898 ? 3 : fd.sched_kind;
7899 fn_index += fd.have_ordered * 4;
7900 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7901 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7902 if (fd.iter_type == long_long_unsigned_type_node)
7904 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7905 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7906 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7907 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7909 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7910 (enum built_in_function) next_ix, inner_stmt);
7913 if (gimple_in_ssa_p (cfun))
7914 update_ssa (TODO_update_ssa_only_virtuals);
7918 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7920 v = GOMP_sections_start (n);
7922 switch (v)
7924 case 0:
7925 goto L2;
7926 case 1:
7927 section 1;
7928 goto L1;
7929 case 2:
7931 case n:
7933 default:
7934 abort ();
7937 v = GOMP_sections_next ();
7938 goto L0;
7940 reduction;
7942 If this is a combined parallel sections, replace the call to
7943 GOMP_sections_start with call to GOMP_sections_next. */
7945 static void
7946 expand_omp_sections (struct omp_region *region)
7948 tree t, u, vin = NULL, vmain, vnext, l2;
7949 unsigned len;
7950 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7951 gimple_stmt_iterator si, switch_si;
7952 gomp_sections *sections_stmt;
7953 gimple stmt;
7954 gomp_continue *cont;
7955 edge_iterator ei;
7956 edge e;
7957 struct omp_region *inner;
7958 unsigned i, casei;
7959 bool exit_reachable = region->cont != NULL;
7961 gcc_assert (region->exit != NULL);
7962 entry_bb = region->entry;
7963 l0_bb = single_succ (entry_bb);
7964 l1_bb = region->cont;
7965 l2_bb = region->exit;
7966 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7967 l2 = gimple_block_label (l2_bb);
7968 else
7970 /* This can happen if there are reductions. */
7971 len = EDGE_COUNT (l0_bb->succs);
7972 gcc_assert (len > 0);
7973 e = EDGE_SUCC (l0_bb, len - 1);
7974 si = gsi_last_bb (e->dest);
7975 l2 = NULL_TREE;
7976 if (gsi_end_p (si)
7977 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7978 l2 = gimple_block_label (e->dest);
7979 else
7980 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7982 si = gsi_last_bb (e->dest);
7983 if (gsi_end_p (si)
7984 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7986 l2 = gimple_block_label (e->dest);
7987 break;
7991 if (exit_reachable)
7992 default_bb = create_empty_bb (l1_bb->prev_bb);
7993 else
7994 default_bb = create_empty_bb (l0_bb);
7996 /* We will build a switch() with enough cases for all the
7997 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7998 and a default case to abort if something goes wrong. */
7999 len = EDGE_COUNT (l0_bb->succs);
8001 /* Use vec::quick_push on label_vec throughout, since we know the size
8002 in advance. */
8003 auto_vec<tree> label_vec (len);
8005 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
8006 GIMPLE_OMP_SECTIONS statement. */
8007 si = gsi_last_bb (entry_bb);
8008 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
8009 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8010 vin = gimple_omp_sections_control (sections_stmt);
8011 if (!is_combined_parallel (region))
8013 /* If we are not inside a combined parallel+sections region,
8014 call GOMP_sections_start. */
8015 t = build_int_cst (unsigned_type_node, len - 1);
8016 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
8017 stmt = gimple_build_call (u, 1, t);
8019 else
8021 /* Otherwise, call GOMP_sections_next. */
8022 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8023 stmt = gimple_build_call (u, 0);
8025 gimple_call_set_lhs (stmt, vin);
8026 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8027 gsi_remove (&si, true);
8029 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8030 L0_BB. */
8031 switch_si = gsi_last_bb (l0_bb);
8032 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8033 if (exit_reachable)
8035 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8036 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8037 vmain = gimple_omp_continue_control_use (cont);
8038 vnext = gimple_omp_continue_control_def (cont);
8040 else
8042 vmain = vin;
8043 vnext = NULL_TREE;
8046 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8047 label_vec.quick_push (t);
8048 i = 1;
8050 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8051 for (inner = region->inner, casei = 1;
8052 inner;
8053 inner = inner->next, i++, casei++)
8055 basic_block s_entry_bb, s_exit_bb;
8057 /* Skip optional reduction region. */
8058 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8060 --i;
8061 --casei;
8062 continue;
8065 s_entry_bb = inner->entry;
8066 s_exit_bb = inner->exit;
8068 t = gimple_block_label (s_entry_bb);
8069 u = build_int_cst (unsigned_type_node, casei);
8070 u = build_case_label (u, NULL, t);
8071 label_vec.quick_push (u);
8073 si = gsi_last_bb (s_entry_bb);
8074 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8075 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8076 gsi_remove (&si, true);
8077 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8079 if (s_exit_bb == NULL)
8080 continue;
8082 si = gsi_last_bb (s_exit_bb);
8083 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8084 gsi_remove (&si, true);
8086 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8089 /* Error handling code goes in DEFAULT_BB. */
8090 t = gimple_block_label (default_bb);
8091 u = build_case_label (NULL, NULL, t);
8092 make_edge (l0_bb, default_bb, 0);
8093 add_bb_to_loop (default_bb, current_loops->tree_root);
8095 stmt = gimple_build_switch (vmain, u, label_vec);
8096 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8097 gsi_remove (&switch_si, true);
8099 si = gsi_start_bb (default_bb);
8100 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8101 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8103 if (exit_reachable)
8105 tree bfn_decl;
8107 /* Code to get the next section goes in L1_BB. */
8108 si = gsi_last_bb (l1_bb);
8109 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8111 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8112 stmt = gimple_build_call (bfn_decl, 0);
8113 gimple_call_set_lhs (stmt, vnext);
8114 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8115 gsi_remove (&si, true);
8117 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8120 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8121 si = gsi_last_bb (l2_bb);
8122 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8123 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8124 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8125 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8126 else
8127 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8128 stmt = gimple_build_call (t, 0);
8129 if (gimple_omp_return_lhs (gsi_stmt (si)))
8130 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8131 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8132 gsi_remove (&si, true);
8134 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8138 /* Expand code for an OpenMP single directive. We've already expanded
8139 much of the code, here we simply place the GOMP_barrier call. */
8141 static void
8142 expand_omp_single (struct omp_region *region)
8144 basic_block entry_bb, exit_bb;
8145 gimple_stmt_iterator si;
8147 entry_bb = region->entry;
8148 exit_bb = region->exit;
8150 si = gsi_last_bb (entry_bb);
8151 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8152 gsi_remove (&si, true);
8153 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8155 si = gsi_last_bb (exit_bb);
8156 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8158 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8159 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8161 gsi_remove (&si, true);
8162 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8166 /* Generic expansion for OpenMP synchronization directives: master,
8167 ordered and critical. All we need to do here is remove the entry
8168 and exit markers for REGION. */
8170 static void
8171 expand_omp_synch (struct omp_region *region)
8173 basic_block entry_bb, exit_bb;
8174 gimple_stmt_iterator si;
8176 entry_bb = region->entry;
8177 exit_bb = region->exit;
8179 si = gsi_last_bb (entry_bb);
8180 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8181 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8182 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8183 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8184 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8185 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8186 gsi_remove (&si, true);
8187 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8189 if (exit_bb)
8191 si = gsi_last_bb (exit_bb);
8192 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8193 gsi_remove (&si, true);
8194 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8198 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8199 operation as a normal volatile load. */
8201 static bool
8202 expand_omp_atomic_load (basic_block load_bb, tree addr,
8203 tree loaded_val, int index)
8205 enum built_in_function tmpbase;
8206 gimple_stmt_iterator gsi;
8207 basic_block store_bb;
8208 location_t loc;
8209 gimple stmt;
8210 tree decl, call, type, itype;
8212 gsi = gsi_last_bb (load_bb);
8213 stmt = gsi_stmt (gsi);
8214 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8215 loc = gimple_location (stmt);
8217 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8218 is smaller than word size, then expand_atomic_load assumes that the load
8219 is atomic. We could avoid the builtin entirely in this case. */
8221 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8222 decl = builtin_decl_explicit (tmpbase);
8223 if (decl == NULL_TREE)
8224 return false;
8226 type = TREE_TYPE (loaded_val);
8227 itype = TREE_TYPE (TREE_TYPE (decl));
8229 call = build_call_expr_loc (loc, decl, 2, addr,
8230 build_int_cst (NULL,
8231 gimple_omp_atomic_seq_cst_p (stmt)
8232 ? MEMMODEL_SEQ_CST
8233 : MEMMODEL_RELAXED));
8234 if (!useless_type_conversion_p (type, itype))
8235 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8236 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8238 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8239 gsi_remove (&gsi, true);
8241 store_bb = single_succ (load_bb);
8242 gsi = gsi_last_bb (store_bb);
8243 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8244 gsi_remove (&gsi, true);
8246 if (gimple_in_ssa_p (cfun))
8247 update_ssa (TODO_update_ssa_no_phi);
8249 return true;
8252 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8253 operation as a normal volatile store. */
8255 static bool
8256 expand_omp_atomic_store (basic_block load_bb, tree addr,
8257 tree loaded_val, tree stored_val, int index)
8259 enum built_in_function tmpbase;
8260 gimple_stmt_iterator gsi;
8261 basic_block store_bb = single_succ (load_bb);
8262 location_t loc;
8263 gimple stmt;
8264 tree decl, call, type, itype;
8265 machine_mode imode;
8266 bool exchange;
8268 gsi = gsi_last_bb (load_bb);
8269 stmt = gsi_stmt (gsi);
8270 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8272 /* If the load value is needed, then this isn't a store but an exchange. */
8273 exchange = gimple_omp_atomic_need_value_p (stmt);
8275 gsi = gsi_last_bb (store_bb);
8276 stmt = gsi_stmt (gsi);
8277 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8278 loc = gimple_location (stmt);
8280 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8281 is smaller than word size, then expand_atomic_store assumes that the store
8282 is atomic. We could avoid the builtin entirely in this case. */
8284 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8285 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8286 decl = builtin_decl_explicit (tmpbase);
8287 if (decl == NULL_TREE)
8288 return false;
8290 type = TREE_TYPE (stored_val);
8292 /* Dig out the type of the function's second argument. */
8293 itype = TREE_TYPE (decl);
8294 itype = TYPE_ARG_TYPES (itype);
8295 itype = TREE_CHAIN (itype);
8296 itype = TREE_VALUE (itype);
8297 imode = TYPE_MODE (itype);
8299 if (exchange && !can_atomic_exchange_p (imode, true))
8300 return false;
8302 if (!useless_type_conversion_p (itype, type))
8303 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8304 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8305 build_int_cst (NULL,
8306 gimple_omp_atomic_seq_cst_p (stmt)
8307 ? MEMMODEL_SEQ_CST
8308 : MEMMODEL_RELAXED));
8309 if (exchange)
8311 if (!useless_type_conversion_p (type, itype))
8312 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8313 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8316 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8317 gsi_remove (&gsi, true);
8319 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8320 gsi = gsi_last_bb (load_bb);
8321 gsi_remove (&gsi, true);
8323 if (gimple_in_ssa_p (cfun))
8324 update_ssa (TODO_update_ssa_no_phi);
8326 return true;
8329 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8330 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8331 size of the data type, and thus usable to find the index of the builtin
8332 decl. Returns false if the expression is not of the proper form. */
8334 static bool
8335 expand_omp_atomic_fetch_op (basic_block load_bb,
8336 tree addr, tree loaded_val,
8337 tree stored_val, int index)
8339 enum built_in_function oldbase, newbase, tmpbase;
8340 tree decl, itype, call;
8341 tree lhs, rhs;
8342 basic_block store_bb = single_succ (load_bb);
8343 gimple_stmt_iterator gsi;
8344 gimple stmt;
8345 location_t loc;
8346 enum tree_code code;
8347 bool need_old, need_new;
8348 machine_mode imode;
8349 bool seq_cst;
8351 /* We expect to find the following sequences:
8353 load_bb:
8354 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8356 store_bb:
8357 val = tmp OP something; (or: something OP tmp)
8358 GIMPLE_OMP_STORE (val)
8360 ???FIXME: Allow a more flexible sequence.
8361 Perhaps use data flow to pick the statements.
8365 gsi = gsi_after_labels (store_bb);
8366 stmt = gsi_stmt (gsi);
8367 loc = gimple_location (stmt);
8368 if (!is_gimple_assign (stmt))
8369 return false;
8370 gsi_next (&gsi);
8371 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8372 return false;
8373 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8374 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8375 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8376 gcc_checking_assert (!need_old || !need_new);
8378 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8379 return false;
8381 /* Check for one of the supported fetch-op operations. */
8382 code = gimple_assign_rhs_code (stmt);
8383 switch (code)
8385 case PLUS_EXPR:
8386 case POINTER_PLUS_EXPR:
8387 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8388 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8389 break;
8390 case MINUS_EXPR:
8391 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8392 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8393 break;
8394 case BIT_AND_EXPR:
8395 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8396 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8397 break;
8398 case BIT_IOR_EXPR:
8399 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8400 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8401 break;
8402 case BIT_XOR_EXPR:
8403 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8404 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8405 break;
8406 default:
8407 return false;
8410 /* Make sure the expression is of the proper form. */
8411 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8412 rhs = gimple_assign_rhs2 (stmt);
8413 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8414 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8415 rhs = gimple_assign_rhs1 (stmt);
8416 else
8417 return false;
8419 tmpbase = ((enum built_in_function)
8420 ((need_new ? newbase : oldbase) + index + 1));
8421 decl = builtin_decl_explicit (tmpbase);
8422 if (decl == NULL_TREE)
8423 return false;
8424 itype = TREE_TYPE (TREE_TYPE (decl));
8425 imode = TYPE_MODE (itype);
8427 /* We could test all of the various optabs involved, but the fact of the
8428 matter is that (with the exception of i486 vs i586 and xadd) all targets
8429 that support any atomic operaton optab also implements compare-and-swap.
8430 Let optabs.c take care of expanding any compare-and-swap loop. */
8431 if (!can_compare_and_swap_p (imode, true))
8432 return false;
8434 gsi = gsi_last_bb (load_bb);
8435 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8437 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8438 It only requires that the operation happen atomically. Thus we can
8439 use the RELAXED memory model. */
8440 call = build_call_expr_loc (loc, decl, 3, addr,
8441 fold_convert_loc (loc, itype, rhs),
8442 build_int_cst (NULL,
8443 seq_cst ? MEMMODEL_SEQ_CST
8444 : MEMMODEL_RELAXED));
8446 if (need_old || need_new)
8448 lhs = need_old ? loaded_val : stored_val;
8449 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8450 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8452 else
8453 call = fold_convert_loc (loc, void_type_node, call);
8454 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8455 gsi_remove (&gsi, true);
8457 gsi = gsi_last_bb (store_bb);
8458 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8459 gsi_remove (&gsi, true);
8460 gsi = gsi_last_bb (store_bb);
8461 gsi_remove (&gsi, true);
8463 if (gimple_in_ssa_p (cfun))
8464 update_ssa (TODO_update_ssa_no_phi);
8466 return true;
8469 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8471 oldval = *addr;
8472 repeat:
8473 newval = rhs; // with oldval replacing *addr in rhs
8474 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8475 if (oldval != newval)
8476 goto repeat;
8478 INDEX is log2 of the size of the data type, and thus usable to find the
8479 index of the builtin decl. */
8481 static bool
8482 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8483 tree addr, tree loaded_val, tree stored_val,
8484 int index)
8486 tree loadedi, storedi, initial, new_storedi, old_vali;
8487 tree type, itype, cmpxchg, iaddr;
8488 gimple_stmt_iterator si;
8489 basic_block loop_header = single_succ (load_bb);
8490 gimple phi, stmt;
8491 edge e;
8492 enum built_in_function fncode;
8494 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8495 order to use the RELAXED memory model effectively. */
8496 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8497 + index + 1);
8498 cmpxchg = builtin_decl_explicit (fncode);
8499 if (cmpxchg == NULL_TREE)
8500 return false;
8501 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8502 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8504 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8505 return false;
8507 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8508 si = gsi_last_bb (load_bb);
8509 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8511 /* For floating-point values, we'll need to view-convert them to integers
8512 so that we can perform the atomic compare and swap. Simplify the
8513 following code by always setting up the "i"ntegral variables. */
8514 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8516 tree iaddr_val;
8518 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8519 true));
8520 iaddr_val
8521 = force_gimple_operand_gsi (&si,
8522 fold_convert (TREE_TYPE (iaddr), addr),
8523 false, NULL_TREE, true, GSI_SAME_STMT);
8524 stmt = gimple_build_assign (iaddr, iaddr_val);
8525 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8526 loadedi = create_tmp_var (itype);
8527 if (gimple_in_ssa_p (cfun))
8528 loadedi = make_ssa_name (loadedi);
8530 else
8532 iaddr = addr;
8533 loadedi = loaded_val;
8536 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8537 tree loaddecl = builtin_decl_explicit (fncode);
8538 if (loaddecl)
8539 initial
8540 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8541 build_call_expr (loaddecl, 2, iaddr,
8542 build_int_cst (NULL_TREE,
8543 MEMMODEL_RELAXED)));
8544 else
8545 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8546 build_int_cst (TREE_TYPE (iaddr), 0));
8548 initial
8549 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8550 GSI_SAME_STMT);
8552 /* Move the value to the LOADEDI temporary. */
8553 if (gimple_in_ssa_p (cfun))
8555 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8556 phi = create_phi_node (loadedi, loop_header);
8557 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8558 initial);
8560 else
8561 gsi_insert_before (&si,
8562 gimple_build_assign (loadedi, initial),
8563 GSI_SAME_STMT);
8564 if (loadedi != loaded_val)
8566 gimple_stmt_iterator gsi2;
8567 tree x;
8569 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8570 gsi2 = gsi_start_bb (loop_header);
8571 if (gimple_in_ssa_p (cfun))
8573 gassign *stmt;
8574 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8575 true, GSI_SAME_STMT);
8576 stmt = gimple_build_assign (loaded_val, x);
8577 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8579 else
8581 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8582 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8583 true, GSI_SAME_STMT);
8586 gsi_remove (&si, true);
8588 si = gsi_last_bb (store_bb);
8589 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8591 if (iaddr == addr)
8592 storedi = stored_val;
8593 else
8594 storedi =
8595 force_gimple_operand_gsi (&si,
8596 build1 (VIEW_CONVERT_EXPR, itype,
8597 stored_val), true, NULL_TREE, true,
8598 GSI_SAME_STMT);
8600 /* Build the compare&swap statement. */
8601 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8602 new_storedi = force_gimple_operand_gsi (&si,
8603 fold_convert (TREE_TYPE (loadedi),
8604 new_storedi),
8605 true, NULL_TREE,
8606 true, GSI_SAME_STMT);
8608 if (gimple_in_ssa_p (cfun))
8609 old_vali = loadedi;
8610 else
8612 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8613 stmt = gimple_build_assign (old_vali, loadedi);
8614 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8616 stmt = gimple_build_assign (loadedi, new_storedi);
8617 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8620 /* Note that we always perform the comparison as an integer, even for
8621 floating point. This allows the atomic operation to properly
8622 succeed even with NaNs and -0.0. */
8623 stmt = gimple_build_cond_empty
8624 (build2 (NE_EXPR, boolean_type_node,
8625 new_storedi, old_vali));
8626 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8628 /* Update cfg. */
8629 e = single_succ_edge (store_bb);
8630 e->flags &= ~EDGE_FALLTHRU;
8631 e->flags |= EDGE_FALSE_VALUE;
8633 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8635 /* Copy the new value to loadedi (we already did that before the condition
8636 if we are not in SSA). */
8637 if (gimple_in_ssa_p (cfun))
8639 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8640 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8643 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8644 gsi_remove (&si, true);
8646 struct loop *loop = alloc_loop ();
8647 loop->header = loop_header;
8648 loop->latch = store_bb;
8649 add_loop (loop, loop_header->loop_father);
8651 if (gimple_in_ssa_p (cfun))
8652 update_ssa (TODO_update_ssa_no_phi);
8654 return true;
8657 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8659 GOMP_atomic_start ();
8660 *addr = rhs;
8661 GOMP_atomic_end ();
8663 The result is not globally atomic, but works so long as all parallel
8664 references are within #pragma omp atomic directives. According to
8665 responses received from omp@openmp.org, appears to be within spec.
8666 Which makes sense, since that's how several other compilers handle
8667 this situation as well.
8668 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8669 expanding. STORED_VAL is the operand of the matching
8670 GIMPLE_OMP_ATOMIC_STORE.
8672 We replace
8673 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8674 loaded_val = *addr;
8676 and replace
8677 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8678 *addr = stored_val;
8681 static bool
8682 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8683 tree addr, tree loaded_val, tree stored_val)
8685 gimple_stmt_iterator si;
8686 gassign *stmt;
8687 tree t;
8689 si = gsi_last_bb (load_bb);
8690 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8692 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8693 t = build_call_expr (t, 0);
8694 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8696 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8697 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8698 gsi_remove (&si, true);
8700 si = gsi_last_bb (store_bb);
8701 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8703 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8704 stored_val);
8705 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8707 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8708 t = build_call_expr (t, 0);
8709 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8710 gsi_remove (&si, true);
8712 if (gimple_in_ssa_p (cfun))
8713 update_ssa (TODO_update_ssa_no_phi);
8714 return true;
8717 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8718 using expand_omp_atomic_fetch_op. If it failed, we try to
8719 call expand_omp_atomic_pipeline, and if it fails too, the
8720 ultimate fallback is wrapping the operation in a mutex
8721 (expand_omp_atomic_mutex). REGION is the atomic region built
8722 by build_omp_regions_1(). */
8724 static void
8725 expand_omp_atomic (struct omp_region *region)
8727 basic_block load_bb = region->entry, store_bb = region->exit;
8728 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8729 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8730 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8731 tree addr = gimple_omp_atomic_load_rhs (load);
8732 tree stored_val = gimple_omp_atomic_store_val (store);
8733 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8734 HOST_WIDE_INT index;
8736 /* Make sure the type is one of the supported sizes. */
8737 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8738 index = exact_log2 (index);
8739 if (index >= 0 && index <= 4)
8741 unsigned int align = TYPE_ALIGN_UNIT (type);
8743 /* __sync builtins require strict data alignment. */
8744 if (exact_log2 (align) >= index)
8746 /* Atomic load. */
8747 if (loaded_val == stored_val
8748 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8749 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8750 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8751 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8752 return;
8754 /* Atomic store. */
8755 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8756 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8757 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8758 && store_bb == single_succ (load_bb)
8759 && first_stmt (store_bb) == store
8760 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8761 stored_val, index))
8762 return;
8764 /* When possible, use specialized atomic update functions. */
8765 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8766 && store_bb == single_succ (load_bb)
8767 && expand_omp_atomic_fetch_op (load_bb, addr,
8768 loaded_val, stored_val, index))
8769 return;
8771 /* If we don't have specialized __sync builtins, try and implement
8772 as a compare and swap loop. */
8773 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8774 loaded_val, stored_val, index))
8775 return;
8779 /* The ultimate fallback is wrapping the operation in a mutex. */
8780 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8784 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8786 static void
8787 expand_omp_target (struct omp_region *region)
8789 basic_block entry_bb, exit_bb, new_bb;
8790 struct function *child_cfun;
8791 tree child_fn, block, t;
8792 gimple_stmt_iterator gsi;
8793 gomp_target *entry_stmt;
8794 gimple stmt;
8795 edge e;
8796 bool offloaded, data_region;
8798 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8799 new_bb = region->entry;
8801 offloaded = is_gimple_omp_offloaded (entry_stmt);
8802 switch (gimple_omp_target_kind (entry_stmt))
8804 case GF_OMP_TARGET_KIND_REGION:
8805 case GF_OMP_TARGET_KIND_UPDATE:
8806 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8807 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8808 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8809 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8810 data_region = false;
8811 break;
8812 case GF_OMP_TARGET_KIND_DATA:
8813 case GF_OMP_TARGET_KIND_OACC_DATA:
8814 data_region = true;
8815 break;
8816 default:
8817 gcc_unreachable ();
8820 child_fn = NULL_TREE;
8821 child_cfun = NULL;
8822 if (offloaded)
8824 child_fn = gimple_omp_target_child_fn (entry_stmt);
8825 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8828 /* Supported by expand_omp_taskreg, but not here. */
8829 if (child_cfun != NULL)
8830 gcc_checking_assert (!child_cfun->cfg);
8831 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8833 entry_bb = region->entry;
8834 exit_bb = region->exit;
8836 if (offloaded)
8838 unsigned srcidx, dstidx, num;
8840 /* If the offloading region needs data sent from the parent
8841 function, then the very first statement (except possible
8842 tree profile counter updates) of the offloading body
8843 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8844 &.OMP_DATA_O is passed as an argument to the child function,
8845 we need to replace it with the argument as seen by the child
8846 function.
8848 In most cases, this will end up being the identity assignment
8849 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8850 a function call that has been inlined, the original PARM_DECL
8851 .OMP_DATA_I may have been converted into a different local
8852 variable. In which case, we need to keep the assignment. */
8853 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8854 if (data_arg)
8856 basic_block entry_succ_bb = single_succ (entry_bb);
8857 gimple_stmt_iterator gsi;
8858 tree arg;
8859 gimple tgtcopy_stmt = NULL;
8860 tree sender = TREE_VEC_ELT (data_arg, 0);
8862 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8864 gcc_assert (!gsi_end_p (gsi));
8865 stmt = gsi_stmt (gsi);
8866 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8867 continue;
8869 if (gimple_num_ops (stmt) == 2)
8871 tree arg = gimple_assign_rhs1 (stmt);
8873 /* We're ignoring the subcode because we're
8874 effectively doing a STRIP_NOPS. */
8876 if (TREE_CODE (arg) == ADDR_EXPR
8877 && TREE_OPERAND (arg, 0) == sender)
8879 tgtcopy_stmt = stmt;
8880 break;
8885 gcc_assert (tgtcopy_stmt != NULL);
8886 arg = DECL_ARGUMENTS (child_fn);
8888 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8889 gsi_remove (&gsi, true);
8892 /* Declare local variables needed in CHILD_CFUN. */
8893 block = DECL_INITIAL (child_fn);
8894 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8895 /* The gimplifier could record temporaries in the offloading block
8896 rather than in containing function's local_decls chain,
8897 which would mean cgraph missed finalizing them. Do it now. */
8898 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8899 if (TREE_CODE (t) == VAR_DECL
8900 && TREE_STATIC (t)
8901 && !DECL_EXTERNAL (t))
8902 varpool_node::finalize_decl (t);
8903 DECL_SAVED_TREE (child_fn) = NULL;
8904 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8905 gimple_set_body (child_fn, NULL);
8906 TREE_USED (block) = 1;
8908 /* Reset DECL_CONTEXT on function arguments. */
8909 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8910 DECL_CONTEXT (t) = child_fn;
8912 /* Split ENTRY_BB at GIMPLE_*,
8913 so that it can be moved to the child function. */
8914 gsi = gsi_last_bb (entry_bb);
8915 stmt = gsi_stmt (gsi);
8916 gcc_assert (stmt
8917 && gimple_code (stmt) == gimple_code (entry_stmt));
8918 e = split_block (entry_bb, stmt);
8919 gsi_remove (&gsi, true);
8920 entry_bb = e->dest;
8921 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8923 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8924 if (exit_bb)
8926 gsi = gsi_last_bb (exit_bb);
8927 gcc_assert (!gsi_end_p (gsi)
8928 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8929 stmt = gimple_build_return (NULL);
8930 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8931 gsi_remove (&gsi, true);
8934 /* Move the offloading region into CHILD_CFUN. */
8936 block = gimple_block (entry_stmt);
8938 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8939 if (exit_bb)
8940 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8941 /* When the OMP expansion process cannot guarantee an up-to-date
8942 loop tree arrange for the child function to fixup loops. */
8943 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8944 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8946 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8947 num = vec_safe_length (child_cfun->local_decls);
8948 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8950 t = (*child_cfun->local_decls)[srcidx];
8951 if (DECL_CONTEXT (t) == cfun->decl)
8952 continue;
8953 if (srcidx != dstidx)
8954 (*child_cfun->local_decls)[dstidx] = t;
8955 dstidx++;
8957 if (dstidx != num)
8958 vec_safe_truncate (child_cfun->local_decls, dstidx);
8960 /* Inform the callgraph about the new function. */
8961 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8962 cgraph_node *node = cgraph_node::get_create (child_fn);
8963 node->parallelized_function = 1;
8964 cgraph_node::add_new_function (child_fn, true);
8966 #ifdef ENABLE_OFFLOADING
8967 /* Add the new function to the offload table. */
8968 vec_safe_push (offload_funcs, child_fn);
8969 #endif
8971 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8972 fixed in a following pass. */
8973 push_cfun (child_cfun);
8974 cgraph_edge::rebuild_edges ();
8976 #ifdef ENABLE_OFFLOADING
8977 /* Prevent IPA from removing child_fn as unreachable, since there are no
8978 refs from the parent function to child_fn in offload LTO mode. */
8979 cgraph_node::get (child_fn)->mark_force_output ();
8980 #endif
8982 /* Some EH regions might become dead, see PR34608. If
8983 pass_cleanup_cfg isn't the first pass to happen with the
8984 new child, these dead EH edges might cause problems.
8985 Clean them up now. */
8986 if (flag_exceptions)
8988 basic_block bb;
8989 bool changed = false;
8991 FOR_EACH_BB_FN (bb, cfun)
8992 changed |= gimple_purge_dead_eh_edges (bb);
8993 if (changed)
8994 cleanup_tree_cfg ();
8996 pop_cfun ();
8999 /* Emit a library call to launch the offloading region, or do data
9000 transfers. */
9001 tree t1, t2, t3, t4, device, cond, c, clauses;
9002 enum built_in_function start_ix;
9003 location_t clause_loc;
9005 switch (gimple_omp_target_kind (entry_stmt))
9007 case GF_OMP_TARGET_KIND_REGION:
9008 start_ix = BUILT_IN_GOMP_TARGET;
9009 break;
9010 case GF_OMP_TARGET_KIND_DATA:
9011 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9012 break;
9013 case GF_OMP_TARGET_KIND_UPDATE:
9014 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9015 break;
9016 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9017 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9018 start_ix = BUILT_IN_GOACC_PARALLEL;
9019 break;
9020 case GF_OMP_TARGET_KIND_OACC_DATA:
9021 start_ix = BUILT_IN_GOACC_DATA_START;
9022 break;
9023 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9024 start_ix = BUILT_IN_GOACC_UPDATE;
9025 break;
9026 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9027 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9028 break;
9029 default:
9030 gcc_unreachable ();
9033 clauses = gimple_omp_target_clauses (entry_stmt);
9035 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9036 library choose) and there is no conditional. */
9037 cond = NULL_TREE;
9038 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
9040 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9041 if (c)
9042 cond = OMP_CLAUSE_IF_EXPR (c);
9044 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9045 if (c)
9047 /* Even if we pass it to all library function calls, it is currently only
9048 defined/used for the OpenMP target ones. */
9049 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9050 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9051 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9053 device = OMP_CLAUSE_DEVICE_ID (c);
9054 clause_loc = OMP_CLAUSE_LOCATION (c);
9056 else
9057 clause_loc = gimple_location (entry_stmt);
9059 /* Ensure 'device' is of the correct type. */
9060 device = fold_convert_loc (clause_loc, integer_type_node, device);
9062 /* If we found the clause 'if (cond)', build
9063 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9064 if (cond)
9066 cond = gimple_boolify (cond);
9068 basic_block cond_bb, then_bb, else_bb;
9069 edge e;
9070 tree tmp_var;
9072 tmp_var = create_tmp_var (TREE_TYPE (device));
9073 if (offloaded)
9074 e = split_block_after_labels (new_bb);
9075 else
9077 gsi = gsi_last_bb (new_bb);
9078 gsi_prev (&gsi);
9079 e = split_block (new_bb, gsi_stmt (gsi));
9081 cond_bb = e->src;
9082 new_bb = e->dest;
9083 remove_edge (e);
9085 then_bb = create_empty_bb (cond_bb);
9086 else_bb = create_empty_bb (then_bb);
9087 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9088 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9090 stmt = gimple_build_cond_empty (cond);
9091 gsi = gsi_last_bb (cond_bb);
9092 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9094 gsi = gsi_start_bb (then_bb);
9095 stmt = gimple_build_assign (tmp_var, device);
9096 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9098 gsi = gsi_start_bb (else_bb);
9099 stmt = gimple_build_assign (tmp_var,
9100 build_int_cst (integer_type_node,
9101 GOMP_DEVICE_HOST_FALLBACK));
9102 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9104 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9105 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9106 add_bb_to_loop (then_bb, cond_bb->loop_father);
9107 add_bb_to_loop (else_bb, cond_bb->loop_father);
9108 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9109 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9111 device = tmp_var;
9114 gsi = gsi_last_bb (new_bb);
9115 t = gimple_omp_target_data_arg (entry_stmt);
9116 if (t == NULL)
9118 t1 = size_zero_node;
9119 t2 = build_zero_cst (ptr_type_node);
9120 t3 = t2;
9121 t4 = t2;
9123 else
9125 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9126 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9127 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9128 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9129 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9132 gimple g;
9133 /* The maximum number used by any start_ix, without varargs. */
9134 auto_vec<tree, 11> args;
9135 args.quick_push (device);
9136 if (offloaded)
9137 args.quick_push (build_fold_addr_expr (child_fn));
9138 switch (start_ix)
9140 case BUILT_IN_GOMP_TARGET:
9141 case BUILT_IN_GOMP_TARGET_DATA:
9142 case BUILT_IN_GOMP_TARGET_UPDATE:
9143 /* This const void * is part of the current ABI, but we're not actually
9144 using it. */
9145 args.quick_push (build_zero_cst (ptr_type_node));
9146 break;
9147 case BUILT_IN_GOACC_DATA_START:
9148 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9149 case BUILT_IN_GOACC_PARALLEL:
9150 case BUILT_IN_GOACC_UPDATE:
9151 break;
9152 default:
9153 gcc_unreachable ();
9155 args.quick_push (t1);
9156 args.quick_push (t2);
9157 args.quick_push (t3);
9158 args.quick_push (t4);
9159 switch (start_ix)
9161 case BUILT_IN_GOACC_DATA_START:
9162 case BUILT_IN_GOMP_TARGET:
9163 case BUILT_IN_GOMP_TARGET_DATA:
9164 case BUILT_IN_GOMP_TARGET_UPDATE:
9165 break;
9166 case BUILT_IN_GOACC_PARALLEL:
9168 tree t_num_gangs, t_num_workers, t_vector_length;
9170 /* Default values for num_gangs, num_workers, and vector_length. */
9171 t_num_gangs = t_num_workers = t_vector_length
9172 = fold_convert_loc (gimple_location (entry_stmt),
9173 integer_type_node, integer_one_node);
9174 /* ..., but if present, use the value specified by the respective
9175 clause, making sure that are of the correct type. */
9176 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9177 if (c)
9178 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9179 integer_type_node,
9180 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9181 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9182 if (c)
9183 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9184 integer_type_node,
9185 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9186 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9187 if (c)
9188 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9189 integer_type_node,
9190 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9191 args.quick_push (t_num_gangs);
9192 args.quick_push (t_num_workers);
9193 args.quick_push (t_vector_length);
9195 /* FALLTHRU */
9196 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9197 case BUILT_IN_GOACC_UPDATE:
9199 tree t_async;
9200 int t_wait_idx;
9202 /* Default values for t_async. */
9203 t_async = fold_convert_loc (gimple_location (entry_stmt),
9204 integer_type_node,
9205 build_int_cst (integer_type_node,
9206 GOMP_ASYNC_SYNC));
9207 /* ..., but if present, use the value specified by the respective
9208 clause, making sure that is of the correct type. */
9209 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9210 if (c)
9211 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9212 integer_type_node,
9213 OMP_CLAUSE_ASYNC_EXPR (c));
9215 args.quick_push (t_async);
9216 /* Save the index, and... */
9217 t_wait_idx = args.length ();
9218 /* ... push a default value. */
9219 args.quick_push (fold_convert_loc (gimple_location (entry_stmt),
9220 integer_type_node,
9221 integer_zero_node));
9222 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9223 if (c)
9225 int n = 0;
9227 for (; c; c = OMP_CLAUSE_CHAIN (c))
9229 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9231 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9232 integer_type_node,
9233 OMP_CLAUSE_WAIT_EXPR (c)));
9234 n++;
9238 /* Now that we know the number, replace the default value. */
9239 args.ordered_remove (t_wait_idx);
9240 args.quick_insert (t_wait_idx,
9241 fold_convert_loc (gimple_location (entry_stmt),
9242 integer_type_node,
9243 build_int_cst (integer_type_node, n)));
9246 break;
9247 default:
9248 gcc_unreachable ();
9251 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
9252 gimple_set_location (g, gimple_location (entry_stmt));
9253 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9254 if (!offloaded)
9256 g = gsi_stmt (gsi);
9257 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9258 gsi_remove (&gsi, true);
9260 if (data_region
9261 && region->exit)
9263 gsi = gsi_last_bb (region->exit);
9264 g = gsi_stmt (gsi);
9265 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9266 gsi_remove (&gsi, true);
9271 /* Expand the parallel region tree rooted at REGION. Expansion
9272 proceeds in depth-first order. Innermost regions are expanded
9273 first. This way, parallel regions that require a new function to
9274 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9275 internal dependencies in their body. */
9277 static void
9278 expand_omp (struct omp_region *region)
9280 while (region)
9282 location_t saved_location;
9283 gimple inner_stmt = NULL;
9285 /* First, determine whether this is a combined parallel+workshare
9286 region. */
9287 if (region->type == GIMPLE_OMP_PARALLEL)
9288 determine_parallel_type (region);
9290 if (region->type == GIMPLE_OMP_FOR
9291 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9292 inner_stmt = last_stmt (region->inner->entry);
9294 if (region->inner)
9295 expand_omp (region->inner);
9297 saved_location = input_location;
9298 if (gimple_has_location (last_stmt (region->entry)))
9299 input_location = gimple_location (last_stmt (region->entry));
9301 switch (region->type)
9303 case GIMPLE_OMP_PARALLEL:
9304 case GIMPLE_OMP_TASK:
9305 expand_omp_taskreg (region);
9306 break;
9308 case GIMPLE_OMP_FOR:
9309 expand_omp_for (region, inner_stmt);
9310 break;
9312 case GIMPLE_OMP_SECTIONS:
9313 expand_omp_sections (region);
9314 break;
9316 case GIMPLE_OMP_SECTION:
9317 /* Individual omp sections are handled together with their
9318 parent GIMPLE_OMP_SECTIONS region. */
9319 break;
9321 case GIMPLE_OMP_SINGLE:
9322 expand_omp_single (region);
9323 break;
9325 case GIMPLE_OMP_MASTER:
9326 case GIMPLE_OMP_TASKGROUP:
9327 case GIMPLE_OMP_ORDERED:
9328 case GIMPLE_OMP_CRITICAL:
9329 case GIMPLE_OMP_TEAMS:
9330 expand_omp_synch (region);
9331 break;
9333 case GIMPLE_OMP_ATOMIC_LOAD:
9334 expand_omp_atomic (region);
9335 break;
9337 case GIMPLE_OMP_TARGET:
9338 expand_omp_target (region);
9339 break;
9341 default:
9342 gcc_unreachable ();
9345 input_location = saved_location;
9346 region = region->next;
9351 /* Helper for build_omp_regions. Scan the dominator tree starting at
9352 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9353 true, the function ends once a single tree is built (otherwise, whole
9354 forest of OMP constructs may be built). */
9356 static void
9357 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9358 bool single_tree)
9360 gimple_stmt_iterator gsi;
9361 gimple stmt;
9362 basic_block son;
9364 gsi = gsi_last_bb (bb);
9365 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9367 struct omp_region *region;
9368 enum gimple_code code;
9370 stmt = gsi_stmt (gsi);
9371 code = gimple_code (stmt);
9372 if (code == GIMPLE_OMP_RETURN)
9374 /* STMT is the return point out of region PARENT. Mark it
9375 as the exit point and make PARENT the immediately
9376 enclosing region. */
9377 gcc_assert (parent);
9378 region = parent;
9379 region->exit = bb;
9380 parent = parent->outer;
9382 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9384 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9385 GIMPLE_OMP_RETURN, but matches with
9386 GIMPLE_OMP_ATOMIC_LOAD. */
9387 gcc_assert (parent);
9388 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9389 region = parent;
9390 region->exit = bb;
9391 parent = parent->outer;
9393 else if (code == GIMPLE_OMP_CONTINUE)
9395 gcc_assert (parent);
9396 parent->cont = bb;
9398 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9400 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9401 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9403 else
9405 region = new_omp_region (bb, code, parent);
9406 /* Otherwise... */
9407 if (code == GIMPLE_OMP_TARGET)
9409 switch (gimple_omp_target_kind (stmt))
9411 case GF_OMP_TARGET_KIND_REGION:
9412 case GF_OMP_TARGET_KIND_DATA:
9413 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9414 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9415 case GF_OMP_TARGET_KIND_OACC_DATA:
9416 break;
9417 case GF_OMP_TARGET_KIND_UPDATE:
9418 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9419 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9420 /* ..., other than for those stand-alone directives... */
9421 region = NULL;
9422 break;
9423 default:
9424 gcc_unreachable ();
9427 /* ..., this directive becomes the parent for a new region. */
9428 if (region)
9429 parent = region;
9433 if (single_tree && !parent)
9434 return;
9436 for (son = first_dom_son (CDI_DOMINATORS, bb);
9437 son;
9438 son = next_dom_son (CDI_DOMINATORS, son))
9439 build_omp_regions_1 (son, parent, single_tree);
9442 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9443 root_omp_region. */
9445 static void
9446 build_omp_regions_root (basic_block root)
9448 gcc_assert (root_omp_region == NULL);
9449 build_omp_regions_1 (root, NULL, true);
9450 gcc_assert (root_omp_region != NULL);
9453 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9455 void
9456 omp_expand_local (basic_block head)
9458 build_omp_regions_root (head);
9459 if (dump_file && (dump_flags & TDF_DETAILS))
9461 fprintf (dump_file, "\nOMP region tree\n\n");
9462 dump_omp_region (dump_file, root_omp_region, 0);
9463 fprintf (dump_file, "\n");
9466 remove_exit_barriers (root_omp_region);
9467 expand_omp (root_omp_region);
9469 free_omp_regions ();
9472 /* Scan the CFG and build a tree of OMP regions. Return the root of
9473 the OMP region tree. */
9475 static void
9476 build_omp_regions (void)
9478 gcc_assert (root_omp_region == NULL);
9479 calculate_dominance_info (CDI_DOMINATORS);
9480 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9483 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9485 static unsigned int
9486 execute_expand_omp (void)
9488 build_omp_regions ();
9490 if (!root_omp_region)
9491 return 0;
9493 if (dump_file)
9495 fprintf (dump_file, "\nOMP region tree\n\n");
9496 dump_omp_region (dump_file, root_omp_region, 0);
9497 fprintf (dump_file, "\n");
9500 remove_exit_barriers (root_omp_region);
9502 expand_omp (root_omp_region);
9504 cleanup_tree_cfg ();
9506 free_omp_regions ();
9508 return 0;
9511 /* OMP expansion -- the default pass, run before creation of SSA form. */
9513 namespace {
9515 const pass_data pass_data_expand_omp =
9517 GIMPLE_PASS, /* type */
9518 "ompexp", /* name */
9519 OPTGROUP_NONE, /* optinfo_flags */
9520 TV_NONE, /* tv_id */
9521 PROP_gimple_any, /* properties_required */
9522 PROP_gimple_eomp, /* properties_provided */
9523 0, /* properties_destroyed */
9524 0, /* todo_flags_start */
9525 0, /* todo_flags_finish */
9528 class pass_expand_omp : public gimple_opt_pass
9530 public:
9531 pass_expand_omp (gcc::context *ctxt)
9532 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9535 /* opt_pass methods: */
9536 virtual unsigned int execute (function *)
9538 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9539 || flag_openmp_simd != 0)
9540 && !seen_error ());
9542 /* This pass always runs, to provide PROP_gimple_eomp.
9543 But often, there is nothing to do. */
9544 if (!gate)
9545 return 0;
9547 return execute_expand_omp ();
9550 }; // class pass_expand_omp
9552 } // anon namespace
9554 gimple_opt_pass *
9555 make_pass_expand_omp (gcc::context *ctxt)
9557 return new pass_expand_omp (ctxt);
9560 namespace {
9562 const pass_data pass_data_expand_omp_ssa =
9564 GIMPLE_PASS, /* type */
9565 "ompexpssa", /* name */
9566 OPTGROUP_NONE, /* optinfo_flags */
9567 TV_NONE, /* tv_id */
9568 PROP_cfg | PROP_ssa, /* properties_required */
9569 PROP_gimple_eomp, /* properties_provided */
9570 0, /* properties_destroyed */
9571 0, /* todo_flags_start */
9572 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9575 class pass_expand_omp_ssa : public gimple_opt_pass
9577 public:
9578 pass_expand_omp_ssa (gcc::context *ctxt)
9579 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9582 /* opt_pass methods: */
9583 virtual bool gate (function *fun)
9585 return !(fun->curr_properties & PROP_gimple_eomp);
9587 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9589 }; // class pass_expand_omp_ssa
9591 } // anon namespace
9593 gimple_opt_pass *
9594 make_pass_expand_omp_ssa (gcc::context *ctxt)
9596 return new pass_expand_omp_ssa (ctxt);
9599 /* Routines to lower OMP directives into OMP-GIMPLE. */
9601 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9602 convert it to gimple. */
9603 static void
9604 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9606 gimple stmt;
9608 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9610 stmt = gimple_build_assign (dest, op, dest, src);
9611 gimple_seq_add_stmt (seq, stmt);
9612 return;
9615 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9616 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9617 gimplify_assign (t, rdest, seq);
9618 rdest = t;
9620 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9621 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9622 gimplify_assign (t, idest, seq);
9623 idest = t;
9625 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9626 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9627 gimplify_assign (t, rsrc, seq);
9628 rsrc = t;
9630 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9631 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9632 gimplify_assign (t, isrc, seq);
9633 isrc = t;
9635 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9636 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9637 tree result;
9639 if (op == PLUS_EXPR)
9641 stmt = gimple_build_assign (r, op, rdest, rsrc);
9642 gimple_seq_add_stmt (seq, stmt);
9644 stmt = gimple_build_assign (i, op, idest, isrc);
9645 gimple_seq_add_stmt (seq, stmt);
9647 else if (op == MULT_EXPR)
9649 /* Let x = a + ib = dest, y = c + id = src.
9650 x * y = (ac - bd) + i(ad + bc) */
9651 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9652 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9653 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9654 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9656 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9657 gimple_seq_add_stmt (seq, stmt);
9659 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9660 gimple_seq_add_stmt (seq, stmt);
9662 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9663 gimple_seq_add_stmt (seq, stmt);
9665 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9666 gimple_seq_add_stmt (seq, stmt);
9668 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9669 gimple_seq_add_stmt (seq, stmt);
9671 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9672 gimple_seq_add_stmt (seq, stmt);
9674 else
9675 gcc_unreachable ();
9677 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9678 gimplify_assign (dest, result, seq);
9681 /* Helper function to initialize local data for the reduction arrays.
9682 The reduction arrays need to be placed inside the calling function
9683 for accelerators, or else the host won't be able to preform the final
9684 reduction. */
9686 static void
9687 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9688 gimple_seq *stmt_seqp, omp_context *ctx)
9690 tree c, t, oc;
9691 gimple stmt;
9692 omp_context *octx;
9694 /* Find the innermost OpenACC parallel context. */
9695 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9696 && (gimple_omp_target_kind (ctx->stmt)
9697 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9698 octx = ctx;
9699 else
9700 octx = ctx->outer;
9701 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9702 && (gimple_omp_target_kind (octx->stmt)
9703 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9705 /* Extract the clauses. */
9706 oc = gimple_omp_target_clauses (octx->stmt);
9708 /* Find the last outer clause. */
9709 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9712 /* Allocate arrays for each reduction variable. */
9713 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9715 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9716 continue;
9718 tree var = OMP_CLAUSE_DECL (c);
9719 tree type = get_base_type (var);
9720 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9721 ctx);
9722 tree size, call;
9724 /* Calculate size of the reduction array. */
9725 t = create_tmp_var (TREE_TYPE (nthreads));
9726 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9727 fold_convert (TREE_TYPE (nthreads),
9728 TYPE_SIZE_UNIT (type)));
9729 gimple_seq_add_stmt (stmt_seqp, stmt);
9731 size = create_tmp_var (sizetype);
9732 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9734 /* Now allocate memory for it. */
9735 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9736 stmt = gimple_build_call (call, 1, size);
9737 gimple_call_set_lhs (stmt, array);
9738 gimple_seq_add_stmt (stmt_seqp, stmt);
9740 /* Map this array into the accelerator. */
9742 /* Add the reduction array to the list of clauses. */
9743 tree x = array;
9744 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9745 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9746 OMP_CLAUSE_DECL (t) = x;
9747 OMP_CLAUSE_CHAIN (t) = NULL;
9748 if (oc)
9749 OMP_CLAUSE_CHAIN (oc) = t;
9750 else
9751 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9752 OMP_CLAUSE_SIZE (t) = size;
9753 oc = t;
9757 /* Helper function to process the array of partial reductions. Nthreads
9758 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9759 cannot be used here, because nthreads on the host may be different than
9760 on the accelerator. */
9762 static void
9763 oacc_finalize_reduction_data (tree clauses, tree nthreads,
9764 gimple_seq *stmt_seqp, omp_context *ctx)
9766 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9767 gimple stmt;
9769 /* Create for loop.
9771 let var = the original reduction variable
9772 let array = reduction variable array
9774 for (i = 0; i < nthreads; i++)
9775 var op= array[i]
9778 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9779 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9780 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9782 /* Create and initialize an index variable. */
9783 tree ix = create_tmp_var (sizetype);
9784 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9785 stmt_seqp);
9787 /* Insert the loop header label here. */
9788 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9790 /* Exit loop if ix >= nthreads. */
9791 x = create_tmp_var (sizetype);
9792 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9793 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9794 gimple_seq_add_stmt (stmt_seqp, stmt);
9796 /* Insert the loop body label here. */
9797 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9799 /* Collapse each reduction array, one element at a time. */
9800 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9802 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9803 continue;
9805 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9807 /* reduction(-:var) sums up the partial results, so it acts
9808 identically to reduction(+:var). */
9809 if (reduction_code == MINUS_EXPR)
9810 reduction_code = PLUS_EXPR;
9812 /* Set up reduction variable var. */
9813 var = OMP_CLAUSE_DECL (c);
9814 type = get_base_type (var);
9815 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9816 (OMP_CLAUSE_DECL (c)), ctx);
9818 /* Calculate the array offset. */
9819 tree offset = create_tmp_var (sizetype);
9820 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9821 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9822 gimple_seq_add_stmt (stmt_seqp, stmt);
9824 tree ptr = create_tmp_var (TREE_TYPE (array));
9825 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9826 gimple_seq_add_stmt (stmt_seqp, stmt);
9828 /* Extract array[ix] into mem. */
9829 tree mem = create_tmp_var (type);
9830 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9832 /* Find the original reduction variable. */
9833 if (is_reference (var))
9834 var = build_simple_mem_ref (var);
9836 tree t = create_tmp_var (type);
9838 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9839 gimplify_and_add (unshare_expr(x), stmt_seqp);
9841 /* var = var op mem */
9842 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9844 case TRUTH_ANDIF_EXPR:
9845 case TRUTH_ORIF_EXPR:
9846 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9847 t, mem);
9848 gimplify_and_add (t, stmt_seqp);
9849 break;
9850 default:
9851 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9852 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9853 stmt_seqp);
9856 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9857 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9858 gimplify_and_add (unshare_expr(x), stmt_seqp);
9861 /* Increment the induction variable. */
9862 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9863 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9864 gimple_seq_add_stmt (stmt_seqp, stmt);
9866 /* Go back to the top of the loop. */
9867 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9869 /* Place the loop exit label here. */
9870 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9873 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9874 scan that for reductions. */
9876 static void
9877 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9878 gimple_seq *out_stmt_seqp, omp_context *ctx)
9880 gimple_stmt_iterator gsi;
9881 gimple_seq inner = NULL;
9883 /* A collapse clause may have inserted a new bind block. */
9884 gsi = gsi_start (*body);
9885 while (!gsi_end_p (gsi))
9887 gimple stmt = gsi_stmt (gsi);
9888 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9890 inner = gimple_bind_body (bind_stmt);
9891 body = &inner;
9892 gsi = gsi_start (*body);
9894 else if (dyn_cast <gomp_for *> (stmt))
9895 break;
9896 else
9897 gsi_next (&gsi);
9900 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9902 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9903 enter, exit;
9904 bool reduction_found = false;
9906 gimple stmt = gsi_stmt (gsi);
9908 switch (gimple_code (stmt))
9910 case GIMPLE_OMP_FOR:
9911 clauses = gimple_omp_for_clauses (stmt);
9913 /* Search for a reduction clause. */
9914 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9915 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9917 reduction_found = true;
9918 break;
9921 if (!reduction_found)
9922 break;
9924 ctx = maybe_lookup_ctx (stmt);
9925 t = NULL_TREE;
9927 /* Extract the number of threads. */
9928 nthreads = create_tmp_var (sizetype);
9929 t = oacc_max_threads (ctx);
9930 gimplify_assign (nthreads, t, in_stmt_seqp);
9932 /* Determine if this is kernel will be executed on the host. */
9933 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9934 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9935 stmt = gimple_build_call (call, 0);
9936 gimple_call_set_lhs (stmt, acc_device);
9937 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9939 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9940 acc_device_host = create_tmp_var (integer_type_node,
9941 ".acc_device_host");
9942 gimplify_assign (acc_device_host,
9943 build_int_cst (integer_type_node,
9944 GOMP_DEVICE_HOST),
9945 in_stmt_seqp);
9947 enter = create_artificial_label (UNKNOWN_LOCATION);
9948 exit = create_artificial_label (UNKNOWN_LOCATION);
9950 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9951 enter, exit);
9952 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9953 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9954 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9955 integer_one_node),
9956 in_stmt_seqp);
9957 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9959 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9960 gimplify_assign (acc_device_host,
9961 build_int_cst (integer_type_node,
9962 GOMP_DEVICE_HOST_NONSHM),
9963 in_stmt_seqp);
9965 enter = create_artificial_label (UNKNOWN_LOCATION);
9966 exit = create_artificial_label (UNKNOWN_LOCATION);
9968 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9969 enter, exit);
9970 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9971 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9972 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9973 integer_one_node),
9974 in_stmt_seqp);
9975 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9977 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9978 ctx);
9979 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9980 break;
9981 default:
9982 // Scan for other directives which support reduction here.
9983 break;
9988 /* If ctx is a worksharing context inside of a cancellable parallel
9989 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9990 and conditional branch to parallel's cancel_label to handle
9991 cancellation in the implicit barrier. */
9993 static void
9994 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9996 gimple omp_return = gimple_seq_last_stmt (*body);
9997 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
9998 if (gimple_omp_return_nowait_p (omp_return))
9999 return;
10000 if (ctx->outer
10001 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
10002 && ctx->outer->cancellable)
10004 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
10005 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
10006 tree lhs = create_tmp_var (c_bool_type);
10007 gimple_omp_return_set_lhs (omp_return, lhs);
10008 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10009 gimple g = gimple_build_cond (NE_EXPR, lhs,
10010 fold_convert (c_bool_type,
10011 boolean_false_node),
10012 ctx->outer->cancel_label, fallthru_label);
10013 gimple_seq_add_stmt (body, g);
10014 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10018 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10019 CTX is the enclosing OMP context for the current statement. */
10021 static void
10022 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10024 tree block, control;
10025 gimple_stmt_iterator tgsi;
10026 gomp_sections *stmt;
10027 gimple t;
10028 gbind *new_stmt, *bind;
10029 gimple_seq ilist, dlist, olist, new_body;
10031 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
10033 push_gimplify_context ();
10035 dlist = NULL;
10036 ilist = NULL;
10037 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10038 &ilist, &dlist, ctx, NULL);
10040 new_body = gimple_omp_body (stmt);
10041 gimple_omp_set_body (stmt, NULL);
10042 tgsi = gsi_start (new_body);
10043 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10045 omp_context *sctx;
10046 gimple sec_start;
10048 sec_start = gsi_stmt (tgsi);
10049 sctx = maybe_lookup_ctx (sec_start);
10050 gcc_assert (sctx);
10052 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10053 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10054 GSI_CONTINUE_LINKING);
10055 gimple_omp_set_body (sec_start, NULL);
10057 if (gsi_one_before_end_p (tgsi))
10059 gimple_seq l = NULL;
10060 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10061 &l, ctx);
10062 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10063 gimple_omp_section_set_last (sec_start);
10066 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10067 GSI_CONTINUE_LINKING);
10070 block = make_node (BLOCK);
10071 bind = gimple_build_bind (NULL, new_body, block);
10073 olist = NULL;
10074 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10076 block = make_node (BLOCK);
10077 new_stmt = gimple_build_bind (NULL, NULL, block);
10078 gsi_replace (gsi_p, new_stmt, true);
10080 pop_gimplify_context (new_stmt);
10081 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10082 BLOCK_VARS (block) = gimple_bind_vars (bind);
10083 if (BLOCK_VARS (block))
10084 TREE_USED (block) = 1;
10086 new_body = NULL;
10087 gimple_seq_add_seq (&new_body, ilist);
10088 gimple_seq_add_stmt (&new_body, stmt);
10089 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10090 gimple_seq_add_stmt (&new_body, bind);
10092 control = create_tmp_var (unsigned_type_node, ".section");
10093 t = gimple_build_omp_continue (control, control);
10094 gimple_omp_sections_set_control (stmt, control);
10095 gimple_seq_add_stmt (&new_body, t);
10097 gimple_seq_add_seq (&new_body, olist);
10098 if (ctx->cancellable)
10099 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10100 gimple_seq_add_seq (&new_body, dlist);
10102 new_body = maybe_catch_exception (new_body);
10104 t = gimple_build_omp_return
10105 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10106 OMP_CLAUSE_NOWAIT));
10107 gimple_seq_add_stmt (&new_body, t);
10108 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10110 gimple_bind_set_body (new_stmt, new_body);
10114 /* A subroutine of lower_omp_single. Expand the simple form of
10115 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10117 if (GOMP_single_start ())
10118 BODY;
10119 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10121 FIXME. It may be better to delay expanding the logic of this until
10122 pass_expand_omp. The expanded logic may make the job more difficult
10123 to a synchronization analysis pass. */
10125 static void
10126 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10128 location_t loc = gimple_location (single_stmt);
10129 tree tlabel = create_artificial_label (loc);
10130 tree flabel = create_artificial_label (loc);
10131 gimple call, cond;
10132 tree lhs, decl;
10134 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10135 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10136 call = gimple_build_call (decl, 0);
10137 gimple_call_set_lhs (call, lhs);
10138 gimple_seq_add_stmt (pre_p, call);
10140 cond = gimple_build_cond (EQ_EXPR, lhs,
10141 fold_convert_loc (loc, TREE_TYPE (lhs),
10142 boolean_true_node),
10143 tlabel, flabel);
10144 gimple_seq_add_stmt (pre_p, cond);
10145 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10146 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10147 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10151 /* A subroutine of lower_omp_single. Expand the simple form of
10152 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10154 #pragma omp single copyprivate (a, b, c)
10156 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10159 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10161 BODY;
10162 copyout.a = a;
10163 copyout.b = b;
10164 copyout.c = c;
10165 GOMP_single_copy_end (&copyout);
10167 else
10169 a = copyout_p->a;
10170 b = copyout_p->b;
10171 c = copyout_p->c;
10173 GOMP_barrier ();
10176 FIXME. It may be better to delay expanding the logic of this until
10177 pass_expand_omp. The expanded logic may make the job more difficult
10178 to a synchronization analysis pass. */
10180 static void
10181 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10182 omp_context *ctx)
10184 tree ptr_type, t, l0, l1, l2, bfn_decl;
10185 gimple_seq copyin_seq;
10186 location_t loc = gimple_location (single_stmt);
10188 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10190 ptr_type = build_pointer_type (ctx->record_type);
10191 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10193 l0 = create_artificial_label (loc);
10194 l1 = create_artificial_label (loc);
10195 l2 = create_artificial_label (loc);
10197 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10198 t = build_call_expr_loc (loc, bfn_decl, 0);
10199 t = fold_convert_loc (loc, ptr_type, t);
10200 gimplify_assign (ctx->receiver_decl, t, pre_p);
10202 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10203 build_int_cst (ptr_type, 0));
10204 t = build3 (COND_EXPR, void_type_node, t,
10205 build_and_jump (&l0), build_and_jump (&l1));
10206 gimplify_and_add (t, pre_p);
10208 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10210 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10212 copyin_seq = NULL;
10213 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10214 &copyin_seq, ctx);
10216 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10217 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10218 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10219 gimplify_and_add (t, pre_p);
10221 t = build_and_jump (&l2);
10222 gimplify_and_add (t, pre_p);
10224 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10226 gimple_seq_add_seq (pre_p, copyin_seq);
10228 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10232 /* Expand code for an OpenMP single directive. */
10234 static void
10235 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10237 tree block;
10238 gimple t;
10239 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10240 gbind *bind;
10241 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10243 push_gimplify_context ();
10245 block = make_node (BLOCK);
10246 bind = gimple_build_bind (NULL, NULL, block);
10247 gsi_replace (gsi_p, bind, true);
10248 bind_body = NULL;
10249 dlist = NULL;
10250 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10251 &bind_body, &dlist, ctx, NULL);
10252 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10254 gimple_seq_add_stmt (&bind_body, single_stmt);
10256 if (ctx->record_type)
10257 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10258 else
10259 lower_omp_single_simple (single_stmt, &bind_body);
10261 gimple_omp_set_body (single_stmt, NULL);
10263 gimple_seq_add_seq (&bind_body, dlist);
10265 bind_body = maybe_catch_exception (bind_body);
10267 t = gimple_build_omp_return
10268 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10269 OMP_CLAUSE_NOWAIT));
10270 gimple_seq_add_stmt (&bind_body_tail, t);
10271 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10272 if (ctx->record_type)
10274 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10275 tree clobber = build_constructor (ctx->record_type, NULL);
10276 TREE_THIS_VOLATILE (clobber) = 1;
10277 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10278 clobber), GSI_SAME_STMT);
10280 gimple_seq_add_seq (&bind_body, bind_body_tail);
10281 gimple_bind_set_body (bind, bind_body);
10283 pop_gimplify_context (bind);
10285 gimple_bind_append_vars (bind, ctx->block_vars);
10286 BLOCK_VARS (block) = ctx->block_vars;
10287 if (BLOCK_VARS (block))
10288 TREE_USED (block) = 1;
10292 /* Expand code for an OpenMP master directive. */
10294 static void
10295 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10297 tree block, lab = NULL, x, bfn_decl;
10298 gimple stmt = gsi_stmt (*gsi_p);
10299 gbind *bind;
10300 location_t loc = gimple_location (stmt);
10301 gimple_seq tseq;
10303 push_gimplify_context ();
10305 block = make_node (BLOCK);
10306 bind = gimple_build_bind (NULL, NULL, block);
10307 gsi_replace (gsi_p, bind, true);
10308 gimple_bind_add_stmt (bind, stmt);
10310 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10311 x = build_call_expr_loc (loc, bfn_decl, 0);
10312 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10313 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10314 tseq = NULL;
10315 gimplify_and_add (x, &tseq);
10316 gimple_bind_add_seq (bind, tseq);
10318 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10319 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10320 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10321 gimple_omp_set_body (stmt, NULL);
10323 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10325 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10327 pop_gimplify_context (bind);
10329 gimple_bind_append_vars (bind, ctx->block_vars);
10330 BLOCK_VARS (block) = ctx->block_vars;
10334 /* Expand code for an OpenMP taskgroup directive. */
10336 static void
10337 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10339 gimple stmt = gsi_stmt (*gsi_p);
10340 gcall *x;
10341 gbind *bind;
10342 tree block = make_node (BLOCK);
10344 bind = gimple_build_bind (NULL, NULL, block);
10345 gsi_replace (gsi_p, bind, true);
10346 gimple_bind_add_stmt (bind, stmt);
10348 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10350 gimple_bind_add_stmt (bind, x);
10352 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10353 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10354 gimple_omp_set_body (stmt, NULL);
10356 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10358 gimple_bind_append_vars (bind, ctx->block_vars);
10359 BLOCK_VARS (block) = ctx->block_vars;
10363 /* Expand code for an OpenMP ordered directive. */
10365 static void
10366 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10368 tree block;
10369 gimple stmt = gsi_stmt (*gsi_p);
10370 gcall *x;
10371 gbind *bind;
10373 push_gimplify_context ();
10375 block = make_node (BLOCK);
10376 bind = gimple_build_bind (NULL, NULL, block);
10377 gsi_replace (gsi_p, bind, true);
10378 gimple_bind_add_stmt (bind, stmt);
10380 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10382 gimple_bind_add_stmt (bind, x);
10384 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10385 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10386 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10387 gimple_omp_set_body (stmt, NULL);
10389 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10390 gimple_bind_add_stmt (bind, x);
10392 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10394 pop_gimplify_context (bind);
10396 gimple_bind_append_vars (bind, ctx->block_vars);
10397 BLOCK_VARS (block) = gimple_bind_vars (bind);
10401 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10402 substitution of a couple of function calls. But in the NAMED case,
10403 requires that languages coordinate a symbol name. It is therefore
10404 best put here in common code. */
10406 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10408 static void
10409 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10411 tree block;
10412 tree name, lock, unlock;
10413 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10414 gbind *bind;
10415 location_t loc = gimple_location (stmt);
10416 gimple_seq tbody;
10418 name = gimple_omp_critical_name (stmt);
10419 if (name)
10421 tree decl;
10423 if (!critical_name_mutexes)
10424 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10426 tree *n = critical_name_mutexes->get (name);
10427 if (n == NULL)
10429 char *new_str;
10431 decl = create_tmp_var_raw (ptr_type_node);
10433 new_str = ACONCAT ((".gomp_critical_user_",
10434 IDENTIFIER_POINTER (name), NULL));
10435 DECL_NAME (decl) = get_identifier (new_str);
10436 TREE_PUBLIC (decl) = 1;
10437 TREE_STATIC (decl) = 1;
10438 DECL_COMMON (decl) = 1;
10439 DECL_ARTIFICIAL (decl) = 1;
10440 DECL_IGNORED_P (decl) = 1;
10442 varpool_node::finalize_decl (decl);
10444 critical_name_mutexes->put (name, decl);
10446 else
10447 decl = *n;
10449 /* If '#pragma omp critical' is inside offloaded region or
10450 inside function marked as offloadable, the symbol must be
10451 marked as offloadable too. */
10452 omp_context *octx;
10453 if (cgraph_node::get (current_function_decl)->offloadable)
10454 varpool_node::get_create (decl)->offloadable = 1;
10455 else
10456 for (octx = ctx->outer; octx; octx = octx->outer)
10457 if (is_gimple_omp_offloaded (octx->stmt))
10459 varpool_node::get_create (decl)->offloadable = 1;
10460 break;
10463 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10464 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10466 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10467 unlock = build_call_expr_loc (loc, unlock, 1,
10468 build_fold_addr_expr_loc (loc, decl));
10470 else
10472 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10473 lock = build_call_expr_loc (loc, lock, 0);
10475 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10476 unlock = build_call_expr_loc (loc, unlock, 0);
10479 push_gimplify_context ();
10481 block = make_node (BLOCK);
10482 bind = gimple_build_bind (NULL, NULL, block);
10483 gsi_replace (gsi_p, bind, true);
10484 gimple_bind_add_stmt (bind, stmt);
10486 tbody = gimple_bind_body (bind);
10487 gimplify_and_add (lock, &tbody);
10488 gimple_bind_set_body (bind, tbody);
10490 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10491 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10492 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10493 gimple_omp_set_body (stmt, NULL);
10495 tbody = gimple_bind_body (bind);
10496 gimplify_and_add (unlock, &tbody);
10497 gimple_bind_set_body (bind, tbody);
10499 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10501 pop_gimplify_context (bind);
10502 gimple_bind_append_vars (bind, ctx->block_vars);
10503 BLOCK_VARS (block) = gimple_bind_vars (bind);
10507 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10508 for a lastprivate clause. Given a loop control predicate of (V
10509 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10510 is appended to *DLIST, iterator initialization is appended to
10511 *BODY_P. */
10513 static void
10514 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10515 gimple_seq *dlist, struct omp_context *ctx)
10517 tree clauses, cond, vinit;
10518 enum tree_code cond_code;
10519 gimple_seq stmts;
10521 cond_code = fd->loop.cond_code;
10522 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10524 /* When possible, use a strict equality expression. This can let VRP
10525 type optimizations deduce the value and remove a copy. */
10526 if (tree_fits_shwi_p (fd->loop.step))
10528 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10529 if (step == 1 || step == -1)
10530 cond_code = EQ_EXPR;
10533 tree n2 = fd->loop.n2;
10534 if (fd->collapse > 1
10535 && TREE_CODE (n2) != INTEGER_CST
10536 && gimple_omp_for_combined_into_p (fd->for_stmt)
10537 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10539 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10540 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
10542 struct omp_for_data outer_fd;
10543 extract_omp_for_data (gfor, &outer_fd, NULL);
10544 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10547 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
10549 clauses = gimple_omp_for_clauses (fd->for_stmt);
10550 stmts = NULL;
10551 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10552 if (!gimple_seq_empty_p (stmts))
10554 gimple_seq_add_seq (&stmts, *dlist);
10555 *dlist = stmts;
10557 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10558 vinit = fd->loop.n1;
10559 if (cond_code == EQ_EXPR
10560 && tree_fits_shwi_p (fd->loop.n2)
10561 && ! integer_zerop (fd->loop.n2))
10562 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10563 else
10564 vinit = unshare_expr (vinit);
10566 /* Initialize the iterator variable, so that threads that don't execute
10567 any iterations don't execute the lastprivate clauses by accident. */
10568 gimplify_assign (fd->loop.v, vinit, body_p);
10573 /* Lower code for an OMP loop directive. */
10575 static void
10576 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10578 tree *rhs_p, block;
10579 struct omp_for_data fd, *fdp = NULL;
10580 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10581 gbind *new_stmt;
10582 gimple_seq omp_for_body, body, dlist;
10583 size_t i;
10585 push_gimplify_context ();
10587 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10589 block = make_node (BLOCK);
10590 new_stmt = gimple_build_bind (NULL, NULL, block);
10591 /* Replace at gsi right away, so that 'stmt' is no member
10592 of a sequence anymore as we're going to add to to a different
10593 one below. */
10594 gsi_replace (gsi_p, new_stmt, true);
10596 /* Move declaration of temporaries in the loop body before we make
10597 it go away. */
10598 omp_for_body = gimple_omp_body (stmt);
10599 if (!gimple_seq_empty_p (omp_for_body)
10600 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10602 gbind *inner_bind
10603 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10604 tree vars = gimple_bind_vars (inner_bind);
10605 gimple_bind_append_vars (new_stmt, vars);
10606 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10607 keep them on the inner_bind and it's block. */
10608 gimple_bind_set_vars (inner_bind, NULL_TREE);
10609 if (gimple_bind_block (inner_bind))
10610 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10613 if (gimple_omp_for_combined_into_p (stmt))
10615 extract_omp_for_data (stmt, &fd, NULL);
10616 fdp = &fd;
10618 /* We need two temporaries with fd.loop.v type (istart/iend)
10619 and then (fd.collapse - 1) temporaries with the same
10620 type for count2 ... countN-1 vars if not constant. */
10621 size_t count = 2;
10622 tree type = fd.iter_type;
10623 if (fd.collapse > 1
10624 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10625 count += fd.collapse - 1;
10626 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10627 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10628 tree clauses = *pc;
10629 if (parallel_for)
10630 outerc
10631 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10632 OMP_CLAUSE__LOOPTEMP_);
10633 for (i = 0; i < count; i++)
10635 tree temp;
10636 if (parallel_for)
10638 gcc_assert (outerc);
10639 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10640 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10641 OMP_CLAUSE__LOOPTEMP_);
10643 else
10645 temp = create_tmp_var (type);
10646 insert_decl_map (&ctx->outer->cb, temp, temp);
10648 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10649 OMP_CLAUSE_DECL (*pc) = temp;
10650 pc = &OMP_CLAUSE_CHAIN (*pc);
10652 *pc = clauses;
10655 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10656 dlist = NULL;
10657 body = NULL;
10658 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10659 fdp);
10660 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10662 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10664 /* Lower the header expressions. At this point, we can assume that
10665 the header is of the form:
10667 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10669 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10670 using the .omp_data_s mapping, if needed. */
10671 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10673 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10674 if (!is_gimple_min_invariant (*rhs_p))
10675 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10677 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10678 if (!is_gimple_min_invariant (*rhs_p))
10679 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10681 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10682 if (!is_gimple_min_invariant (*rhs_p))
10683 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10686 /* Once lowered, extract the bounds and clauses. */
10687 extract_omp_for_data (stmt, &fd, NULL);
10689 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10691 gimple_seq_add_stmt (&body, stmt);
10692 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10694 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10695 fd.loop.v));
10697 /* After the loop, add exit clauses. */
10698 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10700 if (ctx->cancellable)
10701 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10703 gimple_seq_add_seq (&body, dlist);
10705 body = maybe_catch_exception (body);
10707 /* Region exit marker goes at the end of the loop body. */
10708 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10709 maybe_add_implicit_barrier_cancel (ctx, &body);
10710 pop_gimplify_context (new_stmt);
10712 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10713 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10714 if (BLOCK_VARS (block))
10715 TREE_USED (block) = 1;
10717 gimple_bind_set_body (new_stmt, body);
10718 gimple_omp_set_body (stmt, NULL);
10719 gimple_omp_for_set_pre_body (stmt, NULL);
10722 /* Callback for walk_stmts. Check if the current statement only contains
10723 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10725 static tree
10726 check_combined_parallel (gimple_stmt_iterator *gsi_p,
10727 bool *handled_ops_p,
10728 struct walk_stmt_info *wi)
10730 int *info = (int *) wi->info;
10731 gimple stmt = gsi_stmt (*gsi_p);
10733 *handled_ops_p = true;
10734 switch (gimple_code (stmt))
10736 WALK_SUBSTMTS;
10738 case GIMPLE_OMP_FOR:
10739 case GIMPLE_OMP_SECTIONS:
10740 *info = *info == 0 ? 1 : -1;
10741 break;
10742 default:
10743 *info = -1;
10744 break;
10746 return NULL;
10749 struct omp_taskcopy_context
10751 /* This field must be at the beginning, as we do "inheritance": Some
10752 callback functions for tree-inline.c (e.g., omp_copy_decl)
10753 receive a copy_body_data pointer that is up-casted to an
10754 omp_context pointer. */
10755 copy_body_data cb;
10756 omp_context *ctx;
10759 static tree
10760 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10762 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10764 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10765 return create_tmp_var (TREE_TYPE (var));
10767 return var;
10770 static tree
10771 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10773 tree name, new_fields = NULL, type, f;
10775 type = lang_hooks.types.make_type (RECORD_TYPE);
10776 name = DECL_NAME (TYPE_NAME (orig_type));
10777 name = build_decl (gimple_location (tcctx->ctx->stmt),
10778 TYPE_DECL, name, type);
10779 TYPE_NAME (type) = name;
10781 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10783 tree new_f = copy_node (f);
10784 DECL_CONTEXT (new_f) = type;
10785 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10786 TREE_CHAIN (new_f) = new_fields;
10787 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10788 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10789 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10790 &tcctx->cb, NULL);
10791 new_fields = new_f;
10792 tcctx->cb.decl_map->put (f, new_f);
10794 TYPE_FIELDS (type) = nreverse (new_fields);
10795 layout_type (type);
10796 return type;
10799 /* Create task copyfn. */
10801 static void
10802 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
10804 struct function *child_cfun;
10805 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10806 tree record_type, srecord_type, bind, list;
10807 bool record_needs_remap = false, srecord_needs_remap = false;
10808 splay_tree_node n;
10809 struct omp_taskcopy_context tcctx;
10810 location_t loc = gimple_location (task_stmt);
10812 child_fn = gimple_omp_task_copy_fn (task_stmt);
10813 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10814 gcc_assert (child_cfun->cfg == NULL);
10815 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10817 /* Reset DECL_CONTEXT on function arguments. */
10818 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10819 DECL_CONTEXT (t) = child_fn;
10821 /* Populate the function. */
10822 push_gimplify_context ();
10823 push_cfun (child_cfun);
10825 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10826 TREE_SIDE_EFFECTS (bind) = 1;
10827 list = NULL;
10828 DECL_SAVED_TREE (child_fn) = bind;
10829 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10831 /* Remap src and dst argument types if needed. */
10832 record_type = ctx->record_type;
10833 srecord_type = ctx->srecord_type;
10834 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10835 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10837 record_needs_remap = true;
10838 break;
10840 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10841 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10843 srecord_needs_remap = true;
10844 break;
10847 if (record_needs_remap || srecord_needs_remap)
10849 memset (&tcctx, '\0', sizeof (tcctx));
10850 tcctx.cb.src_fn = ctx->cb.src_fn;
10851 tcctx.cb.dst_fn = child_fn;
10852 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
10853 gcc_checking_assert (tcctx.cb.src_node);
10854 tcctx.cb.dst_node = tcctx.cb.src_node;
10855 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10856 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10857 tcctx.cb.eh_lp_nr = 0;
10858 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10859 tcctx.cb.decl_map = new hash_map<tree, tree>;
10860 tcctx.ctx = ctx;
10862 if (record_needs_remap)
10863 record_type = task_copyfn_remap_type (&tcctx, record_type);
10864 if (srecord_needs_remap)
10865 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10867 else
10868 tcctx.cb.decl_map = NULL;
10870 arg = DECL_ARGUMENTS (child_fn);
10871 TREE_TYPE (arg) = build_pointer_type (record_type);
10872 sarg = DECL_CHAIN (arg);
10873 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10875 /* First pass: initialize temporaries used in record_type and srecord_type
10876 sizes and field offsets. */
10877 if (tcctx.cb.decl_map)
10878 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10879 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10881 tree *p;
10883 decl = OMP_CLAUSE_DECL (c);
10884 p = tcctx.cb.decl_map->get (decl);
10885 if (p == NULL)
10886 continue;
10887 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10888 sf = (tree) n->value;
10889 sf = *tcctx.cb.decl_map->get (sf);
10890 src = build_simple_mem_ref_loc (loc, sarg);
10891 src = omp_build_component_ref (src, sf);
10892 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10893 append_to_statement_list (t, &list);
10896 /* Second pass: copy shared var pointers and copy construct non-VLA
10897 firstprivate vars. */
10898 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10899 switch (OMP_CLAUSE_CODE (c))
10901 case OMP_CLAUSE_SHARED:
10902 decl = OMP_CLAUSE_DECL (c);
10903 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10904 if (n == NULL)
10905 break;
10906 f = (tree) n->value;
10907 if (tcctx.cb.decl_map)
10908 f = *tcctx.cb.decl_map->get (f);
10909 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10910 sf = (tree) n->value;
10911 if (tcctx.cb.decl_map)
10912 sf = *tcctx.cb.decl_map->get (sf);
10913 src = build_simple_mem_ref_loc (loc, sarg);
10914 src = omp_build_component_ref (src, sf);
10915 dst = build_simple_mem_ref_loc (loc, arg);
10916 dst = omp_build_component_ref (dst, f);
10917 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10918 append_to_statement_list (t, &list);
10919 break;
10920 case OMP_CLAUSE_FIRSTPRIVATE:
10921 decl = OMP_CLAUSE_DECL (c);
10922 if (is_variable_sized (decl))
10923 break;
10924 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10925 if (n == NULL)
10926 break;
10927 f = (tree) n->value;
10928 if (tcctx.cb.decl_map)
10929 f = *tcctx.cb.decl_map->get (f);
10930 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10931 if (n != NULL)
10933 sf = (tree) n->value;
10934 if (tcctx.cb.decl_map)
10935 sf = *tcctx.cb.decl_map->get (sf);
10936 src = build_simple_mem_ref_loc (loc, sarg);
10937 src = omp_build_component_ref (src, sf);
10938 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
10939 src = build_simple_mem_ref_loc (loc, src);
10941 else
10942 src = decl;
10943 dst = build_simple_mem_ref_loc (loc, arg);
10944 dst = omp_build_component_ref (dst, f);
10945 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10946 append_to_statement_list (t, &list);
10947 break;
10948 case OMP_CLAUSE_PRIVATE:
10949 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10950 break;
10951 decl = OMP_CLAUSE_DECL (c);
10952 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10953 f = (tree) n->value;
10954 if (tcctx.cb.decl_map)
10955 f = *tcctx.cb.decl_map->get (f);
10956 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10957 if (n != NULL)
10959 sf = (tree) n->value;
10960 if (tcctx.cb.decl_map)
10961 sf = *tcctx.cb.decl_map->get (sf);
10962 src = build_simple_mem_ref_loc (loc, sarg);
10963 src = omp_build_component_ref (src, sf);
10964 if (use_pointer_for_field (decl, NULL))
10965 src = build_simple_mem_ref_loc (loc, src);
10967 else
10968 src = decl;
10969 dst = build_simple_mem_ref_loc (loc, arg);
10970 dst = omp_build_component_ref (dst, f);
10971 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10972 append_to_statement_list (t, &list);
10973 break;
10974 default:
10975 break;
10978 /* Last pass: handle VLA firstprivates. */
10979 if (tcctx.cb.decl_map)
10980 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10981 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10983 tree ind, ptr, df;
10985 decl = OMP_CLAUSE_DECL (c);
10986 if (!is_variable_sized (decl))
10987 continue;
10988 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10989 if (n == NULL)
10990 continue;
10991 f = (tree) n->value;
10992 f = *tcctx.cb.decl_map->get (f);
10993 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10994 ind = DECL_VALUE_EXPR (decl);
10995 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10996 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10997 n = splay_tree_lookup (ctx->sfield_map,
10998 (splay_tree_key) TREE_OPERAND (ind, 0));
10999 sf = (tree) n->value;
11000 sf = *tcctx.cb.decl_map->get (sf);
11001 src = build_simple_mem_ref_loc (loc, sarg);
11002 src = omp_build_component_ref (src, sf);
11003 src = build_simple_mem_ref_loc (loc, src);
11004 dst = build_simple_mem_ref_loc (loc, arg);
11005 dst = omp_build_component_ref (dst, f);
11006 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11007 append_to_statement_list (t, &list);
11008 n = splay_tree_lookup (ctx->field_map,
11009 (splay_tree_key) TREE_OPERAND (ind, 0));
11010 df = (tree) n->value;
11011 df = *tcctx.cb.decl_map->get (df);
11012 ptr = build_simple_mem_ref_loc (loc, arg);
11013 ptr = omp_build_component_ref (ptr, df);
11014 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
11015 build_fold_addr_expr_loc (loc, dst));
11016 append_to_statement_list (t, &list);
11019 t = build1 (RETURN_EXPR, void_type_node, NULL);
11020 append_to_statement_list (t, &list);
11022 if (tcctx.cb.decl_map)
11023 delete tcctx.cb.decl_map;
11024 pop_gimplify_context (NULL);
11025 BIND_EXPR_BODY (bind) = list;
11026 pop_cfun ();
11029 static void
11030 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
11032 tree c, clauses;
11033 gimple g;
11034 size_t n_in = 0, n_out = 0, idx = 2, i;
11036 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11037 OMP_CLAUSE_DEPEND);
11038 gcc_assert (clauses);
11039 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11040 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11041 switch (OMP_CLAUSE_DEPEND_KIND (c))
11043 case OMP_CLAUSE_DEPEND_IN:
11044 n_in++;
11045 break;
11046 case OMP_CLAUSE_DEPEND_OUT:
11047 case OMP_CLAUSE_DEPEND_INOUT:
11048 n_out++;
11049 break;
11050 default:
11051 gcc_unreachable ();
11053 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11054 tree array = create_tmp_var (type);
11055 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11056 NULL_TREE);
11057 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11058 gimple_seq_add_stmt (iseq, g);
11059 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11060 NULL_TREE);
11061 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11062 gimple_seq_add_stmt (iseq, g);
11063 for (i = 0; i < 2; i++)
11065 if ((i ? n_in : n_out) == 0)
11066 continue;
11067 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11068 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11069 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11071 tree t = OMP_CLAUSE_DECL (c);
11072 t = fold_convert (ptr_type_node, t);
11073 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11074 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11075 NULL_TREE, NULL_TREE);
11076 g = gimple_build_assign (r, t);
11077 gimple_seq_add_stmt (iseq, g);
11080 tree *p = gimple_omp_task_clauses_ptr (stmt);
11081 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11082 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11083 OMP_CLAUSE_CHAIN (c) = *p;
11084 *p = c;
11085 tree clobber = build_constructor (type, NULL);
11086 TREE_THIS_VOLATILE (clobber) = 1;
11087 g = gimple_build_assign (array, clobber);
11088 gimple_seq_add_stmt (oseq, g);
11091 /* Lower the OpenMP parallel or task directive in the current statement
11092 in GSI_P. CTX holds context information for the directive. */
11094 static void
11095 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11097 tree clauses;
11098 tree child_fn, t;
11099 gimple stmt = gsi_stmt (*gsi_p);
11100 gbind *par_bind, *bind, *dep_bind = NULL;
11101 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11102 location_t loc = gimple_location (stmt);
11104 clauses = gimple_omp_taskreg_clauses (stmt);
11105 par_bind
11106 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11107 par_body = gimple_bind_body (par_bind);
11108 child_fn = ctx->cb.dst_fn;
11109 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11110 && !gimple_omp_parallel_combined_p (stmt))
11112 struct walk_stmt_info wi;
11113 int ws_num = 0;
11115 memset (&wi, 0, sizeof (wi));
11116 wi.info = &ws_num;
11117 wi.val_only = true;
11118 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11119 if (ws_num == 1)
11120 gimple_omp_parallel_set_combined_p (stmt, true);
11122 gimple_seq dep_ilist = NULL;
11123 gimple_seq dep_olist = NULL;
11124 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11125 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11127 push_gimplify_context ();
11128 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11129 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11132 if (ctx->srecord_type)
11133 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11135 push_gimplify_context ();
11137 par_olist = NULL;
11138 par_ilist = NULL;
11139 par_rlist = NULL;
11140 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11141 lower_omp (&par_body, ctx);
11142 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11143 lower_reduction_clauses (clauses, &par_rlist, ctx);
11145 /* Declare all the variables created by mapping and the variables
11146 declared in the scope of the parallel body. */
11147 record_vars_into (ctx->block_vars, child_fn);
11148 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11150 if (ctx->record_type)
11152 ctx->sender_decl
11153 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11154 : ctx->record_type, ".omp_data_o");
11155 DECL_NAMELESS (ctx->sender_decl) = 1;
11156 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11157 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11160 olist = NULL;
11161 ilist = NULL;
11162 lower_send_clauses (clauses, &ilist, &olist, ctx);
11163 lower_send_shared_vars (&ilist, &olist, ctx);
11165 if (ctx->record_type)
11167 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11168 TREE_THIS_VOLATILE (clobber) = 1;
11169 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11170 clobber));
11173 /* Once all the expansions are done, sequence all the different
11174 fragments inside gimple_omp_body. */
11176 new_body = NULL;
11178 if (ctx->record_type)
11180 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11181 /* fixup_child_record_type might have changed receiver_decl's type. */
11182 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11183 gimple_seq_add_stmt (&new_body,
11184 gimple_build_assign (ctx->receiver_decl, t));
11187 gimple_seq_add_seq (&new_body, par_ilist);
11188 gimple_seq_add_seq (&new_body, par_body);
11189 gimple_seq_add_seq (&new_body, par_rlist);
11190 if (ctx->cancellable)
11191 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11192 gimple_seq_add_seq (&new_body, par_olist);
11193 new_body = maybe_catch_exception (new_body);
11194 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
11195 gimple_seq_add_stmt (&new_body,
11196 gimple_build_omp_continue (integer_zero_node,
11197 integer_zero_node));
11198 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11199 gimple_omp_set_body (stmt, new_body);
11201 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11202 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11203 gimple_bind_add_seq (bind, ilist);
11204 gimple_bind_add_stmt (bind, stmt);
11205 gimple_bind_add_seq (bind, olist);
11207 pop_gimplify_context (NULL);
11209 if (dep_bind)
11211 gimple_bind_add_seq (dep_bind, dep_ilist);
11212 gimple_bind_add_stmt (dep_bind, bind);
11213 gimple_bind_add_seq (dep_bind, dep_olist);
11214 pop_gimplify_context (dep_bind);
11218 /* Lower the GIMPLE_OMP_TARGET in the current statement
11219 in GSI_P. CTX holds context information for the directive. */
11221 static void
11222 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11224 tree clauses;
11225 tree child_fn, t, c;
11226 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11227 gbind *tgt_bind, *bind;
11228 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11229 location_t loc = gimple_location (stmt);
11230 bool offloaded, data_region;
11231 unsigned int map_cnt = 0;
11233 offloaded = is_gimple_omp_offloaded (stmt);
11234 switch (gimple_omp_target_kind (stmt))
11236 case GF_OMP_TARGET_KIND_REGION:
11237 case GF_OMP_TARGET_KIND_UPDATE:
11238 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11239 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11240 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11241 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11242 data_region = false;
11243 break;
11244 case GF_OMP_TARGET_KIND_DATA:
11245 case GF_OMP_TARGET_KIND_OACC_DATA:
11246 data_region = true;
11247 break;
11248 default:
11249 gcc_unreachable ();
11252 clauses = gimple_omp_target_clauses (stmt);
11254 tgt_bind = NULL;
11255 tgt_body = NULL;
11256 if (offloaded)
11258 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11259 tgt_body = gimple_bind_body (tgt_bind);
11261 else if (data_region)
11262 tgt_body = gimple_omp_body (stmt);
11263 child_fn = ctx->cb.dst_fn;
11265 push_gimplify_context ();
11267 irlist = NULL;
11268 orlist = NULL;
11269 if (offloaded
11270 && is_gimple_omp_oacc (stmt))
11271 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11273 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11274 switch (OMP_CLAUSE_CODE (c))
11276 tree var, x;
11278 default:
11279 break;
11280 case OMP_CLAUSE_MAP:
11281 #ifdef ENABLE_CHECKING
11282 /* First check what we're prepared to handle in the following. */
11283 switch (OMP_CLAUSE_MAP_KIND (c))
11285 case GOMP_MAP_ALLOC:
11286 case GOMP_MAP_TO:
11287 case GOMP_MAP_FROM:
11288 case GOMP_MAP_TOFROM:
11289 case GOMP_MAP_POINTER:
11290 case GOMP_MAP_TO_PSET:
11291 break;
11292 case GOMP_MAP_FORCE_ALLOC:
11293 case GOMP_MAP_FORCE_TO:
11294 case GOMP_MAP_FORCE_FROM:
11295 case GOMP_MAP_FORCE_TOFROM:
11296 case GOMP_MAP_FORCE_PRESENT:
11297 case GOMP_MAP_FORCE_DEALLOC:
11298 case GOMP_MAP_FORCE_DEVICEPTR:
11299 gcc_assert (is_gimple_omp_oacc (stmt));
11300 break;
11301 default:
11302 gcc_unreachable ();
11304 #endif
11305 /* FALLTHRU */
11306 case OMP_CLAUSE_TO:
11307 case OMP_CLAUSE_FROM:
11308 var = OMP_CLAUSE_DECL (c);
11309 if (!DECL_P (var))
11311 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11312 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11313 map_cnt++;
11314 continue;
11317 if (DECL_SIZE (var)
11318 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11320 tree var2 = DECL_VALUE_EXPR (var);
11321 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11322 var2 = TREE_OPERAND (var2, 0);
11323 gcc_assert (DECL_P (var2));
11324 var = var2;
11327 if (!maybe_lookup_field (var, ctx))
11328 continue;
11330 if (offloaded)
11332 x = build_receiver_ref (var, true, ctx);
11333 tree new_var = lookup_decl (var, ctx);
11334 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11335 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11336 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11337 x = build_simple_mem_ref (x);
11338 SET_DECL_VALUE_EXPR (new_var, x);
11339 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11341 map_cnt++;
11344 if (offloaded)
11346 target_nesting_level++;
11347 lower_omp (&tgt_body, ctx);
11348 target_nesting_level--;
11350 else if (data_region)
11351 lower_omp (&tgt_body, ctx);
11353 if (offloaded)
11355 /* Declare all the variables created by mapping and the variables
11356 declared in the scope of the target body. */
11357 record_vars_into (ctx->block_vars, child_fn);
11358 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11361 olist = NULL;
11362 ilist = NULL;
11363 if (ctx->record_type)
11365 ctx->sender_decl
11366 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11367 DECL_NAMELESS (ctx->sender_decl) = 1;
11368 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11369 t = make_tree_vec (3);
11370 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11371 TREE_VEC_ELT (t, 1)
11372 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11373 ".omp_data_sizes");
11374 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11375 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11376 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11377 tree tkind_type;
11378 int talign_shift;
11379 if (is_gimple_omp_oacc (stmt))
11381 tkind_type = short_unsigned_type_node;
11382 talign_shift = 8;
11384 else
11386 tkind_type = unsigned_char_type_node;
11387 talign_shift = 3;
11389 TREE_VEC_ELT (t, 2)
11390 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11391 ".omp_data_kinds");
11392 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11393 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11394 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11395 gimple_omp_target_set_data_arg (stmt, t);
11397 vec<constructor_elt, va_gc> *vsize;
11398 vec<constructor_elt, va_gc> *vkind;
11399 vec_alloc (vsize, map_cnt);
11400 vec_alloc (vkind, map_cnt);
11401 unsigned int map_idx = 0;
11403 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11404 switch (OMP_CLAUSE_CODE (c))
11406 tree ovar, nc;
11408 default:
11409 break;
11410 case OMP_CLAUSE_MAP:
11411 case OMP_CLAUSE_TO:
11412 case OMP_CLAUSE_FROM:
11413 nc = c;
11414 ovar = OMP_CLAUSE_DECL (c);
11415 if (!DECL_P (ovar))
11417 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11418 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11420 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11421 == get_base_address (ovar));
11422 nc = OMP_CLAUSE_CHAIN (c);
11423 ovar = OMP_CLAUSE_DECL (nc);
11425 else
11427 tree x = build_sender_ref (ovar, ctx);
11428 tree v
11429 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11430 gimplify_assign (x, v, &ilist);
11431 nc = NULL_TREE;
11434 else
11436 if (DECL_SIZE (ovar)
11437 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11439 tree ovar2 = DECL_VALUE_EXPR (ovar);
11440 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11441 ovar2 = TREE_OPERAND (ovar2, 0);
11442 gcc_assert (DECL_P (ovar2));
11443 ovar = ovar2;
11445 if (!maybe_lookup_field (ovar, ctx))
11446 continue;
11449 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11450 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11451 talign = DECL_ALIGN_UNIT (ovar);
11452 if (nc)
11454 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11455 tree x = build_sender_ref (ovar, ctx);
11456 if (maybe_lookup_oacc_reduction (var, ctx))
11458 gcc_checking_assert (offloaded
11459 && is_gimple_omp_oacc (stmt));
11460 gimplify_assign (x, var, &ilist);
11462 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11463 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11464 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11465 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11467 gcc_assert (offloaded);
11468 tree avar
11469 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11470 mark_addressable (avar);
11471 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11472 talign = DECL_ALIGN_UNIT (avar);
11473 avar = build_fold_addr_expr (avar);
11474 gimplify_assign (x, avar, &ilist);
11476 else if (is_gimple_reg (var))
11478 gcc_assert (offloaded);
11479 tree avar = create_tmp_var (TREE_TYPE (var));
11480 mark_addressable (avar);
11481 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11482 if (GOMP_MAP_COPY_TO_P (map_kind)
11483 || map_kind == GOMP_MAP_POINTER
11484 || map_kind == GOMP_MAP_TO_PSET
11485 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11486 gimplify_assign (avar, var, &ilist);
11487 avar = build_fold_addr_expr (avar);
11488 gimplify_assign (x, avar, &ilist);
11489 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11490 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11491 && !TYPE_READONLY (TREE_TYPE (var)))
11493 x = build_sender_ref (ovar, ctx);
11494 x = build_simple_mem_ref (x);
11495 gimplify_assign (var, x, &olist);
11498 else
11500 var = build_fold_addr_expr (var);
11501 gimplify_assign (x, var, &ilist);
11504 tree s = OMP_CLAUSE_SIZE (c);
11505 if (s == NULL_TREE)
11506 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11507 s = fold_convert (size_type_node, s);
11508 tree purpose = size_int (map_idx++);
11509 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11510 if (TREE_CODE (s) != INTEGER_CST)
11511 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11513 unsigned HOST_WIDE_INT tkind;
11514 switch (OMP_CLAUSE_CODE (c))
11516 case OMP_CLAUSE_MAP:
11517 tkind = OMP_CLAUSE_MAP_KIND (c);
11518 break;
11519 case OMP_CLAUSE_TO:
11520 tkind = GOMP_MAP_TO;
11521 break;
11522 case OMP_CLAUSE_FROM:
11523 tkind = GOMP_MAP_FROM;
11524 break;
11525 default:
11526 gcc_unreachable ();
11528 gcc_checking_assert (tkind
11529 < (HOST_WIDE_INT_C (1U) << talign_shift));
11530 talign = ceil_log2 (talign);
11531 tkind |= talign << talign_shift;
11532 gcc_checking_assert (tkind
11533 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11534 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11535 build_int_cstu (tkind_type, tkind));
11536 if (nc && nc != c)
11537 c = nc;
11540 gcc_assert (map_idx == map_cnt);
11542 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11543 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11544 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11545 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11546 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11548 gimple_seq initlist = NULL;
11549 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11550 TREE_VEC_ELT (t, 1)),
11551 &initlist, true, NULL_TREE);
11552 gimple_seq_add_seq (&ilist, initlist);
11554 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11555 NULL);
11556 TREE_THIS_VOLATILE (clobber) = 1;
11557 gimple_seq_add_stmt (&olist,
11558 gimple_build_assign (TREE_VEC_ELT (t, 1),
11559 clobber));
11562 tree clobber = build_constructor (ctx->record_type, NULL);
11563 TREE_THIS_VOLATILE (clobber) = 1;
11564 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11565 clobber));
11568 /* Once all the expansions are done, sequence all the different
11569 fragments inside gimple_omp_body. */
11571 new_body = NULL;
11573 if (offloaded
11574 && ctx->record_type)
11576 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11577 /* fixup_child_record_type might have changed receiver_decl's type. */
11578 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11579 gimple_seq_add_stmt (&new_body,
11580 gimple_build_assign (ctx->receiver_decl, t));
11583 if (offloaded)
11585 gimple_seq_add_seq (&new_body, tgt_body);
11586 new_body = maybe_catch_exception (new_body);
11588 else if (data_region)
11589 new_body = tgt_body;
11590 if (offloaded || data_region)
11592 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11593 gimple_omp_set_body (stmt, new_body);
11596 bind = gimple_build_bind (NULL, NULL,
11597 tgt_bind ? gimple_bind_block (tgt_bind)
11598 : NULL_TREE);
11599 gsi_replace (gsi_p, bind, true);
11600 gimple_bind_add_seq (bind, irlist);
11601 gimple_bind_add_seq (bind, ilist);
11602 gimple_bind_add_stmt (bind, stmt);
11603 gimple_bind_add_seq (bind, olist);
11604 gimple_bind_add_seq (bind, orlist);
11606 pop_gimplify_context (NULL);
11609 /* Expand code for an OpenMP teams directive. */
11611 static void
11612 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11614 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11615 push_gimplify_context ();
11617 tree block = make_node (BLOCK);
11618 gbind *bind = gimple_build_bind (NULL, NULL, block);
11619 gsi_replace (gsi_p, bind, true);
11620 gimple_seq bind_body = NULL;
11621 gimple_seq dlist = NULL;
11622 gimple_seq olist = NULL;
11624 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11625 OMP_CLAUSE_NUM_TEAMS);
11626 if (num_teams == NULL_TREE)
11627 num_teams = build_int_cst (unsigned_type_node, 0);
11628 else
11630 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11631 num_teams = fold_convert (unsigned_type_node, num_teams);
11632 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11634 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11635 OMP_CLAUSE_THREAD_LIMIT);
11636 if (thread_limit == NULL_TREE)
11637 thread_limit = build_int_cst (unsigned_type_node, 0);
11638 else
11640 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11641 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11642 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11643 fb_rvalue);
11646 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11647 &bind_body, &dlist, ctx, NULL);
11648 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11649 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11650 gimple_seq_add_stmt (&bind_body, teams_stmt);
11652 location_t loc = gimple_location (teams_stmt);
11653 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11654 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11655 gimple_set_location (call, loc);
11656 gimple_seq_add_stmt (&bind_body, call);
11658 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11659 gimple_omp_set_body (teams_stmt, NULL);
11660 gimple_seq_add_seq (&bind_body, olist);
11661 gimple_seq_add_seq (&bind_body, dlist);
11662 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11663 gimple_bind_set_body (bind, bind_body);
11665 pop_gimplify_context (bind);
11667 gimple_bind_append_vars (bind, ctx->block_vars);
11668 BLOCK_VARS (block) = ctx->block_vars;
11669 if (BLOCK_VARS (block))
11670 TREE_USED (block) = 1;
11674 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11675 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11676 of OMP context, but with task_shared_vars set. */
11678 static tree
11679 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11680 void *data)
11682 tree t = *tp;
11684 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11685 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11686 return t;
11688 if (task_shared_vars
11689 && DECL_P (t)
11690 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11691 return t;
11693 /* If a global variable has been privatized, TREE_CONSTANT on
11694 ADDR_EXPR might be wrong. */
11695 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11696 recompute_tree_invariant_for_addr_expr (t);
11698 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11699 return NULL_TREE;
11702 static void
11703 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11705 gimple stmt = gsi_stmt (*gsi_p);
11706 struct walk_stmt_info wi;
11707 gcall *call_stmt;
11709 if (gimple_has_location (stmt))
11710 input_location = gimple_location (stmt);
11712 if (task_shared_vars)
11713 memset (&wi, '\0', sizeof (wi));
11715 /* If we have issued syntax errors, avoid doing any heavy lifting.
11716 Just replace the OMP directives with a NOP to avoid
11717 confusing RTL expansion. */
11718 if (seen_error () && is_gimple_omp (stmt))
11720 gsi_replace (gsi_p, gimple_build_nop (), true);
11721 return;
11724 switch (gimple_code (stmt))
11726 case GIMPLE_COND:
11728 gcond *cond_stmt = as_a <gcond *> (stmt);
11729 if ((ctx || task_shared_vars)
11730 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11731 lower_omp_regimplify_p,
11732 ctx ? NULL : &wi, NULL)
11733 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11734 lower_omp_regimplify_p,
11735 ctx ? NULL : &wi, NULL)))
11736 gimple_regimplify_operands (cond_stmt, gsi_p);
11738 break;
11739 case GIMPLE_CATCH:
11740 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
11741 break;
11742 case GIMPLE_EH_FILTER:
11743 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
11744 break;
11745 case GIMPLE_TRY:
11746 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11747 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
11748 break;
11749 case GIMPLE_TRANSACTION:
11750 lower_omp (gimple_transaction_body_ptr (
11751 as_a <gtransaction *> (stmt)),
11752 ctx);
11753 break;
11754 case GIMPLE_BIND:
11755 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
11756 break;
11757 case GIMPLE_OMP_PARALLEL:
11758 case GIMPLE_OMP_TASK:
11759 ctx = maybe_lookup_ctx (stmt);
11760 gcc_assert (ctx);
11761 if (ctx->cancellable)
11762 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11763 lower_omp_taskreg (gsi_p, ctx);
11764 break;
11765 case GIMPLE_OMP_FOR:
11766 ctx = maybe_lookup_ctx (stmt);
11767 gcc_assert (ctx);
11768 if (ctx->cancellable)
11769 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11770 lower_omp_for (gsi_p, ctx);
11771 break;
11772 case GIMPLE_OMP_SECTIONS:
11773 ctx = maybe_lookup_ctx (stmt);
11774 gcc_assert (ctx);
11775 if (ctx->cancellable)
11776 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11777 lower_omp_sections (gsi_p, ctx);
11778 break;
11779 case GIMPLE_OMP_SINGLE:
11780 ctx = maybe_lookup_ctx (stmt);
11781 gcc_assert (ctx);
11782 lower_omp_single (gsi_p, ctx);
11783 break;
11784 case GIMPLE_OMP_MASTER:
11785 ctx = maybe_lookup_ctx (stmt);
11786 gcc_assert (ctx);
11787 lower_omp_master (gsi_p, ctx);
11788 break;
11789 case GIMPLE_OMP_TASKGROUP:
11790 ctx = maybe_lookup_ctx (stmt);
11791 gcc_assert (ctx);
11792 lower_omp_taskgroup (gsi_p, ctx);
11793 break;
11794 case GIMPLE_OMP_ORDERED:
11795 ctx = maybe_lookup_ctx (stmt);
11796 gcc_assert (ctx);
11797 lower_omp_ordered (gsi_p, ctx);
11798 break;
11799 case GIMPLE_OMP_CRITICAL:
11800 ctx = maybe_lookup_ctx (stmt);
11801 gcc_assert (ctx);
11802 lower_omp_critical (gsi_p, ctx);
11803 break;
11804 case GIMPLE_OMP_ATOMIC_LOAD:
11805 if ((ctx || task_shared_vars)
11806 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11807 as_a <gomp_atomic_load *> (stmt)),
11808 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11809 gimple_regimplify_operands (stmt, gsi_p);
11810 break;
11811 case GIMPLE_OMP_TARGET:
11812 ctx = maybe_lookup_ctx (stmt);
11813 gcc_assert (ctx);
11814 lower_omp_target (gsi_p, ctx);
11815 break;
11816 case GIMPLE_OMP_TEAMS:
11817 ctx = maybe_lookup_ctx (stmt);
11818 gcc_assert (ctx);
11819 lower_omp_teams (gsi_p, ctx);
11820 break;
11821 case GIMPLE_CALL:
11822 tree fndecl;
11823 call_stmt = as_a <gcall *> (stmt);
11824 fndecl = gimple_call_fndecl (call_stmt);
11825 if (fndecl
11826 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11827 switch (DECL_FUNCTION_CODE (fndecl))
11829 case BUILT_IN_GOMP_BARRIER:
11830 if (ctx == NULL)
11831 break;
11832 /* FALLTHRU */
11833 case BUILT_IN_GOMP_CANCEL:
11834 case BUILT_IN_GOMP_CANCELLATION_POINT:
11835 omp_context *cctx;
11836 cctx = ctx;
11837 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11838 cctx = cctx->outer;
11839 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
11840 if (!cctx->cancellable)
11842 if (DECL_FUNCTION_CODE (fndecl)
11843 == BUILT_IN_GOMP_CANCELLATION_POINT)
11845 stmt = gimple_build_nop ();
11846 gsi_replace (gsi_p, stmt, false);
11848 break;
11850 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11852 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
11853 gimple_call_set_fndecl (call_stmt, fndecl);
11854 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
11856 tree lhs;
11857 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
11858 gimple_call_set_lhs (call_stmt, lhs);
11859 tree fallthru_label;
11860 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11861 gimple g;
11862 g = gimple_build_label (fallthru_label);
11863 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11864 g = gimple_build_cond (NE_EXPR, lhs,
11865 fold_convert (TREE_TYPE (lhs),
11866 boolean_false_node),
11867 cctx->cancel_label, fallthru_label);
11868 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11869 break;
11870 default:
11871 break;
11873 /* FALLTHRU */
11874 default:
11875 if ((ctx || task_shared_vars)
11876 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11877 ctx ? NULL : &wi))
11879 /* Just remove clobbers, this should happen only if we have
11880 "privatized" local addressable variables in SIMD regions,
11881 the clobber isn't needed in that case and gimplifying address
11882 of the ARRAY_REF into a pointer and creating MEM_REF based
11883 clobber would create worse code than we get with the clobber
11884 dropped. */
11885 if (gimple_clobber_p (stmt))
11887 gsi_replace (gsi_p, gimple_build_nop (), true);
11888 break;
11890 gimple_regimplify_operands (stmt, gsi_p);
11892 break;
11896 static void
11897 lower_omp (gimple_seq *body, omp_context *ctx)
11899 location_t saved_location = input_location;
11900 gimple_stmt_iterator gsi;
11901 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11902 lower_omp_1 (&gsi, ctx);
11903 /* During gimplification, we haven't folded statments inside offloading
11904 regions (gimplify.c:maybe_fold_stmt); do that now. */
11905 if (target_nesting_level)
11906 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11907 fold_stmt (&gsi);
11908 input_location = saved_location;
11911 /* Main entry point. */
11913 static unsigned int
11914 execute_lower_omp (void)
11916 gimple_seq body;
11917 int i;
11918 omp_context *ctx;
11920 /* This pass always runs, to provide PROP_gimple_lomp.
11921 But often, there is nothing to do. */
11922 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11923 && flag_openmp_simd == 0)
11924 return 0;
11926 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11927 delete_omp_context);
11929 body = gimple_body (current_function_decl);
11930 scan_omp (&body, NULL);
11931 gcc_assert (taskreg_nesting_level == 0);
11932 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11933 finish_taskreg_scan (ctx);
11934 taskreg_contexts.release ();
11936 if (all_contexts->root)
11938 if (task_shared_vars)
11939 push_gimplify_context ();
11940 lower_omp (&body, NULL);
11941 if (task_shared_vars)
11942 pop_gimplify_context (NULL);
11945 if (all_contexts)
11947 splay_tree_delete (all_contexts);
11948 all_contexts = NULL;
11950 BITMAP_FREE (task_shared_vars);
11951 return 0;
11954 namespace {
11956 const pass_data pass_data_lower_omp =
11958 GIMPLE_PASS, /* type */
11959 "omplower", /* name */
11960 OPTGROUP_NONE, /* optinfo_flags */
11961 TV_NONE, /* tv_id */
11962 PROP_gimple_any, /* properties_required */
11963 PROP_gimple_lomp, /* properties_provided */
11964 0, /* properties_destroyed */
11965 0, /* todo_flags_start */
11966 0, /* todo_flags_finish */
11969 class pass_lower_omp : public gimple_opt_pass
11971 public:
11972 pass_lower_omp (gcc::context *ctxt)
11973 : gimple_opt_pass (pass_data_lower_omp, ctxt)
11976 /* opt_pass methods: */
11977 virtual unsigned int execute (function *) { return execute_lower_omp (); }
11979 }; // class pass_lower_omp
11981 } // anon namespace
11983 gimple_opt_pass *
11984 make_pass_lower_omp (gcc::context *ctxt)
11986 return new pass_lower_omp (ctxt);
11989 /* The following is a utility to diagnose structured block violations.
11990 It is not part of the "omplower" pass, as that's invoked too late. It
11991 should be invoked by the respective front ends after gimplification. */
11993 static splay_tree all_labels;
11995 /* Check for mismatched contexts and generate an error if needed. Return
11996 true if an error is detected. */
11998 static bool
11999 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
12000 gimple branch_ctx, gimple label_ctx)
12002 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
12003 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
12005 if (label_ctx == branch_ctx)
12006 return false;
12008 const char* kind = NULL;
12010 if (flag_cilkplus)
12012 if ((branch_ctx
12013 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12014 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12015 || (label_ctx
12016 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12017 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12018 kind = "Cilk Plus";
12020 if (flag_openacc)
12022 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
12023 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
12025 gcc_checking_assert (kind == NULL);
12026 kind = "OpenACC";
12029 if (kind == NULL)
12031 gcc_checking_assert (flag_openmp);
12032 kind = "OpenMP";
12036 Previously we kept track of the label's entire context in diagnose_sb_[12]
12037 so we could traverse it and issue a correct "exit" or "enter" error
12038 message upon a structured block violation.
12040 We built the context by building a list with tree_cons'ing, but there is
12041 no easy counterpart in gimple tuples. It seems like far too much work
12042 for issuing exit/enter error messages. If someone really misses the
12043 distinct error message... patches welcome.
12046 #if 0
12047 /* Try to avoid confusing the user by producing and error message
12048 with correct "exit" or "enter" verbiage. We prefer "exit"
12049 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12050 if (branch_ctx == NULL)
12051 exit_p = false;
12052 else
12054 while (label_ctx)
12056 if (TREE_VALUE (label_ctx) == branch_ctx)
12058 exit_p = false;
12059 break;
12061 label_ctx = TREE_CHAIN (label_ctx);
12065 if (exit_p)
12066 error ("invalid exit from %s structured block", kind);
12067 else
12068 error ("invalid entry to %s structured block", kind);
12069 #endif
12071 /* If it's obvious we have an invalid entry, be specific about the error. */
12072 if (branch_ctx == NULL)
12073 error ("invalid entry to %s structured block", kind);
12074 else
12076 /* Otherwise, be vague and lazy, but efficient. */
12077 error ("invalid branch to/from %s structured block", kind);
12080 gsi_replace (gsi_p, gimple_build_nop (), false);
12081 return true;
12084 /* Pass 1: Create a minimal tree of structured blocks, and record
12085 where each label is found. */
12087 static tree
12088 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12089 struct walk_stmt_info *wi)
12091 gimple context = (gimple) wi->info;
12092 gimple inner_context;
12093 gimple stmt = gsi_stmt (*gsi_p);
12095 *handled_ops_p = true;
12097 switch (gimple_code (stmt))
12099 WALK_SUBSTMTS;
12101 case GIMPLE_OMP_PARALLEL:
12102 case GIMPLE_OMP_TASK:
12103 case GIMPLE_OMP_SECTIONS:
12104 case GIMPLE_OMP_SINGLE:
12105 case GIMPLE_OMP_SECTION:
12106 case GIMPLE_OMP_MASTER:
12107 case GIMPLE_OMP_ORDERED:
12108 case GIMPLE_OMP_CRITICAL:
12109 case GIMPLE_OMP_TARGET:
12110 case GIMPLE_OMP_TEAMS:
12111 case GIMPLE_OMP_TASKGROUP:
12112 /* The minimal context here is just the current OMP construct. */
12113 inner_context = stmt;
12114 wi->info = inner_context;
12115 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12116 wi->info = context;
12117 break;
12119 case GIMPLE_OMP_FOR:
12120 inner_context = stmt;
12121 wi->info = inner_context;
12122 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12123 walk them. */
12124 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12125 diagnose_sb_1, NULL, wi);
12126 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12127 wi->info = context;
12128 break;
12130 case GIMPLE_LABEL:
12131 splay_tree_insert (all_labels,
12132 (splay_tree_key) gimple_label_label (
12133 as_a <glabel *> (stmt)),
12134 (splay_tree_value) context);
12135 break;
12137 default:
12138 break;
12141 return NULL_TREE;
12144 /* Pass 2: Check each branch and see if its context differs from that of
12145 the destination label's context. */
12147 static tree
12148 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12149 struct walk_stmt_info *wi)
12151 gimple context = (gimple) wi->info;
12152 splay_tree_node n;
12153 gimple stmt = gsi_stmt (*gsi_p);
12155 *handled_ops_p = true;
12157 switch (gimple_code (stmt))
12159 WALK_SUBSTMTS;
12161 case GIMPLE_OMP_PARALLEL:
12162 case GIMPLE_OMP_TASK:
12163 case GIMPLE_OMP_SECTIONS:
12164 case GIMPLE_OMP_SINGLE:
12165 case GIMPLE_OMP_SECTION:
12166 case GIMPLE_OMP_MASTER:
12167 case GIMPLE_OMP_ORDERED:
12168 case GIMPLE_OMP_CRITICAL:
12169 case GIMPLE_OMP_TARGET:
12170 case GIMPLE_OMP_TEAMS:
12171 case GIMPLE_OMP_TASKGROUP:
12172 wi->info = stmt;
12173 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12174 wi->info = context;
12175 break;
12177 case GIMPLE_OMP_FOR:
12178 wi->info = stmt;
12179 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12180 walk them. */
12181 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12182 diagnose_sb_2, NULL, wi);
12183 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12184 wi->info = context;
12185 break;
12187 case GIMPLE_COND:
12189 gcond *cond_stmt = as_a <gcond *> (stmt);
12190 tree lab = gimple_cond_true_label (cond_stmt);
12191 if (lab)
12193 n = splay_tree_lookup (all_labels,
12194 (splay_tree_key) lab);
12195 diagnose_sb_0 (gsi_p, context,
12196 n ? (gimple) n->value : NULL);
12198 lab = gimple_cond_false_label (cond_stmt);
12199 if (lab)
12201 n = splay_tree_lookup (all_labels,
12202 (splay_tree_key) lab);
12203 diagnose_sb_0 (gsi_p, context,
12204 n ? (gimple) n->value : NULL);
12207 break;
12209 case GIMPLE_GOTO:
12211 tree lab = gimple_goto_dest (stmt);
12212 if (TREE_CODE (lab) != LABEL_DECL)
12213 break;
12215 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12216 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
12218 break;
12220 case GIMPLE_SWITCH:
12222 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12223 unsigned int i;
12224 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12226 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12227 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12228 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
12229 break;
12232 break;
12234 case GIMPLE_RETURN:
12235 diagnose_sb_0 (gsi_p, context, NULL);
12236 break;
12238 default:
12239 break;
12242 return NULL_TREE;
12245 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12246 GIMPLE_* codes. */
12247 bool
12248 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12249 int *region_idx)
12251 gimple last = last_stmt (bb);
12252 enum gimple_code code = gimple_code (last);
12253 struct omp_region *cur_region = *region;
12254 bool fallthru = false;
12256 switch (code)
12258 case GIMPLE_OMP_PARALLEL:
12259 case GIMPLE_OMP_TASK:
12260 case GIMPLE_OMP_FOR:
12261 case GIMPLE_OMP_SINGLE:
12262 case GIMPLE_OMP_TEAMS:
12263 case GIMPLE_OMP_MASTER:
12264 case GIMPLE_OMP_TASKGROUP:
12265 case GIMPLE_OMP_ORDERED:
12266 case GIMPLE_OMP_CRITICAL:
12267 case GIMPLE_OMP_SECTION:
12268 cur_region = new_omp_region (bb, code, cur_region);
12269 fallthru = true;
12270 break;
12272 case GIMPLE_OMP_TARGET:
12273 cur_region = new_omp_region (bb, code, cur_region);
12274 fallthru = true;
12275 switch (gimple_omp_target_kind (last))
12277 case GF_OMP_TARGET_KIND_REGION:
12278 case GF_OMP_TARGET_KIND_DATA:
12279 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12280 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12281 case GF_OMP_TARGET_KIND_OACC_DATA:
12282 break;
12283 case GF_OMP_TARGET_KIND_UPDATE:
12284 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12285 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12286 cur_region = cur_region->outer;
12287 break;
12288 default:
12289 gcc_unreachable ();
12291 break;
12293 case GIMPLE_OMP_SECTIONS:
12294 cur_region = new_omp_region (bb, code, cur_region);
12295 fallthru = true;
12296 break;
12298 case GIMPLE_OMP_SECTIONS_SWITCH:
12299 fallthru = false;
12300 break;
12302 case GIMPLE_OMP_ATOMIC_LOAD:
12303 case GIMPLE_OMP_ATOMIC_STORE:
12304 fallthru = true;
12305 break;
12307 case GIMPLE_OMP_RETURN:
12308 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12309 somewhere other than the next block. This will be
12310 created later. */
12311 cur_region->exit = bb;
12312 if (cur_region->type == GIMPLE_OMP_TASK)
12313 /* Add an edge corresponding to not scheduling the task
12314 immediately. */
12315 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
12316 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12317 cur_region = cur_region->outer;
12318 break;
12320 case GIMPLE_OMP_CONTINUE:
12321 cur_region->cont = bb;
12322 switch (cur_region->type)
12324 case GIMPLE_OMP_FOR:
12325 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12326 succs edges as abnormal to prevent splitting
12327 them. */
12328 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12329 /* Make the loopback edge. */
12330 make_edge (bb, single_succ (cur_region->entry),
12331 EDGE_ABNORMAL);
12333 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12334 corresponds to the case that the body of the loop
12335 is not executed at all. */
12336 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12337 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12338 fallthru = false;
12339 break;
12341 case GIMPLE_OMP_SECTIONS:
12342 /* Wire up the edges into and out of the nested sections. */
12344 basic_block switch_bb = single_succ (cur_region->entry);
12346 struct omp_region *i;
12347 for (i = cur_region->inner; i ; i = i->next)
12349 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12350 make_edge (switch_bb, i->entry, 0);
12351 make_edge (i->exit, bb, EDGE_FALLTHRU);
12354 /* Make the loopback edge to the block with
12355 GIMPLE_OMP_SECTIONS_SWITCH. */
12356 make_edge (bb, switch_bb, 0);
12358 /* Make the edge from the switch to exit. */
12359 make_edge (switch_bb, bb->next_bb, 0);
12360 fallthru = false;
12362 break;
12364 case GIMPLE_OMP_TASK:
12365 fallthru = true;
12366 break;
12368 default:
12369 gcc_unreachable ();
12371 break;
12373 default:
12374 gcc_unreachable ();
12377 if (*region != cur_region)
12379 *region = cur_region;
12380 if (cur_region)
12381 *region_idx = cur_region->entry->index;
12382 else
12383 *region_idx = 0;
12386 return fallthru;
12389 static unsigned int
12390 diagnose_omp_structured_block_errors (void)
12392 struct walk_stmt_info wi;
12393 gimple_seq body = gimple_body (current_function_decl);
12395 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12397 memset (&wi, 0, sizeof (wi));
12398 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12400 memset (&wi, 0, sizeof (wi));
12401 wi.want_locations = true;
12402 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12404 gimple_set_body (current_function_decl, body);
12406 splay_tree_delete (all_labels);
12407 all_labels = NULL;
12409 return 0;
12412 namespace {
12414 const pass_data pass_data_diagnose_omp_blocks =
12416 GIMPLE_PASS, /* type */
12417 "*diagnose_omp_blocks", /* name */
12418 OPTGROUP_NONE, /* optinfo_flags */
12419 TV_NONE, /* tv_id */
12420 PROP_gimple_any, /* properties_required */
12421 0, /* properties_provided */
12422 0, /* properties_destroyed */
12423 0, /* todo_flags_start */
12424 0, /* todo_flags_finish */
12427 class pass_diagnose_omp_blocks : public gimple_opt_pass
12429 public:
12430 pass_diagnose_omp_blocks (gcc::context *ctxt)
12431 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12434 /* opt_pass methods: */
12435 virtual bool gate (function *)
12437 return flag_cilkplus || flag_openacc || flag_openmp;
12439 virtual unsigned int execute (function *)
12441 return diagnose_omp_structured_block_errors ();
12444 }; // class pass_diagnose_omp_blocks
12446 } // anon namespace
12448 gimple_opt_pass *
12449 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12451 return new pass_diagnose_omp_blocks (ctxt);
12454 /* SIMD clone supporting code. */
12456 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12457 of arguments to reserve space for. */
12459 static struct cgraph_simd_clone *
12460 simd_clone_struct_alloc (int nargs)
12462 struct cgraph_simd_clone *clone_info;
12463 size_t len = (sizeof (struct cgraph_simd_clone)
12464 + nargs * sizeof (struct cgraph_simd_clone_arg));
12465 clone_info = (struct cgraph_simd_clone *)
12466 ggc_internal_cleared_alloc (len);
12467 return clone_info;
12470 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12472 static inline void
12473 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12474 struct cgraph_simd_clone *from)
12476 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12477 + ((from->nargs - from->inbranch)
12478 * sizeof (struct cgraph_simd_clone_arg))));
12481 /* Return vector of parameter types of function FNDECL. This uses
12482 TYPE_ARG_TYPES if available, otherwise falls back to types of
12483 DECL_ARGUMENTS types. */
12485 vec<tree>
12486 simd_clone_vector_of_formal_parm_types (tree fndecl)
12488 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12489 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12490 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12491 unsigned int i;
12492 tree arg;
12493 FOR_EACH_VEC_ELT (args, i, arg)
12494 args[i] = TREE_TYPE (args[i]);
12495 return args;
12498 /* Given a simd function in NODE, extract the simd specific
12499 information from the OMP clauses passed in CLAUSES, and return
12500 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12501 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12502 otherwise set to FALSE. */
12504 static struct cgraph_simd_clone *
12505 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12506 bool *inbranch_specified)
12508 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12509 tree t;
12510 int n;
12511 *inbranch_specified = false;
12513 n = args.length ();
12514 if (n > 0 && args.last () == void_type_node)
12515 n--;
12517 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12518 be cloned have a distinctive artificial label in addition to "omp
12519 declare simd". */
12520 bool cilk_clone
12521 = (flag_cilkplus
12522 && lookup_attribute ("cilk simd function",
12523 DECL_ATTRIBUTES (node->decl)));
12525 /* Allocate one more than needed just in case this is an in-branch
12526 clone which will require a mask argument. */
12527 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12528 clone_info->nargs = n;
12529 clone_info->cilk_elemental = cilk_clone;
12531 if (!clauses)
12533 args.release ();
12534 return clone_info;
12536 clauses = TREE_VALUE (clauses);
12537 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12538 return clone_info;
12540 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12542 switch (OMP_CLAUSE_CODE (t))
12544 case OMP_CLAUSE_INBRANCH:
12545 clone_info->inbranch = 1;
12546 *inbranch_specified = true;
12547 break;
12548 case OMP_CLAUSE_NOTINBRANCH:
12549 clone_info->inbranch = 0;
12550 *inbranch_specified = true;
12551 break;
12552 case OMP_CLAUSE_SIMDLEN:
12553 clone_info->simdlen
12554 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12555 break;
12556 case OMP_CLAUSE_LINEAR:
12558 tree decl = OMP_CLAUSE_DECL (t);
12559 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12560 int argno = TREE_INT_CST_LOW (decl);
12561 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12563 clone_info->args[argno].arg_type
12564 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12565 clone_info->args[argno].linear_step = tree_to_shwi (step);
12566 gcc_assert (clone_info->args[argno].linear_step >= 0
12567 && clone_info->args[argno].linear_step < n);
12569 else
12571 if (POINTER_TYPE_P (args[argno]))
12572 step = fold_convert (ssizetype, step);
12573 if (!tree_fits_shwi_p (step))
12575 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12576 "ignoring large linear step");
12577 args.release ();
12578 return NULL;
12580 else if (integer_zerop (step))
12582 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12583 "ignoring zero linear step");
12584 args.release ();
12585 return NULL;
12587 else
12589 clone_info->args[argno].arg_type
12590 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12591 clone_info->args[argno].linear_step = tree_to_shwi (step);
12594 break;
12596 case OMP_CLAUSE_UNIFORM:
12598 tree decl = OMP_CLAUSE_DECL (t);
12599 int argno = tree_to_uhwi (decl);
12600 clone_info->args[argno].arg_type
12601 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12602 break;
12604 case OMP_CLAUSE_ALIGNED:
12606 tree decl = OMP_CLAUSE_DECL (t);
12607 int argno = tree_to_uhwi (decl);
12608 clone_info->args[argno].alignment
12609 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12610 break;
12612 default:
12613 break;
12616 args.release ();
12617 return clone_info;
12620 /* Given a SIMD clone in NODE, calculate the characteristic data
12621 type and return the coresponding type. The characteristic data
12622 type is computed as described in the Intel Vector ABI. */
12624 static tree
12625 simd_clone_compute_base_data_type (struct cgraph_node *node,
12626 struct cgraph_simd_clone *clone_info)
12628 tree type = integer_type_node;
12629 tree fndecl = node->decl;
12631 /* a) For non-void function, the characteristic data type is the
12632 return type. */
12633 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12634 type = TREE_TYPE (TREE_TYPE (fndecl));
12636 /* b) If the function has any non-uniform, non-linear parameters,
12637 then the characteristic data type is the type of the first
12638 such parameter. */
12639 else
12641 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12642 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12643 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12645 type = map[i];
12646 break;
12648 map.release ();
12651 /* c) If the characteristic data type determined by a) or b) above
12652 is struct, union, or class type which is pass-by-value (except
12653 for the type that maps to the built-in complex data type), the
12654 characteristic data type is int. */
12655 if (RECORD_OR_UNION_TYPE_P (type)
12656 && !aggregate_value_p (type, NULL)
12657 && TREE_CODE (type) != COMPLEX_TYPE)
12658 return integer_type_node;
12660 /* d) If none of the above three classes is applicable, the
12661 characteristic data type is int. */
12663 return type;
12665 /* e) For Intel Xeon Phi native and offload compilation, if the
12666 resulting characteristic data type is 8-bit or 16-bit integer
12667 data type, the characteristic data type is int. */
12668 /* Well, we don't handle Xeon Phi yet. */
12671 static tree
12672 simd_clone_mangle (struct cgraph_node *node,
12673 struct cgraph_simd_clone *clone_info)
12675 char vecsize_mangle = clone_info->vecsize_mangle;
12676 char mask = clone_info->inbranch ? 'M' : 'N';
12677 unsigned int simdlen = clone_info->simdlen;
12678 unsigned int n;
12679 pretty_printer pp;
12681 gcc_assert (vecsize_mangle && simdlen);
12683 pp_string (&pp, "_ZGV");
12684 pp_character (&pp, vecsize_mangle);
12685 pp_character (&pp, mask);
12686 pp_decimal_int (&pp, simdlen);
12688 for (n = 0; n < clone_info->nargs; ++n)
12690 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12692 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12693 pp_character (&pp, 'u');
12694 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12696 gcc_assert (arg.linear_step != 0);
12697 pp_character (&pp, 'l');
12698 if (arg.linear_step > 1)
12699 pp_unsigned_wide_integer (&pp, arg.linear_step);
12700 else if (arg.linear_step < 0)
12702 pp_character (&pp, 'n');
12703 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12704 arg.linear_step));
12707 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12709 pp_character (&pp, 's');
12710 pp_unsigned_wide_integer (&pp, arg.linear_step);
12712 else
12713 pp_character (&pp, 'v');
12714 if (arg.alignment)
12716 pp_character (&pp, 'a');
12717 pp_decimal_int (&pp, arg.alignment);
12721 pp_underscore (&pp);
12722 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12723 if (*str == '*')
12724 ++str;
12725 pp_string (&pp, str);
12726 str = pp_formatted_text (&pp);
12728 /* If there already is a SIMD clone with the same mangled name, don't
12729 add another one. This can happen e.g. for
12730 #pragma omp declare simd
12731 #pragma omp declare simd simdlen(8)
12732 int foo (int, int);
12733 if the simdlen is assumed to be 8 for the first one, etc. */
12734 for (struct cgraph_node *clone = node->simd_clones; clone;
12735 clone = clone->simdclone->next_clone)
12736 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12737 str) == 0)
12738 return NULL_TREE;
12740 return get_identifier (str);
12743 /* Create a simd clone of OLD_NODE and return it. */
12745 static struct cgraph_node *
12746 simd_clone_create (struct cgraph_node *old_node)
12748 struct cgraph_node *new_node;
12749 if (old_node->definition)
12751 if (!old_node->has_gimple_body_p ())
12752 return NULL;
12753 old_node->get_body ();
12754 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12755 false, NULL, NULL,
12756 "simdclone");
12758 else
12760 tree old_decl = old_node->decl;
12761 tree new_decl = copy_node (old_node->decl);
12762 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12763 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12764 SET_DECL_RTL (new_decl, NULL);
12765 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12766 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
12767 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
12768 symtab->call_cgraph_insertion_hooks (new_node);
12770 if (new_node == NULL)
12771 return new_node;
12773 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12775 /* The function cgraph_function_versioning () will force the new
12776 symbol local. Undo this, and inherit external visability from
12777 the old node. */
12778 new_node->local.local = old_node->local.local;
12779 new_node->externally_visible = old_node->externally_visible;
12781 return new_node;
12784 /* Adjust the return type of the given function to its appropriate
12785 vector counterpart. Returns a simd array to be used throughout the
12786 function as a return value. */
12788 static tree
12789 simd_clone_adjust_return_type (struct cgraph_node *node)
12791 tree fndecl = node->decl;
12792 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12793 unsigned int veclen;
12794 tree t;
12796 /* Adjust the function return type. */
12797 if (orig_rettype == void_type_node)
12798 return NULL_TREE;
12799 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
12800 t = TREE_TYPE (TREE_TYPE (fndecl));
12801 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
12802 veclen = node->simdclone->vecsize_int;
12803 else
12804 veclen = node->simdclone->vecsize_float;
12805 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
12806 if (veclen > node->simdclone->simdlen)
12807 veclen = node->simdclone->simdlen;
12808 if (POINTER_TYPE_P (t))
12809 t = pointer_sized_int_node;
12810 if (veclen == node->simdclone->simdlen)
12811 t = build_vector_type (t, node->simdclone->simdlen);
12812 else
12814 t = build_vector_type (t, veclen);
12815 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
12817 TREE_TYPE (TREE_TYPE (fndecl)) = t;
12818 if (!node->definition)
12819 return NULL_TREE;
12821 t = DECL_RESULT (fndecl);
12822 /* Adjust the DECL_RESULT. */
12823 gcc_assert (TREE_TYPE (t) != void_type_node);
12824 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12825 relayout_decl (t);
12827 tree atype = build_array_type_nelts (orig_rettype,
12828 node->simdclone->simdlen);
12829 if (veclen != node->simdclone->simdlen)
12830 return build1 (VIEW_CONVERT_EXPR, atype, t);
12832 /* Set up a SIMD array to use as the return value. */
12833 tree retval = create_tmp_var_raw (atype, "retval");
12834 gimple_add_tmp_var (retval);
12835 return retval;
12838 /* Each vector argument has a corresponding array to be used locally
12839 as part of the eventual loop. Create such temporary array and
12840 return it.
12842 PREFIX is the prefix to be used for the temporary.
12844 TYPE is the inner element type.
12846 SIMDLEN is the number of elements. */
12848 static tree
12849 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12851 tree atype = build_array_type_nelts (type, simdlen);
12852 tree avar = create_tmp_var_raw (atype, prefix);
12853 gimple_add_tmp_var (avar);
12854 return avar;
12857 /* Modify the function argument types to their corresponding vector
12858 counterparts if appropriate. Also, create one array for each simd
12859 argument to be used locally when using the function arguments as
12860 part of the loop.
12862 NODE is the function whose arguments are to be adjusted.
12864 Returns an adjustment vector that will be filled describing how the
12865 argument types will be adjusted. */
12867 static ipa_parm_adjustment_vec
12868 simd_clone_adjust_argument_types (struct cgraph_node *node)
12870 vec<tree> args;
12871 ipa_parm_adjustment_vec adjustments;
12873 if (node->definition)
12874 args = ipa_get_vector_of_formal_parms (node->decl);
12875 else
12876 args = simd_clone_vector_of_formal_parm_types (node->decl);
12877 adjustments.create (args.length ());
12878 unsigned i, j, veclen;
12879 struct ipa_parm_adjustment adj;
12880 for (i = 0; i < node->simdclone->nargs; ++i)
12882 memset (&adj, 0, sizeof (adj));
12883 tree parm = args[i];
12884 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12885 adj.base_index = i;
12886 adj.base = parm;
12888 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12889 node->simdclone->args[i].orig_type = parm_type;
12891 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12893 /* No adjustment necessary for scalar arguments. */
12894 adj.op = IPA_PARM_OP_COPY;
12896 else
12898 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12899 veclen = node->simdclone->vecsize_int;
12900 else
12901 veclen = node->simdclone->vecsize_float;
12902 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12903 if (veclen > node->simdclone->simdlen)
12904 veclen = node->simdclone->simdlen;
12905 adj.arg_prefix = "simd";
12906 if (POINTER_TYPE_P (parm_type))
12907 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12908 else
12909 adj.type = build_vector_type (parm_type, veclen);
12910 node->simdclone->args[i].vector_type = adj.type;
12911 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12913 adjustments.safe_push (adj);
12914 if (j == veclen)
12916 memset (&adj, 0, sizeof (adj));
12917 adj.op = IPA_PARM_OP_NEW;
12918 adj.arg_prefix = "simd";
12919 adj.base_index = i;
12920 adj.type = node->simdclone->args[i].vector_type;
12924 if (node->definition)
12925 node->simdclone->args[i].simd_array
12926 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12927 parm_type, node->simdclone->simdlen);
12929 adjustments.safe_push (adj);
12932 if (node->simdclone->inbranch)
12934 tree base_type
12935 = simd_clone_compute_base_data_type (node->simdclone->origin,
12936 node->simdclone);
12938 memset (&adj, 0, sizeof (adj));
12939 adj.op = IPA_PARM_OP_NEW;
12940 adj.arg_prefix = "mask";
12942 adj.base_index = i;
12943 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12944 veclen = node->simdclone->vecsize_int;
12945 else
12946 veclen = node->simdclone->vecsize_float;
12947 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12948 if (veclen > node->simdclone->simdlen)
12949 veclen = node->simdclone->simdlen;
12950 if (POINTER_TYPE_P (base_type))
12951 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12952 else
12953 adj.type = build_vector_type (base_type, veclen);
12954 adjustments.safe_push (adj);
12956 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12957 adjustments.safe_push (adj);
12959 /* We have previously allocated one extra entry for the mask. Use
12960 it and fill it. */
12961 struct cgraph_simd_clone *sc = node->simdclone;
12962 sc->nargs++;
12963 if (node->definition)
12965 sc->args[i].orig_arg
12966 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12967 sc->args[i].simd_array
12968 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12970 sc->args[i].orig_type = base_type;
12971 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12974 if (node->definition)
12975 ipa_modify_formal_parameters (node->decl, adjustments);
12976 else
12978 tree new_arg_types = NULL_TREE, new_reversed;
12979 bool last_parm_void = false;
12980 if (args.length () > 0 && args.last () == void_type_node)
12981 last_parm_void = true;
12983 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12984 j = adjustments.length ();
12985 for (i = 0; i < j; i++)
12987 struct ipa_parm_adjustment *adj = &adjustments[i];
12988 tree ptype;
12989 if (adj->op == IPA_PARM_OP_COPY)
12990 ptype = args[adj->base_index];
12991 else
12992 ptype = adj->type;
12993 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12995 new_reversed = nreverse (new_arg_types);
12996 if (last_parm_void)
12998 if (new_reversed)
12999 TREE_CHAIN (new_arg_types) = void_list_node;
13000 else
13001 new_reversed = void_list_node;
13004 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
13005 TYPE_ARG_TYPES (new_type) = new_reversed;
13006 TREE_TYPE (node->decl) = new_type;
13008 adjustments.release ();
13010 args.release ();
13011 return adjustments;
13014 /* Initialize and copy the function arguments in NODE to their
13015 corresponding local simd arrays. Returns a fresh gimple_seq with
13016 the instruction sequence generated. */
13018 static gimple_seq
13019 simd_clone_init_simd_arrays (struct cgraph_node *node,
13020 ipa_parm_adjustment_vec adjustments)
13022 gimple_seq seq = NULL;
13023 unsigned i = 0, j = 0, k;
13025 for (tree arg = DECL_ARGUMENTS (node->decl);
13026 arg;
13027 arg = DECL_CHAIN (arg), i++, j++)
13029 if (adjustments[j].op == IPA_PARM_OP_COPY)
13030 continue;
13032 node->simdclone->args[i].vector_arg = arg;
13034 tree array = node->simdclone->args[i].simd_array;
13035 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13037 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13038 tree ptr = build_fold_addr_expr (array);
13039 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13040 build_int_cst (ptype, 0));
13041 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13042 gimplify_and_add (t, &seq);
13044 else
13046 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13047 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13048 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13050 tree ptr = build_fold_addr_expr (array);
13051 int elemsize;
13052 if (k)
13054 arg = DECL_CHAIN (arg);
13055 j++;
13057 elemsize
13058 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13059 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13060 build_int_cst (ptype, k * elemsize));
13061 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13062 gimplify_and_add (t, &seq);
13066 return seq;
13069 /* Callback info for ipa_simd_modify_stmt_ops below. */
13071 struct modify_stmt_info {
13072 ipa_parm_adjustment_vec adjustments;
13073 gimple stmt;
13074 /* True if the parent statement was modified by
13075 ipa_simd_modify_stmt_ops. */
13076 bool modified;
13079 /* Callback for walk_gimple_op.
13081 Adjust operands from a given statement as specified in the
13082 adjustments vector in the callback data. */
13084 static tree
13085 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13087 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13088 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13089 tree *orig_tp = tp;
13090 if (TREE_CODE (*tp) == ADDR_EXPR)
13091 tp = &TREE_OPERAND (*tp, 0);
13092 struct ipa_parm_adjustment *cand = NULL;
13093 if (TREE_CODE (*tp) == PARM_DECL)
13094 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13095 else
13097 if (TYPE_P (*tp))
13098 *walk_subtrees = 0;
13101 tree repl = NULL_TREE;
13102 if (cand)
13103 repl = unshare_expr (cand->new_decl);
13104 else
13106 if (tp != orig_tp)
13108 *walk_subtrees = 0;
13109 bool modified = info->modified;
13110 info->modified = false;
13111 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13112 if (!info->modified)
13114 info->modified = modified;
13115 return NULL_TREE;
13117 info->modified = modified;
13118 repl = *tp;
13120 else
13121 return NULL_TREE;
13124 if (tp != orig_tp)
13126 repl = build_fold_addr_expr (repl);
13127 gimple stmt;
13128 if (is_gimple_debug (info->stmt))
13130 tree vexpr = make_node (DEBUG_EXPR_DECL);
13131 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13132 DECL_ARTIFICIAL (vexpr) = 1;
13133 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13134 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13135 repl = vexpr;
13137 else
13139 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13140 repl = gimple_assign_lhs (stmt);
13142 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13143 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13144 *orig_tp = repl;
13146 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13148 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13149 *tp = vce;
13151 else
13152 *tp = repl;
13154 info->modified = true;
13155 return NULL_TREE;
13158 /* Traverse the function body and perform all modifications as
13159 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13160 modified such that the replacement/reduction value will now be an
13161 offset into the corresponding simd_array.
13163 This function will replace all function argument uses with their
13164 corresponding simd array elements, and ajust the return values
13165 accordingly. */
13167 static void
13168 ipa_simd_modify_function_body (struct cgraph_node *node,
13169 ipa_parm_adjustment_vec adjustments,
13170 tree retval_array, tree iter)
13172 basic_block bb;
13173 unsigned int i, j, l;
13175 /* Re-use the adjustments array, but this time use it to replace
13176 every function argument use to an offset into the corresponding
13177 simd_array. */
13178 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13180 if (!node->simdclone->args[i].vector_arg)
13181 continue;
13183 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13184 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13185 adjustments[j].new_decl
13186 = build4 (ARRAY_REF,
13187 basetype,
13188 node->simdclone->args[i].simd_array,
13189 iter,
13190 NULL_TREE, NULL_TREE);
13191 if (adjustments[j].op == IPA_PARM_OP_NONE
13192 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13193 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13196 l = adjustments.length ();
13197 for (i = 1; i < num_ssa_names; i++)
13199 tree name = ssa_name (i);
13200 if (name
13201 && SSA_NAME_VAR (name)
13202 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13204 for (j = 0; j < l; j++)
13205 if (SSA_NAME_VAR (name) == adjustments[j].base
13206 && adjustments[j].new_decl)
13208 tree base_var;
13209 if (adjustments[j].new_ssa_base == NULL_TREE)
13211 base_var
13212 = copy_var_decl (adjustments[j].base,
13213 DECL_NAME (adjustments[j].base),
13214 TREE_TYPE (adjustments[j].base));
13215 adjustments[j].new_ssa_base = base_var;
13217 else
13218 base_var = adjustments[j].new_ssa_base;
13219 if (SSA_NAME_IS_DEFAULT_DEF (name))
13221 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13222 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13223 tree new_decl = unshare_expr (adjustments[j].new_decl);
13224 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13225 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13226 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13227 gimple stmt = gimple_build_assign (name, new_decl);
13228 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13230 else
13231 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13236 struct modify_stmt_info info;
13237 info.adjustments = adjustments;
13239 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13241 gimple_stmt_iterator gsi;
13243 gsi = gsi_start_bb (bb);
13244 while (!gsi_end_p (gsi))
13246 gimple stmt = gsi_stmt (gsi);
13247 info.stmt = stmt;
13248 struct walk_stmt_info wi;
13250 memset (&wi, 0, sizeof (wi));
13251 info.modified = false;
13252 wi.info = &info;
13253 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13255 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13257 tree retval = gimple_return_retval (return_stmt);
13258 if (!retval)
13260 gsi_remove (&gsi, true);
13261 continue;
13264 /* Replace `return foo' with `retval_array[iter] = foo'. */
13265 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13266 retval_array, iter, NULL, NULL);
13267 stmt = gimple_build_assign (ref, retval);
13268 gsi_replace (&gsi, stmt, true);
13269 info.modified = true;
13272 if (info.modified)
13274 update_stmt (stmt);
13275 if (maybe_clean_eh_stmt (stmt))
13276 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13278 gsi_next (&gsi);
13283 /* Adjust the argument types in NODE to their appropriate vector
13284 counterparts. */
13286 static void
13287 simd_clone_adjust (struct cgraph_node *node)
13289 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13291 targetm.simd_clone.adjust (node);
13293 tree retval = simd_clone_adjust_return_type (node);
13294 ipa_parm_adjustment_vec adjustments
13295 = simd_clone_adjust_argument_types (node);
13297 push_gimplify_context ();
13299 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13301 /* Adjust all uses of vector arguments accordingly. Adjust all
13302 return values accordingly. */
13303 tree iter = create_tmp_var (unsigned_type_node, "iter");
13304 tree iter1 = make_ssa_name (iter);
13305 tree iter2 = make_ssa_name (iter);
13306 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13308 /* Initialize the iteration variable. */
13309 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13310 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13311 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13312 /* Insert the SIMD array and iv initialization at function
13313 entry. */
13314 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13316 pop_gimplify_context (NULL);
13318 /* Create a new BB right before the original exit BB, to hold the
13319 iteration increment and the condition/branch. */
13320 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13321 basic_block incr_bb = create_empty_bb (orig_exit);
13322 add_bb_to_loop (incr_bb, body_bb->loop_father);
13323 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13324 flag. Set it now to be a FALLTHRU_EDGE. */
13325 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13326 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13327 for (unsigned i = 0;
13328 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13330 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13331 redirect_edge_succ (e, incr_bb);
13333 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13334 e->probability = REG_BR_PROB_BASE;
13335 gsi = gsi_last_bb (incr_bb);
13336 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13337 build_int_cst (unsigned_type_node, 1));
13338 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13340 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13341 struct loop *loop = alloc_loop ();
13342 cfun->has_force_vectorize_loops = true;
13343 loop->safelen = node->simdclone->simdlen;
13344 loop->force_vectorize = true;
13345 loop->header = body_bb;
13347 /* Branch around the body if the mask applies. */
13348 if (node->simdclone->inbranch)
13350 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13351 tree mask_array
13352 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13353 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13354 tree aref = build4 (ARRAY_REF,
13355 TREE_TYPE (TREE_TYPE (mask_array)),
13356 mask_array, iter1,
13357 NULL, NULL);
13358 g = gimple_build_assign (mask, aref);
13359 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13360 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13361 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13363 aref = build1 (VIEW_CONVERT_EXPR,
13364 build_nonstandard_integer_type (bitsize, 0), mask);
13365 mask = make_ssa_name (TREE_TYPE (aref));
13366 g = gimple_build_assign (mask, aref);
13367 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13370 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13371 NULL, NULL);
13372 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13373 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13374 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13377 /* Generate the condition. */
13378 g = gimple_build_cond (LT_EXPR,
13379 iter2,
13380 build_int_cst (unsigned_type_node,
13381 node->simdclone->simdlen),
13382 NULL, NULL);
13383 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13384 e = split_block (incr_bb, gsi_stmt (gsi));
13385 basic_block latch_bb = e->dest;
13386 basic_block new_exit_bb;
13387 new_exit_bb = split_block_after_labels (latch_bb)->dest;
13388 loop->latch = latch_bb;
13390 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13392 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13393 /* The successor of incr_bb is already pointing to latch_bb; just
13394 change the flags.
13395 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13396 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13398 gphi *phi = create_phi_node (iter1, body_bb);
13399 edge preheader_edge = find_edge (entry_bb, body_bb);
13400 edge latch_edge = single_succ_edge (latch_bb);
13401 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13402 UNKNOWN_LOCATION);
13403 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13405 /* Generate the new return. */
13406 gsi = gsi_last_bb (new_exit_bb);
13407 if (retval
13408 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13409 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13410 retval = TREE_OPERAND (retval, 0);
13411 else if (retval)
13413 retval = build1 (VIEW_CONVERT_EXPR,
13414 TREE_TYPE (TREE_TYPE (node->decl)),
13415 retval);
13416 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13417 false, GSI_CONTINUE_LINKING);
13419 g = gimple_build_return (retval);
13420 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13422 /* Handle aligned clauses by replacing default defs of the aligned
13423 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13424 lhs. Handle linear by adding PHIs. */
13425 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13426 if (node->simdclone->args[i].alignment
13427 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13428 && (node->simdclone->args[i].alignment
13429 & (node->simdclone->args[i].alignment - 1)) == 0
13430 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13431 == POINTER_TYPE)
13433 unsigned int alignment = node->simdclone->args[i].alignment;
13434 tree orig_arg = node->simdclone->args[i].orig_arg;
13435 tree def = ssa_default_def (cfun, orig_arg);
13436 if (def && !has_zero_uses (def))
13438 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13439 gimple_seq seq = NULL;
13440 bool need_cvt = false;
13441 gcall *call
13442 = gimple_build_call (fn, 2, def, size_int (alignment));
13443 g = call;
13444 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13445 ptr_type_node))
13446 need_cvt = true;
13447 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13448 gimple_call_set_lhs (g, t);
13449 gimple_seq_add_stmt_without_update (&seq, g);
13450 if (need_cvt)
13452 t = make_ssa_name (orig_arg);
13453 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13454 gimple_seq_add_stmt_without_update (&seq, g);
13456 gsi_insert_seq_on_edge_immediate
13457 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13459 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13460 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13461 entry_bb);
13462 node->create_edge (cgraph_node::get_create (fn),
13463 call, entry_bb->count, freq);
13465 imm_use_iterator iter;
13466 use_operand_p use_p;
13467 gimple use_stmt;
13468 tree repl = gimple_get_lhs (g);
13469 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13470 if (is_gimple_debug (use_stmt) || use_stmt == call)
13471 continue;
13472 else
13473 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13474 SET_USE (use_p, repl);
13477 else if (node->simdclone->args[i].arg_type
13478 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13480 tree orig_arg = node->simdclone->args[i].orig_arg;
13481 tree def = ssa_default_def (cfun, orig_arg);
13482 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13483 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13484 if (def && !has_zero_uses (def))
13486 iter1 = make_ssa_name (orig_arg);
13487 iter2 = make_ssa_name (orig_arg);
13488 phi = create_phi_node (iter1, body_bb);
13489 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13490 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13491 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13492 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13493 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13494 ? TREE_TYPE (orig_arg) : sizetype;
13495 tree addcst
13496 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13497 g = gimple_build_assign (iter2, code, iter1, addcst);
13498 gsi = gsi_last_bb (incr_bb);
13499 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13501 imm_use_iterator iter;
13502 use_operand_p use_p;
13503 gimple use_stmt;
13504 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13505 if (use_stmt == phi)
13506 continue;
13507 else
13508 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13509 SET_USE (use_p, iter1);
13513 calculate_dominance_info (CDI_DOMINATORS);
13514 add_loop (loop, loop->header->loop_father);
13515 update_ssa (TODO_update_ssa);
13517 pop_cfun ();
13520 /* If the function in NODE is tagged as an elemental SIMD function,
13521 create the appropriate SIMD clones. */
13523 static void
13524 expand_simd_clones (struct cgraph_node *node)
13526 tree attr = lookup_attribute ("omp declare simd",
13527 DECL_ATTRIBUTES (node->decl));
13528 if (attr == NULL_TREE
13529 || node->global.inlined_to
13530 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13531 return;
13533 /* Ignore
13534 #pragma omp declare simd
13535 extern int foo ();
13536 in C, there we don't know the argument types at all. */
13537 if (!node->definition
13538 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13539 return;
13543 /* Start with parsing the "omp declare simd" attribute(s). */
13544 bool inbranch_clause_specified;
13545 struct cgraph_simd_clone *clone_info
13546 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13547 &inbranch_clause_specified);
13548 if (clone_info == NULL)
13549 continue;
13551 int orig_simdlen = clone_info->simdlen;
13552 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13553 /* The target can return 0 (no simd clones should be created),
13554 1 (just one ISA of simd clones should be created) or higher
13555 count of ISA variants. In that case, clone_info is initialized
13556 for the first ISA variant. */
13557 int count
13558 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13559 base_type, 0);
13560 if (count == 0)
13561 continue;
13563 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13564 also create one inbranch and one !inbranch clone of it. */
13565 for (int i = 0; i < count * 2; i++)
13567 struct cgraph_simd_clone *clone = clone_info;
13568 if (inbranch_clause_specified && (i & 1) != 0)
13569 continue;
13571 if (i != 0)
13573 clone = simd_clone_struct_alloc (clone_info->nargs
13574 + ((i & 1) != 0));
13575 simd_clone_struct_copy (clone, clone_info);
13576 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13577 and simd_clone_adjust_argument_types did to the first
13578 clone's info. */
13579 clone->nargs -= clone_info->inbranch;
13580 clone->simdlen = orig_simdlen;
13581 /* And call the target hook again to get the right ISA. */
13582 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13583 base_type,
13584 i / 2);
13585 if ((i & 1) != 0)
13586 clone->inbranch = 1;
13589 /* simd_clone_mangle might fail if such a clone has been created
13590 already. */
13591 tree id = simd_clone_mangle (node, clone);
13592 if (id == NULL_TREE)
13593 continue;
13595 /* Only when we are sure we want to create the clone actually
13596 clone the function (or definitions) or create another
13597 extern FUNCTION_DECL (for prototypes without definitions). */
13598 struct cgraph_node *n = simd_clone_create (node);
13599 if (n == NULL)
13600 continue;
13602 n->simdclone = clone;
13603 clone->origin = node;
13604 clone->next_clone = NULL;
13605 if (node->simd_clones == NULL)
13607 clone->prev_clone = n;
13608 node->simd_clones = n;
13610 else
13612 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13613 clone->prev_clone->simdclone->next_clone = n;
13614 node->simd_clones->simdclone->prev_clone = n;
13616 symtab->change_decl_assembler_name (n->decl, id);
13617 /* And finally adjust the return type, parameters and for
13618 definitions also function body. */
13619 if (node->definition)
13620 simd_clone_adjust (n);
13621 else
13623 simd_clone_adjust_return_type (n);
13624 simd_clone_adjust_argument_types (n);
13628 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13631 /* Entry point for IPA simd clone creation pass. */
13633 static unsigned int
13634 ipa_omp_simd_clone (void)
13636 struct cgraph_node *node;
13637 FOR_EACH_FUNCTION (node)
13638 expand_simd_clones (node);
13639 return 0;
13642 namespace {
13644 const pass_data pass_data_omp_simd_clone =
13646 SIMPLE_IPA_PASS, /* type */
13647 "simdclone", /* name */
13648 OPTGROUP_NONE, /* optinfo_flags */
13649 TV_NONE, /* tv_id */
13650 ( PROP_ssa | PROP_cfg ), /* properties_required */
13651 0, /* properties_provided */
13652 0, /* properties_destroyed */
13653 0, /* todo_flags_start */
13654 0, /* todo_flags_finish */
13657 class pass_omp_simd_clone : public simple_ipa_opt_pass
13659 public:
13660 pass_omp_simd_clone(gcc::context *ctxt)
13661 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13664 /* opt_pass methods: */
13665 virtual bool gate (function *);
13666 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
13669 bool
13670 pass_omp_simd_clone::gate (function *)
13672 return ((flag_openmp || flag_openmp_simd
13673 || flag_cilkplus
13674 || (in_lto_p && !flag_wpa))
13675 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13678 } // anon namespace
13680 simple_ipa_opt_pass *
13681 make_pass_omp_simd_clone (gcc::context *ctxt)
13683 return new pass_omp_simd_clone (ctxt);
13686 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13687 adds their addresses and sizes to constructor-vector V_CTOR. */
13688 static void
13689 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13690 vec<constructor_elt, va_gc> *v_ctor)
13692 unsigned len = vec_safe_length (v_decls);
13693 for (unsigned i = 0; i < len; i++)
13695 tree it = (*v_decls)[i];
13696 bool is_function = TREE_CODE (it) != VAR_DECL;
13698 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13699 if (!is_function)
13700 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13701 fold_convert (const_ptr_type_node,
13702 DECL_SIZE_UNIT (it)));
13706 /* Create new symbols containing (address, size) pairs for global variables,
13707 marked with "omp declare target" attribute, as well as addresses for the
13708 functions, which are outlined offloading regions. */
13709 void
13710 omp_finish_file (void)
13712 unsigned num_funcs = vec_safe_length (offload_funcs);
13713 unsigned num_vars = vec_safe_length (offload_vars);
13715 if (num_funcs == 0 && num_vars == 0)
13716 return;
13718 if (targetm_common.have_named_sections)
13720 vec<constructor_elt, va_gc> *v_f, *v_v;
13721 vec_alloc (v_f, num_funcs);
13722 vec_alloc (v_v, num_vars * 2);
13724 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13725 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13727 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13728 num_vars * 2);
13729 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13730 num_funcs);
13731 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13732 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13733 tree ctor_v = build_constructor (vars_decl_type, v_v);
13734 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13735 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13736 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13737 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13738 get_identifier (".offload_func_table"),
13739 funcs_decl_type);
13740 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13741 get_identifier (".offload_var_table"),
13742 vars_decl_type);
13743 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13744 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13745 otherwise a joint table in a binary will contain padding between
13746 tables from multiple object files. */
13747 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13748 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13749 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13750 DECL_INITIAL (funcs_decl) = ctor_f;
13751 DECL_INITIAL (vars_decl) = ctor_v;
13752 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13753 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13755 varpool_node::finalize_decl (vars_decl);
13756 varpool_node::finalize_decl (funcs_decl);
13758 else
13760 for (unsigned i = 0; i < num_funcs; i++)
13762 tree it = (*offload_funcs)[i];
13763 targetm.record_offload_symbol (it);
13765 for (unsigned i = 0; i < num_vars; i++)
13767 tree it = (*offload_vars)[i];
13768 targetm.record_offload_symbol (it);
13773 #include "gt-omp-low.h"