[PR67828] don't unswitch on default defs of non-parms
[official-gcc.git] / gcc / omp-low.c
blobcdcf9d6d9c8477cef406a5c70c1e07c867f93ec9
1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "cfghooks.h"
30 #include "tree.h"
31 #include "gimple.h"
32 #include "rtl.h"
33 #include "ssa.h"
34 #include "alias.h"
35 #include "fold-const.h"
36 #include "stor-layout.h"
37 #include "cfganal.h"
38 #include "internal-fn.h"
39 #include "gimple-fold.h"
40 #include "gimplify.h"
41 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
43 #include "gimple-walk.h"
44 #include "tree-iterator.h"
45 #include "tree-inline.h"
46 #include "langhooks.h"
47 #include "diagnostic-core.h"
48 #include "cgraph.h"
49 #include "tree-cfg.h"
50 #include "tree-into-ssa.h"
51 #include "flags.h"
52 #include "insn-config.h"
53 #include "expmed.h"
54 #include "dojump.h"
55 #include "explow.h"
56 #include "calls.h"
57 #include "emit-rtl.h"
58 #include "varasm.h"
59 #include "stmt.h"
60 #include "expr.h"
61 #include "tree-dfa.h"
62 #include "tree-ssa.h"
63 #include "tree-pass.h"
64 #include "except.h"
65 #include "splay-tree.h"
66 #include "insn-codes.h"
67 #include "optabs.h"
68 #include "cfgloop.h"
69 #include "target.h"
70 #include "common/common-target.h"
71 #include "omp-low.h"
72 #include "gimple-low.h"
73 #include "tree-cfgcleanup.h"
74 #include "pretty-print.h"
75 #include "alloc-pool.h"
76 #include "symbol-summary.h"
77 #include "ipa-prop.h"
78 #include "tree-nested.h"
79 #include "tree-eh.h"
80 #include "cilk.h"
81 #include "context.h"
82 #include "lto-section-names.h"
83 #include "gomp-constants.h"
85 /* Lowering of OMP parallel and workshare constructs proceeds in two
86 phases. The first phase scans the function looking for OMP statements
87 and then for variables that must be replaced to satisfy data sharing
88 clauses. The second phase expands code for the constructs, as well as
89 re-gimplifying things when variables have been replaced with complex
90 expressions.
92 Final code generation is done by pass_expand_omp. The flowgraph is
93 scanned for regions which are then moved to a new
94 function, to be invoked by the thread library, or offloaded. */
96 /* OMP region information. Every parallel and workshare
97 directive is enclosed between two markers, the OMP_* directive
98 and a corresponding OMP_RETURN statement. */
100 struct omp_region
102 /* The enclosing region. */
103 struct omp_region *outer;
105 /* First child region. */
106 struct omp_region *inner;
108 /* Next peer region. */
109 struct omp_region *next;
111 /* Block containing the omp directive as its last stmt. */
112 basic_block entry;
114 /* Block containing the OMP_RETURN as its last stmt. */
115 basic_block exit;
117 /* Block containing the OMP_CONTINUE as its last stmt. */
118 basic_block cont;
120 /* If this is a combined parallel+workshare region, this is a list
121 of additional arguments needed by the combined parallel+workshare
122 library call. */
123 vec<tree, va_gc> *ws_args;
125 /* The code for the omp directive of this region. */
126 enum gimple_code type;
128 /* Schedule kind, only used for OMP_FOR type regions. */
129 enum omp_clause_schedule_kind sched_kind;
131 /* True if this is a combined parallel+workshare region. */
132 bool is_combined_parallel;
135 /* Levels of parallelism as defined by OpenACC. Increasing numbers
136 correspond to deeper loop nesting levels. */
137 #define MASK_GANG 1
138 #define MASK_WORKER 2
139 #define MASK_VECTOR 4
141 /* Context structure. Used to store information about each parallel
142 directive in the code. */
144 struct omp_context
146 /* This field must be at the beginning, as we do "inheritance": Some
147 callback functions for tree-inline.c (e.g., omp_copy_decl)
148 receive a copy_body_data pointer that is up-casted to an
149 omp_context pointer. */
150 copy_body_data cb;
152 /* The tree of contexts corresponding to the encountered constructs. */
153 struct omp_context *outer;
154 gimple *stmt;
156 /* Map variables to fields in a structure that allows communication
157 between sending and receiving threads. */
158 splay_tree field_map;
159 tree record_type;
160 tree sender_decl;
161 tree receiver_decl;
163 /* These are used just by task contexts, if task firstprivate fn is
164 needed. srecord_type is used to communicate from the thread
165 that encountered the task construct to task firstprivate fn,
166 record_type is allocated by GOMP_task, initialized by task firstprivate
167 fn and passed to the task body fn. */
168 splay_tree sfield_map;
169 tree srecord_type;
171 /* A chain of variables to add to the top-level block surrounding the
172 construct. In the case of a parallel, this is in the child function. */
173 tree block_vars;
175 /* A map of reduction pointer variables. For accelerators, each
176 reduction variable is replaced with an array. Each thread, in turn,
177 is assigned to a slot on that array. */
178 splay_tree reduction_map;
180 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
181 barriers should jump to during omplower pass. */
182 tree cancel_label;
184 /* What to do with variables with implicitly determined sharing
185 attributes. */
186 enum omp_clause_default_kind default_kind;
188 /* Nesting depth of this context. Used to beautify error messages re
189 invalid gotos. The outermost ctx is depth 1, with depth 0 being
190 reserved for the main body of the function. */
191 int depth;
193 /* True if this parallel directive is nested within another. */
194 bool is_nested;
196 /* True if this construct can be cancelled. */
197 bool cancellable;
199 /* For OpenACC loops, a mask of gang, worker and vector used at
200 levels below this one. */
201 int gwv_below;
202 /* For OpenACC loops, a mask of gang, worker and vector used at
203 this level and above. For parallel and kernels clauses, a mask
204 indicating which of num_gangs/num_workers/num_vectors was used. */
205 int gwv_this;
208 /* A structure holding the elements of:
209 for (V = N1; V cond N2; V += STEP) [...] */
211 struct omp_for_data_loop
213 tree v, n1, n2, step;
214 enum tree_code cond_code;
217 /* A structure describing the main elements of a parallel loop. */
219 struct omp_for_data
221 struct omp_for_data_loop loop;
222 tree chunk_size;
223 gomp_for *for_stmt;
224 tree pre, iter_type;
225 int collapse;
226 bool have_nowait, have_ordered;
227 enum omp_clause_schedule_kind sched_kind;
228 struct omp_for_data_loop *loops;
232 static splay_tree all_contexts;
233 static int taskreg_nesting_level;
234 static int target_nesting_level;
235 static struct omp_region *root_omp_region;
236 static bitmap task_shared_vars;
237 static vec<omp_context *> taskreg_contexts;
239 static void scan_omp (gimple_seq *, omp_context *);
240 static tree scan_omp_1_op (tree *, int *, void *);
242 #define WALK_SUBSTMTS \
243 case GIMPLE_BIND: \
244 case GIMPLE_TRY: \
245 case GIMPLE_CATCH: \
246 case GIMPLE_EH_FILTER: \
247 case GIMPLE_TRANSACTION: \
248 /* The sub-statements for these should be walked. */ \
249 *handled_ops_p = false; \
250 break;
252 /* Helper function to get the name of the array containing the partial
253 reductions for OpenACC reductions. */
254 static const char *
255 oacc_get_reduction_array_id (tree node)
257 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
258 int len = strlen ("OACC") + strlen (id);
259 char *temp_name = XALLOCAVEC (char, len + 1);
260 snprintf (temp_name, len + 1, "OACC%s", id);
261 return IDENTIFIER_POINTER (get_identifier (temp_name));
264 /* Determine the number of threads OpenACC threads used to determine the
265 size of the array of partial reductions. Currently, this is num_gangs
266 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
267 because it is independed of the device used. */
269 static tree
270 oacc_max_threads (omp_context *ctx)
272 tree nthreads, vector_length, gangs, clauses;
274 gangs = fold_convert (sizetype, integer_one_node);
275 vector_length = gangs;
277 /* The reduction clause may be nested inside a loop directive.
278 Scan for the innermost vector_length clause. */
279 for (omp_context *oc = ctx; oc; oc = oc->outer)
281 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
282 || (gimple_omp_target_kind (oc->stmt)
283 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
284 continue;
286 clauses = gimple_omp_target_clauses (oc->stmt);
288 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
289 if (vector_length)
290 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
291 sizetype,
292 OMP_CLAUSE_VECTOR_LENGTH_EXPR
293 (vector_length));
294 else
295 vector_length = fold_convert (sizetype, integer_one_node);
297 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
298 if (gangs)
299 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
300 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
301 else
302 gangs = fold_convert (sizetype, integer_one_node);
304 break;
307 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
309 return nthreads;
312 /* Holds offload tables with decls. */
313 vec<tree, va_gc> *offload_funcs, *offload_vars;
315 /* Convenience function for calling scan_omp_1_op on tree operands. */
317 static inline tree
318 scan_omp_op (tree *tp, omp_context *ctx)
320 struct walk_stmt_info wi;
322 memset (&wi, 0, sizeof (wi));
323 wi.info = ctx;
324 wi.want_locations = true;
326 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
329 static void lower_omp (gimple_seq *, omp_context *);
330 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
331 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
333 /* Find an OMP clause of type KIND within CLAUSES. */
335 tree
336 find_omp_clause (tree clauses, enum omp_clause_code kind)
338 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
339 if (OMP_CLAUSE_CODE (clauses) == kind)
340 return clauses;
342 return NULL_TREE;
345 /* Return true if CTX is for an omp parallel. */
347 static inline bool
348 is_parallel_ctx (omp_context *ctx)
350 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
354 /* Return true if CTX is for an omp task. */
356 static inline bool
357 is_task_ctx (omp_context *ctx)
359 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
363 /* Return true if CTX is for an omp parallel or omp task. */
365 static inline bool
366 is_taskreg_ctx (omp_context *ctx)
368 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
369 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
373 /* Return true if REGION is a combined parallel+workshare region. */
375 static inline bool
376 is_combined_parallel (struct omp_region *region)
378 return region->is_combined_parallel;
382 /* Extract the header elements of parallel loop FOR_STMT and store
383 them into *FD. */
385 static void
386 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
387 struct omp_for_data_loop *loops)
389 tree t, var, *collapse_iter, *collapse_count;
390 tree count = NULL_TREE, iter_type = long_integer_type_node;
391 struct omp_for_data_loop *loop;
392 int i;
393 struct omp_for_data_loop dummy_loop;
394 location_t loc = gimple_location (for_stmt);
395 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
396 bool distribute = gimple_omp_for_kind (for_stmt)
397 == GF_OMP_FOR_KIND_DISTRIBUTE;
399 fd->for_stmt = for_stmt;
400 fd->pre = NULL;
401 fd->collapse = gimple_omp_for_collapse (for_stmt);
402 if (fd->collapse > 1)
403 fd->loops = loops;
404 else
405 fd->loops = &fd->loop;
407 fd->have_nowait = distribute || simd;
408 fd->have_ordered = false;
409 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
410 fd->chunk_size = NULL_TREE;
411 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
412 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
413 collapse_iter = NULL;
414 collapse_count = NULL;
416 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
417 switch (OMP_CLAUSE_CODE (t))
419 case OMP_CLAUSE_NOWAIT:
420 fd->have_nowait = true;
421 break;
422 case OMP_CLAUSE_ORDERED:
423 fd->have_ordered = true;
424 break;
425 case OMP_CLAUSE_SCHEDULE:
426 gcc_assert (!distribute);
427 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
428 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
429 break;
430 case OMP_CLAUSE_DIST_SCHEDULE:
431 gcc_assert (distribute);
432 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
433 break;
434 case OMP_CLAUSE_COLLAPSE:
435 if (fd->collapse > 1)
437 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
438 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
440 break;
441 default:
442 break;
445 /* FIXME: for now map schedule(auto) to schedule(static).
446 There should be analysis to determine whether all iterations
447 are approximately the same amount of work (then schedule(static)
448 is best) or if it varies (then schedule(dynamic,N) is better). */
449 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
451 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
452 gcc_assert (fd->chunk_size == NULL);
454 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
455 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
456 gcc_assert (fd->chunk_size == NULL);
457 else if (fd->chunk_size == NULL)
459 /* We only need to compute a default chunk size for ordered
460 static loops and dynamic loops. */
461 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
462 || fd->have_ordered)
463 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
464 ? integer_zero_node : integer_one_node;
467 for (i = 0; i < fd->collapse; i++)
469 if (fd->collapse == 1)
470 loop = &fd->loop;
471 else if (loops != NULL)
472 loop = loops + i;
473 else
474 loop = &dummy_loop;
476 loop->v = gimple_omp_for_index (for_stmt, i);
477 gcc_assert (SSA_VAR_P (loop->v));
478 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
479 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
480 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
481 loop->n1 = gimple_omp_for_initial (for_stmt, i);
483 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
484 loop->n2 = gimple_omp_for_final (for_stmt, i);
485 switch (loop->cond_code)
487 case LT_EXPR:
488 case GT_EXPR:
489 break;
490 case NE_EXPR:
491 gcc_assert (gimple_omp_for_kind (for_stmt)
492 == GF_OMP_FOR_KIND_CILKSIMD
493 || (gimple_omp_for_kind (for_stmt)
494 == GF_OMP_FOR_KIND_CILKFOR));
495 break;
496 case LE_EXPR:
497 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
498 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
499 else
500 loop->n2 = fold_build2_loc (loc,
501 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
502 build_int_cst (TREE_TYPE (loop->n2), 1));
503 loop->cond_code = LT_EXPR;
504 break;
505 case GE_EXPR:
506 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
507 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
508 else
509 loop->n2 = fold_build2_loc (loc,
510 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
511 build_int_cst (TREE_TYPE (loop->n2), 1));
512 loop->cond_code = GT_EXPR;
513 break;
514 default:
515 gcc_unreachable ();
518 t = gimple_omp_for_incr (for_stmt, i);
519 gcc_assert (TREE_OPERAND (t, 0) == var);
520 switch (TREE_CODE (t))
522 case PLUS_EXPR:
523 loop->step = TREE_OPERAND (t, 1);
524 break;
525 case POINTER_PLUS_EXPR:
526 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
527 break;
528 case MINUS_EXPR:
529 loop->step = TREE_OPERAND (t, 1);
530 loop->step = fold_build1_loc (loc,
531 NEGATE_EXPR, TREE_TYPE (loop->step),
532 loop->step);
533 break;
534 default:
535 gcc_unreachable ();
538 if (simd
539 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
540 && !fd->have_ordered))
542 if (fd->collapse == 1)
543 iter_type = TREE_TYPE (loop->v);
544 else if (i == 0
545 || TYPE_PRECISION (iter_type)
546 < TYPE_PRECISION (TREE_TYPE (loop->v)))
547 iter_type
548 = build_nonstandard_integer_type
549 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
551 else if (iter_type != long_long_unsigned_type_node)
553 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
554 iter_type = long_long_unsigned_type_node;
555 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
556 && TYPE_PRECISION (TREE_TYPE (loop->v))
557 >= TYPE_PRECISION (iter_type))
559 tree n;
561 if (loop->cond_code == LT_EXPR)
562 n = fold_build2_loc (loc,
563 PLUS_EXPR, TREE_TYPE (loop->v),
564 loop->n2, loop->step);
565 else
566 n = loop->n1;
567 if (TREE_CODE (n) != INTEGER_CST
568 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
569 iter_type = long_long_unsigned_type_node;
571 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
572 > TYPE_PRECISION (iter_type))
574 tree n1, n2;
576 if (loop->cond_code == LT_EXPR)
578 n1 = loop->n1;
579 n2 = fold_build2_loc (loc,
580 PLUS_EXPR, TREE_TYPE (loop->v),
581 loop->n2, loop->step);
583 else
585 n1 = fold_build2_loc (loc,
586 MINUS_EXPR, TREE_TYPE (loop->v),
587 loop->n2, loop->step);
588 n2 = loop->n1;
590 if (TREE_CODE (n1) != INTEGER_CST
591 || TREE_CODE (n2) != INTEGER_CST
592 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
593 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
594 iter_type = long_long_unsigned_type_node;
598 if (collapse_count && *collapse_count == NULL)
600 t = fold_binary (loop->cond_code, boolean_type_node,
601 fold_convert (TREE_TYPE (loop->v), loop->n1),
602 fold_convert (TREE_TYPE (loop->v), loop->n2));
603 if (t && integer_zerop (t))
604 count = build_zero_cst (long_long_unsigned_type_node);
605 else if ((i == 0 || count != NULL_TREE)
606 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
607 && TREE_CONSTANT (loop->n1)
608 && TREE_CONSTANT (loop->n2)
609 && TREE_CODE (loop->step) == INTEGER_CST)
611 tree itype = TREE_TYPE (loop->v);
613 if (POINTER_TYPE_P (itype))
614 itype = signed_type_for (itype);
615 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
616 t = fold_build2_loc (loc,
617 PLUS_EXPR, itype,
618 fold_convert_loc (loc, itype, loop->step), t);
619 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
620 fold_convert_loc (loc, itype, loop->n2));
621 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
622 fold_convert_loc (loc, itype, loop->n1));
623 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
624 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
625 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
626 fold_build1_loc (loc, NEGATE_EXPR, itype,
627 fold_convert_loc (loc, itype,
628 loop->step)));
629 else
630 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
631 fold_convert_loc (loc, itype, loop->step));
632 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
633 if (count != NULL_TREE)
634 count = fold_build2_loc (loc,
635 MULT_EXPR, long_long_unsigned_type_node,
636 count, t);
637 else
638 count = t;
639 if (TREE_CODE (count) != INTEGER_CST)
640 count = NULL_TREE;
642 else if (count && !integer_zerop (count))
643 count = NULL_TREE;
647 if (count
648 && !simd
649 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
650 || fd->have_ordered))
652 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
653 iter_type = long_long_unsigned_type_node;
654 else
655 iter_type = long_integer_type_node;
657 else if (collapse_iter && *collapse_iter != NULL)
658 iter_type = TREE_TYPE (*collapse_iter);
659 fd->iter_type = iter_type;
660 if (collapse_iter && *collapse_iter == NULL)
661 *collapse_iter = create_tmp_var (iter_type, ".iter");
662 if (collapse_count && *collapse_count == NULL)
664 if (count)
665 *collapse_count = fold_convert_loc (loc, iter_type, count);
666 else
667 *collapse_count = create_tmp_var (iter_type, ".count");
670 if (fd->collapse > 1)
672 fd->loop.v = *collapse_iter;
673 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
674 fd->loop.n2 = *collapse_count;
675 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
676 fd->loop.cond_code = LT_EXPR;
679 /* For OpenACC loops, force a chunk size of one, as this avoids the default
680 scheduling where several subsequent iterations are being executed by the
681 same thread. */
682 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
684 gcc_assert (fd->chunk_size == NULL_TREE);
685 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
690 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
691 is the immediate dominator of PAR_ENTRY_BB, return true if there
692 are no data dependencies that would prevent expanding the parallel
693 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
695 When expanding a combined parallel+workshare region, the call to
696 the child function may need additional arguments in the case of
697 GIMPLE_OMP_FOR regions. In some cases, these arguments are
698 computed out of variables passed in from the parent to the child
699 via 'struct .omp_data_s'. For instance:
701 #pragma omp parallel for schedule (guided, i * 4)
702 for (j ...)
704 Is lowered into:
706 # BLOCK 2 (PAR_ENTRY_BB)
707 .omp_data_o.i = i;
708 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
710 # BLOCK 3 (WS_ENTRY_BB)
711 .omp_data_i = &.omp_data_o;
712 D.1667 = .omp_data_i->i;
713 D.1598 = D.1667 * 4;
714 #pragma omp for schedule (guided, D.1598)
716 When we outline the parallel region, the call to the child function
717 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
718 that value is computed *after* the call site. So, in principle we
719 cannot do the transformation.
721 To see whether the code in WS_ENTRY_BB blocks the combined
722 parallel+workshare call, we collect all the variables used in the
723 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
724 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
725 call.
727 FIXME. If we had the SSA form built at this point, we could merely
728 hoist the code in block 3 into block 2 and be done with it. But at
729 this point we don't have dataflow information and though we could
730 hack something up here, it is really not worth the aggravation. */
732 static bool
733 workshare_safe_to_combine_p (basic_block ws_entry_bb)
735 struct omp_for_data fd;
736 gimple *ws_stmt = last_stmt (ws_entry_bb);
738 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
739 return true;
741 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
743 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
745 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
746 return false;
747 if (fd.iter_type != long_integer_type_node)
748 return false;
750 /* FIXME. We give up too easily here. If any of these arguments
751 are not constants, they will likely involve variables that have
752 been mapped into fields of .omp_data_s for sharing with the child
753 function. With appropriate data flow, it would be possible to
754 see through this. */
755 if (!is_gimple_min_invariant (fd.loop.n1)
756 || !is_gimple_min_invariant (fd.loop.n2)
757 || !is_gimple_min_invariant (fd.loop.step)
758 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
759 return false;
761 return true;
765 /* Collect additional arguments needed to emit a combined
766 parallel+workshare call. WS_STMT is the workshare directive being
767 expanded. */
769 static vec<tree, va_gc> *
770 get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
772 tree t;
773 location_t loc = gimple_location (ws_stmt);
774 vec<tree, va_gc> *ws_args;
776 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
778 struct omp_for_data fd;
779 tree n1, n2;
781 extract_omp_for_data (for_stmt, &fd, NULL);
782 n1 = fd.loop.n1;
783 n2 = fd.loop.n2;
785 if (gimple_omp_for_combined_into_p (for_stmt))
787 tree innerc
788 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
789 OMP_CLAUSE__LOOPTEMP_);
790 gcc_assert (innerc);
791 n1 = OMP_CLAUSE_DECL (innerc);
792 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
793 OMP_CLAUSE__LOOPTEMP_);
794 gcc_assert (innerc);
795 n2 = OMP_CLAUSE_DECL (innerc);
798 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
800 t = fold_convert_loc (loc, long_integer_type_node, n1);
801 ws_args->quick_push (t);
803 t = fold_convert_loc (loc, long_integer_type_node, n2);
804 ws_args->quick_push (t);
806 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
807 ws_args->quick_push (t);
809 if (fd.chunk_size)
811 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
812 ws_args->quick_push (t);
815 return ws_args;
817 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
819 /* Number of sections is equal to the number of edges from the
820 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
821 the exit of the sections region. */
822 basic_block bb = single_succ (gimple_bb (ws_stmt));
823 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
824 vec_alloc (ws_args, 1);
825 ws_args->quick_push (t);
826 return ws_args;
829 gcc_unreachable ();
833 /* Discover whether REGION is a combined parallel+workshare region. */
835 static void
836 determine_parallel_type (struct omp_region *region)
838 basic_block par_entry_bb, par_exit_bb;
839 basic_block ws_entry_bb, ws_exit_bb;
841 if (region == NULL || region->inner == NULL
842 || region->exit == NULL || region->inner->exit == NULL
843 || region->inner->cont == NULL)
844 return;
846 /* We only support parallel+for and parallel+sections. */
847 if (region->type != GIMPLE_OMP_PARALLEL
848 || (region->inner->type != GIMPLE_OMP_FOR
849 && region->inner->type != GIMPLE_OMP_SECTIONS))
850 return;
852 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
853 WS_EXIT_BB -> PAR_EXIT_BB. */
854 par_entry_bb = region->entry;
855 par_exit_bb = region->exit;
856 ws_entry_bb = region->inner->entry;
857 ws_exit_bb = region->inner->exit;
859 if (single_succ (par_entry_bb) == ws_entry_bb
860 && single_succ (ws_exit_bb) == par_exit_bb
861 && workshare_safe_to_combine_p (ws_entry_bb)
862 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
863 || (last_and_only_stmt (ws_entry_bb)
864 && last_and_only_stmt (par_exit_bb))))
866 gimple *par_stmt = last_stmt (par_entry_bb);
867 gimple *ws_stmt = last_stmt (ws_entry_bb);
869 if (region->inner->type == GIMPLE_OMP_FOR)
871 /* If this is a combined parallel loop, we need to determine
872 whether or not to use the combined library calls. There
873 are two cases where we do not apply the transformation:
874 static loops and any kind of ordered loop. In the first
875 case, we already open code the loop so there is no need
876 to do anything else. In the latter case, the combined
877 parallel loop call would still need extra synchronization
878 to implement ordered semantics, so there would not be any
879 gain in using the combined call. */
880 tree clauses = gimple_omp_for_clauses (ws_stmt);
881 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
882 if (c == NULL
883 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
884 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
886 region->is_combined_parallel = false;
887 region->inner->is_combined_parallel = false;
888 return;
892 region->is_combined_parallel = true;
893 region->inner->is_combined_parallel = true;
894 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
899 /* Return true if EXPR is variable sized. */
901 static inline bool
902 is_variable_sized (const_tree expr)
904 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
907 /* Return true if DECL is a reference type. */
909 static inline bool
910 is_reference (tree decl)
912 return lang_hooks.decls.omp_privatize_by_reference (decl);
915 /* Return the type of a decl. If the decl is reference type,
916 return its base type. */
917 static inline tree
918 get_base_type (tree decl)
920 tree type = TREE_TYPE (decl);
921 if (is_reference (decl))
922 type = TREE_TYPE (type);
923 return type;
926 /* Lookup variables. The "maybe" form
927 allows for the variable form to not have been entered, otherwise we
928 assert that the variable must have been entered. */
930 static inline tree
931 lookup_decl (tree var, omp_context *ctx)
933 tree *n = ctx->cb.decl_map->get (var);
934 return *n;
937 static inline tree
938 maybe_lookup_decl (const_tree var, omp_context *ctx)
940 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
941 return n ? *n : NULL_TREE;
944 static inline tree
945 lookup_field (tree var, omp_context *ctx)
947 splay_tree_node n;
948 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
949 return (tree) n->value;
952 static inline tree
953 lookup_sfield (tree var, omp_context *ctx)
955 splay_tree_node n;
956 n = splay_tree_lookup (ctx->sfield_map
957 ? ctx->sfield_map : ctx->field_map,
958 (splay_tree_key) var);
959 return (tree) n->value;
962 static inline tree
963 maybe_lookup_field (tree var, omp_context *ctx)
965 splay_tree_node n;
966 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
967 return n ? (tree) n->value : NULL_TREE;
970 static inline tree
971 lookup_oacc_reduction (const char *id, omp_context *ctx)
973 splay_tree_node n;
974 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
975 return (tree) n->value;
978 static inline tree
979 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
981 splay_tree_node n = NULL;
982 if (ctx->reduction_map)
983 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
984 return n ? (tree) n->value : NULL_TREE;
987 /* Return true if DECL should be copied by pointer. SHARED_CTX is
988 the parallel context if DECL is to be shared. */
990 static bool
991 use_pointer_for_field (tree decl, omp_context *shared_ctx)
993 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
994 return true;
996 /* We can only use copy-in/copy-out semantics for shared variables
997 when we know the value is not accessible from an outer scope. */
998 if (shared_ctx)
1000 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1002 /* ??? Trivially accessible from anywhere. But why would we even
1003 be passing an address in this case? Should we simply assert
1004 this to be false, or should we have a cleanup pass that removes
1005 these from the list of mappings? */
1006 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1007 return true;
1009 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1010 without analyzing the expression whether or not its location
1011 is accessible to anyone else. In the case of nested parallel
1012 regions it certainly may be. */
1013 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1014 return true;
1016 /* Do not use copy-in/copy-out for variables that have their
1017 address taken. */
1018 if (TREE_ADDRESSABLE (decl))
1019 return true;
1021 /* lower_send_shared_vars only uses copy-in, but not copy-out
1022 for these. */
1023 if (TREE_READONLY (decl)
1024 || ((TREE_CODE (decl) == RESULT_DECL
1025 || TREE_CODE (decl) == PARM_DECL)
1026 && DECL_BY_REFERENCE (decl)))
1027 return false;
1029 /* Disallow copy-in/out in nested parallel if
1030 decl is shared in outer parallel, otherwise
1031 each thread could store the shared variable
1032 in its own copy-in location, making the
1033 variable no longer really shared. */
1034 if (shared_ctx->is_nested)
1036 omp_context *up;
1038 for (up = shared_ctx->outer; up; up = up->outer)
1039 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1040 break;
1042 if (up)
1044 tree c;
1046 for (c = gimple_omp_taskreg_clauses (up->stmt);
1047 c; c = OMP_CLAUSE_CHAIN (c))
1048 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1049 && OMP_CLAUSE_DECL (c) == decl)
1050 break;
1052 if (c)
1053 goto maybe_mark_addressable_and_ret;
1057 /* For tasks avoid using copy-in/out. As tasks can be
1058 deferred or executed in different thread, when GOMP_task
1059 returns, the task hasn't necessarily terminated. */
1060 if (is_task_ctx (shared_ctx))
1062 tree outer;
1063 maybe_mark_addressable_and_ret:
1064 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1065 if (is_gimple_reg (outer))
1067 /* Taking address of OUTER in lower_send_shared_vars
1068 might need regimplification of everything that uses the
1069 variable. */
1070 if (!task_shared_vars)
1071 task_shared_vars = BITMAP_ALLOC (NULL);
1072 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1073 TREE_ADDRESSABLE (outer) = 1;
1075 return true;
1079 return false;
1082 /* Construct a new automatic decl similar to VAR. */
1084 static tree
1085 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1087 tree copy = copy_var_decl (var, name, type);
1089 DECL_CONTEXT (copy) = current_function_decl;
1090 DECL_CHAIN (copy) = ctx->block_vars;
1091 ctx->block_vars = copy;
1093 return copy;
1096 static tree
1097 omp_copy_decl_1 (tree var, omp_context *ctx)
1099 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1102 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1103 as appropriate. */
1104 static tree
1105 omp_build_component_ref (tree obj, tree field)
1107 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1108 if (TREE_THIS_VOLATILE (field))
1109 TREE_THIS_VOLATILE (ret) |= 1;
1110 if (TREE_READONLY (field))
1111 TREE_READONLY (ret) |= 1;
1112 return ret;
1115 /* Build tree nodes to access the field for VAR on the receiver side. */
1117 static tree
1118 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1120 tree x, field = lookup_field (var, ctx);
1122 /* If the receiver record type was remapped in the child function,
1123 remap the field into the new record type. */
1124 x = maybe_lookup_field (field, ctx);
1125 if (x != NULL)
1126 field = x;
1128 x = build_simple_mem_ref (ctx->receiver_decl);
1129 TREE_THIS_NOTRAP (x) = 1;
1130 x = omp_build_component_ref (x, field);
1131 if (by_ref)
1132 x = build_simple_mem_ref (x);
1134 return x;
1137 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1138 of a parallel, this is a component reference; for workshare constructs
1139 this is some variable. */
1141 static tree
1142 build_outer_var_ref (tree var, omp_context *ctx)
1144 tree x;
1146 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1147 x = var;
1148 else if (is_variable_sized (var))
1150 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1151 x = build_outer_var_ref (x, ctx);
1152 x = build_simple_mem_ref (x);
1154 else if (is_taskreg_ctx (ctx))
1156 bool by_ref = use_pointer_for_field (var, NULL);
1157 x = build_receiver_ref (var, by_ref, ctx);
1159 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1160 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1162 /* #pragma omp simd isn't a worksharing construct, and can reference even
1163 private vars in its linear etc. clauses. */
1164 x = NULL_TREE;
1165 if (ctx->outer && is_taskreg_ctx (ctx))
1166 x = lookup_decl (var, ctx->outer);
1167 else if (ctx->outer)
1168 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1169 if (x == NULL_TREE)
1170 x = var;
1172 else if (ctx->outer)
1173 x = lookup_decl (var, ctx->outer);
1174 else if (is_reference (var))
1175 /* This can happen with orphaned constructs. If var is reference, it is
1176 possible it is shared and as such valid. */
1177 x = var;
1178 else
1179 gcc_unreachable ();
1181 if (is_reference (var))
1182 x = build_simple_mem_ref (x);
1184 return x;
1187 /* Build tree nodes to access the field for VAR on the sender side. */
1189 static tree
1190 build_sender_ref (tree var, omp_context *ctx)
1192 tree field = lookup_sfield (var, ctx);
1193 return omp_build_component_ref (ctx->sender_decl, field);
1196 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1198 static void
1199 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1201 tree field, type, sfield = NULL_TREE;
1203 gcc_assert ((mask & 1) == 0
1204 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1205 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1206 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1207 gcc_assert ((mask & 3) == 3
1208 || !is_gimple_omp_oacc (ctx->stmt));
1210 type = TREE_TYPE (var);
1211 if (mask & 4)
1213 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1214 type = build_pointer_type (build_pointer_type (type));
1216 else if (by_ref)
1217 type = build_pointer_type (type);
1218 else if ((mask & 3) == 1 && is_reference (var))
1219 type = TREE_TYPE (type);
1221 field = build_decl (DECL_SOURCE_LOCATION (var),
1222 FIELD_DECL, DECL_NAME (var), type);
1224 /* Remember what variable this field was created for. This does have a
1225 side effect of making dwarf2out ignore this member, so for helpful
1226 debugging we clear it later in delete_omp_context. */
1227 DECL_ABSTRACT_ORIGIN (field) = var;
1228 if (type == TREE_TYPE (var))
1230 DECL_ALIGN (field) = DECL_ALIGN (var);
1231 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1232 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1234 else
1235 DECL_ALIGN (field) = TYPE_ALIGN (type);
1237 if ((mask & 3) == 3)
1239 insert_field_into_struct (ctx->record_type, field);
1240 if (ctx->srecord_type)
1242 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1243 FIELD_DECL, DECL_NAME (var), type);
1244 DECL_ABSTRACT_ORIGIN (sfield) = var;
1245 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1246 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1247 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1248 insert_field_into_struct (ctx->srecord_type, sfield);
1251 else
1253 if (ctx->srecord_type == NULL_TREE)
1255 tree t;
1257 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1258 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1259 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1261 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1262 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1263 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1264 insert_field_into_struct (ctx->srecord_type, sfield);
1265 splay_tree_insert (ctx->sfield_map,
1266 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1267 (splay_tree_value) sfield);
1270 sfield = field;
1271 insert_field_into_struct ((mask & 1) ? ctx->record_type
1272 : ctx->srecord_type, field);
1275 if (mask & 1)
1276 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1277 (splay_tree_value) field);
1278 if ((mask & 2) && ctx->sfield_map)
1279 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1280 (splay_tree_value) sfield);
1283 static tree
1284 install_var_local (tree var, omp_context *ctx)
1286 tree new_var = omp_copy_decl_1 (var, ctx);
1287 insert_decl_map (&ctx->cb, var, new_var);
1288 return new_var;
1291 /* Adjust the replacement for DECL in CTX for the new context. This means
1292 copying the DECL_VALUE_EXPR, and fixing up the type. */
1294 static void
1295 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1297 tree new_decl, size;
1299 new_decl = lookup_decl (decl, ctx);
1301 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1303 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1304 && DECL_HAS_VALUE_EXPR_P (decl))
1306 tree ve = DECL_VALUE_EXPR (decl);
1307 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1308 SET_DECL_VALUE_EXPR (new_decl, ve);
1309 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1312 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1314 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1315 if (size == error_mark_node)
1316 size = TYPE_SIZE (TREE_TYPE (new_decl));
1317 DECL_SIZE (new_decl) = size;
1319 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1320 if (size == error_mark_node)
1321 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1322 DECL_SIZE_UNIT (new_decl) = size;
1326 /* The callback for remap_decl. Search all containing contexts for a
1327 mapping of the variable; this avoids having to duplicate the splay
1328 tree ahead of time. We know a mapping doesn't already exist in the
1329 given context. Create new mappings to implement default semantics. */
1331 static tree
1332 omp_copy_decl (tree var, copy_body_data *cb)
1334 omp_context *ctx = (omp_context *) cb;
1335 tree new_var;
1337 if (TREE_CODE (var) == LABEL_DECL)
1339 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1340 DECL_CONTEXT (new_var) = current_function_decl;
1341 insert_decl_map (&ctx->cb, var, new_var);
1342 return new_var;
1345 while (!is_taskreg_ctx (ctx))
1347 ctx = ctx->outer;
1348 if (ctx == NULL)
1349 return var;
1350 new_var = maybe_lookup_decl (var, ctx);
1351 if (new_var)
1352 return new_var;
1355 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1356 return var;
1358 return error_mark_node;
1362 /* Debugging dumps for parallel regions. */
1363 void dump_omp_region (FILE *, struct omp_region *, int);
1364 void debug_omp_region (struct omp_region *);
1365 void debug_all_omp_regions (void);
1367 /* Dump the parallel region tree rooted at REGION. */
1369 void
1370 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1372 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1373 gimple_code_name[region->type]);
1375 if (region->inner)
1376 dump_omp_region (file, region->inner, indent + 4);
1378 if (region->cont)
1380 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1381 region->cont->index);
1384 if (region->exit)
1385 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1386 region->exit->index);
1387 else
1388 fprintf (file, "%*s[no exit marker]\n", indent, "");
1390 if (region->next)
1391 dump_omp_region (file, region->next, indent);
1394 DEBUG_FUNCTION void
1395 debug_omp_region (struct omp_region *region)
1397 dump_omp_region (stderr, region, 0);
1400 DEBUG_FUNCTION void
1401 debug_all_omp_regions (void)
1403 dump_omp_region (stderr, root_omp_region, 0);
1407 /* Create a new parallel region starting at STMT inside region PARENT. */
1409 static struct omp_region *
1410 new_omp_region (basic_block bb, enum gimple_code type,
1411 struct omp_region *parent)
1413 struct omp_region *region = XCNEW (struct omp_region);
1415 region->outer = parent;
1416 region->entry = bb;
1417 region->type = type;
1419 if (parent)
1421 /* This is a nested region. Add it to the list of inner
1422 regions in PARENT. */
1423 region->next = parent->inner;
1424 parent->inner = region;
1426 else
1428 /* This is a toplevel region. Add it to the list of toplevel
1429 regions in ROOT_OMP_REGION. */
1430 region->next = root_omp_region;
1431 root_omp_region = region;
1434 return region;
1437 /* Release the memory associated with the region tree rooted at REGION. */
1439 static void
1440 free_omp_region_1 (struct omp_region *region)
1442 struct omp_region *i, *n;
1444 for (i = region->inner; i ; i = n)
1446 n = i->next;
1447 free_omp_region_1 (i);
1450 free (region);
1453 /* Release the memory for the entire omp region tree. */
1455 void
1456 free_omp_regions (void)
1458 struct omp_region *r, *n;
1459 for (r = root_omp_region; r ; r = n)
1461 n = r->next;
1462 free_omp_region_1 (r);
1464 root_omp_region = NULL;
1468 /* Create a new context, with OUTER_CTX being the surrounding context. */
1470 static omp_context *
1471 new_omp_context (gimple *stmt, omp_context *outer_ctx)
1473 omp_context *ctx = XCNEW (omp_context);
1475 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1476 (splay_tree_value) ctx);
1477 ctx->stmt = stmt;
1479 if (outer_ctx)
1481 ctx->outer = outer_ctx;
1482 ctx->cb = outer_ctx->cb;
1483 ctx->cb.block = NULL;
1484 ctx->depth = outer_ctx->depth + 1;
1485 ctx->reduction_map = outer_ctx->reduction_map;
1487 else
1489 ctx->cb.src_fn = current_function_decl;
1490 ctx->cb.dst_fn = current_function_decl;
1491 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1492 gcc_checking_assert (ctx->cb.src_node);
1493 ctx->cb.dst_node = ctx->cb.src_node;
1494 ctx->cb.src_cfun = cfun;
1495 ctx->cb.copy_decl = omp_copy_decl;
1496 ctx->cb.eh_lp_nr = 0;
1497 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1498 ctx->depth = 1;
1501 ctx->cb.decl_map = new hash_map<tree, tree>;
1503 return ctx;
1506 static gimple_seq maybe_catch_exception (gimple_seq);
1508 /* Finalize task copyfn. */
1510 static void
1511 finalize_task_copyfn (gomp_task *task_stmt)
1513 struct function *child_cfun;
1514 tree child_fn;
1515 gimple_seq seq = NULL, new_seq;
1516 gbind *bind;
1518 child_fn = gimple_omp_task_copy_fn (task_stmt);
1519 if (child_fn == NULL_TREE)
1520 return;
1522 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1523 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1525 push_cfun (child_cfun);
1526 bind = gimplify_body (child_fn, false);
1527 gimple_seq_add_stmt (&seq, bind);
1528 new_seq = maybe_catch_exception (seq);
1529 if (new_seq != seq)
1531 bind = gimple_build_bind (NULL, new_seq, NULL);
1532 seq = NULL;
1533 gimple_seq_add_stmt (&seq, bind);
1535 gimple_set_body (child_fn, seq);
1536 pop_cfun ();
1538 /* Inform the callgraph about the new function. */
1539 cgraph_node *node = cgraph_node::get_create (child_fn);
1540 node->parallelized_function = 1;
1541 cgraph_node::add_new_function (child_fn, false);
1544 /* Destroy a omp_context data structures. Called through the splay tree
1545 value delete callback. */
1547 static void
1548 delete_omp_context (splay_tree_value value)
1550 omp_context *ctx = (omp_context *) value;
1552 delete ctx->cb.decl_map;
1554 if (ctx->field_map)
1555 splay_tree_delete (ctx->field_map);
1556 if (ctx->sfield_map)
1557 splay_tree_delete (ctx->sfield_map);
1558 /* Reduction map is copied to nested contexts, so only delete it in the
1559 owner. */
1560 if (ctx->reduction_map
1561 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1562 && is_gimple_omp_offloaded (ctx->stmt)
1563 && is_gimple_omp_oacc (ctx->stmt))
1564 splay_tree_delete (ctx->reduction_map);
1566 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1567 it produces corrupt debug information. */
1568 if (ctx->record_type)
1570 tree t;
1571 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1572 DECL_ABSTRACT_ORIGIN (t) = NULL;
1574 if (ctx->srecord_type)
1576 tree t;
1577 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1578 DECL_ABSTRACT_ORIGIN (t) = NULL;
1581 if (is_task_ctx (ctx))
1582 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1584 XDELETE (ctx);
1587 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1588 context. */
1590 static void
1591 fixup_child_record_type (omp_context *ctx)
1593 tree f, type = ctx->record_type;
1595 /* ??? It isn't sufficient to just call remap_type here, because
1596 variably_modified_type_p doesn't work the way we expect for
1597 record types. Testing each field for whether it needs remapping
1598 and creating a new record by hand works, however. */
1599 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1600 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1601 break;
1602 if (f)
1604 tree name, new_fields = NULL;
1606 type = lang_hooks.types.make_type (RECORD_TYPE);
1607 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1608 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1609 TYPE_DECL, name, type);
1610 TYPE_NAME (type) = name;
1612 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1614 tree new_f = copy_node (f);
1615 DECL_CONTEXT (new_f) = type;
1616 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1617 DECL_CHAIN (new_f) = new_fields;
1618 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1619 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1620 &ctx->cb, NULL);
1621 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1622 &ctx->cb, NULL);
1623 new_fields = new_f;
1625 /* Arrange to be able to look up the receiver field
1626 given the sender field. */
1627 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1628 (splay_tree_value) new_f);
1630 TYPE_FIELDS (type) = nreverse (new_fields);
1631 layout_type (type);
1634 TREE_TYPE (ctx->receiver_decl)
1635 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1638 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1639 specified by CLAUSES. */
1641 static void
1642 scan_sharing_clauses (tree clauses, omp_context *ctx)
1644 tree c, decl;
1645 bool scan_array_reductions = false;
1647 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1649 bool by_ref;
1651 switch (OMP_CLAUSE_CODE (c))
1653 case OMP_CLAUSE_PRIVATE:
1654 decl = OMP_CLAUSE_DECL (c);
1655 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1656 goto do_private;
1657 else if (!is_variable_sized (decl))
1658 install_var_local (decl, ctx);
1659 break;
1661 case OMP_CLAUSE_SHARED:
1662 decl = OMP_CLAUSE_DECL (c);
1663 /* Ignore shared directives in teams construct. */
1664 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1666 /* Global variables don't need to be copied,
1667 the receiver side will use them directly. */
1668 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1669 if (is_global_var (odecl))
1670 break;
1671 insert_decl_map (&ctx->cb, decl, odecl);
1672 break;
1674 gcc_assert (is_taskreg_ctx (ctx));
1675 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1676 || !is_variable_sized (decl));
1677 /* Global variables don't need to be copied,
1678 the receiver side will use them directly. */
1679 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1680 break;
1681 by_ref = use_pointer_for_field (decl, ctx);
1682 if (! TREE_READONLY (decl)
1683 || TREE_ADDRESSABLE (decl)
1684 || by_ref
1685 || is_reference (decl))
1687 install_var_field (decl, by_ref, 3, ctx);
1688 install_var_local (decl, ctx);
1689 break;
1691 /* We don't need to copy const scalar vars back. */
1692 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1693 goto do_private;
1695 case OMP_CLAUSE_LASTPRIVATE:
1696 /* Let the corresponding firstprivate clause create
1697 the variable. */
1698 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1699 break;
1700 /* FALLTHRU */
1702 case OMP_CLAUSE_FIRSTPRIVATE:
1703 if (is_gimple_omp_oacc (ctx->stmt))
1705 sorry ("clause not supported yet");
1706 break;
1708 /* FALLTHRU */
1709 case OMP_CLAUSE_REDUCTION:
1710 case OMP_CLAUSE_LINEAR:
1711 decl = OMP_CLAUSE_DECL (c);
1712 do_private:
1713 if (is_variable_sized (decl))
1715 if (is_task_ctx (ctx))
1716 install_var_field (decl, false, 1, ctx);
1717 break;
1719 else if (is_taskreg_ctx (ctx))
1721 bool global
1722 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1723 by_ref = use_pointer_for_field (decl, NULL);
1725 if (is_task_ctx (ctx)
1726 && (global || by_ref || is_reference (decl)))
1728 install_var_field (decl, false, 1, ctx);
1729 if (!global)
1730 install_var_field (decl, by_ref, 2, ctx);
1732 else if (!global)
1733 install_var_field (decl, by_ref, 3, ctx);
1735 install_var_local (decl, ctx);
1736 if (is_gimple_omp_oacc (ctx->stmt)
1737 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1739 /* Create a decl for the reduction array. */
1740 tree var = OMP_CLAUSE_DECL (c);
1741 tree type = get_base_type (var);
1742 tree ptype = build_pointer_type (type);
1743 tree array = create_tmp_var (ptype,
1744 oacc_get_reduction_array_id (var));
1745 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1746 install_var_field (array, true, 3, c);
1747 install_var_local (array, c);
1749 /* Insert it into the current context. */
1750 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1751 oacc_get_reduction_array_id (var),
1752 (splay_tree_value) array);
1753 splay_tree_insert (ctx->reduction_map,
1754 (splay_tree_key) array,
1755 (splay_tree_value) array);
1757 break;
1759 case OMP_CLAUSE__LOOPTEMP_:
1760 gcc_assert (is_parallel_ctx (ctx));
1761 decl = OMP_CLAUSE_DECL (c);
1762 install_var_field (decl, false, 3, ctx);
1763 install_var_local (decl, ctx);
1764 break;
1766 case OMP_CLAUSE_COPYPRIVATE:
1767 case OMP_CLAUSE_COPYIN:
1768 decl = OMP_CLAUSE_DECL (c);
1769 by_ref = use_pointer_for_field (decl, NULL);
1770 install_var_field (decl, by_ref, 3, ctx);
1771 break;
1773 case OMP_CLAUSE_DEFAULT:
1774 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1775 break;
1777 case OMP_CLAUSE_FINAL:
1778 case OMP_CLAUSE_IF:
1779 case OMP_CLAUSE_NUM_THREADS:
1780 case OMP_CLAUSE_NUM_TEAMS:
1781 case OMP_CLAUSE_THREAD_LIMIT:
1782 case OMP_CLAUSE_DEVICE:
1783 case OMP_CLAUSE_SCHEDULE:
1784 case OMP_CLAUSE_DIST_SCHEDULE:
1785 case OMP_CLAUSE_DEPEND:
1786 case OMP_CLAUSE__CILK_FOR_COUNT_:
1787 case OMP_CLAUSE_NUM_GANGS:
1788 case OMP_CLAUSE_NUM_WORKERS:
1789 case OMP_CLAUSE_VECTOR_LENGTH:
1790 if (ctx->outer)
1791 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1792 break;
1794 case OMP_CLAUSE_TO:
1795 case OMP_CLAUSE_FROM:
1796 case OMP_CLAUSE_MAP:
1797 if (ctx->outer)
1798 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1799 decl = OMP_CLAUSE_DECL (c);
1800 /* Global variables with "omp declare target" attribute
1801 don't need to be copied, the receiver side will use them
1802 directly. */
1803 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1804 && DECL_P (decl)
1805 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1806 && varpool_node::get_create (decl)->offloadable)
1807 break;
1808 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1809 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
1811 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1812 not offloaded; there is nothing to map for those. */
1813 if (!is_gimple_omp_offloaded (ctx->stmt)
1814 && !POINTER_TYPE_P (TREE_TYPE (decl))
1815 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
1816 break;
1818 if (DECL_P (decl))
1820 if (DECL_SIZE (decl)
1821 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1823 tree decl2 = DECL_VALUE_EXPR (decl);
1824 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1825 decl2 = TREE_OPERAND (decl2, 0);
1826 gcc_assert (DECL_P (decl2));
1827 install_var_field (decl2, true, 3, ctx);
1828 install_var_local (decl2, ctx);
1829 install_var_local (decl, ctx);
1831 else
1833 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1834 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1835 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1836 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1837 install_var_field (decl, true, 7, ctx);
1838 else
1839 install_var_field (decl, true, 3, ctx);
1840 if (is_gimple_omp_offloaded (ctx->stmt))
1841 install_var_local (decl, ctx);
1844 else
1846 tree base = get_base_address (decl);
1847 tree nc = OMP_CLAUSE_CHAIN (c);
1848 if (DECL_P (base)
1849 && nc != NULL_TREE
1850 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1851 && OMP_CLAUSE_DECL (nc) == base
1852 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1853 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1855 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1856 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1858 else
1860 if (ctx->outer)
1862 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1863 decl = OMP_CLAUSE_DECL (c);
1865 gcc_assert (!splay_tree_lookup (ctx->field_map,
1866 (splay_tree_key) decl));
1867 tree field
1868 = build_decl (OMP_CLAUSE_LOCATION (c),
1869 FIELD_DECL, NULL_TREE, ptr_type_node);
1870 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1871 insert_field_into_struct (ctx->record_type, field);
1872 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1873 (splay_tree_value) field);
1876 break;
1878 case OMP_CLAUSE_NOWAIT:
1879 case OMP_CLAUSE_ORDERED:
1880 case OMP_CLAUSE_COLLAPSE:
1881 case OMP_CLAUSE_UNTIED:
1882 case OMP_CLAUSE_MERGEABLE:
1883 case OMP_CLAUSE_PROC_BIND:
1884 case OMP_CLAUSE_SAFELEN:
1885 case OMP_CLAUSE_ASYNC:
1886 case OMP_CLAUSE_WAIT:
1887 case OMP_CLAUSE_GANG:
1888 case OMP_CLAUSE_WORKER:
1889 case OMP_CLAUSE_VECTOR:
1890 break;
1892 case OMP_CLAUSE_ALIGNED:
1893 decl = OMP_CLAUSE_DECL (c);
1894 if (is_global_var (decl)
1895 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1896 install_var_local (decl, ctx);
1897 break;
1899 case OMP_CLAUSE_DEVICE_RESIDENT:
1900 case OMP_CLAUSE_USE_DEVICE:
1901 case OMP_CLAUSE__CACHE_:
1902 case OMP_CLAUSE_INDEPENDENT:
1903 case OMP_CLAUSE_AUTO:
1904 case OMP_CLAUSE_SEQ:
1905 sorry ("Clause not supported yet");
1906 break;
1908 default:
1909 gcc_unreachable ();
1913 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1915 switch (OMP_CLAUSE_CODE (c))
1917 case OMP_CLAUSE_LASTPRIVATE:
1918 /* Let the corresponding firstprivate clause create
1919 the variable. */
1920 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1921 scan_array_reductions = true;
1922 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1923 break;
1924 /* FALLTHRU */
1926 case OMP_CLAUSE_FIRSTPRIVATE:
1927 if (is_gimple_omp_oacc (ctx->stmt))
1929 sorry ("clause not supported yet");
1930 break;
1932 /* FALLTHRU */
1933 case OMP_CLAUSE_PRIVATE:
1934 case OMP_CLAUSE_REDUCTION:
1935 case OMP_CLAUSE_LINEAR:
1936 decl = OMP_CLAUSE_DECL (c);
1937 if (is_variable_sized (decl))
1938 install_var_local (decl, ctx);
1939 fixup_remapped_decl (decl, ctx,
1940 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1941 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1942 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1943 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1944 scan_array_reductions = true;
1945 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1946 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1947 scan_array_reductions = true;
1948 break;
1950 case OMP_CLAUSE_SHARED:
1951 /* Ignore shared directives in teams construct. */
1952 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1953 break;
1954 decl = OMP_CLAUSE_DECL (c);
1955 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1956 fixup_remapped_decl (decl, ctx, false);
1957 break;
1959 case OMP_CLAUSE_MAP:
1960 if (!is_gimple_omp_offloaded (ctx->stmt))
1961 break;
1962 decl = OMP_CLAUSE_DECL (c);
1963 if (DECL_P (decl)
1964 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1965 && varpool_node::get_create (decl)->offloadable)
1966 break;
1967 if (DECL_P (decl))
1969 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1970 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1971 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1973 tree new_decl = lookup_decl (decl, ctx);
1974 TREE_TYPE (new_decl)
1975 = remap_type (TREE_TYPE (decl), &ctx->cb);
1977 else if (DECL_SIZE (decl)
1978 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1980 tree decl2 = DECL_VALUE_EXPR (decl);
1981 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1982 decl2 = TREE_OPERAND (decl2, 0);
1983 gcc_assert (DECL_P (decl2));
1984 fixup_remapped_decl (decl2, ctx, false);
1985 fixup_remapped_decl (decl, ctx, true);
1987 else
1988 fixup_remapped_decl (decl, ctx, false);
1990 break;
1992 case OMP_CLAUSE_COPYPRIVATE:
1993 case OMP_CLAUSE_COPYIN:
1994 case OMP_CLAUSE_DEFAULT:
1995 case OMP_CLAUSE_IF:
1996 case OMP_CLAUSE_NUM_THREADS:
1997 case OMP_CLAUSE_NUM_TEAMS:
1998 case OMP_CLAUSE_THREAD_LIMIT:
1999 case OMP_CLAUSE_DEVICE:
2000 case OMP_CLAUSE_SCHEDULE:
2001 case OMP_CLAUSE_DIST_SCHEDULE:
2002 case OMP_CLAUSE_NOWAIT:
2003 case OMP_CLAUSE_ORDERED:
2004 case OMP_CLAUSE_COLLAPSE:
2005 case OMP_CLAUSE_UNTIED:
2006 case OMP_CLAUSE_FINAL:
2007 case OMP_CLAUSE_MERGEABLE:
2008 case OMP_CLAUSE_PROC_BIND:
2009 case OMP_CLAUSE_SAFELEN:
2010 case OMP_CLAUSE_ALIGNED:
2011 case OMP_CLAUSE_DEPEND:
2012 case OMP_CLAUSE__LOOPTEMP_:
2013 case OMP_CLAUSE_TO:
2014 case OMP_CLAUSE_FROM:
2015 case OMP_CLAUSE__CILK_FOR_COUNT_:
2016 case OMP_CLAUSE_ASYNC:
2017 case OMP_CLAUSE_WAIT:
2018 case OMP_CLAUSE_NUM_GANGS:
2019 case OMP_CLAUSE_NUM_WORKERS:
2020 case OMP_CLAUSE_VECTOR_LENGTH:
2021 case OMP_CLAUSE_GANG:
2022 case OMP_CLAUSE_WORKER:
2023 case OMP_CLAUSE_VECTOR:
2024 break;
2026 case OMP_CLAUSE_DEVICE_RESIDENT:
2027 case OMP_CLAUSE_USE_DEVICE:
2028 case OMP_CLAUSE__CACHE_:
2029 case OMP_CLAUSE_INDEPENDENT:
2030 case OMP_CLAUSE_AUTO:
2031 case OMP_CLAUSE_SEQ:
2032 sorry ("Clause not supported yet");
2033 break;
2035 default:
2036 gcc_unreachable ();
2040 gcc_checking_assert (!scan_array_reductions
2041 || !is_gimple_omp_oacc (ctx->stmt));
2042 if (scan_array_reductions)
2043 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2044 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2045 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2047 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2048 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2050 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2051 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2052 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2053 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2054 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2055 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2058 /* Create a new name for omp child function. Returns an identifier. If
2059 IS_CILK_FOR is true then the suffix for the child function is
2060 "_cilk_for_fn." */
2062 static tree
2063 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2065 if (is_cilk_for)
2066 return clone_function_name (current_function_decl, "_cilk_for_fn");
2067 return clone_function_name (current_function_decl,
2068 task_copy ? "_omp_cpyfn" : "_omp_fn");
2071 /* Returns the type of the induction variable for the child function for
2072 _Cilk_for and the types for _high and _low variables based on TYPE. */
2074 static tree
2075 cilk_for_check_loop_diff_type (tree type)
2077 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2079 if (TYPE_UNSIGNED (type))
2080 return uint32_type_node;
2081 else
2082 return integer_type_node;
2084 else
2086 if (TYPE_UNSIGNED (type))
2087 return uint64_type_node;
2088 else
2089 return long_long_integer_type_node;
2093 /* Build a decl for the omp child function. It'll not contain a body
2094 yet, just the bare decl. */
2096 static void
2097 create_omp_child_function (omp_context *ctx, bool task_copy)
2099 tree decl, type, name, t;
2101 tree cilk_for_count
2102 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2103 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2104 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2105 tree cilk_var_type = NULL_TREE;
2107 name = create_omp_child_function_name (task_copy,
2108 cilk_for_count != NULL_TREE);
2109 if (task_copy)
2110 type = build_function_type_list (void_type_node, ptr_type_node,
2111 ptr_type_node, NULL_TREE);
2112 else if (cilk_for_count)
2114 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2115 cilk_var_type = cilk_for_check_loop_diff_type (type);
2116 type = build_function_type_list (void_type_node, ptr_type_node,
2117 cilk_var_type, cilk_var_type, NULL_TREE);
2119 else
2120 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2122 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2124 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2125 || !task_copy);
2126 if (!task_copy)
2127 ctx->cb.dst_fn = decl;
2128 else
2129 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2131 TREE_STATIC (decl) = 1;
2132 TREE_USED (decl) = 1;
2133 DECL_ARTIFICIAL (decl) = 1;
2134 DECL_IGNORED_P (decl) = 0;
2135 TREE_PUBLIC (decl) = 0;
2136 DECL_UNINLINABLE (decl) = 1;
2137 DECL_EXTERNAL (decl) = 0;
2138 DECL_CONTEXT (decl) = NULL_TREE;
2139 DECL_INITIAL (decl) = make_node (BLOCK);
2140 if (cgraph_node::get (current_function_decl)->offloadable)
2141 cgraph_node::get_create (decl)->offloadable = 1;
2142 else
2144 omp_context *octx;
2145 for (octx = ctx; octx; octx = octx->outer)
2146 if (is_gimple_omp_offloaded (octx->stmt))
2148 cgraph_node::get_create (decl)->offloadable = 1;
2149 #ifdef ENABLE_OFFLOADING
2150 g->have_offload = true;
2151 #endif
2152 break;
2156 if (cgraph_node::get_create (decl)->offloadable
2157 && !lookup_attribute ("omp declare target",
2158 DECL_ATTRIBUTES (current_function_decl)))
2159 DECL_ATTRIBUTES (decl)
2160 = tree_cons (get_identifier ("omp target entrypoint"),
2161 NULL_TREE, DECL_ATTRIBUTES (decl));
2163 t = build_decl (DECL_SOURCE_LOCATION (decl),
2164 RESULT_DECL, NULL_TREE, void_type_node);
2165 DECL_ARTIFICIAL (t) = 1;
2166 DECL_IGNORED_P (t) = 1;
2167 DECL_CONTEXT (t) = decl;
2168 DECL_RESULT (decl) = t;
2170 /* _Cilk_for's child function requires two extra parameters called
2171 __low and __high that are set the by Cilk runtime when it calls this
2172 function. */
2173 if (cilk_for_count)
2175 t = build_decl (DECL_SOURCE_LOCATION (decl),
2176 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2177 DECL_ARTIFICIAL (t) = 1;
2178 DECL_NAMELESS (t) = 1;
2179 DECL_ARG_TYPE (t) = ptr_type_node;
2180 DECL_CONTEXT (t) = current_function_decl;
2181 TREE_USED (t) = 1;
2182 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2183 DECL_ARGUMENTS (decl) = t;
2185 t = build_decl (DECL_SOURCE_LOCATION (decl),
2186 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2187 DECL_ARTIFICIAL (t) = 1;
2188 DECL_NAMELESS (t) = 1;
2189 DECL_ARG_TYPE (t) = ptr_type_node;
2190 DECL_CONTEXT (t) = current_function_decl;
2191 TREE_USED (t) = 1;
2192 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2193 DECL_ARGUMENTS (decl) = t;
2196 tree data_name = get_identifier (".omp_data_i");
2197 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2198 ptr_type_node);
2199 DECL_ARTIFICIAL (t) = 1;
2200 DECL_NAMELESS (t) = 1;
2201 DECL_ARG_TYPE (t) = ptr_type_node;
2202 DECL_CONTEXT (t) = current_function_decl;
2203 TREE_USED (t) = 1;
2204 if (cilk_for_count)
2205 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2206 DECL_ARGUMENTS (decl) = t;
2207 if (!task_copy)
2208 ctx->receiver_decl = t;
2209 else
2211 t = build_decl (DECL_SOURCE_LOCATION (decl),
2212 PARM_DECL, get_identifier (".omp_data_o"),
2213 ptr_type_node);
2214 DECL_ARTIFICIAL (t) = 1;
2215 DECL_NAMELESS (t) = 1;
2216 DECL_ARG_TYPE (t) = ptr_type_node;
2217 DECL_CONTEXT (t) = current_function_decl;
2218 TREE_USED (t) = 1;
2219 TREE_ADDRESSABLE (t) = 1;
2220 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2221 DECL_ARGUMENTS (decl) = t;
2224 /* Allocate memory for the function structure. The call to
2225 allocate_struct_function clobbers CFUN, so we need to restore
2226 it afterward. */
2227 push_struct_function (decl);
2228 cfun->function_end_locus = gimple_location (ctx->stmt);
2229 pop_cfun ();
2232 /* Callback for walk_gimple_seq. Check if combined parallel
2233 contains gimple_omp_for_combined_into_p OMP_FOR. */
2235 static tree
2236 find_combined_for (gimple_stmt_iterator *gsi_p,
2237 bool *handled_ops_p,
2238 struct walk_stmt_info *wi)
2240 gimple *stmt = gsi_stmt (*gsi_p);
2242 *handled_ops_p = true;
2243 switch (gimple_code (stmt))
2245 WALK_SUBSTMTS;
2247 case GIMPLE_OMP_FOR:
2248 if (gimple_omp_for_combined_into_p (stmt)
2249 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2251 wi->info = stmt;
2252 return integer_zero_node;
2254 break;
2255 default:
2256 break;
2258 return NULL;
2261 /* Scan an OpenMP parallel directive. */
2263 static void
2264 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2266 omp_context *ctx;
2267 tree name;
2268 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2270 /* Ignore parallel directives with empty bodies, unless there
2271 are copyin clauses. */
2272 if (optimize > 0
2273 && empty_body_p (gimple_omp_body (stmt))
2274 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2275 OMP_CLAUSE_COPYIN) == NULL)
2277 gsi_replace (gsi, gimple_build_nop (), false);
2278 return;
2281 if (gimple_omp_parallel_combined_p (stmt))
2283 struct walk_stmt_info wi;
2285 memset (&wi, 0, sizeof (wi));
2286 wi.val_only = true;
2287 walk_gimple_seq (gimple_omp_body (stmt),
2288 find_combined_for, NULL, &wi);
2289 if (wi.info)
2291 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2292 struct omp_for_data fd;
2293 extract_omp_for_data (for_stmt, &fd, NULL);
2294 /* We need two temporaries with fd.loop.v type (istart/iend)
2295 and then (fd.collapse - 1) temporaries with the same
2296 type for count2 ... countN-1 vars if not constant. */
2297 size_t count = 2, i;
2298 tree type = fd.iter_type;
2299 if (fd.collapse > 1
2300 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2301 count += fd.collapse - 1;
2302 for (i = 0; i < count; i++)
2304 tree temp = create_tmp_var (type);
2305 tree c = build_omp_clause (UNKNOWN_LOCATION,
2306 OMP_CLAUSE__LOOPTEMP_);
2307 insert_decl_map (&outer_ctx->cb, temp, temp);
2308 OMP_CLAUSE_DECL (c) = temp;
2309 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2310 gimple_omp_parallel_set_clauses (stmt, c);
2315 ctx = new_omp_context (stmt, outer_ctx);
2316 taskreg_contexts.safe_push (ctx);
2317 if (taskreg_nesting_level > 1)
2318 ctx->is_nested = true;
2319 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2320 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2321 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2322 name = create_tmp_var_name (".omp_data_s");
2323 name = build_decl (gimple_location (stmt),
2324 TYPE_DECL, name, ctx->record_type);
2325 DECL_ARTIFICIAL (name) = 1;
2326 DECL_NAMELESS (name) = 1;
2327 TYPE_NAME (ctx->record_type) = name;
2328 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2329 create_omp_child_function (ctx, false);
2330 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2332 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2333 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2335 if (TYPE_FIELDS (ctx->record_type) == NULL)
2336 ctx->record_type = ctx->receiver_decl = NULL;
2339 /* Scan an OpenMP task directive. */
2341 static void
2342 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2344 omp_context *ctx;
2345 tree name, t;
2346 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2348 /* Ignore task directives with empty bodies. */
2349 if (optimize > 0
2350 && empty_body_p (gimple_omp_body (stmt)))
2352 gsi_replace (gsi, gimple_build_nop (), false);
2353 return;
2356 ctx = new_omp_context (stmt, outer_ctx);
2357 taskreg_contexts.safe_push (ctx);
2358 if (taskreg_nesting_level > 1)
2359 ctx->is_nested = true;
2360 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2361 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2362 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2363 name = create_tmp_var_name (".omp_data_s");
2364 name = build_decl (gimple_location (stmt),
2365 TYPE_DECL, name, ctx->record_type);
2366 DECL_ARTIFICIAL (name) = 1;
2367 DECL_NAMELESS (name) = 1;
2368 TYPE_NAME (ctx->record_type) = name;
2369 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2370 create_omp_child_function (ctx, false);
2371 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2373 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2375 if (ctx->srecord_type)
2377 name = create_tmp_var_name (".omp_data_a");
2378 name = build_decl (gimple_location (stmt),
2379 TYPE_DECL, name, ctx->srecord_type);
2380 DECL_ARTIFICIAL (name) = 1;
2381 DECL_NAMELESS (name) = 1;
2382 TYPE_NAME (ctx->srecord_type) = name;
2383 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2384 create_omp_child_function (ctx, true);
2387 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2389 if (TYPE_FIELDS (ctx->record_type) == NULL)
2391 ctx->record_type = ctx->receiver_decl = NULL;
2392 t = build_int_cst (long_integer_type_node, 0);
2393 gimple_omp_task_set_arg_size (stmt, t);
2394 t = build_int_cst (long_integer_type_node, 1);
2395 gimple_omp_task_set_arg_align (stmt, t);
2400 /* If any decls have been made addressable during scan_omp,
2401 adjust their fields if needed, and layout record types
2402 of parallel/task constructs. */
2404 static void
2405 finish_taskreg_scan (omp_context *ctx)
2407 if (ctx->record_type == NULL_TREE)
2408 return;
2410 /* If any task_shared_vars were needed, verify all
2411 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2412 statements if use_pointer_for_field hasn't changed
2413 because of that. If it did, update field types now. */
2414 if (task_shared_vars)
2416 tree c;
2418 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2419 c; c = OMP_CLAUSE_CHAIN (c))
2420 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2422 tree decl = OMP_CLAUSE_DECL (c);
2424 /* Global variables don't need to be copied,
2425 the receiver side will use them directly. */
2426 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2427 continue;
2428 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2429 || !use_pointer_for_field (decl, ctx))
2430 continue;
2431 tree field = lookup_field (decl, ctx);
2432 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2433 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2434 continue;
2435 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2436 TREE_THIS_VOLATILE (field) = 0;
2437 DECL_USER_ALIGN (field) = 0;
2438 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2439 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2440 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2441 if (ctx->srecord_type)
2443 tree sfield = lookup_sfield (decl, ctx);
2444 TREE_TYPE (sfield) = TREE_TYPE (field);
2445 TREE_THIS_VOLATILE (sfield) = 0;
2446 DECL_USER_ALIGN (sfield) = 0;
2447 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2448 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2449 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2454 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2456 layout_type (ctx->record_type);
2457 fixup_child_record_type (ctx);
2459 else
2461 location_t loc = gimple_location (ctx->stmt);
2462 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2463 /* Move VLA fields to the end. */
2464 p = &TYPE_FIELDS (ctx->record_type);
2465 while (*p)
2466 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2467 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2469 *q = *p;
2470 *p = TREE_CHAIN (*p);
2471 TREE_CHAIN (*q) = NULL_TREE;
2472 q = &TREE_CHAIN (*q);
2474 else
2475 p = &DECL_CHAIN (*p);
2476 *p = vla_fields;
2477 layout_type (ctx->record_type);
2478 fixup_child_record_type (ctx);
2479 if (ctx->srecord_type)
2480 layout_type (ctx->srecord_type);
2481 tree t = fold_convert_loc (loc, long_integer_type_node,
2482 TYPE_SIZE_UNIT (ctx->record_type));
2483 gimple_omp_task_set_arg_size (ctx->stmt, t);
2484 t = build_int_cst (long_integer_type_node,
2485 TYPE_ALIGN_UNIT (ctx->record_type));
2486 gimple_omp_task_set_arg_align (ctx->stmt, t);
2491 static omp_context *
2492 enclosing_target_ctx (omp_context *ctx)
2494 while (ctx != NULL
2495 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2496 ctx = ctx->outer;
2497 gcc_assert (ctx != NULL);
2498 return ctx;
2501 static bool
2502 oacc_loop_or_target_p (gimple *stmt)
2504 enum gimple_code outer_type = gimple_code (stmt);
2505 return ((outer_type == GIMPLE_OMP_TARGET
2506 && ((gimple_omp_target_kind (stmt)
2507 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2508 || (gimple_omp_target_kind (stmt)
2509 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2510 || (outer_type == GIMPLE_OMP_FOR
2511 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2514 /* Scan a GIMPLE_OMP_FOR. */
2516 static void
2517 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2519 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
2520 omp_context *ctx;
2521 size_t i;
2522 tree clauses = gimple_omp_for_clauses (stmt);
2524 if (outer_ctx)
2525 outer_type = gimple_code (outer_ctx->stmt);
2527 ctx = new_omp_context (stmt, outer_ctx);
2529 if (is_gimple_omp_oacc (stmt))
2531 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2532 ctx->gwv_this = outer_ctx->gwv_this;
2533 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2535 int val;
2536 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2537 val = MASK_GANG;
2538 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2539 val = MASK_WORKER;
2540 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2541 val = MASK_VECTOR;
2542 else
2543 continue;
2544 ctx->gwv_this |= val;
2545 if (!outer_ctx)
2547 /* Skip; not nested inside a region. */
2548 continue;
2550 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2552 /* Skip; not nested inside an OpenACC region. */
2553 continue;
2555 if (outer_type == GIMPLE_OMP_FOR)
2556 outer_ctx->gwv_below |= val;
2557 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2559 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2560 if (gimple_omp_target_kind (enclosing->stmt)
2561 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2562 error_at (gimple_location (stmt),
2563 "no arguments allowed to gang, worker and vector clauses inside parallel");
2568 scan_sharing_clauses (clauses, ctx);
2570 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2571 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2573 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2574 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2575 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2576 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2578 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2580 if (is_gimple_omp_oacc (stmt))
2582 if (ctx->gwv_this & ctx->gwv_below)
2583 error_at (gimple_location (stmt),
2584 "gang, worker and vector may occur only once in a loop nest");
2585 else if (ctx->gwv_below != 0
2586 && ctx->gwv_this > ctx->gwv_below)
2587 error_at (gimple_location (stmt),
2588 "gang, worker and vector must occur in this order in a loop nest");
2589 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2590 outer_ctx->gwv_below |= ctx->gwv_below;
2594 /* Scan an OpenMP sections directive. */
2596 static void
2597 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2599 omp_context *ctx;
2601 ctx = new_omp_context (stmt, outer_ctx);
2602 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2603 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2606 /* Scan an OpenMP single directive. */
2608 static void
2609 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2611 omp_context *ctx;
2612 tree name;
2614 ctx = new_omp_context (stmt, outer_ctx);
2615 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2616 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2617 name = create_tmp_var_name (".omp_copy_s");
2618 name = build_decl (gimple_location (stmt),
2619 TYPE_DECL, name, ctx->record_type);
2620 TYPE_NAME (ctx->record_type) = name;
2622 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2623 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2625 if (TYPE_FIELDS (ctx->record_type) == NULL)
2626 ctx->record_type = NULL;
2627 else
2628 layout_type (ctx->record_type);
2631 /* Scan a GIMPLE_OMP_TARGET. */
2633 static void
2634 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2636 omp_context *ctx;
2637 tree name;
2638 bool offloaded = is_gimple_omp_offloaded (stmt);
2639 tree clauses = gimple_omp_target_clauses (stmt);
2641 ctx = new_omp_context (stmt, outer_ctx);
2642 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2643 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2644 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2645 name = create_tmp_var_name (".omp_data_t");
2646 name = build_decl (gimple_location (stmt),
2647 TYPE_DECL, name, ctx->record_type);
2648 DECL_ARTIFICIAL (name) = 1;
2649 DECL_NAMELESS (name) = 1;
2650 TYPE_NAME (ctx->record_type) = name;
2651 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2652 if (offloaded)
2654 if (is_gimple_omp_oacc (stmt))
2655 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2656 0, 0);
2658 create_omp_child_function (ctx, false);
2659 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2662 if (is_gimple_omp_oacc (stmt))
2664 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2666 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2667 ctx->gwv_this |= MASK_GANG;
2668 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2669 ctx->gwv_this |= MASK_WORKER;
2670 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2671 ctx->gwv_this |= MASK_VECTOR;
2675 scan_sharing_clauses (clauses, ctx);
2676 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2678 if (TYPE_FIELDS (ctx->record_type) == NULL)
2679 ctx->record_type = ctx->receiver_decl = NULL;
2680 else
2682 TYPE_FIELDS (ctx->record_type)
2683 = nreverse (TYPE_FIELDS (ctx->record_type));
2684 #ifdef ENABLE_CHECKING
2685 tree field;
2686 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2687 for (field = TYPE_FIELDS (ctx->record_type);
2688 field;
2689 field = DECL_CHAIN (field))
2690 gcc_assert (DECL_ALIGN (field) == align);
2691 #endif
2692 layout_type (ctx->record_type);
2693 if (offloaded)
2694 fixup_child_record_type (ctx);
2698 /* Scan an OpenMP teams directive. */
2700 static void
2701 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2703 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2704 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2705 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2708 /* Check nesting restrictions. */
2709 static bool
2710 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
2712 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2713 inside an OpenACC CTX. */
2714 if (!(is_gimple_omp (stmt)
2715 && is_gimple_omp_oacc (stmt)))
2717 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2718 if (is_gimple_omp (ctx_->stmt)
2719 && is_gimple_omp_oacc (ctx_->stmt))
2721 error_at (gimple_location (stmt),
2722 "non-OpenACC construct inside of OpenACC region");
2723 return false;
2727 if (ctx != NULL)
2729 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2730 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2732 error_at (gimple_location (stmt),
2733 "OpenMP constructs may not be nested inside simd region");
2734 return false;
2736 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2738 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2739 || (gimple_omp_for_kind (stmt)
2740 != GF_OMP_FOR_KIND_DISTRIBUTE))
2741 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2743 error_at (gimple_location (stmt),
2744 "only distribute or parallel constructs are allowed to "
2745 "be closely nested inside teams construct");
2746 return false;
2750 switch (gimple_code (stmt))
2752 case GIMPLE_OMP_FOR:
2753 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2754 return true;
2755 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2757 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2759 error_at (gimple_location (stmt),
2760 "distribute construct must be closely nested inside "
2761 "teams construct");
2762 return false;
2764 return true;
2766 /* FALLTHRU */
2767 case GIMPLE_CALL:
2768 if (is_gimple_call (stmt)
2769 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2770 == BUILT_IN_GOMP_CANCEL
2771 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2772 == BUILT_IN_GOMP_CANCELLATION_POINT))
2774 const char *bad = NULL;
2775 const char *kind = NULL;
2776 if (ctx == NULL)
2778 error_at (gimple_location (stmt), "orphaned %qs construct",
2779 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2780 == BUILT_IN_GOMP_CANCEL
2781 ? "#pragma omp cancel"
2782 : "#pragma omp cancellation point");
2783 return false;
2785 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2786 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2787 : 0)
2789 case 1:
2790 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2791 bad = "#pragma omp parallel";
2792 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2793 == BUILT_IN_GOMP_CANCEL
2794 && !integer_zerop (gimple_call_arg (stmt, 1)))
2795 ctx->cancellable = true;
2796 kind = "parallel";
2797 break;
2798 case 2:
2799 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2800 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2801 bad = "#pragma omp for";
2802 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2803 == BUILT_IN_GOMP_CANCEL
2804 && !integer_zerop (gimple_call_arg (stmt, 1)))
2806 ctx->cancellable = true;
2807 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2808 OMP_CLAUSE_NOWAIT))
2809 warning_at (gimple_location (stmt), 0,
2810 "%<#pragma omp cancel for%> inside "
2811 "%<nowait%> for construct");
2812 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2813 OMP_CLAUSE_ORDERED))
2814 warning_at (gimple_location (stmt), 0,
2815 "%<#pragma omp cancel for%> inside "
2816 "%<ordered%> for construct");
2818 kind = "for";
2819 break;
2820 case 4:
2821 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2822 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2823 bad = "#pragma omp sections";
2824 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2825 == BUILT_IN_GOMP_CANCEL
2826 && !integer_zerop (gimple_call_arg (stmt, 1)))
2828 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2830 ctx->cancellable = true;
2831 if (find_omp_clause (gimple_omp_sections_clauses
2832 (ctx->stmt),
2833 OMP_CLAUSE_NOWAIT))
2834 warning_at (gimple_location (stmt), 0,
2835 "%<#pragma omp cancel sections%> inside "
2836 "%<nowait%> sections construct");
2838 else
2840 gcc_assert (ctx->outer
2841 && gimple_code (ctx->outer->stmt)
2842 == GIMPLE_OMP_SECTIONS);
2843 ctx->outer->cancellable = true;
2844 if (find_omp_clause (gimple_omp_sections_clauses
2845 (ctx->outer->stmt),
2846 OMP_CLAUSE_NOWAIT))
2847 warning_at (gimple_location (stmt), 0,
2848 "%<#pragma omp cancel sections%> inside "
2849 "%<nowait%> sections construct");
2852 kind = "sections";
2853 break;
2854 case 8:
2855 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2856 bad = "#pragma omp task";
2857 else
2858 ctx->cancellable = true;
2859 kind = "taskgroup";
2860 break;
2861 default:
2862 error_at (gimple_location (stmt), "invalid arguments");
2863 return false;
2865 if (bad)
2867 error_at (gimple_location (stmt),
2868 "%<%s %s%> construct not closely nested inside of %qs",
2869 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2870 == BUILT_IN_GOMP_CANCEL
2871 ? "#pragma omp cancel"
2872 : "#pragma omp cancellation point", kind, bad);
2873 return false;
2876 /* FALLTHRU */
2877 case GIMPLE_OMP_SECTIONS:
2878 case GIMPLE_OMP_SINGLE:
2879 for (; ctx != NULL; ctx = ctx->outer)
2880 switch (gimple_code (ctx->stmt))
2882 case GIMPLE_OMP_FOR:
2883 case GIMPLE_OMP_SECTIONS:
2884 case GIMPLE_OMP_SINGLE:
2885 case GIMPLE_OMP_ORDERED:
2886 case GIMPLE_OMP_MASTER:
2887 case GIMPLE_OMP_TASK:
2888 case GIMPLE_OMP_CRITICAL:
2889 if (is_gimple_call (stmt))
2891 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2892 != BUILT_IN_GOMP_BARRIER)
2893 return true;
2894 error_at (gimple_location (stmt),
2895 "barrier region may not be closely nested inside "
2896 "of work-sharing, critical, ordered, master or "
2897 "explicit task region");
2898 return false;
2900 error_at (gimple_location (stmt),
2901 "work-sharing region may not be closely nested inside "
2902 "of work-sharing, critical, ordered, master or explicit "
2903 "task region");
2904 return false;
2905 case GIMPLE_OMP_PARALLEL:
2906 return true;
2907 default:
2908 break;
2910 break;
2911 case GIMPLE_OMP_MASTER:
2912 for (; ctx != NULL; ctx = ctx->outer)
2913 switch (gimple_code (ctx->stmt))
2915 case GIMPLE_OMP_FOR:
2916 case GIMPLE_OMP_SECTIONS:
2917 case GIMPLE_OMP_SINGLE:
2918 case GIMPLE_OMP_TASK:
2919 error_at (gimple_location (stmt),
2920 "master region may not be closely nested inside "
2921 "of work-sharing or explicit task region");
2922 return false;
2923 case GIMPLE_OMP_PARALLEL:
2924 return true;
2925 default:
2926 break;
2928 break;
2929 case GIMPLE_OMP_ORDERED:
2930 for (; ctx != NULL; ctx = ctx->outer)
2931 switch (gimple_code (ctx->stmt))
2933 case GIMPLE_OMP_CRITICAL:
2934 case GIMPLE_OMP_TASK:
2935 error_at (gimple_location (stmt),
2936 "ordered region may not be closely nested inside "
2937 "of critical or explicit task region");
2938 return false;
2939 case GIMPLE_OMP_FOR:
2940 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2941 OMP_CLAUSE_ORDERED) == NULL)
2943 error_at (gimple_location (stmt),
2944 "ordered region must be closely nested inside "
2945 "a loop region with an ordered clause");
2946 return false;
2948 return true;
2949 case GIMPLE_OMP_PARALLEL:
2950 error_at (gimple_location (stmt),
2951 "ordered region must be closely nested inside "
2952 "a loop region with an ordered clause");
2953 return false;
2954 default:
2955 break;
2957 break;
2958 case GIMPLE_OMP_CRITICAL:
2960 tree this_stmt_name
2961 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2962 for (; ctx != NULL; ctx = ctx->outer)
2963 if (gomp_critical *other_crit
2964 = dyn_cast <gomp_critical *> (ctx->stmt))
2965 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2967 error_at (gimple_location (stmt),
2968 "critical region may not be nested inside a critical "
2969 "region with the same name");
2970 return false;
2973 break;
2974 case GIMPLE_OMP_TEAMS:
2975 if (ctx == NULL
2976 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2977 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2979 error_at (gimple_location (stmt),
2980 "teams construct not closely nested inside of target "
2981 "region");
2982 return false;
2984 break;
2985 case GIMPLE_OMP_TARGET:
2986 for (; ctx != NULL; ctx = ctx->outer)
2988 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2990 if (is_gimple_omp (stmt)
2991 && is_gimple_omp_oacc (stmt)
2992 && is_gimple_omp (ctx->stmt))
2994 error_at (gimple_location (stmt),
2995 "OpenACC construct inside of non-OpenACC region");
2996 return false;
2998 continue;
3001 const char *stmt_name, *ctx_stmt_name;
3002 switch (gimple_omp_target_kind (stmt))
3004 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3005 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3006 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3007 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3008 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3009 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3010 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3011 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3012 default: gcc_unreachable ();
3014 switch (gimple_omp_target_kind (ctx->stmt))
3016 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3017 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3018 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3019 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3020 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3021 default: gcc_unreachable ();
3024 /* OpenACC/OpenMP mismatch? */
3025 if (is_gimple_omp_oacc (stmt)
3026 != is_gimple_omp_oacc (ctx->stmt))
3028 error_at (gimple_location (stmt),
3029 "%s %s construct inside of %s %s region",
3030 (is_gimple_omp_oacc (stmt)
3031 ? "OpenACC" : "OpenMP"), stmt_name,
3032 (is_gimple_omp_oacc (ctx->stmt)
3033 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3034 return false;
3036 if (is_gimple_omp_offloaded (ctx->stmt))
3038 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3039 if (is_gimple_omp_oacc (ctx->stmt))
3041 error_at (gimple_location (stmt),
3042 "%s construct inside of %s region",
3043 stmt_name, ctx_stmt_name);
3044 return false;
3046 else
3048 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3049 warning_at (gimple_location (stmt), 0,
3050 "%s construct inside of %s region",
3051 stmt_name, ctx_stmt_name);
3055 break;
3056 default:
3057 break;
3059 return true;
3063 /* Helper function scan_omp.
3065 Callback for walk_tree or operators in walk_gimple_stmt used to
3066 scan for OMP directives in TP. */
3068 static tree
3069 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3071 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3072 omp_context *ctx = (omp_context *) wi->info;
3073 tree t = *tp;
3075 switch (TREE_CODE (t))
3077 case VAR_DECL:
3078 case PARM_DECL:
3079 case LABEL_DECL:
3080 case RESULT_DECL:
3081 if (ctx)
3082 *tp = remap_decl (t, &ctx->cb);
3083 break;
3085 default:
3086 if (ctx && TYPE_P (t))
3087 *tp = remap_type (t, &ctx->cb);
3088 else if (!DECL_P (t))
3090 *walk_subtrees = 1;
3091 if (ctx)
3093 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3094 if (tem != TREE_TYPE (t))
3096 if (TREE_CODE (t) == INTEGER_CST)
3097 *tp = wide_int_to_tree (tem, t);
3098 else
3099 TREE_TYPE (t) = tem;
3103 break;
3106 return NULL_TREE;
3109 /* Return true if FNDECL is a setjmp or a longjmp. */
3111 static bool
3112 setjmp_or_longjmp_p (const_tree fndecl)
3114 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3115 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3116 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3117 return true;
3119 tree declname = DECL_NAME (fndecl);
3120 if (!declname)
3121 return false;
3122 const char *name = IDENTIFIER_POINTER (declname);
3123 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3127 /* Helper function for scan_omp.
3129 Callback for walk_gimple_stmt used to scan for OMP directives in
3130 the current statement in GSI. */
3132 static tree
3133 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3134 struct walk_stmt_info *wi)
3136 gimple *stmt = gsi_stmt (*gsi);
3137 omp_context *ctx = (omp_context *) wi->info;
3139 if (gimple_has_location (stmt))
3140 input_location = gimple_location (stmt);
3142 /* Check the nesting restrictions. */
3143 bool remove = false;
3144 if (is_gimple_omp (stmt))
3145 remove = !check_omp_nesting_restrictions (stmt, ctx);
3146 else if (is_gimple_call (stmt))
3148 tree fndecl = gimple_call_fndecl (stmt);
3149 if (fndecl)
3151 if (setjmp_or_longjmp_p (fndecl)
3152 && ctx
3153 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3154 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3156 remove = true;
3157 error_at (gimple_location (stmt),
3158 "setjmp/longjmp inside simd construct");
3160 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3161 switch (DECL_FUNCTION_CODE (fndecl))
3163 case BUILT_IN_GOMP_BARRIER:
3164 case BUILT_IN_GOMP_CANCEL:
3165 case BUILT_IN_GOMP_CANCELLATION_POINT:
3166 case BUILT_IN_GOMP_TASKYIELD:
3167 case BUILT_IN_GOMP_TASKWAIT:
3168 case BUILT_IN_GOMP_TASKGROUP_START:
3169 case BUILT_IN_GOMP_TASKGROUP_END:
3170 remove = !check_omp_nesting_restrictions (stmt, ctx);
3171 break;
3172 default:
3173 break;
3177 if (remove)
3179 stmt = gimple_build_nop ();
3180 gsi_replace (gsi, stmt, false);
3183 *handled_ops_p = true;
3185 switch (gimple_code (stmt))
3187 case GIMPLE_OMP_PARALLEL:
3188 taskreg_nesting_level++;
3189 scan_omp_parallel (gsi, ctx);
3190 taskreg_nesting_level--;
3191 break;
3193 case GIMPLE_OMP_TASK:
3194 taskreg_nesting_level++;
3195 scan_omp_task (gsi, ctx);
3196 taskreg_nesting_level--;
3197 break;
3199 case GIMPLE_OMP_FOR:
3200 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3201 break;
3203 case GIMPLE_OMP_SECTIONS:
3204 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3205 break;
3207 case GIMPLE_OMP_SINGLE:
3208 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3209 break;
3211 case GIMPLE_OMP_SECTION:
3212 case GIMPLE_OMP_MASTER:
3213 case GIMPLE_OMP_TASKGROUP:
3214 case GIMPLE_OMP_ORDERED:
3215 case GIMPLE_OMP_CRITICAL:
3216 ctx = new_omp_context (stmt, ctx);
3217 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3218 break;
3220 case GIMPLE_OMP_TARGET:
3221 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3222 break;
3224 case GIMPLE_OMP_TEAMS:
3225 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3226 break;
3228 case GIMPLE_BIND:
3230 tree var;
3232 *handled_ops_p = false;
3233 if (ctx)
3234 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3235 var ;
3236 var = DECL_CHAIN (var))
3237 insert_decl_map (&ctx->cb, var, var);
3239 break;
3240 default:
3241 *handled_ops_p = false;
3242 break;
3245 return NULL_TREE;
3249 /* Scan all the statements starting at the current statement. CTX
3250 contains context information about the OMP directives and
3251 clauses found during the scan. */
3253 static void
3254 scan_omp (gimple_seq *body_p, omp_context *ctx)
3256 location_t saved_location;
3257 struct walk_stmt_info wi;
3259 memset (&wi, 0, sizeof (wi));
3260 wi.info = ctx;
3261 wi.want_locations = true;
3263 saved_location = input_location;
3264 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3265 input_location = saved_location;
3268 /* Re-gimplification and code generation routines. */
3270 /* Build a call to GOMP_barrier. */
3272 static gimple *
3273 build_omp_barrier (tree lhs)
3275 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3276 : BUILT_IN_GOMP_BARRIER);
3277 gcall *g = gimple_build_call (fndecl, 0);
3278 if (lhs)
3279 gimple_call_set_lhs (g, lhs);
3280 return g;
3283 /* If a context was created for STMT when it was scanned, return it. */
3285 static omp_context *
3286 maybe_lookup_ctx (gimple *stmt)
3288 splay_tree_node n;
3289 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3290 return n ? (omp_context *) n->value : NULL;
3294 /* Find the mapping for DECL in CTX or the immediately enclosing
3295 context that has a mapping for DECL.
3297 If CTX is a nested parallel directive, we may have to use the decl
3298 mappings created in CTX's parent context. Suppose that we have the
3299 following parallel nesting (variable UIDs showed for clarity):
3301 iD.1562 = 0;
3302 #omp parallel shared(iD.1562) -> outer parallel
3303 iD.1562 = iD.1562 + 1;
3305 #omp parallel shared (iD.1562) -> inner parallel
3306 iD.1562 = iD.1562 - 1;
3308 Each parallel structure will create a distinct .omp_data_s structure
3309 for copying iD.1562 in/out of the directive:
3311 outer parallel .omp_data_s.1.i -> iD.1562
3312 inner parallel .omp_data_s.2.i -> iD.1562
3314 A shared variable mapping will produce a copy-out operation before
3315 the parallel directive and a copy-in operation after it. So, in
3316 this case we would have:
3318 iD.1562 = 0;
3319 .omp_data_o.1.i = iD.1562;
3320 #omp parallel shared(iD.1562) -> outer parallel
3321 .omp_data_i.1 = &.omp_data_o.1
3322 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3324 .omp_data_o.2.i = iD.1562; -> **
3325 #omp parallel shared(iD.1562) -> inner parallel
3326 .omp_data_i.2 = &.omp_data_o.2
3327 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3330 ** This is a problem. The symbol iD.1562 cannot be referenced
3331 inside the body of the outer parallel region. But since we are
3332 emitting this copy operation while expanding the inner parallel
3333 directive, we need to access the CTX structure of the outer
3334 parallel directive to get the correct mapping:
3336 .omp_data_o.2.i = .omp_data_i.1->i
3338 Since there may be other workshare or parallel directives enclosing
3339 the parallel directive, it may be necessary to walk up the context
3340 parent chain. This is not a problem in general because nested
3341 parallelism happens only rarely. */
3343 static tree
3344 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3346 tree t;
3347 omp_context *up;
3349 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3350 t = maybe_lookup_decl (decl, up);
3352 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3354 return t ? t : decl;
3358 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3359 in outer contexts. */
3361 static tree
3362 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3364 tree t = NULL;
3365 omp_context *up;
3367 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3368 t = maybe_lookup_decl (decl, up);
3370 return t ? t : decl;
3374 /* Construct the initialization value for reduction operation OP. */
3376 tree
3377 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
3379 switch (op)
3381 case PLUS_EXPR:
3382 case MINUS_EXPR:
3383 case BIT_IOR_EXPR:
3384 case BIT_XOR_EXPR:
3385 case TRUTH_OR_EXPR:
3386 case TRUTH_ORIF_EXPR:
3387 case TRUTH_XOR_EXPR:
3388 case NE_EXPR:
3389 return build_zero_cst (type);
3391 case MULT_EXPR:
3392 case TRUTH_AND_EXPR:
3393 case TRUTH_ANDIF_EXPR:
3394 case EQ_EXPR:
3395 return fold_convert_loc (loc, type, integer_one_node);
3397 case BIT_AND_EXPR:
3398 return fold_convert_loc (loc, type, integer_minus_one_node);
3400 case MAX_EXPR:
3401 if (SCALAR_FLOAT_TYPE_P (type))
3403 REAL_VALUE_TYPE max, min;
3404 if (HONOR_INFINITIES (type))
3406 real_inf (&max);
3407 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3409 else
3410 real_maxval (&min, 1, TYPE_MODE (type));
3411 return build_real (type, min);
3413 else if (POINTER_TYPE_P (type))
3415 wide_int min
3416 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3417 return wide_int_to_tree (type, min);
3419 else
3421 gcc_assert (INTEGRAL_TYPE_P (type));
3422 return TYPE_MIN_VALUE (type);
3425 case MIN_EXPR:
3426 if (SCALAR_FLOAT_TYPE_P (type))
3428 REAL_VALUE_TYPE max;
3429 if (HONOR_INFINITIES (type))
3430 real_inf (&max);
3431 else
3432 real_maxval (&max, 0, TYPE_MODE (type));
3433 return build_real (type, max);
3435 else if (POINTER_TYPE_P (type))
3437 wide_int max
3438 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
3439 return wide_int_to_tree (type, max);
3441 else
3443 gcc_assert (INTEGRAL_TYPE_P (type));
3444 return TYPE_MAX_VALUE (type);
3447 default:
3448 gcc_unreachable ();
3452 /* Construct the initialization value for reduction CLAUSE. */
3454 tree
3455 omp_reduction_init (tree clause, tree type)
3457 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
3458 OMP_CLAUSE_REDUCTION_CODE (clause), type);
3461 /* Return alignment to be assumed for var in CLAUSE, which should be
3462 OMP_CLAUSE_ALIGNED. */
3464 static tree
3465 omp_clause_aligned_alignment (tree clause)
3467 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3468 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3470 /* Otherwise return implementation defined alignment. */
3471 unsigned int al = 1;
3472 machine_mode mode, vmode;
3473 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3474 if (vs)
3475 vs = 1 << floor_log2 (vs);
3476 static enum mode_class classes[]
3477 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3478 for (int i = 0; i < 4; i += 2)
3479 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3480 mode != VOIDmode;
3481 mode = GET_MODE_WIDER_MODE (mode))
3483 vmode = targetm.vectorize.preferred_simd_mode (mode);
3484 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3485 continue;
3486 while (vs
3487 && GET_MODE_SIZE (vmode) < vs
3488 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3489 vmode = GET_MODE_2XWIDER_MODE (vmode);
3491 tree type = lang_hooks.types.type_for_mode (mode, 1);
3492 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3493 continue;
3494 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3495 / GET_MODE_SIZE (mode));
3496 if (TYPE_MODE (type) != vmode)
3497 continue;
3498 if (TYPE_ALIGN_UNIT (type) > al)
3499 al = TYPE_ALIGN_UNIT (type);
3501 return build_int_cst (integer_type_node, al);
3504 /* Return maximum possible vectorization factor for the target. */
3506 static int
3507 omp_max_vf (void)
3509 if (!optimize
3510 || optimize_debug
3511 || !flag_tree_loop_optimize
3512 || (!flag_tree_loop_vectorize
3513 && (global_options_set.x_flag_tree_loop_vectorize
3514 || global_options_set.x_flag_tree_vectorize)))
3515 return 1;
3517 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3518 if (vs)
3520 vs = 1 << floor_log2 (vs);
3521 return vs;
3523 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3524 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3525 return GET_MODE_NUNITS (vqimode);
3526 return 1;
3529 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3530 privatization. */
3532 static bool
3533 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3534 tree &idx, tree &lane, tree &ivar, tree &lvar)
3536 if (max_vf == 0)
3538 max_vf = omp_max_vf ();
3539 if (max_vf > 1)
3541 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3542 OMP_CLAUSE_SAFELEN);
3543 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3544 max_vf = 1;
3545 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3546 max_vf) == -1)
3547 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3549 if (max_vf > 1)
3551 idx = create_tmp_var (unsigned_type_node);
3552 lane = create_tmp_var (unsigned_type_node);
3555 if (max_vf == 1)
3556 return false;
3558 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3559 tree avar = create_tmp_var_raw (atype);
3560 if (TREE_ADDRESSABLE (new_var))
3561 TREE_ADDRESSABLE (avar) = 1;
3562 DECL_ATTRIBUTES (avar)
3563 = tree_cons (get_identifier ("omp simd array"), NULL,
3564 DECL_ATTRIBUTES (avar));
3565 gimple_add_tmp_var (avar);
3566 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3567 NULL_TREE, NULL_TREE);
3568 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3569 NULL_TREE, NULL_TREE);
3570 if (DECL_P (new_var))
3572 SET_DECL_VALUE_EXPR (new_var, lvar);
3573 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3575 return true;
3578 /* Helper function of lower_rec_input_clauses. For a reference
3579 in simd reduction, add an underlying variable it will reference. */
3581 static void
3582 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3584 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3585 if (TREE_CONSTANT (z))
3587 const char *name = NULL;
3588 if (DECL_NAME (new_vard))
3589 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3591 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3592 gimple_add_tmp_var (z);
3593 TREE_ADDRESSABLE (z) = 1;
3594 z = build_fold_addr_expr_loc (loc, z);
3595 gimplify_assign (new_vard, z, ilist);
3599 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3600 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3601 private variables. Initialization statements go in ILIST, while calls
3602 to destructors go in DLIST. */
3604 static void
3605 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3606 omp_context *ctx, struct omp_for_data *fd)
3608 tree c, dtor, copyin_seq, x, ptr;
3609 bool copyin_by_ref = false;
3610 bool lastprivate_firstprivate = false;
3611 bool reduction_omp_orig_ref = false;
3612 int pass;
3613 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3614 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3615 int max_vf = 0;
3616 tree lane = NULL_TREE, idx = NULL_TREE;
3617 tree ivar = NULL_TREE, lvar = NULL_TREE;
3618 gimple_seq llist[2] = { NULL, NULL };
3620 copyin_seq = NULL;
3622 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3623 with data sharing clauses referencing variable sized vars. That
3624 is unnecessarily hard to support and very unlikely to result in
3625 vectorized code anyway. */
3626 if (is_simd)
3627 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3628 switch (OMP_CLAUSE_CODE (c))
3630 case OMP_CLAUSE_LINEAR:
3631 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3632 max_vf = 1;
3633 /* FALLTHRU */
3634 case OMP_CLAUSE_REDUCTION:
3635 case OMP_CLAUSE_PRIVATE:
3636 case OMP_CLAUSE_FIRSTPRIVATE:
3637 case OMP_CLAUSE_LASTPRIVATE:
3638 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3639 max_vf = 1;
3640 break;
3641 default:
3642 continue;
3645 /* Do all the fixed sized types in the first pass, and the variable sized
3646 types in the second pass. This makes sure that the scalar arguments to
3647 the variable sized types are processed before we use them in the
3648 variable sized operations. */
3649 for (pass = 0; pass < 2; ++pass)
3651 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3653 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3654 tree var, new_var;
3655 bool by_ref;
3656 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3658 switch (c_kind)
3660 case OMP_CLAUSE_PRIVATE:
3661 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3662 continue;
3663 break;
3664 case OMP_CLAUSE_SHARED:
3665 /* Ignore shared directives in teams construct. */
3666 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3667 continue;
3668 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3670 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3671 continue;
3673 case OMP_CLAUSE_FIRSTPRIVATE:
3674 case OMP_CLAUSE_COPYIN:
3675 case OMP_CLAUSE_LINEAR:
3676 break;
3677 case OMP_CLAUSE_REDUCTION:
3678 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3679 reduction_omp_orig_ref = true;
3680 break;
3681 case OMP_CLAUSE__LOOPTEMP_:
3682 /* Handle _looptemp_ clauses only on parallel. */
3683 if (fd)
3684 continue;
3685 break;
3686 case OMP_CLAUSE_LASTPRIVATE:
3687 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3689 lastprivate_firstprivate = true;
3690 if (pass != 0)
3691 continue;
3693 /* Even without corresponding firstprivate, if
3694 decl is Fortran allocatable, it needs outer var
3695 reference. */
3696 else if (pass == 0
3697 && lang_hooks.decls.omp_private_outer_ref
3698 (OMP_CLAUSE_DECL (c)))
3699 lastprivate_firstprivate = true;
3700 break;
3701 case OMP_CLAUSE_ALIGNED:
3702 if (pass == 0)
3703 continue;
3704 var = OMP_CLAUSE_DECL (c);
3705 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3706 && !is_global_var (var))
3708 new_var = maybe_lookup_decl (var, ctx);
3709 if (new_var == NULL_TREE)
3710 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3711 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3712 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3713 omp_clause_aligned_alignment (c));
3714 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3715 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3716 gimplify_and_add (x, ilist);
3718 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3719 && is_global_var (var))
3721 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3722 new_var = lookup_decl (var, ctx);
3723 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3724 t = build_fold_addr_expr_loc (clause_loc, t);
3725 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3726 t = build_call_expr_loc (clause_loc, t2, 2, t,
3727 omp_clause_aligned_alignment (c));
3728 t = fold_convert_loc (clause_loc, ptype, t);
3729 x = create_tmp_var (ptype);
3730 t = build2 (MODIFY_EXPR, ptype, x, t);
3731 gimplify_and_add (t, ilist);
3732 t = build_simple_mem_ref_loc (clause_loc, x);
3733 SET_DECL_VALUE_EXPR (new_var, t);
3734 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3736 continue;
3737 default:
3738 continue;
3741 new_var = var = OMP_CLAUSE_DECL (c);
3742 if (c_kind != OMP_CLAUSE_COPYIN)
3743 new_var = lookup_decl (var, ctx);
3745 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3747 if (pass != 0)
3748 continue;
3750 else if (is_variable_sized (var))
3752 /* For variable sized types, we need to allocate the
3753 actual storage here. Call alloca and store the
3754 result in the pointer decl that we created elsewhere. */
3755 if (pass == 0)
3756 continue;
3758 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3760 gcall *stmt;
3761 tree tmp, atmp;
3763 ptr = DECL_VALUE_EXPR (new_var);
3764 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3765 ptr = TREE_OPERAND (ptr, 0);
3766 gcc_assert (DECL_P (ptr));
3767 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3769 /* void *tmp = __builtin_alloca */
3770 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3771 stmt = gimple_build_call (atmp, 1, x);
3772 tmp = create_tmp_var_raw (ptr_type_node);
3773 gimple_add_tmp_var (tmp);
3774 gimple_call_set_lhs (stmt, tmp);
3776 gimple_seq_add_stmt (ilist, stmt);
3778 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3779 gimplify_assign (ptr, x, ilist);
3782 else if (is_reference (var))
3784 /* For references that are being privatized for Fortran,
3785 allocate new backing storage for the new pointer
3786 variable. This allows us to avoid changing all the
3787 code that expects a pointer to something that expects
3788 a direct variable. */
3789 if (pass == 0)
3790 continue;
3792 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3793 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3795 x = build_receiver_ref (var, false, ctx);
3796 x = build_fold_addr_expr_loc (clause_loc, x);
3798 else if (TREE_CONSTANT (x))
3800 /* For reduction in SIMD loop, defer adding the
3801 initialization of the reference, because if we decide
3802 to use SIMD array for it, the initilization could cause
3803 expansion ICE. */
3804 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3805 x = NULL_TREE;
3806 else
3808 const char *name = NULL;
3809 if (DECL_NAME (var))
3810 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3812 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3813 name);
3814 gimple_add_tmp_var (x);
3815 TREE_ADDRESSABLE (x) = 1;
3816 x = build_fold_addr_expr_loc (clause_loc, x);
3819 else
3821 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3822 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3825 if (x)
3827 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3828 gimplify_assign (new_var, x, ilist);
3831 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3833 else if (c_kind == OMP_CLAUSE_REDUCTION
3834 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3836 if (pass == 0)
3837 continue;
3839 else if (pass != 0)
3840 continue;
3842 switch (OMP_CLAUSE_CODE (c))
3844 case OMP_CLAUSE_SHARED:
3845 /* Ignore shared directives in teams construct. */
3846 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3847 continue;
3848 /* Shared global vars are just accessed directly. */
3849 if (is_global_var (new_var))
3850 break;
3851 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3852 needs to be delayed until after fixup_child_record_type so
3853 that we get the correct type during the dereference. */
3854 by_ref = use_pointer_for_field (var, ctx);
3855 x = build_receiver_ref (var, by_ref, ctx);
3856 SET_DECL_VALUE_EXPR (new_var, x);
3857 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3859 /* ??? If VAR is not passed by reference, and the variable
3860 hasn't been initialized yet, then we'll get a warning for
3861 the store into the omp_data_s structure. Ideally, we'd be
3862 able to notice this and not store anything at all, but
3863 we're generating code too early. Suppress the warning. */
3864 if (!by_ref)
3865 TREE_NO_WARNING (var) = 1;
3866 break;
3868 case OMP_CLAUSE_LASTPRIVATE:
3869 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3870 break;
3871 /* FALLTHRU */
3873 case OMP_CLAUSE_PRIVATE:
3874 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3875 x = build_outer_var_ref (var, ctx);
3876 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3878 if (is_task_ctx (ctx))
3879 x = build_receiver_ref (var, false, ctx);
3880 else
3881 x = build_outer_var_ref (var, ctx);
3883 else
3884 x = NULL;
3885 do_private:
3886 tree nx;
3887 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3888 if (is_simd)
3890 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3891 if ((TREE_ADDRESSABLE (new_var) || nx || y
3892 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3893 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3894 idx, lane, ivar, lvar))
3896 if (nx)
3897 x = lang_hooks.decls.omp_clause_default_ctor
3898 (c, unshare_expr (ivar), x);
3899 if (nx && x)
3900 gimplify_and_add (x, &llist[0]);
3901 if (y)
3903 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3904 if (y)
3906 gimple_seq tseq = NULL;
3908 dtor = y;
3909 gimplify_stmt (&dtor, &tseq);
3910 gimple_seq_add_seq (&llist[1], tseq);
3913 break;
3916 if (nx)
3917 gimplify_and_add (nx, ilist);
3918 /* FALLTHRU */
3920 do_dtor:
3921 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3922 if (x)
3924 gimple_seq tseq = NULL;
3926 dtor = x;
3927 gimplify_stmt (&dtor, &tseq);
3928 gimple_seq_add_seq (dlist, tseq);
3930 break;
3932 case OMP_CLAUSE_LINEAR:
3933 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3934 goto do_firstprivate;
3935 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3936 x = NULL;
3937 else
3938 x = build_outer_var_ref (var, ctx);
3939 goto do_private;
3941 case OMP_CLAUSE_FIRSTPRIVATE:
3942 if (is_task_ctx (ctx))
3944 if (is_reference (var) || is_variable_sized (var))
3945 goto do_dtor;
3946 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3947 ctx))
3948 || use_pointer_for_field (var, NULL))
3950 x = build_receiver_ref (var, false, ctx);
3951 SET_DECL_VALUE_EXPR (new_var, x);
3952 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3953 goto do_dtor;
3956 do_firstprivate:
3957 x = build_outer_var_ref (var, ctx);
3958 if (is_simd)
3960 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3961 && gimple_omp_for_combined_into_p (ctx->stmt))
3963 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3964 tree stept = TREE_TYPE (t);
3965 tree ct = find_omp_clause (clauses,
3966 OMP_CLAUSE__LOOPTEMP_);
3967 gcc_assert (ct);
3968 tree l = OMP_CLAUSE_DECL (ct);
3969 tree n1 = fd->loop.n1;
3970 tree step = fd->loop.step;
3971 tree itype = TREE_TYPE (l);
3972 if (POINTER_TYPE_P (itype))
3973 itype = signed_type_for (itype);
3974 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3975 if (TYPE_UNSIGNED (itype)
3976 && fd->loop.cond_code == GT_EXPR)
3977 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3978 fold_build1 (NEGATE_EXPR, itype, l),
3979 fold_build1 (NEGATE_EXPR,
3980 itype, step));
3981 else
3982 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3983 t = fold_build2 (MULT_EXPR, stept,
3984 fold_convert (stept, l), t);
3986 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3988 x = lang_hooks.decls.omp_clause_linear_ctor
3989 (c, new_var, x, t);
3990 gimplify_and_add (x, ilist);
3991 goto do_dtor;
3994 if (POINTER_TYPE_P (TREE_TYPE (x)))
3995 x = fold_build2 (POINTER_PLUS_EXPR,
3996 TREE_TYPE (x), x, t);
3997 else
3998 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4001 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4002 || TREE_ADDRESSABLE (new_var))
4003 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4004 idx, lane, ivar, lvar))
4006 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4008 tree iv = create_tmp_var (TREE_TYPE (new_var));
4009 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4010 gimplify_and_add (x, ilist);
4011 gimple_stmt_iterator gsi
4012 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4013 gassign *g
4014 = gimple_build_assign (unshare_expr (lvar), iv);
4015 gsi_insert_before_without_update (&gsi, g,
4016 GSI_SAME_STMT);
4017 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4018 enum tree_code code = PLUS_EXPR;
4019 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4020 code = POINTER_PLUS_EXPR;
4021 g = gimple_build_assign (iv, code, iv, t);
4022 gsi_insert_before_without_update (&gsi, g,
4023 GSI_SAME_STMT);
4024 break;
4026 x = lang_hooks.decls.omp_clause_copy_ctor
4027 (c, unshare_expr (ivar), x);
4028 gimplify_and_add (x, &llist[0]);
4029 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4030 if (x)
4032 gimple_seq tseq = NULL;
4034 dtor = x;
4035 gimplify_stmt (&dtor, &tseq);
4036 gimple_seq_add_seq (&llist[1], tseq);
4038 break;
4041 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4042 gimplify_and_add (x, ilist);
4043 goto do_dtor;
4045 case OMP_CLAUSE__LOOPTEMP_:
4046 gcc_assert (is_parallel_ctx (ctx));
4047 x = build_outer_var_ref (var, ctx);
4048 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4049 gimplify_and_add (x, ilist);
4050 break;
4052 case OMP_CLAUSE_COPYIN:
4053 by_ref = use_pointer_for_field (var, NULL);
4054 x = build_receiver_ref (var, by_ref, ctx);
4055 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4056 append_to_statement_list (x, &copyin_seq);
4057 copyin_by_ref |= by_ref;
4058 break;
4060 case OMP_CLAUSE_REDUCTION:
4061 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4063 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4064 gimple *tseq;
4065 x = build_outer_var_ref (var, ctx);
4067 if (is_reference (var)
4068 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4069 TREE_TYPE (x)))
4070 x = build_fold_addr_expr_loc (clause_loc, x);
4071 SET_DECL_VALUE_EXPR (placeholder, x);
4072 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4073 tree new_vard = new_var;
4074 if (is_reference (var))
4076 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4077 new_vard = TREE_OPERAND (new_var, 0);
4078 gcc_assert (DECL_P (new_vard));
4080 if (is_simd
4081 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4082 idx, lane, ivar, lvar))
4084 if (new_vard == new_var)
4086 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4087 SET_DECL_VALUE_EXPR (new_var, ivar);
4089 else
4091 SET_DECL_VALUE_EXPR (new_vard,
4092 build_fold_addr_expr (ivar));
4093 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4095 x = lang_hooks.decls.omp_clause_default_ctor
4096 (c, unshare_expr (ivar),
4097 build_outer_var_ref (var, ctx));
4098 if (x)
4099 gimplify_and_add (x, &llist[0]);
4100 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4102 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4103 lower_omp (&tseq, ctx);
4104 gimple_seq_add_seq (&llist[0], tseq);
4106 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4107 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4108 lower_omp (&tseq, ctx);
4109 gimple_seq_add_seq (&llist[1], tseq);
4110 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4111 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4112 if (new_vard == new_var)
4113 SET_DECL_VALUE_EXPR (new_var, lvar);
4114 else
4115 SET_DECL_VALUE_EXPR (new_vard,
4116 build_fold_addr_expr (lvar));
4117 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4118 if (x)
4120 tseq = NULL;
4121 dtor = x;
4122 gimplify_stmt (&dtor, &tseq);
4123 gimple_seq_add_seq (&llist[1], tseq);
4125 break;
4127 /* If this is a reference to constant size reduction var
4128 with placeholder, we haven't emitted the initializer
4129 for it because it is undesirable if SIMD arrays are used.
4130 But if they aren't used, we need to emit the deferred
4131 initialization now. */
4132 else if (is_reference (var) && is_simd)
4133 handle_simd_reference (clause_loc, new_vard, ilist);
4134 x = lang_hooks.decls.omp_clause_default_ctor
4135 (c, unshare_expr (new_var),
4136 build_outer_var_ref (var, ctx));
4137 if (x)
4138 gimplify_and_add (x, ilist);
4139 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4141 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4142 lower_omp (&tseq, ctx);
4143 gimple_seq_add_seq (ilist, tseq);
4145 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4146 if (is_simd)
4148 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4149 lower_omp (&tseq, ctx);
4150 gimple_seq_add_seq (dlist, tseq);
4151 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4153 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4154 goto do_dtor;
4156 else
4158 x = omp_reduction_init (c, TREE_TYPE (new_var));
4159 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4160 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4162 /* reduction(-:var) sums up the partial results, so it
4163 acts identically to reduction(+:var). */
4164 if (code == MINUS_EXPR)
4165 code = PLUS_EXPR;
4167 tree new_vard = new_var;
4168 if (is_simd && is_reference (var))
4170 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4171 new_vard = TREE_OPERAND (new_var, 0);
4172 gcc_assert (DECL_P (new_vard));
4174 if (is_simd
4175 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4176 idx, lane, ivar, lvar))
4178 tree ref = build_outer_var_ref (var, ctx);
4180 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4182 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4183 ref = build_outer_var_ref (var, ctx);
4184 gimplify_assign (ref, x, &llist[1]);
4186 if (new_vard != new_var)
4188 SET_DECL_VALUE_EXPR (new_vard,
4189 build_fold_addr_expr (lvar));
4190 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4193 else
4195 if (is_reference (var) && is_simd)
4196 handle_simd_reference (clause_loc, new_vard, ilist);
4197 gimplify_assign (new_var, x, ilist);
4198 if (is_simd)
4200 tree ref = build_outer_var_ref (var, ctx);
4202 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4203 ref = build_outer_var_ref (var, ctx);
4204 gimplify_assign (ref, x, dlist);
4208 break;
4210 default:
4211 gcc_unreachable ();
4216 if (lane)
4218 tree uid = create_tmp_var (ptr_type_node, "simduid");
4219 /* Don't want uninit warnings on simduid, it is always uninitialized,
4220 but we use it not for the value, but for the DECL_UID only. */
4221 TREE_NO_WARNING (uid) = 1;
4222 gimple *g
4223 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4224 gimple_call_set_lhs (g, lane);
4225 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4226 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4227 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4228 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4229 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4230 gimple_omp_for_set_clauses (ctx->stmt, c);
4231 g = gimple_build_assign (lane, INTEGER_CST,
4232 build_int_cst (unsigned_type_node, 0));
4233 gimple_seq_add_stmt (ilist, g);
4234 for (int i = 0; i < 2; i++)
4235 if (llist[i])
4237 tree vf = create_tmp_var (unsigned_type_node);
4238 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4239 gimple_call_set_lhs (g, vf);
4240 gimple_seq *seq = i == 0 ? ilist : dlist;
4241 gimple_seq_add_stmt (seq, g);
4242 tree t = build_int_cst (unsigned_type_node, 0);
4243 g = gimple_build_assign (idx, INTEGER_CST, t);
4244 gimple_seq_add_stmt (seq, g);
4245 tree body = create_artificial_label (UNKNOWN_LOCATION);
4246 tree header = create_artificial_label (UNKNOWN_LOCATION);
4247 tree end = create_artificial_label (UNKNOWN_LOCATION);
4248 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4249 gimple_seq_add_stmt (seq, gimple_build_label (body));
4250 gimple_seq_add_seq (seq, llist[i]);
4251 t = build_int_cst (unsigned_type_node, 1);
4252 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4253 gimple_seq_add_stmt (seq, g);
4254 gimple_seq_add_stmt (seq, gimple_build_label (header));
4255 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4256 gimple_seq_add_stmt (seq, g);
4257 gimple_seq_add_stmt (seq, gimple_build_label (end));
4261 /* The copyin sequence is not to be executed by the main thread, since
4262 that would result in self-copies. Perhaps not visible to scalars,
4263 but it certainly is to C++ operator=. */
4264 if (copyin_seq)
4266 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4268 x = build2 (NE_EXPR, boolean_type_node, x,
4269 build_int_cst (TREE_TYPE (x), 0));
4270 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4271 gimplify_and_add (x, ilist);
4274 /* If any copyin variable is passed by reference, we must ensure the
4275 master thread doesn't modify it before it is copied over in all
4276 threads. Similarly for variables in both firstprivate and
4277 lastprivate clauses we need to ensure the lastprivate copying
4278 happens after firstprivate copying in all threads. And similarly
4279 for UDRs if initializer expression refers to omp_orig. */
4280 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4282 /* Don't add any barrier for #pragma omp simd or
4283 #pragma omp distribute. */
4284 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4285 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4286 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4289 /* If max_vf is non-zero, then we can use only a vectorization factor
4290 up to the max_vf we chose. So stick it into the safelen clause. */
4291 if (max_vf)
4293 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4294 OMP_CLAUSE_SAFELEN);
4295 if (c == NULL_TREE
4296 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4297 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4298 max_vf) == 1))
4300 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4301 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4302 max_vf);
4303 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4304 gimple_omp_for_set_clauses (ctx->stmt, c);
4310 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4311 both parallel and workshare constructs. PREDICATE may be NULL if it's
4312 always true. */
4314 static void
4315 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4316 omp_context *ctx)
4318 tree x, c, label = NULL, orig_clauses = clauses;
4319 bool par_clauses = false;
4320 tree simduid = NULL, lastlane = NULL;
4322 /* Early exit if there are no lastprivate or linear clauses. */
4323 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4324 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4325 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4326 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4327 break;
4328 if (clauses == NULL)
4330 /* If this was a workshare clause, see if it had been combined
4331 with its parallel. In that case, look for the clauses on the
4332 parallel statement itself. */
4333 if (is_parallel_ctx (ctx))
4334 return;
4336 ctx = ctx->outer;
4337 if (ctx == NULL || !is_parallel_ctx (ctx))
4338 return;
4340 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4341 OMP_CLAUSE_LASTPRIVATE);
4342 if (clauses == NULL)
4343 return;
4344 par_clauses = true;
4347 if (predicate)
4349 gcond *stmt;
4350 tree label_true, arm1, arm2;
4352 label = create_artificial_label (UNKNOWN_LOCATION);
4353 label_true = create_artificial_label (UNKNOWN_LOCATION);
4354 arm1 = TREE_OPERAND (predicate, 0);
4355 arm2 = TREE_OPERAND (predicate, 1);
4356 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4357 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4358 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4359 label_true, label);
4360 gimple_seq_add_stmt (stmt_list, stmt);
4361 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4364 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4365 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4367 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4368 if (simduid)
4369 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4372 for (c = clauses; c ;)
4374 tree var, new_var;
4375 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4377 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4378 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4379 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4381 var = OMP_CLAUSE_DECL (c);
4382 new_var = lookup_decl (var, ctx);
4384 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4386 tree val = DECL_VALUE_EXPR (new_var);
4387 if (TREE_CODE (val) == ARRAY_REF
4388 && VAR_P (TREE_OPERAND (val, 0))
4389 && lookup_attribute ("omp simd array",
4390 DECL_ATTRIBUTES (TREE_OPERAND (val,
4391 0))))
4393 if (lastlane == NULL)
4395 lastlane = create_tmp_var (unsigned_type_node);
4396 gcall *g
4397 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4398 2, simduid,
4399 TREE_OPERAND (val, 1));
4400 gimple_call_set_lhs (g, lastlane);
4401 gimple_seq_add_stmt (stmt_list, g);
4403 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4404 TREE_OPERAND (val, 0), lastlane,
4405 NULL_TREE, NULL_TREE);
4409 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4410 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4412 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4413 gimple_seq_add_seq (stmt_list,
4414 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4415 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4417 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4418 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4420 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4421 gimple_seq_add_seq (stmt_list,
4422 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4423 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4426 x = build_outer_var_ref (var, ctx);
4427 if (is_reference (var))
4428 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4429 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4430 gimplify_and_add (x, stmt_list);
4432 c = OMP_CLAUSE_CHAIN (c);
4433 if (c == NULL && !par_clauses)
4435 /* If this was a workshare clause, see if it had been combined
4436 with its parallel. In that case, continue looking for the
4437 clauses also on the parallel statement itself. */
4438 if (is_parallel_ctx (ctx))
4439 break;
4441 ctx = ctx->outer;
4442 if (ctx == NULL || !is_parallel_ctx (ctx))
4443 break;
4445 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4446 OMP_CLAUSE_LASTPRIVATE);
4447 par_clauses = true;
4451 if (label)
4452 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4455 static void
4456 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4457 tree tid, tree var, tree new_var)
4459 /* The atomic add at the end of the sum creates unnecessary
4460 write contention on accelerators. To work around this,
4461 create an array to store the partial reductions. Later, in
4462 lower_omp_for (for openacc), the values of array will be
4463 combined. */
4465 tree t = NULL_TREE, array, x;
4466 tree type = get_base_type (var);
4467 gimple *stmt;
4469 /* Now insert the partial reductions into the array. */
4471 /* Find the reduction array. */
4473 tree ptype = build_pointer_type (type);
4475 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4476 t = build_receiver_ref (t, false, ctx->outer);
4478 array = create_tmp_var (ptype);
4479 gimplify_assign (array, t, stmt_seqp);
4481 tree ptr = create_tmp_var (TREE_TYPE (array));
4483 /* Find the reduction array. */
4485 /* testing a unary conversion. */
4486 tree offset = create_tmp_var (sizetype);
4487 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4488 stmt_seqp);
4489 t = create_tmp_var (sizetype);
4490 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4491 stmt_seqp);
4492 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4493 gimple_seq_add_stmt (stmt_seqp, stmt);
4495 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4496 of adding sizeof(var) to the array? */
4497 ptr = create_tmp_var (ptype);
4498 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4499 offset);
4500 gimple_seq_add_stmt (stmt_seqp, stmt);
4502 /* Move the local sum to gfc$sum[i]. */
4503 x = unshare_expr (build_simple_mem_ref (ptr));
4504 stmt = gimplify_assign (x, new_var, stmt_seqp);
4507 /* Generate code to implement the REDUCTION clauses. */
4509 static void
4510 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4512 gimple_seq sub_seq = NULL;
4513 gimple *stmt;
4514 tree x, c, tid = NULL_TREE;
4515 int count = 0;
4517 /* SIMD reductions are handled in lower_rec_input_clauses. */
4518 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4519 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4520 return;
4522 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4523 update in that case, otherwise use a lock. */
4524 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4525 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4527 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4529 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4530 count = -1;
4531 break;
4533 count++;
4536 if (count == 0)
4537 return;
4539 /* Initialize thread info for OpenACC. */
4540 if (is_gimple_omp_oacc (ctx->stmt))
4542 /* Get the current thread id. */
4543 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4544 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4545 gimple *stmt = gimple_build_call (call, 0);
4546 gimple_call_set_lhs (stmt, tid);
4547 gimple_seq_add_stmt (stmt_seqp, stmt);
4550 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4552 tree var, ref, new_var;
4553 enum tree_code code;
4554 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4556 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4557 continue;
4559 var = OMP_CLAUSE_DECL (c);
4560 new_var = lookup_decl (var, ctx);
4561 if (is_reference (var))
4562 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4563 ref = build_outer_var_ref (var, ctx);
4564 code = OMP_CLAUSE_REDUCTION_CODE (c);
4566 /* reduction(-:var) sums up the partial results, so it acts
4567 identically to reduction(+:var). */
4568 if (code == MINUS_EXPR)
4569 code = PLUS_EXPR;
4571 if (is_gimple_omp_oacc (ctx->stmt))
4573 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4575 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4577 else if (count == 1)
4579 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4581 addr = save_expr (addr);
4582 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4583 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4584 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4585 gimplify_and_add (x, stmt_seqp);
4586 return;
4588 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4590 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4592 if (is_reference (var)
4593 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4594 TREE_TYPE (ref)))
4595 ref = build_fold_addr_expr_loc (clause_loc, ref);
4596 SET_DECL_VALUE_EXPR (placeholder, ref);
4597 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4598 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4599 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4600 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4601 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4603 else
4605 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4606 ref = build_outer_var_ref (var, ctx);
4607 gimplify_assign (ref, x, &sub_seq);
4611 if (is_gimple_omp_oacc (ctx->stmt))
4612 return;
4614 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4616 gimple_seq_add_stmt (stmt_seqp, stmt);
4618 gimple_seq_add_seq (stmt_seqp, sub_seq);
4620 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4622 gimple_seq_add_stmt (stmt_seqp, stmt);
4626 /* Generate code to implement the COPYPRIVATE clauses. */
4628 static void
4629 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4630 omp_context *ctx)
4632 tree c;
4634 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4636 tree var, new_var, ref, x;
4637 bool by_ref;
4638 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4640 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4641 continue;
4643 var = OMP_CLAUSE_DECL (c);
4644 by_ref = use_pointer_for_field (var, NULL);
4646 ref = build_sender_ref (var, ctx);
4647 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4648 if (by_ref)
4650 x = build_fold_addr_expr_loc (clause_loc, new_var);
4651 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4653 gimplify_assign (ref, x, slist);
4655 ref = build_receiver_ref (var, false, ctx);
4656 if (by_ref)
4658 ref = fold_convert_loc (clause_loc,
4659 build_pointer_type (TREE_TYPE (new_var)),
4660 ref);
4661 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4663 if (is_reference (var))
4665 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4666 ref = build_simple_mem_ref_loc (clause_loc, ref);
4667 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4669 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4670 gimplify_and_add (x, rlist);
4675 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4676 and REDUCTION from the sender (aka parent) side. */
4678 static void
4679 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4680 omp_context *ctx)
4682 tree c;
4684 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4686 tree val, ref, x, var;
4687 bool by_ref, do_in = false, do_out = false;
4688 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4690 switch (OMP_CLAUSE_CODE (c))
4692 case OMP_CLAUSE_PRIVATE:
4693 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4694 break;
4695 continue;
4696 case OMP_CLAUSE_FIRSTPRIVATE:
4697 case OMP_CLAUSE_COPYIN:
4698 case OMP_CLAUSE_LASTPRIVATE:
4699 case OMP_CLAUSE_REDUCTION:
4700 case OMP_CLAUSE__LOOPTEMP_:
4701 break;
4702 default:
4703 continue;
4706 val = OMP_CLAUSE_DECL (c);
4707 var = lookup_decl_in_outer_ctx (val, ctx);
4709 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4710 && is_global_var (var))
4711 continue;
4712 if (is_variable_sized (val))
4713 continue;
4714 by_ref = use_pointer_for_field (val, NULL);
4716 switch (OMP_CLAUSE_CODE (c))
4718 case OMP_CLAUSE_PRIVATE:
4719 case OMP_CLAUSE_FIRSTPRIVATE:
4720 case OMP_CLAUSE_COPYIN:
4721 case OMP_CLAUSE__LOOPTEMP_:
4722 do_in = true;
4723 break;
4725 case OMP_CLAUSE_LASTPRIVATE:
4726 if (by_ref || is_reference (val))
4728 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4729 continue;
4730 do_in = true;
4732 else
4734 do_out = true;
4735 if (lang_hooks.decls.omp_private_outer_ref (val))
4736 do_in = true;
4738 break;
4740 case OMP_CLAUSE_REDUCTION:
4741 do_in = true;
4742 do_out = !(by_ref || is_reference (val));
4743 break;
4745 default:
4746 gcc_unreachable ();
4749 if (do_in)
4751 ref = build_sender_ref (val, ctx);
4752 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4753 gimplify_assign (ref, x, ilist);
4754 if (is_task_ctx (ctx))
4755 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4758 if (do_out)
4760 ref = build_sender_ref (val, ctx);
4761 gimplify_assign (var, ref, olist);
4766 /* Generate code to implement SHARED from the sender (aka parent)
4767 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4768 list things that got automatically shared. */
4770 static void
4771 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4773 tree var, ovar, nvar, f, x, record_type;
4775 if (ctx->record_type == NULL)
4776 return;
4778 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4779 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4781 ovar = DECL_ABSTRACT_ORIGIN (f);
4782 nvar = maybe_lookup_decl (ovar, ctx);
4783 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4784 continue;
4786 /* If CTX is a nested parallel directive. Find the immediately
4787 enclosing parallel or workshare construct that contains a
4788 mapping for OVAR. */
4789 var = lookup_decl_in_outer_ctx (ovar, ctx);
4791 if (use_pointer_for_field (ovar, ctx))
4793 x = build_sender_ref (ovar, ctx);
4794 var = build_fold_addr_expr (var);
4795 gimplify_assign (x, var, ilist);
4797 else
4799 x = build_sender_ref (ovar, ctx);
4800 gimplify_assign (x, var, ilist);
4802 if (!TREE_READONLY (var)
4803 /* We don't need to receive a new reference to a result
4804 or parm decl. In fact we may not store to it as we will
4805 invalidate any pending RSO and generate wrong gimple
4806 during inlining. */
4807 && !((TREE_CODE (var) == RESULT_DECL
4808 || TREE_CODE (var) == PARM_DECL)
4809 && DECL_BY_REFERENCE (var)))
4811 x = build_sender_ref (ovar, ctx);
4812 gimplify_assign (var, x, olist);
4819 /* A convenience function to build an empty GIMPLE_COND with just the
4820 condition. */
4822 static gcond *
4823 gimple_build_cond_empty (tree cond)
4825 enum tree_code pred_code;
4826 tree lhs, rhs;
4828 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4829 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4833 /* Build the function calls to GOMP_parallel_start etc to actually
4834 generate the parallel operation. REGION is the parallel region
4835 being expanded. BB is the block where to insert the code. WS_ARGS
4836 will be set if this is a call to a combined parallel+workshare
4837 construct, it contains the list of additional arguments needed by
4838 the workshare construct. */
4840 static void
4841 expand_parallel_call (struct omp_region *region, basic_block bb,
4842 gomp_parallel *entry_stmt,
4843 vec<tree, va_gc> *ws_args)
4845 tree t, t1, t2, val, cond, c, clauses, flags;
4846 gimple_stmt_iterator gsi;
4847 gimple *stmt;
4848 enum built_in_function start_ix;
4849 int start_ix2;
4850 location_t clause_loc;
4851 vec<tree, va_gc> *args;
4853 clauses = gimple_omp_parallel_clauses (entry_stmt);
4855 /* Determine what flavor of GOMP_parallel we will be
4856 emitting. */
4857 start_ix = BUILT_IN_GOMP_PARALLEL;
4858 if (is_combined_parallel (region))
4860 switch (region->inner->type)
4862 case GIMPLE_OMP_FOR:
4863 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4864 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4865 + (region->inner->sched_kind
4866 == OMP_CLAUSE_SCHEDULE_RUNTIME
4867 ? 3 : region->inner->sched_kind));
4868 start_ix = (enum built_in_function)start_ix2;
4869 break;
4870 case GIMPLE_OMP_SECTIONS:
4871 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4872 break;
4873 default:
4874 gcc_unreachable ();
4878 /* By default, the value of NUM_THREADS is zero (selected at run time)
4879 and there is no conditional. */
4880 cond = NULL_TREE;
4881 val = build_int_cst (unsigned_type_node, 0);
4882 flags = build_int_cst (unsigned_type_node, 0);
4884 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4885 if (c)
4886 cond = OMP_CLAUSE_IF_EXPR (c);
4888 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4889 if (c)
4891 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4892 clause_loc = OMP_CLAUSE_LOCATION (c);
4894 else
4895 clause_loc = gimple_location (entry_stmt);
4897 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4898 if (c)
4899 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4901 /* Ensure 'val' is of the correct type. */
4902 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4904 /* If we found the clause 'if (cond)', build either
4905 (cond != 0) or (cond ? val : 1u). */
4906 if (cond)
4908 cond = gimple_boolify (cond);
4910 if (integer_zerop (val))
4911 val = fold_build2_loc (clause_loc,
4912 EQ_EXPR, unsigned_type_node, cond,
4913 build_int_cst (TREE_TYPE (cond), 0));
4914 else
4916 basic_block cond_bb, then_bb, else_bb;
4917 edge e, e_then, e_else;
4918 tree tmp_then, tmp_else, tmp_join, tmp_var;
4920 tmp_var = create_tmp_var (TREE_TYPE (val));
4921 if (gimple_in_ssa_p (cfun))
4923 tmp_then = make_ssa_name (tmp_var);
4924 tmp_else = make_ssa_name (tmp_var);
4925 tmp_join = make_ssa_name (tmp_var);
4927 else
4929 tmp_then = tmp_var;
4930 tmp_else = tmp_var;
4931 tmp_join = tmp_var;
4934 e = split_block_after_labels (bb);
4935 cond_bb = e->src;
4936 bb = e->dest;
4937 remove_edge (e);
4939 then_bb = create_empty_bb (cond_bb);
4940 else_bb = create_empty_bb (then_bb);
4941 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4942 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4944 stmt = gimple_build_cond_empty (cond);
4945 gsi = gsi_start_bb (cond_bb);
4946 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4948 gsi = gsi_start_bb (then_bb);
4949 stmt = gimple_build_assign (tmp_then, val);
4950 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4952 gsi = gsi_start_bb (else_bb);
4953 stmt = gimple_build_assign
4954 (tmp_else, build_int_cst (unsigned_type_node, 1));
4955 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4957 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4958 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4959 add_bb_to_loop (then_bb, cond_bb->loop_father);
4960 add_bb_to_loop (else_bb, cond_bb->loop_father);
4961 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4962 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4964 if (gimple_in_ssa_p (cfun))
4966 gphi *phi = create_phi_node (tmp_join, bb);
4967 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4968 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4971 val = tmp_join;
4974 gsi = gsi_start_bb (bb);
4975 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4976 false, GSI_CONTINUE_LINKING);
4979 gsi = gsi_last_bb (bb);
4980 t = gimple_omp_parallel_data_arg (entry_stmt);
4981 if (t == NULL)
4982 t1 = null_pointer_node;
4983 else
4984 t1 = build_fold_addr_expr (t);
4985 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4987 vec_alloc (args, 4 + vec_safe_length (ws_args));
4988 args->quick_push (t2);
4989 args->quick_push (t1);
4990 args->quick_push (val);
4991 if (ws_args)
4992 args->splice (*ws_args);
4993 args->quick_push (flags);
4995 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4996 builtin_decl_explicit (start_ix), args);
4998 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4999 false, GSI_CONTINUE_LINKING);
5002 /* Insert a function call whose name is FUNC_NAME with the information from
5003 ENTRY_STMT into the basic_block BB. */
5005 static void
5006 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
5007 vec <tree, va_gc> *ws_args)
5009 tree t, t1, t2;
5010 gimple_stmt_iterator gsi;
5011 vec <tree, va_gc> *args;
5013 gcc_assert (vec_safe_length (ws_args) == 2);
5014 tree func_name = (*ws_args)[0];
5015 tree grain = (*ws_args)[1];
5017 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5018 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5019 gcc_assert (count != NULL_TREE);
5020 count = OMP_CLAUSE_OPERAND (count, 0);
5022 gsi = gsi_last_bb (bb);
5023 t = gimple_omp_parallel_data_arg (entry_stmt);
5024 if (t == NULL)
5025 t1 = null_pointer_node;
5026 else
5027 t1 = build_fold_addr_expr (t);
5028 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5030 vec_alloc (args, 4);
5031 args->quick_push (t2);
5032 args->quick_push (t1);
5033 args->quick_push (count);
5034 args->quick_push (grain);
5035 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5037 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5038 GSI_CONTINUE_LINKING);
5041 /* Build the function call to GOMP_task to actually
5042 generate the task operation. BB is the block where to insert the code. */
5044 static void
5045 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5047 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5048 gimple_stmt_iterator gsi;
5049 location_t loc = gimple_location (entry_stmt);
5051 clauses = gimple_omp_task_clauses (entry_stmt);
5053 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5054 if (c)
5055 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5056 else
5057 cond = boolean_true_node;
5059 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5060 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5061 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5062 flags = build_int_cst (unsigned_type_node,
5063 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5065 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5066 if (c)
5068 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5069 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5070 build_int_cst (unsigned_type_node, 2),
5071 build_int_cst (unsigned_type_node, 0));
5072 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5074 if (depend)
5075 depend = OMP_CLAUSE_DECL (depend);
5076 else
5077 depend = build_int_cst (ptr_type_node, 0);
5079 gsi = gsi_last_bb (bb);
5080 t = gimple_omp_task_data_arg (entry_stmt);
5081 if (t == NULL)
5082 t2 = null_pointer_node;
5083 else
5084 t2 = build_fold_addr_expr_loc (loc, t);
5085 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5086 t = gimple_omp_task_copy_fn (entry_stmt);
5087 if (t == NULL)
5088 t3 = null_pointer_node;
5089 else
5090 t3 = build_fold_addr_expr_loc (loc, t);
5092 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5093 8, t1, t2, t3,
5094 gimple_omp_task_arg_size (entry_stmt),
5095 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5096 depend);
5098 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5099 false, GSI_CONTINUE_LINKING);
5103 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5104 catch handler and return it. This prevents programs from violating the
5105 structured block semantics with throws. */
5107 static gimple_seq
5108 maybe_catch_exception (gimple_seq body)
5110 gimple *g;
5111 tree decl;
5113 if (!flag_exceptions)
5114 return body;
5116 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5117 decl = lang_hooks.eh_protect_cleanup_actions ();
5118 else
5119 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5121 g = gimple_build_eh_must_not_throw (decl);
5122 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5123 GIMPLE_TRY_CATCH);
5125 return gimple_seq_alloc_with_stmt (g);
5128 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5130 static tree
5131 vec2chain (vec<tree, va_gc> *v)
5133 tree chain = NULL_TREE, t;
5134 unsigned ix;
5136 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5138 DECL_CHAIN (t) = chain;
5139 chain = t;
5142 return chain;
5146 /* Remove barriers in REGION->EXIT's block. Note that this is only
5147 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5148 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5149 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5150 removed. */
5152 static void
5153 remove_exit_barrier (struct omp_region *region)
5155 gimple_stmt_iterator gsi;
5156 basic_block exit_bb;
5157 edge_iterator ei;
5158 edge e;
5159 gimple *stmt;
5160 int any_addressable_vars = -1;
5162 exit_bb = region->exit;
5164 /* If the parallel region doesn't return, we don't have REGION->EXIT
5165 block at all. */
5166 if (! exit_bb)
5167 return;
5169 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5170 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5171 statements that can appear in between are extremely limited -- no
5172 memory operations at all. Here, we allow nothing at all, so the
5173 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5174 gsi = gsi_last_bb (exit_bb);
5175 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5176 gsi_prev (&gsi);
5177 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5178 return;
5180 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5182 gsi = gsi_last_bb (e->src);
5183 if (gsi_end_p (gsi))
5184 continue;
5185 stmt = gsi_stmt (gsi);
5186 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5187 && !gimple_omp_return_nowait_p (stmt))
5189 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5190 in many cases. If there could be tasks queued, the barrier
5191 might be needed to let the tasks run before some local
5192 variable of the parallel that the task uses as shared
5193 runs out of scope. The task can be spawned either
5194 from within current function (this would be easy to check)
5195 or from some function it calls and gets passed an address
5196 of such a variable. */
5197 if (any_addressable_vars < 0)
5199 gomp_parallel *parallel_stmt
5200 = as_a <gomp_parallel *> (last_stmt (region->entry));
5201 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5202 tree local_decls, block, decl;
5203 unsigned ix;
5205 any_addressable_vars = 0;
5206 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5207 if (TREE_ADDRESSABLE (decl))
5209 any_addressable_vars = 1;
5210 break;
5212 for (block = gimple_block (stmt);
5213 !any_addressable_vars
5214 && block
5215 && TREE_CODE (block) == BLOCK;
5216 block = BLOCK_SUPERCONTEXT (block))
5218 for (local_decls = BLOCK_VARS (block);
5219 local_decls;
5220 local_decls = DECL_CHAIN (local_decls))
5221 if (TREE_ADDRESSABLE (local_decls))
5223 any_addressable_vars = 1;
5224 break;
5226 if (block == gimple_block (parallel_stmt))
5227 break;
5230 if (!any_addressable_vars)
5231 gimple_omp_return_set_nowait (stmt);
5236 static void
5237 remove_exit_barriers (struct omp_region *region)
5239 if (region->type == GIMPLE_OMP_PARALLEL)
5240 remove_exit_barrier (region);
5242 if (region->inner)
5244 region = region->inner;
5245 remove_exit_barriers (region);
5246 while (region->next)
5248 region = region->next;
5249 remove_exit_barriers (region);
5254 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5255 calls. These can't be declared as const functions, but
5256 within one parallel body they are constant, so they can be
5257 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5258 which are declared const. Similarly for task body, except
5259 that in untied task omp_get_thread_num () can change at any task
5260 scheduling point. */
5262 static void
5263 optimize_omp_library_calls (gimple *entry_stmt)
5265 basic_block bb;
5266 gimple_stmt_iterator gsi;
5267 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5268 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5269 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5270 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5271 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5272 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5273 OMP_CLAUSE_UNTIED) != NULL);
5275 FOR_EACH_BB_FN (bb, cfun)
5276 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5278 gimple *call = gsi_stmt (gsi);
5279 tree decl;
5281 if (is_gimple_call (call)
5282 && (decl = gimple_call_fndecl (call))
5283 && DECL_EXTERNAL (decl)
5284 && TREE_PUBLIC (decl)
5285 && DECL_INITIAL (decl) == NULL)
5287 tree built_in;
5289 if (DECL_NAME (decl) == thr_num_id)
5291 /* In #pragma omp task untied omp_get_thread_num () can change
5292 during the execution of the task region. */
5293 if (untied_task)
5294 continue;
5295 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5297 else if (DECL_NAME (decl) == num_thr_id)
5298 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5299 else
5300 continue;
5302 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5303 || gimple_call_num_args (call) != 0)
5304 continue;
5306 if (flag_exceptions && !TREE_NOTHROW (decl))
5307 continue;
5309 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5310 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5311 TREE_TYPE (TREE_TYPE (built_in))))
5312 continue;
5314 gimple_call_set_fndecl (call, built_in);
5319 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5320 regimplified. */
5322 static tree
5323 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5325 tree t = *tp;
5327 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5328 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5329 return t;
5331 if (TREE_CODE (t) == ADDR_EXPR)
5332 recompute_tree_invariant_for_addr_expr (t);
5334 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5335 return NULL_TREE;
5338 /* Prepend TO = FROM assignment before *GSI_P. */
5340 static void
5341 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5343 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5344 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5345 true, GSI_SAME_STMT);
5346 gimple *stmt = gimple_build_assign (to, from);
5347 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5348 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5349 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5351 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5352 gimple_regimplify_operands (stmt, &gsi);
5356 /* Expand the OpenMP parallel or task directive starting at REGION. */
5358 static void
5359 expand_omp_taskreg (struct omp_region *region)
5361 basic_block entry_bb, exit_bb, new_bb;
5362 struct function *child_cfun;
5363 tree child_fn, block, t;
5364 gimple_stmt_iterator gsi;
5365 gimple *entry_stmt, *stmt;
5366 edge e;
5367 vec<tree, va_gc> *ws_args;
5369 entry_stmt = last_stmt (region->entry);
5370 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5371 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5373 entry_bb = region->entry;
5374 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
5375 exit_bb = region->cont;
5376 else
5377 exit_bb = region->exit;
5379 bool is_cilk_for
5380 = (flag_cilkplus
5381 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5382 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5383 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5385 if (is_cilk_for)
5386 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5387 and the inner statement contains the name of the built-in function
5388 and grain. */
5389 ws_args = region->inner->ws_args;
5390 else if (is_combined_parallel (region))
5391 ws_args = region->ws_args;
5392 else
5393 ws_args = NULL;
5395 if (child_cfun->cfg)
5397 /* Due to inlining, it may happen that we have already outlined
5398 the region, in which case all we need to do is make the
5399 sub-graph unreachable and emit the parallel call. */
5400 edge entry_succ_e, exit_succ_e;
5402 entry_succ_e = single_succ_edge (entry_bb);
5404 gsi = gsi_last_bb (entry_bb);
5405 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5406 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5407 gsi_remove (&gsi, true);
5409 new_bb = entry_bb;
5410 if (exit_bb)
5412 exit_succ_e = single_succ_edge (exit_bb);
5413 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5415 remove_edge_and_dominated_blocks (entry_succ_e);
5417 else
5419 unsigned srcidx, dstidx, num;
5421 /* If the parallel region needs data sent from the parent
5422 function, then the very first statement (except possible
5423 tree profile counter updates) of the parallel body
5424 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5425 &.OMP_DATA_O is passed as an argument to the child function,
5426 we need to replace it with the argument as seen by the child
5427 function.
5429 In most cases, this will end up being the identity assignment
5430 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5431 a function call that has been inlined, the original PARM_DECL
5432 .OMP_DATA_I may have been converted into a different local
5433 variable. In which case, we need to keep the assignment. */
5434 if (gimple_omp_taskreg_data_arg (entry_stmt))
5436 basic_block entry_succ_bb
5437 = single_succ_p (entry_bb) ? single_succ (entry_bb)
5438 : FALLTHRU_EDGE (entry_bb)->dest;
5439 tree arg;
5440 gimple *parcopy_stmt = NULL;
5442 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5444 gimple *stmt;
5446 gcc_assert (!gsi_end_p (gsi));
5447 stmt = gsi_stmt (gsi);
5448 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5449 continue;
5451 if (gimple_num_ops (stmt) == 2)
5453 tree arg = gimple_assign_rhs1 (stmt);
5455 /* We're ignore the subcode because we're
5456 effectively doing a STRIP_NOPS. */
5458 if (TREE_CODE (arg) == ADDR_EXPR
5459 && TREE_OPERAND (arg, 0)
5460 == gimple_omp_taskreg_data_arg (entry_stmt))
5462 parcopy_stmt = stmt;
5463 break;
5468 gcc_assert (parcopy_stmt != NULL);
5469 arg = DECL_ARGUMENTS (child_fn);
5471 if (!gimple_in_ssa_p (cfun))
5473 if (gimple_assign_lhs (parcopy_stmt) == arg)
5474 gsi_remove (&gsi, true);
5475 else
5477 /* ?? Is setting the subcode really necessary ?? */
5478 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5479 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5482 else
5484 tree lhs = gimple_assign_lhs (parcopy_stmt);
5485 gcc_assert (SSA_NAME_VAR (lhs) == arg);
5486 /* We'd like to set the rhs to the default def in the child_fn,
5487 but it's too early to create ssa names in the child_fn.
5488 Instead, we set the rhs to the parm. In
5489 move_sese_region_to_fn, we introduce a default def for the
5490 parm, map the parm to it's default def, and once we encounter
5491 this stmt, replace the parm with the default def. */
5492 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5493 update_stmt (parcopy_stmt);
5497 /* Declare local variables needed in CHILD_CFUN. */
5498 block = DECL_INITIAL (child_fn);
5499 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5500 /* The gimplifier could record temporaries in parallel/task block
5501 rather than in containing function's local_decls chain,
5502 which would mean cgraph missed finalizing them. Do it now. */
5503 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5504 if (TREE_CODE (t) == VAR_DECL
5505 && TREE_STATIC (t)
5506 && !DECL_EXTERNAL (t))
5507 varpool_node::finalize_decl (t);
5508 DECL_SAVED_TREE (child_fn) = NULL;
5509 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5510 gimple_set_body (child_fn, NULL);
5511 TREE_USED (block) = 1;
5513 /* Reset DECL_CONTEXT on function arguments. */
5514 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5515 DECL_CONTEXT (t) = child_fn;
5517 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5518 so that it can be moved to the child function. */
5519 gsi = gsi_last_bb (entry_bb);
5520 stmt = gsi_stmt (gsi);
5521 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5522 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5523 e = split_block (entry_bb, stmt);
5524 gsi_remove (&gsi, true);
5525 entry_bb = e->dest;
5526 edge e2 = NULL;
5527 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5528 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5529 else
5531 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
5532 gcc_assert (e2->dest == region->exit);
5533 remove_edge (BRANCH_EDGE (entry_bb));
5534 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
5535 gsi = gsi_last_bb (region->exit);
5536 gcc_assert (!gsi_end_p (gsi)
5537 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5538 gsi_remove (&gsi, true);
5541 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5542 if (exit_bb)
5544 gsi = gsi_last_bb (exit_bb);
5545 gcc_assert (!gsi_end_p (gsi)
5546 && (gimple_code (gsi_stmt (gsi))
5547 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
5548 stmt = gimple_build_return (NULL);
5549 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5550 gsi_remove (&gsi, true);
5553 /* Move the parallel region into CHILD_CFUN. */
5555 if (gimple_in_ssa_p (cfun))
5557 init_tree_ssa (child_cfun);
5558 init_ssa_operands (child_cfun);
5559 child_cfun->gimple_df->in_ssa_p = true;
5560 block = NULL_TREE;
5562 else
5563 block = gimple_block (entry_stmt);
5565 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5566 if (exit_bb)
5567 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5568 if (e2)
5570 basic_block dest_bb = e2->dest;
5571 if (!exit_bb)
5572 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
5573 remove_edge (e2);
5574 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
5576 /* When the OMP expansion process cannot guarantee an up-to-date
5577 loop tree arrange for the child function to fixup loops. */
5578 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5579 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5581 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5582 num = vec_safe_length (child_cfun->local_decls);
5583 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5585 t = (*child_cfun->local_decls)[srcidx];
5586 if (DECL_CONTEXT (t) == cfun->decl)
5587 continue;
5588 if (srcidx != dstidx)
5589 (*child_cfun->local_decls)[dstidx] = t;
5590 dstidx++;
5592 if (dstidx != num)
5593 vec_safe_truncate (child_cfun->local_decls, dstidx);
5595 /* Inform the callgraph about the new function. */
5596 child_cfun->curr_properties = cfun->curr_properties;
5597 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
5598 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
5599 cgraph_node *node = cgraph_node::get_create (child_fn);
5600 node->parallelized_function = 1;
5601 cgraph_node::add_new_function (child_fn, true);
5603 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5604 fixed in a following pass. */
5605 push_cfun (child_cfun);
5606 if (optimize)
5607 optimize_omp_library_calls (entry_stmt);
5608 cgraph_edge::rebuild_edges ();
5610 /* Some EH regions might become dead, see PR34608. If
5611 pass_cleanup_cfg isn't the first pass to happen with the
5612 new child, these dead EH edges might cause problems.
5613 Clean them up now. */
5614 if (flag_exceptions)
5616 basic_block bb;
5617 bool changed = false;
5619 FOR_EACH_BB_FN (bb, cfun)
5620 changed |= gimple_purge_dead_eh_edges (bb);
5621 if (changed)
5622 cleanup_tree_cfg ();
5624 if (gimple_in_ssa_p (cfun))
5625 update_ssa (TODO_update_ssa);
5626 #ifdef ENABLE_CHECKING
5627 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5628 verify_loop_structure ();
5629 #endif
5630 pop_cfun ();
5633 /* Emit a library call to launch the children threads. */
5634 if (is_cilk_for)
5635 expand_cilk_for_call (new_bb,
5636 as_a <gomp_parallel *> (entry_stmt), ws_args);
5637 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5638 expand_parallel_call (region, new_bb,
5639 as_a <gomp_parallel *> (entry_stmt), ws_args);
5640 else
5641 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5642 if (gimple_in_ssa_p (cfun))
5643 update_ssa (TODO_update_ssa_only_virtuals);
5647 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5648 of the combined collapse > 1 loop constructs, generate code like:
5649 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5650 if (cond3 is <)
5651 adj = STEP3 - 1;
5652 else
5653 adj = STEP3 + 1;
5654 count3 = (adj + N32 - N31) / STEP3;
5655 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5656 if (cond2 is <)
5657 adj = STEP2 - 1;
5658 else
5659 adj = STEP2 + 1;
5660 count2 = (adj + N22 - N21) / STEP2;
5661 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5662 if (cond1 is <)
5663 adj = STEP1 - 1;
5664 else
5665 adj = STEP1 + 1;
5666 count1 = (adj + N12 - N11) / STEP1;
5667 count = count1 * count2 * count3;
5668 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5669 count = 0;
5670 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5671 of the combined loop constructs, just initialize COUNTS array
5672 from the _looptemp_ clauses. */
5674 /* NOTE: It *could* be better to moosh all of the BBs together,
5675 creating one larger BB with all the computation and the unexpected
5676 jump at the end. I.e.
5678 bool zero3, zero2, zero1, zero;
5680 zero3 = N32 c3 N31;
5681 count3 = (N32 - N31) /[cl] STEP3;
5682 zero2 = N22 c2 N21;
5683 count2 = (N22 - N21) /[cl] STEP2;
5684 zero1 = N12 c1 N11;
5685 count1 = (N12 - N11) /[cl] STEP1;
5686 zero = zero3 || zero2 || zero1;
5687 count = count1 * count2 * count3;
5688 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5690 After all, we expect the zero=false, and thus we expect to have to
5691 evaluate all of the comparison expressions, so short-circuiting
5692 oughtn't be a win. Since the condition isn't protecting a
5693 denominator, we're not concerned about divide-by-zero, so we can
5694 fully evaluate count even if a numerator turned out to be wrong.
5696 It seems like putting this all together would create much better
5697 scheduling opportunities, and less pressure on the chip's branch
5698 predictor. */
5700 static void
5701 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5702 basic_block &entry_bb, tree *counts,
5703 basic_block &zero_iter_bb, int &first_zero_iter,
5704 basic_block &l2_dom_bb)
5706 tree t, type = TREE_TYPE (fd->loop.v);
5707 edge e, ne;
5708 int i;
5710 /* Collapsed loops need work for expansion into SSA form. */
5711 gcc_assert (!gimple_in_ssa_p (cfun));
5713 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5714 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5716 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5717 isn't supposed to be handled, as the inner loop doesn't
5718 use it. */
5719 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5720 OMP_CLAUSE__LOOPTEMP_);
5721 gcc_assert (innerc);
5722 for (i = 0; i < fd->collapse; i++)
5724 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5725 OMP_CLAUSE__LOOPTEMP_);
5726 gcc_assert (innerc);
5727 if (i)
5728 counts[i] = OMP_CLAUSE_DECL (innerc);
5729 else
5730 counts[0] = NULL_TREE;
5732 return;
5735 for (i = 0; i < fd->collapse; i++)
5737 tree itype = TREE_TYPE (fd->loops[i].v);
5739 if (SSA_VAR_P (fd->loop.n2)
5740 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5741 fold_convert (itype, fd->loops[i].n1),
5742 fold_convert (itype, fd->loops[i].n2)))
5743 == NULL_TREE || !integer_onep (t)))
5745 gcond *cond_stmt;
5746 tree n1, n2;
5747 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5748 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5749 true, GSI_SAME_STMT);
5750 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5751 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5752 true, GSI_SAME_STMT);
5753 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5754 NULL_TREE, NULL_TREE);
5755 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5756 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5757 expand_omp_regimplify_p, NULL, NULL)
5758 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5759 expand_omp_regimplify_p, NULL, NULL))
5761 *gsi = gsi_for_stmt (cond_stmt);
5762 gimple_regimplify_operands (cond_stmt, gsi);
5764 e = split_block (entry_bb, cond_stmt);
5765 if (zero_iter_bb == NULL)
5767 gassign *assign_stmt;
5768 first_zero_iter = i;
5769 zero_iter_bb = create_empty_bb (entry_bb);
5770 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5771 *gsi = gsi_after_labels (zero_iter_bb);
5772 assign_stmt = gimple_build_assign (fd->loop.n2,
5773 build_zero_cst (type));
5774 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5775 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5776 entry_bb);
5778 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5779 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5780 e->flags = EDGE_TRUE_VALUE;
5781 e->probability = REG_BR_PROB_BASE - ne->probability;
5782 if (l2_dom_bb == NULL)
5783 l2_dom_bb = entry_bb;
5784 entry_bb = e->dest;
5785 *gsi = gsi_last_bb (entry_bb);
5788 if (POINTER_TYPE_P (itype))
5789 itype = signed_type_for (itype);
5790 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5791 ? -1 : 1));
5792 t = fold_build2 (PLUS_EXPR, itype,
5793 fold_convert (itype, fd->loops[i].step), t);
5794 t = fold_build2 (PLUS_EXPR, itype, t,
5795 fold_convert (itype, fd->loops[i].n2));
5796 t = fold_build2 (MINUS_EXPR, itype, t,
5797 fold_convert (itype, fd->loops[i].n1));
5798 /* ?? We could probably use CEIL_DIV_EXPR instead of
5799 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5800 generate the same code in the end because generically we
5801 don't know that the values involved must be negative for
5802 GT?? */
5803 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5804 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5805 fold_build1 (NEGATE_EXPR, itype, t),
5806 fold_build1 (NEGATE_EXPR, itype,
5807 fold_convert (itype,
5808 fd->loops[i].step)));
5809 else
5810 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5811 fold_convert (itype, fd->loops[i].step));
5812 t = fold_convert (type, t);
5813 if (TREE_CODE (t) == INTEGER_CST)
5814 counts[i] = t;
5815 else
5817 counts[i] = create_tmp_reg (type, ".count");
5818 expand_omp_build_assign (gsi, counts[i], t);
5820 if (SSA_VAR_P (fd->loop.n2))
5822 if (i == 0)
5823 t = counts[0];
5824 else
5825 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5826 expand_omp_build_assign (gsi, fd->loop.n2, t);
5832 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5833 T = V;
5834 V3 = N31 + (T % count3) * STEP3;
5835 T = T / count3;
5836 V2 = N21 + (T % count2) * STEP2;
5837 T = T / count2;
5838 V1 = N11 + T * STEP1;
5839 if this loop doesn't have an inner loop construct combined with it.
5840 If it does have an inner loop construct combined with it and the
5841 iteration count isn't known constant, store values from counts array
5842 into its _looptemp_ temporaries instead. */
5844 static void
5845 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5846 tree *counts, gimple *inner_stmt, tree startvar)
5848 int i;
5849 if (gimple_omp_for_combined_p (fd->for_stmt))
5851 /* If fd->loop.n2 is constant, then no propagation of the counts
5852 is needed, they are constant. */
5853 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5854 return;
5856 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5857 ? gimple_omp_parallel_clauses (inner_stmt)
5858 : gimple_omp_for_clauses (inner_stmt);
5859 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5860 isn't supposed to be handled, as the inner loop doesn't
5861 use it. */
5862 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5863 gcc_assert (innerc);
5864 for (i = 0; i < fd->collapse; i++)
5866 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5867 OMP_CLAUSE__LOOPTEMP_);
5868 gcc_assert (innerc);
5869 if (i)
5871 tree tem = OMP_CLAUSE_DECL (innerc);
5872 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5873 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5874 false, GSI_CONTINUE_LINKING);
5875 gassign *stmt = gimple_build_assign (tem, t);
5876 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5879 return;
5882 tree type = TREE_TYPE (fd->loop.v);
5883 tree tem = create_tmp_reg (type, ".tem");
5884 gassign *stmt = gimple_build_assign (tem, startvar);
5885 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5887 for (i = fd->collapse - 1; i >= 0; i--)
5889 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5890 itype = vtype;
5891 if (POINTER_TYPE_P (vtype))
5892 itype = signed_type_for (vtype);
5893 if (i != 0)
5894 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5895 else
5896 t = tem;
5897 t = fold_convert (itype, t);
5898 t = fold_build2 (MULT_EXPR, itype, t,
5899 fold_convert (itype, fd->loops[i].step));
5900 if (POINTER_TYPE_P (vtype))
5901 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5902 else
5903 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5904 t = force_gimple_operand_gsi (gsi, t,
5905 DECL_P (fd->loops[i].v)
5906 && TREE_ADDRESSABLE (fd->loops[i].v),
5907 NULL_TREE, false,
5908 GSI_CONTINUE_LINKING);
5909 stmt = gimple_build_assign (fd->loops[i].v, t);
5910 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5911 if (i != 0)
5913 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5914 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5915 false, GSI_CONTINUE_LINKING);
5916 stmt = gimple_build_assign (tem, t);
5917 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5923 /* Helper function for expand_omp_for_*. Generate code like:
5924 L10:
5925 V3 += STEP3;
5926 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5927 L11:
5928 V3 = N31;
5929 V2 += STEP2;
5930 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5931 L12:
5932 V2 = N21;
5933 V1 += STEP1;
5934 goto BODY_BB; */
5936 static basic_block
5937 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5938 basic_block body_bb)
5940 basic_block last_bb, bb, collapse_bb = NULL;
5941 int i;
5942 gimple_stmt_iterator gsi;
5943 edge e;
5944 tree t;
5945 gimple *stmt;
5947 last_bb = cont_bb;
5948 for (i = fd->collapse - 1; i >= 0; i--)
5950 tree vtype = TREE_TYPE (fd->loops[i].v);
5952 bb = create_empty_bb (last_bb);
5953 add_bb_to_loop (bb, last_bb->loop_father);
5954 gsi = gsi_start_bb (bb);
5956 if (i < fd->collapse - 1)
5958 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5959 e->probability = REG_BR_PROB_BASE / 8;
5961 t = fd->loops[i + 1].n1;
5962 t = force_gimple_operand_gsi (&gsi, t,
5963 DECL_P (fd->loops[i + 1].v)
5964 && TREE_ADDRESSABLE (fd->loops[i
5965 + 1].v),
5966 NULL_TREE, false,
5967 GSI_CONTINUE_LINKING);
5968 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5969 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5971 else
5972 collapse_bb = bb;
5974 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5976 if (POINTER_TYPE_P (vtype))
5977 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5978 else
5979 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5980 t = force_gimple_operand_gsi (&gsi, t,
5981 DECL_P (fd->loops[i].v)
5982 && TREE_ADDRESSABLE (fd->loops[i].v),
5983 NULL_TREE, false, GSI_CONTINUE_LINKING);
5984 stmt = gimple_build_assign (fd->loops[i].v, t);
5985 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5987 if (i > 0)
5989 t = fd->loops[i].n2;
5990 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5991 false, GSI_CONTINUE_LINKING);
5992 tree v = fd->loops[i].v;
5993 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5994 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5995 false, GSI_CONTINUE_LINKING);
5996 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5997 stmt = gimple_build_cond_empty (t);
5998 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5999 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
6000 e->probability = REG_BR_PROB_BASE * 7 / 8;
6002 else
6003 make_edge (bb, body_bb, EDGE_FALLTHRU);
6004 last_bb = bb;
6007 return collapse_bb;
6011 /* A subroutine of expand_omp_for. Generate code for a parallel
6012 loop with any schedule. Given parameters:
6014 for (V = N1; V cond N2; V += STEP) BODY;
6016 where COND is "<" or ">", we generate pseudocode
6018 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
6019 if (more) goto L0; else goto L3;
6021 V = istart0;
6022 iend = iend0;
6024 BODY;
6025 V += STEP;
6026 if (V cond iend) goto L1; else goto L2;
6028 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6031 If this is a combined omp parallel loop, instead of the call to
6032 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6033 If this is gimple_omp_for_combined_p loop, then instead of assigning
6034 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6035 inner GIMPLE_OMP_FOR and V += STEP; and
6036 if (V cond iend) goto L1; else goto L2; are removed.
6038 For collapsed loops, given parameters:
6039 collapse(3)
6040 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6041 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6042 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6043 BODY;
6045 we generate pseudocode
6047 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6048 if (cond3 is <)
6049 adj = STEP3 - 1;
6050 else
6051 adj = STEP3 + 1;
6052 count3 = (adj + N32 - N31) / STEP3;
6053 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6054 if (cond2 is <)
6055 adj = STEP2 - 1;
6056 else
6057 adj = STEP2 + 1;
6058 count2 = (adj + N22 - N21) / STEP2;
6059 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6060 if (cond1 is <)
6061 adj = STEP1 - 1;
6062 else
6063 adj = STEP1 + 1;
6064 count1 = (adj + N12 - N11) / STEP1;
6065 count = count1 * count2 * count3;
6066 goto Z1;
6068 count = 0;
6070 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6071 if (more) goto L0; else goto L3;
6073 V = istart0;
6074 T = V;
6075 V3 = N31 + (T % count3) * STEP3;
6076 T = T / count3;
6077 V2 = N21 + (T % count2) * STEP2;
6078 T = T / count2;
6079 V1 = N11 + T * STEP1;
6080 iend = iend0;
6082 BODY;
6083 V += 1;
6084 if (V < iend) goto L10; else goto L2;
6085 L10:
6086 V3 += STEP3;
6087 if (V3 cond3 N32) goto L1; else goto L11;
6088 L11:
6089 V3 = N31;
6090 V2 += STEP2;
6091 if (V2 cond2 N22) goto L1; else goto L12;
6092 L12:
6093 V2 = N21;
6094 V1 += STEP1;
6095 goto L1;
6097 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6102 static void
6103 expand_omp_for_generic (struct omp_region *region,
6104 struct omp_for_data *fd,
6105 enum built_in_function start_fn,
6106 enum built_in_function next_fn,
6107 gimple *inner_stmt)
6109 tree type, istart0, iend0, iend;
6110 tree t, vmain, vback, bias = NULL_TREE;
6111 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6112 basic_block l2_bb = NULL, l3_bb = NULL;
6113 gimple_stmt_iterator gsi;
6114 gassign *assign_stmt;
6115 bool in_combined_parallel = is_combined_parallel (region);
6116 bool broken_loop = region->cont == NULL;
6117 edge e, ne;
6118 tree *counts = NULL;
6119 int i;
6121 gcc_assert (!broken_loop || !in_combined_parallel);
6122 gcc_assert (fd->iter_type == long_integer_type_node
6123 || !in_combined_parallel);
6125 type = TREE_TYPE (fd->loop.v);
6126 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6127 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6128 TREE_ADDRESSABLE (istart0) = 1;
6129 TREE_ADDRESSABLE (iend0) = 1;
6131 /* See if we need to bias by LLONG_MIN. */
6132 if (fd->iter_type == long_long_unsigned_type_node
6133 && TREE_CODE (type) == INTEGER_TYPE
6134 && !TYPE_UNSIGNED (type))
6136 tree n1, n2;
6138 if (fd->loop.cond_code == LT_EXPR)
6140 n1 = fd->loop.n1;
6141 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6143 else
6145 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6146 n2 = fd->loop.n1;
6148 if (TREE_CODE (n1) != INTEGER_CST
6149 || TREE_CODE (n2) != INTEGER_CST
6150 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6151 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6154 entry_bb = region->entry;
6155 cont_bb = region->cont;
6156 collapse_bb = NULL;
6157 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6158 gcc_assert (broken_loop
6159 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6160 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6161 l1_bb = single_succ (l0_bb);
6162 if (!broken_loop)
6164 l2_bb = create_empty_bb (cont_bb);
6165 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6166 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6168 else
6169 l2_bb = NULL;
6170 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6171 exit_bb = region->exit;
6173 gsi = gsi_last_bb (entry_bb);
6175 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6176 if (fd->collapse > 1)
6178 int first_zero_iter = -1;
6179 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6181 counts = XALLOCAVEC (tree, fd->collapse);
6182 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6183 zero_iter_bb, first_zero_iter,
6184 l2_dom_bb);
6186 if (zero_iter_bb)
6188 /* Some counts[i] vars might be uninitialized if
6189 some loop has zero iterations. But the body shouldn't
6190 be executed in that case, so just avoid uninit warnings. */
6191 for (i = first_zero_iter; i < fd->collapse; i++)
6192 if (SSA_VAR_P (counts[i]))
6193 TREE_NO_WARNING (counts[i]) = 1;
6194 gsi_prev (&gsi);
6195 e = split_block (entry_bb, gsi_stmt (gsi));
6196 entry_bb = e->dest;
6197 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6198 gsi = gsi_last_bb (entry_bb);
6199 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6200 get_immediate_dominator (CDI_DOMINATORS,
6201 zero_iter_bb));
6204 if (in_combined_parallel)
6206 /* In a combined parallel loop, emit a call to
6207 GOMP_loop_foo_next. */
6208 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6209 build_fold_addr_expr (istart0),
6210 build_fold_addr_expr (iend0));
6212 else
6214 tree t0, t1, t2, t3, t4;
6215 /* If this is not a combined parallel loop, emit a call to
6216 GOMP_loop_foo_start in ENTRY_BB. */
6217 t4 = build_fold_addr_expr (iend0);
6218 t3 = build_fold_addr_expr (istart0);
6219 t2 = fold_convert (fd->iter_type, fd->loop.step);
6220 t1 = fd->loop.n2;
6221 t0 = fd->loop.n1;
6222 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6224 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6225 OMP_CLAUSE__LOOPTEMP_);
6226 gcc_assert (innerc);
6227 t0 = OMP_CLAUSE_DECL (innerc);
6228 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6229 OMP_CLAUSE__LOOPTEMP_);
6230 gcc_assert (innerc);
6231 t1 = OMP_CLAUSE_DECL (innerc);
6233 if (POINTER_TYPE_P (TREE_TYPE (t0))
6234 && TYPE_PRECISION (TREE_TYPE (t0))
6235 != TYPE_PRECISION (fd->iter_type))
6237 /* Avoid casting pointers to integer of a different size. */
6238 tree itype = signed_type_for (type);
6239 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6240 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6242 else
6244 t1 = fold_convert (fd->iter_type, t1);
6245 t0 = fold_convert (fd->iter_type, t0);
6247 if (bias)
6249 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6250 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6252 if (fd->iter_type == long_integer_type_node)
6254 if (fd->chunk_size)
6256 t = fold_convert (fd->iter_type, fd->chunk_size);
6257 t = build_call_expr (builtin_decl_explicit (start_fn),
6258 6, t0, t1, t2, t, t3, t4);
6260 else
6261 t = build_call_expr (builtin_decl_explicit (start_fn),
6262 5, t0, t1, t2, t3, t4);
6264 else
6266 tree t5;
6267 tree c_bool_type;
6268 tree bfn_decl;
6270 /* The GOMP_loop_ull_*start functions have additional boolean
6271 argument, true for < loops and false for > loops.
6272 In Fortran, the C bool type can be different from
6273 boolean_type_node. */
6274 bfn_decl = builtin_decl_explicit (start_fn);
6275 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6276 t5 = build_int_cst (c_bool_type,
6277 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6278 if (fd->chunk_size)
6280 tree bfn_decl = builtin_decl_explicit (start_fn);
6281 t = fold_convert (fd->iter_type, fd->chunk_size);
6282 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6284 else
6285 t = build_call_expr (builtin_decl_explicit (start_fn),
6286 6, t5, t0, t1, t2, t3, t4);
6289 if (TREE_TYPE (t) != boolean_type_node)
6290 t = fold_build2 (NE_EXPR, boolean_type_node,
6291 t, build_int_cst (TREE_TYPE (t), 0));
6292 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6293 true, GSI_SAME_STMT);
6294 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6296 /* Remove the GIMPLE_OMP_FOR statement. */
6297 gsi_remove (&gsi, true);
6299 /* Iteration setup for sequential loop goes in L0_BB. */
6300 tree startvar = fd->loop.v;
6301 tree endvar = NULL_TREE;
6303 if (gimple_omp_for_combined_p (fd->for_stmt))
6305 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6306 && gimple_omp_for_kind (inner_stmt)
6307 == GF_OMP_FOR_KIND_SIMD);
6308 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6309 OMP_CLAUSE__LOOPTEMP_);
6310 gcc_assert (innerc);
6311 startvar = OMP_CLAUSE_DECL (innerc);
6312 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6313 OMP_CLAUSE__LOOPTEMP_);
6314 gcc_assert (innerc);
6315 endvar = OMP_CLAUSE_DECL (innerc);
6318 gsi = gsi_start_bb (l0_bb);
6319 t = istart0;
6320 if (bias)
6321 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6322 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6323 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6324 t = fold_convert (TREE_TYPE (startvar), t);
6325 t = force_gimple_operand_gsi (&gsi, t,
6326 DECL_P (startvar)
6327 && TREE_ADDRESSABLE (startvar),
6328 NULL_TREE, false, GSI_CONTINUE_LINKING);
6329 assign_stmt = gimple_build_assign (startvar, t);
6330 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6332 t = iend0;
6333 if (bias)
6334 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6335 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6336 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6337 t = fold_convert (TREE_TYPE (startvar), t);
6338 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6339 false, GSI_CONTINUE_LINKING);
6340 if (endvar)
6342 assign_stmt = gimple_build_assign (endvar, iend);
6343 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6344 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6345 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6346 else
6347 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6348 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6350 if (fd->collapse > 1)
6351 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6353 if (!broken_loop)
6355 /* Code to control the increment and predicate for the sequential
6356 loop goes in the CONT_BB. */
6357 gsi = gsi_last_bb (cont_bb);
6358 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6359 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6360 vmain = gimple_omp_continue_control_use (cont_stmt);
6361 vback = gimple_omp_continue_control_def (cont_stmt);
6363 if (!gimple_omp_for_combined_p (fd->for_stmt))
6365 if (POINTER_TYPE_P (type))
6366 t = fold_build_pointer_plus (vmain, fd->loop.step);
6367 else
6368 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6369 t = force_gimple_operand_gsi (&gsi, t,
6370 DECL_P (vback)
6371 && TREE_ADDRESSABLE (vback),
6372 NULL_TREE, true, GSI_SAME_STMT);
6373 assign_stmt = gimple_build_assign (vback, t);
6374 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6376 t = build2 (fd->loop.cond_code, boolean_type_node,
6377 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6378 iend);
6379 gcond *cond_stmt = gimple_build_cond_empty (t);
6380 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6383 /* Remove GIMPLE_OMP_CONTINUE. */
6384 gsi_remove (&gsi, true);
6386 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6387 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6389 /* Emit code to get the next parallel iteration in L2_BB. */
6390 gsi = gsi_start_bb (l2_bb);
6392 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6393 build_fold_addr_expr (istart0),
6394 build_fold_addr_expr (iend0));
6395 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6396 false, GSI_CONTINUE_LINKING);
6397 if (TREE_TYPE (t) != boolean_type_node)
6398 t = fold_build2 (NE_EXPR, boolean_type_node,
6399 t, build_int_cst (TREE_TYPE (t), 0));
6400 gcond *cond_stmt = gimple_build_cond_empty (t);
6401 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6404 /* Add the loop cleanup function. */
6405 gsi = gsi_last_bb (exit_bb);
6406 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6407 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6408 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6409 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6410 else
6411 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6412 gcall *call_stmt = gimple_build_call (t, 0);
6413 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6414 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6415 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6416 gsi_remove (&gsi, true);
6418 /* Connect the new blocks. */
6419 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6420 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6422 if (!broken_loop)
6424 gimple_seq phis;
6426 e = find_edge (cont_bb, l3_bb);
6427 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6429 phis = phi_nodes (l3_bb);
6430 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6432 gimple *phi = gsi_stmt (gsi);
6433 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6434 PHI_ARG_DEF_FROM_EDGE (phi, e));
6436 remove_edge (e);
6438 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6439 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6440 e = find_edge (cont_bb, l1_bb);
6441 if (gimple_omp_for_combined_p (fd->for_stmt))
6443 remove_edge (e);
6444 e = NULL;
6446 else if (fd->collapse > 1)
6448 remove_edge (e);
6449 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6451 else
6452 e->flags = EDGE_TRUE_VALUE;
6453 if (e)
6455 e->probability = REG_BR_PROB_BASE * 7 / 8;
6456 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6458 else
6460 e = find_edge (cont_bb, l2_bb);
6461 e->flags = EDGE_FALLTHRU;
6463 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6465 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6466 recompute_dominator (CDI_DOMINATORS, l2_bb));
6467 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6468 recompute_dominator (CDI_DOMINATORS, l3_bb));
6469 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6470 recompute_dominator (CDI_DOMINATORS, l0_bb));
6471 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6472 recompute_dominator (CDI_DOMINATORS, l1_bb));
6474 struct loop *outer_loop = alloc_loop ();
6475 outer_loop->header = l0_bb;
6476 outer_loop->latch = l2_bb;
6477 add_loop (outer_loop, l0_bb->loop_father);
6479 if (!gimple_omp_for_combined_p (fd->for_stmt))
6481 struct loop *loop = alloc_loop ();
6482 loop->header = l1_bb;
6483 /* The loop may have multiple latches. */
6484 add_loop (loop, outer_loop);
6490 /* A subroutine of expand_omp_for. Generate code for a parallel
6491 loop with static schedule and no specified chunk size. Given
6492 parameters:
6494 for (V = N1; V cond N2; V += STEP) BODY;
6496 where COND is "<" or ">", we generate pseudocode
6498 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6499 if (cond is <)
6500 adj = STEP - 1;
6501 else
6502 adj = STEP + 1;
6503 if ((__typeof (V)) -1 > 0 && cond is >)
6504 n = -(adj + N2 - N1) / -STEP;
6505 else
6506 n = (adj + N2 - N1) / STEP;
6507 q = n / nthreads;
6508 tt = n % nthreads;
6509 if (threadid < tt) goto L3; else goto L4;
6511 tt = 0;
6512 q = q + 1;
6514 s0 = q * threadid + tt;
6515 e0 = s0 + q;
6516 V = s0 * STEP + N1;
6517 if (s0 >= e0) goto L2; else goto L0;
6519 e = e0 * STEP + N1;
6521 BODY;
6522 V += STEP;
6523 if (V cond e) goto L1;
6527 static void
6528 expand_omp_for_static_nochunk (struct omp_region *region,
6529 struct omp_for_data *fd,
6530 gimple *inner_stmt)
6532 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6533 tree type, itype, vmain, vback;
6534 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6535 basic_block body_bb, cont_bb, collapse_bb = NULL;
6536 basic_block fin_bb;
6537 gimple_stmt_iterator gsi;
6538 edge ep;
6539 bool broken_loop = region->cont == NULL;
6540 tree *counts = NULL;
6541 tree n1, n2, step;
6543 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6544 != GF_OMP_FOR_KIND_OACC_LOOP)
6545 || !inner_stmt);
6547 itype = type = TREE_TYPE (fd->loop.v);
6548 if (POINTER_TYPE_P (type))
6549 itype = signed_type_for (type);
6551 entry_bb = region->entry;
6552 cont_bb = region->cont;
6553 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6554 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6555 gcc_assert (broken_loop
6556 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6557 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6558 body_bb = single_succ (seq_start_bb);
6559 if (!broken_loop)
6561 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
6562 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
6563 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6565 exit_bb = region->exit;
6567 /* Iteration space partitioning goes in ENTRY_BB. */
6568 gsi = gsi_last_bb (entry_bb);
6569 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6571 if (fd->collapse > 1)
6573 int first_zero_iter = -1;
6574 basic_block l2_dom_bb = NULL;
6576 counts = XALLOCAVEC (tree, fd->collapse);
6577 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6578 fin_bb, first_zero_iter,
6579 l2_dom_bb);
6580 t = NULL_TREE;
6582 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6583 t = integer_one_node;
6584 else
6585 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6586 fold_convert (type, fd->loop.n1),
6587 fold_convert (type, fd->loop.n2));
6588 if (fd->collapse == 1
6589 && TYPE_UNSIGNED (type)
6590 && (t == NULL_TREE || !integer_onep (t)))
6592 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6593 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6594 true, GSI_SAME_STMT);
6595 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6596 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6597 true, GSI_SAME_STMT);
6598 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6599 NULL_TREE, NULL_TREE);
6600 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6601 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6602 expand_omp_regimplify_p, NULL, NULL)
6603 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6604 expand_omp_regimplify_p, NULL, NULL))
6606 gsi = gsi_for_stmt (cond_stmt);
6607 gimple_regimplify_operands (cond_stmt, &gsi);
6609 ep = split_block (entry_bb, cond_stmt);
6610 ep->flags = EDGE_TRUE_VALUE;
6611 entry_bb = ep->dest;
6612 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6613 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6614 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6615 if (gimple_in_ssa_p (cfun))
6617 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6618 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6619 !gsi_end_p (gpi); gsi_next (&gpi))
6621 gphi *phi = gpi.phi ();
6622 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6623 ep, UNKNOWN_LOCATION);
6626 gsi = gsi_last_bb (entry_bb);
6629 switch (gimple_omp_for_kind (fd->for_stmt))
6631 case GF_OMP_FOR_KIND_FOR:
6632 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6633 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6634 break;
6635 case GF_OMP_FOR_KIND_DISTRIBUTE:
6636 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6637 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6638 break;
6639 case GF_OMP_FOR_KIND_OACC_LOOP:
6640 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6641 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6642 break;
6643 default:
6644 gcc_unreachable ();
6646 nthreads = build_call_expr (nthreads, 0);
6647 nthreads = fold_convert (itype, nthreads);
6648 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6649 true, GSI_SAME_STMT);
6650 threadid = build_call_expr (threadid, 0);
6651 threadid = fold_convert (itype, threadid);
6652 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6653 true, GSI_SAME_STMT);
6655 n1 = fd->loop.n1;
6656 n2 = fd->loop.n2;
6657 step = fd->loop.step;
6658 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6660 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6661 OMP_CLAUSE__LOOPTEMP_);
6662 gcc_assert (innerc);
6663 n1 = OMP_CLAUSE_DECL (innerc);
6664 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6665 OMP_CLAUSE__LOOPTEMP_);
6666 gcc_assert (innerc);
6667 n2 = OMP_CLAUSE_DECL (innerc);
6669 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6670 true, NULL_TREE, true, GSI_SAME_STMT);
6671 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6672 true, NULL_TREE, true, GSI_SAME_STMT);
6673 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6674 true, NULL_TREE, true, GSI_SAME_STMT);
6676 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6677 t = fold_build2 (PLUS_EXPR, itype, step, t);
6678 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6679 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6680 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6681 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6682 fold_build1 (NEGATE_EXPR, itype, t),
6683 fold_build1 (NEGATE_EXPR, itype, step));
6684 else
6685 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6686 t = fold_convert (itype, t);
6687 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6689 q = create_tmp_reg (itype, "q");
6690 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6691 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6692 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6694 tt = create_tmp_reg (itype, "tt");
6695 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6696 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6697 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6699 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6700 gcond *cond_stmt = gimple_build_cond_empty (t);
6701 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6703 second_bb = split_block (entry_bb, cond_stmt)->dest;
6704 gsi = gsi_last_bb (second_bb);
6705 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6707 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6708 GSI_SAME_STMT);
6709 gassign *assign_stmt
6710 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6711 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6713 third_bb = split_block (second_bb, assign_stmt)->dest;
6714 gsi = gsi_last_bb (third_bb);
6715 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6717 t = build2 (MULT_EXPR, itype, q, threadid);
6718 t = build2 (PLUS_EXPR, itype, t, tt);
6719 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6721 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6722 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6724 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6725 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6727 /* Remove the GIMPLE_OMP_FOR statement. */
6728 gsi_remove (&gsi, true);
6730 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6731 gsi = gsi_start_bb (seq_start_bb);
6733 tree startvar = fd->loop.v;
6734 tree endvar = NULL_TREE;
6736 if (gimple_omp_for_combined_p (fd->for_stmt))
6738 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6739 ? gimple_omp_parallel_clauses (inner_stmt)
6740 : gimple_omp_for_clauses (inner_stmt);
6741 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6742 gcc_assert (innerc);
6743 startvar = OMP_CLAUSE_DECL (innerc);
6744 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6745 OMP_CLAUSE__LOOPTEMP_);
6746 gcc_assert (innerc);
6747 endvar = OMP_CLAUSE_DECL (innerc);
6749 t = fold_convert (itype, s0);
6750 t = fold_build2 (MULT_EXPR, itype, t, step);
6751 if (POINTER_TYPE_P (type))
6752 t = fold_build_pointer_plus (n1, t);
6753 else
6754 t = fold_build2 (PLUS_EXPR, type, t, n1);
6755 t = fold_convert (TREE_TYPE (startvar), t);
6756 t = force_gimple_operand_gsi (&gsi, t,
6757 DECL_P (startvar)
6758 && TREE_ADDRESSABLE (startvar),
6759 NULL_TREE, false, GSI_CONTINUE_LINKING);
6760 assign_stmt = gimple_build_assign (startvar, t);
6761 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6763 t = fold_convert (itype, e0);
6764 t = fold_build2 (MULT_EXPR, itype, t, step);
6765 if (POINTER_TYPE_P (type))
6766 t = fold_build_pointer_plus (n1, t);
6767 else
6768 t = fold_build2 (PLUS_EXPR, type, t, n1);
6769 t = fold_convert (TREE_TYPE (startvar), t);
6770 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6771 false, GSI_CONTINUE_LINKING);
6772 if (endvar)
6774 assign_stmt = gimple_build_assign (endvar, e);
6775 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6776 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6777 assign_stmt = gimple_build_assign (fd->loop.v, e);
6778 else
6779 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6780 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6782 if (fd->collapse > 1)
6783 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6785 if (!broken_loop)
6787 /* The code controlling the sequential loop replaces the
6788 GIMPLE_OMP_CONTINUE. */
6789 gsi = gsi_last_bb (cont_bb);
6790 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6791 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6792 vmain = gimple_omp_continue_control_use (cont_stmt);
6793 vback = gimple_omp_continue_control_def (cont_stmt);
6795 if (!gimple_omp_for_combined_p (fd->for_stmt))
6797 if (POINTER_TYPE_P (type))
6798 t = fold_build_pointer_plus (vmain, step);
6799 else
6800 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6801 t = force_gimple_operand_gsi (&gsi, t,
6802 DECL_P (vback)
6803 && TREE_ADDRESSABLE (vback),
6804 NULL_TREE, true, GSI_SAME_STMT);
6805 assign_stmt = gimple_build_assign (vback, t);
6806 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6808 t = build2 (fd->loop.cond_code, boolean_type_node,
6809 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6810 ? t : vback, e);
6811 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6814 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6815 gsi_remove (&gsi, true);
6817 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6818 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6821 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6822 gsi = gsi_last_bb (exit_bb);
6823 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6825 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6826 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6827 gcc_checking_assert (t == NULL_TREE);
6828 else
6829 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6831 gsi_remove (&gsi, true);
6833 /* Connect all the blocks. */
6834 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6835 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6836 ep = find_edge (entry_bb, second_bb);
6837 ep->flags = EDGE_TRUE_VALUE;
6838 ep->probability = REG_BR_PROB_BASE / 4;
6839 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6840 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6842 if (!broken_loop)
6844 ep = find_edge (cont_bb, body_bb);
6845 if (ep == NULL)
6847 ep = BRANCH_EDGE (cont_bb);
6848 gcc_assert (single_succ (ep->dest) == body_bb);
6850 if (gimple_omp_for_combined_p (fd->for_stmt))
6852 remove_edge (ep);
6853 ep = NULL;
6855 else if (fd->collapse > 1)
6857 remove_edge (ep);
6858 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6860 else
6861 ep->flags = EDGE_TRUE_VALUE;
6862 find_edge (cont_bb, fin_bb)->flags
6863 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6866 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6867 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6868 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6870 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6871 recompute_dominator (CDI_DOMINATORS, body_bb));
6872 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6873 recompute_dominator (CDI_DOMINATORS, fin_bb));
6875 struct loop *loop = body_bb->loop_father;
6876 if (loop != entry_bb->loop_father)
6878 gcc_assert (loop->header == body_bb);
6879 gcc_assert (broken_loop
6880 || loop->latch == region->cont
6881 || single_pred (loop->latch) == region->cont);
6882 return;
6885 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6887 loop = alloc_loop ();
6888 loop->header = body_bb;
6889 if (collapse_bb == NULL)
6890 loop->latch = cont_bb;
6891 add_loop (loop, body_bb->loop_father);
6895 /* Return phi in E->DEST with ARG on edge E. */
6897 static gphi *
6898 find_phi_with_arg_on_edge (tree arg, edge e)
6900 basic_block bb = e->dest;
6902 for (gphi_iterator gpi = gsi_start_phis (bb);
6903 !gsi_end_p (gpi);
6904 gsi_next (&gpi))
6906 gphi *phi = gpi.phi ();
6907 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
6908 return phi;
6911 return NULL;
6914 /* A subroutine of expand_omp_for. Generate code for a parallel
6915 loop with static schedule and a specified chunk size. Given
6916 parameters:
6918 for (V = N1; V cond N2; V += STEP) BODY;
6920 where COND is "<" or ">", we generate pseudocode
6922 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6923 if (cond is <)
6924 adj = STEP - 1;
6925 else
6926 adj = STEP + 1;
6927 if ((__typeof (V)) -1 > 0 && cond is >)
6928 n = -(adj + N2 - N1) / -STEP;
6929 else
6930 n = (adj + N2 - N1) / STEP;
6931 trip = 0;
6932 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6933 here so that V is defined
6934 if the loop is not entered
6936 s0 = (trip * nthreads + threadid) * CHUNK;
6937 e0 = min(s0 + CHUNK, n);
6938 if (s0 < n) goto L1; else goto L4;
6940 V = s0 * STEP + N1;
6941 e = e0 * STEP + N1;
6943 BODY;
6944 V += STEP;
6945 if (V cond e) goto L2; else goto L3;
6947 trip += 1;
6948 goto L0;
6952 static void
6953 expand_omp_for_static_chunk (struct omp_region *region,
6954 struct omp_for_data *fd, gimple *inner_stmt)
6956 tree n, s0, e0, e, t;
6957 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6958 tree type, itype, vmain, vback, vextra;
6959 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6960 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6961 gimple_stmt_iterator gsi;
6962 edge se;
6963 bool broken_loop = region->cont == NULL;
6964 tree *counts = NULL;
6965 tree n1, n2, step;
6967 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6968 != GF_OMP_FOR_KIND_OACC_LOOP)
6969 || !inner_stmt);
6971 itype = type = TREE_TYPE (fd->loop.v);
6972 if (POINTER_TYPE_P (type))
6973 itype = signed_type_for (type);
6975 entry_bb = region->entry;
6976 se = split_block (entry_bb, last_stmt (entry_bb));
6977 entry_bb = se->src;
6978 iter_part_bb = se->dest;
6979 cont_bb = region->cont;
6980 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6981 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6982 gcc_assert (broken_loop
6983 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6984 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6985 body_bb = single_succ (seq_start_bb);
6986 if (!broken_loop)
6988 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
6989 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
6990 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6991 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6993 exit_bb = region->exit;
6995 /* Trip and adjustment setup goes in ENTRY_BB. */
6996 gsi = gsi_last_bb (entry_bb);
6997 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6999 if (fd->collapse > 1)
7001 int first_zero_iter = -1;
7002 basic_block l2_dom_bb = NULL;
7004 counts = XALLOCAVEC (tree, fd->collapse);
7005 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7006 fin_bb, first_zero_iter,
7007 l2_dom_bb);
7008 t = NULL_TREE;
7010 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
7011 t = integer_one_node;
7012 else
7013 t = fold_binary (fd->loop.cond_code, boolean_type_node,
7014 fold_convert (type, fd->loop.n1),
7015 fold_convert (type, fd->loop.n2));
7016 if (fd->collapse == 1
7017 && TYPE_UNSIGNED (type)
7018 && (t == NULL_TREE || !integer_onep (t)))
7020 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
7021 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
7022 true, GSI_SAME_STMT);
7023 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
7024 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
7025 true, GSI_SAME_STMT);
7026 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
7027 NULL_TREE, NULL_TREE);
7028 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
7029 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7030 expand_omp_regimplify_p, NULL, NULL)
7031 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7032 expand_omp_regimplify_p, NULL, NULL))
7034 gsi = gsi_for_stmt (cond_stmt);
7035 gimple_regimplify_operands (cond_stmt, &gsi);
7037 se = split_block (entry_bb, cond_stmt);
7038 se->flags = EDGE_TRUE_VALUE;
7039 entry_bb = se->dest;
7040 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
7041 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
7042 se->probability = REG_BR_PROB_BASE / 2000 - 1;
7043 if (gimple_in_ssa_p (cfun))
7045 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
7046 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
7047 !gsi_end_p (gpi); gsi_next (&gpi))
7049 gphi *phi = gpi.phi ();
7050 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
7051 se, UNKNOWN_LOCATION);
7054 gsi = gsi_last_bb (entry_bb);
7057 switch (gimple_omp_for_kind (fd->for_stmt))
7059 case GF_OMP_FOR_KIND_FOR:
7060 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7061 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7062 break;
7063 case GF_OMP_FOR_KIND_DISTRIBUTE:
7064 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7065 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7066 break;
7067 case GF_OMP_FOR_KIND_OACC_LOOP:
7068 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7069 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7070 break;
7071 default:
7072 gcc_unreachable ();
7074 nthreads = build_call_expr (nthreads, 0);
7075 nthreads = fold_convert (itype, nthreads);
7076 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7077 true, GSI_SAME_STMT);
7078 threadid = build_call_expr (threadid, 0);
7079 threadid = fold_convert (itype, threadid);
7080 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7081 true, GSI_SAME_STMT);
7083 n1 = fd->loop.n1;
7084 n2 = fd->loop.n2;
7085 step = fd->loop.step;
7086 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7088 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7089 OMP_CLAUSE__LOOPTEMP_);
7090 gcc_assert (innerc);
7091 n1 = OMP_CLAUSE_DECL (innerc);
7092 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7093 OMP_CLAUSE__LOOPTEMP_);
7094 gcc_assert (innerc);
7095 n2 = OMP_CLAUSE_DECL (innerc);
7097 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7098 true, NULL_TREE, true, GSI_SAME_STMT);
7099 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7100 true, NULL_TREE, true, GSI_SAME_STMT);
7101 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7102 true, NULL_TREE, true, GSI_SAME_STMT);
7103 fd->chunk_size
7104 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7105 true, NULL_TREE, true, GSI_SAME_STMT);
7107 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7108 t = fold_build2 (PLUS_EXPR, itype, step, t);
7109 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7110 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7111 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7112 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7113 fold_build1 (NEGATE_EXPR, itype, t),
7114 fold_build1 (NEGATE_EXPR, itype, step));
7115 else
7116 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7117 t = fold_convert (itype, t);
7118 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7119 true, GSI_SAME_STMT);
7121 trip_var = create_tmp_reg (itype, ".trip");
7122 if (gimple_in_ssa_p (cfun))
7124 trip_init = make_ssa_name (trip_var);
7125 trip_main = make_ssa_name (trip_var);
7126 trip_back = make_ssa_name (trip_var);
7128 else
7130 trip_init = trip_var;
7131 trip_main = trip_var;
7132 trip_back = trip_var;
7135 gassign *assign_stmt
7136 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7137 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7139 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7140 t = fold_build2 (MULT_EXPR, itype, t, step);
7141 if (POINTER_TYPE_P (type))
7142 t = fold_build_pointer_plus (n1, t);
7143 else
7144 t = fold_build2 (PLUS_EXPR, type, t, n1);
7145 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7146 true, GSI_SAME_STMT);
7148 /* Remove the GIMPLE_OMP_FOR. */
7149 gsi_remove (&gsi, true);
7151 /* Iteration space partitioning goes in ITER_PART_BB. */
7152 gsi = gsi_last_bb (iter_part_bb);
7154 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7155 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7156 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7157 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7158 false, GSI_CONTINUE_LINKING);
7160 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7161 t = fold_build2 (MIN_EXPR, itype, t, n);
7162 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7163 false, GSI_CONTINUE_LINKING);
7165 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7166 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7168 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7169 gsi = gsi_start_bb (seq_start_bb);
7171 tree startvar = fd->loop.v;
7172 tree endvar = NULL_TREE;
7174 if (gimple_omp_for_combined_p (fd->for_stmt))
7176 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7177 ? gimple_omp_parallel_clauses (inner_stmt)
7178 : gimple_omp_for_clauses (inner_stmt);
7179 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7180 gcc_assert (innerc);
7181 startvar = OMP_CLAUSE_DECL (innerc);
7182 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7183 OMP_CLAUSE__LOOPTEMP_);
7184 gcc_assert (innerc);
7185 endvar = OMP_CLAUSE_DECL (innerc);
7188 t = fold_convert (itype, s0);
7189 t = fold_build2 (MULT_EXPR, itype, t, step);
7190 if (POINTER_TYPE_P (type))
7191 t = fold_build_pointer_plus (n1, t);
7192 else
7193 t = fold_build2 (PLUS_EXPR, type, t, n1);
7194 t = fold_convert (TREE_TYPE (startvar), t);
7195 t = force_gimple_operand_gsi (&gsi, t,
7196 DECL_P (startvar)
7197 && TREE_ADDRESSABLE (startvar),
7198 NULL_TREE, false, GSI_CONTINUE_LINKING);
7199 assign_stmt = gimple_build_assign (startvar, t);
7200 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7202 t = fold_convert (itype, e0);
7203 t = fold_build2 (MULT_EXPR, itype, t, step);
7204 if (POINTER_TYPE_P (type))
7205 t = fold_build_pointer_plus (n1, t);
7206 else
7207 t = fold_build2 (PLUS_EXPR, type, t, n1);
7208 t = fold_convert (TREE_TYPE (startvar), t);
7209 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7210 false, GSI_CONTINUE_LINKING);
7211 if (endvar)
7213 assign_stmt = gimple_build_assign (endvar, e);
7214 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7215 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7216 assign_stmt = gimple_build_assign (fd->loop.v, e);
7217 else
7218 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7219 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7221 if (fd->collapse > 1)
7222 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7224 if (!broken_loop)
7226 /* The code controlling the sequential loop goes in CONT_BB,
7227 replacing the GIMPLE_OMP_CONTINUE. */
7228 gsi = gsi_last_bb (cont_bb);
7229 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7230 vmain = gimple_omp_continue_control_use (cont_stmt);
7231 vback = gimple_omp_continue_control_def (cont_stmt);
7233 if (!gimple_omp_for_combined_p (fd->for_stmt))
7235 if (POINTER_TYPE_P (type))
7236 t = fold_build_pointer_plus (vmain, step);
7237 else
7238 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7239 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7240 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7241 true, GSI_SAME_STMT);
7242 assign_stmt = gimple_build_assign (vback, t);
7243 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7245 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
7246 t = build2 (EQ_EXPR, boolean_type_node,
7247 build_int_cst (itype, 0),
7248 build_int_cst (itype, 1));
7249 else
7250 t = build2 (fd->loop.cond_code, boolean_type_node,
7251 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7252 ? t : vback, e);
7253 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7256 /* Remove GIMPLE_OMP_CONTINUE. */
7257 gsi_remove (&gsi, true);
7259 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7260 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7262 /* Trip update code goes into TRIP_UPDATE_BB. */
7263 gsi = gsi_start_bb (trip_update_bb);
7265 t = build_int_cst (itype, 1);
7266 t = build2 (PLUS_EXPR, itype, trip_main, t);
7267 assign_stmt = gimple_build_assign (trip_back, t);
7268 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7271 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7272 gsi = gsi_last_bb (exit_bb);
7273 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7275 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7276 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7277 gcc_checking_assert (t == NULL_TREE);
7278 else
7279 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7281 gsi_remove (&gsi, true);
7283 /* Connect the new blocks. */
7284 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7285 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7287 if (!broken_loop)
7289 se = find_edge (cont_bb, body_bb);
7290 if (se == NULL)
7292 se = BRANCH_EDGE (cont_bb);
7293 gcc_assert (single_succ (se->dest) == body_bb);
7295 if (gimple_omp_for_combined_p (fd->for_stmt))
7297 remove_edge (se);
7298 se = NULL;
7300 else if (fd->collapse > 1)
7302 remove_edge (se);
7303 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7305 else
7306 se->flags = EDGE_TRUE_VALUE;
7307 find_edge (cont_bb, trip_update_bb)->flags
7308 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7310 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7313 if (gimple_in_ssa_p (cfun))
7315 gphi_iterator psi;
7316 gphi *phi;
7317 edge re, ene;
7318 edge_var_map *vm;
7319 size_t i;
7321 gcc_assert (fd->collapse == 1 && !broken_loop);
7323 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7324 remove arguments of the phi nodes in fin_bb. We need to create
7325 appropriate phi nodes in iter_part_bb instead. */
7326 se = find_edge (iter_part_bb, fin_bb);
7327 re = single_succ_edge (trip_update_bb);
7328 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7329 ene = single_succ_edge (entry_bb);
7331 psi = gsi_start_phis (fin_bb);
7332 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7333 gsi_next (&psi), ++i)
7335 gphi *nphi;
7336 source_location locus;
7338 phi = psi.phi ();
7339 t = gimple_phi_result (phi);
7340 gcc_assert (t == redirect_edge_var_map_result (vm));
7342 if (!single_pred_p (fin_bb))
7343 t = copy_ssa_name (t, phi);
7345 nphi = create_phi_node (t, iter_part_bb);
7347 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7348 locus = gimple_phi_arg_location_from_edge (phi, se);
7350 /* A special case -- fd->loop.v is not yet computed in
7351 iter_part_bb, we need to use vextra instead. */
7352 if (t == fd->loop.v)
7353 t = vextra;
7354 add_phi_arg (nphi, t, ene, locus);
7355 locus = redirect_edge_var_map_location (vm);
7356 tree back_arg = redirect_edge_var_map_def (vm);
7357 add_phi_arg (nphi, back_arg, re, locus);
7358 edge ce = find_edge (cont_bb, body_bb);
7359 if (ce == NULL)
7361 ce = BRANCH_EDGE (cont_bb);
7362 gcc_assert (single_succ (ce->dest) == body_bb);
7363 ce = single_succ_edge (ce->dest);
7365 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
7366 gcc_assert (inner_loop_phi != NULL);
7367 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
7368 find_edge (seq_start_bb, body_bb), locus);
7370 if (!single_pred_p (fin_bb))
7371 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
7373 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
7374 redirect_edge_var_map_clear (re);
7375 if (single_pred_p (fin_bb))
7376 while (1)
7378 psi = gsi_start_phis (fin_bb);
7379 if (gsi_end_p (psi))
7380 break;
7381 remove_phi_node (&psi, false);
7384 /* Make phi node for trip. */
7385 phi = create_phi_node (trip_main, iter_part_bb);
7386 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7387 UNKNOWN_LOCATION);
7388 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7389 UNKNOWN_LOCATION);
7392 if (!broken_loop)
7393 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7394 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7395 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7396 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7397 recompute_dominator (CDI_DOMINATORS, fin_bb));
7398 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7399 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7400 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7401 recompute_dominator (CDI_DOMINATORS, body_bb));
7403 if (!broken_loop)
7405 struct loop *loop = body_bb->loop_father;
7406 struct loop *trip_loop = alloc_loop ();
7407 trip_loop->header = iter_part_bb;
7408 trip_loop->latch = trip_update_bb;
7409 add_loop (trip_loop, iter_part_bb->loop_father);
7411 if (loop != entry_bb->loop_father)
7413 gcc_assert (loop->header == body_bb);
7414 gcc_assert (loop->latch == region->cont
7415 || single_pred (loop->latch) == region->cont);
7416 trip_loop->inner = loop;
7417 return;
7420 if (!gimple_omp_for_combined_p (fd->for_stmt))
7422 loop = alloc_loop ();
7423 loop->header = body_bb;
7424 if (collapse_bb == NULL)
7425 loop->latch = cont_bb;
7426 add_loop (loop, trip_loop);
7431 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7432 Given parameters:
7433 for (V = N1; V cond N2; V += STEP) BODY;
7435 where COND is "<" or ">" or "!=", we generate pseudocode
7437 for (ind_var = low; ind_var < high; ind_var++)
7439 V = n1 + (ind_var * STEP)
7441 <BODY>
7444 In the above pseudocode, low and high are function parameters of the
7445 child function. In the function below, we are inserting a temp.
7446 variable that will be making a call to two OMP functions that will not be
7447 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7448 with _Cilk_for). These functions are replaced with low and high
7449 by the function that handles taskreg. */
7452 static void
7453 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7455 bool broken_loop = region->cont == NULL;
7456 basic_block entry_bb = region->entry;
7457 basic_block cont_bb = region->cont;
7459 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7460 gcc_assert (broken_loop
7461 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7462 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7463 basic_block l1_bb, l2_bb;
7465 if (!broken_loop)
7467 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7468 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7469 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7470 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7472 else
7474 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7475 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7476 l2_bb = single_succ (l1_bb);
7478 basic_block exit_bb = region->exit;
7479 basic_block l2_dom_bb = NULL;
7481 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7483 /* Below statements until the "tree high_val = ..." are pseudo statements
7484 used to pass information to be used by expand_omp_taskreg.
7485 low_val and high_val will be replaced by the __low and __high
7486 parameter from the child function.
7488 The call_exprs part is a place-holder, it is mainly used
7489 to distinctly identify to the top-level part that this is
7490 where we should put low and high (reasoning given in header
7491 comment). */
7493 tree child_fndecl
7494 = gimple_omp_parallel_child_fn (
7495 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7496 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7497 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7499 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7500 high_val = t;
7501 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7502 low_val = t;
7504 gcc_assert (low_val && high_val);
7506 tree type = TREE_TYPE (low_val);
7507 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7508 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7510 /* Not needed in SSA form right now. */
7511 gcc_assert (!gimple_in_ssa_p (cfun));
7512 if (l2_dom_bb == NULL)
7513 l2_dom_bb = l1_bb;
7515 tree n1 = low_val;
7516 tree n2 = high_val;
7518 gimple *stmt = gimple_build_assign (ind_var, n1);
7520 /* Replace the GIMPLE_OMP_FOR statement. */
7521 gsi_replace (&gsi, stmt, true);
7523 if (!broken_loop)
7525 /* Code to control the increment goes in the CONT_BB. */
7526 gsi = gsi_last_bb (cont_bb);
7527 stmt = gsi_stmt (gsi);
7528 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7529 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7530 build_one_cst (type));
7532 /* Replace GIMPLE_OMP_CONTINUE. */
7533 gsi_replace (&gsi, stmt, true);
7536 /* Emit the condition in L1_BB. */
7537 gsi = gsi_after_labels (l1_bb);
7538 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7539 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7540 fd->loop.step);
7541 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7542 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7543 fd->loop.n1, fold_convert (sizetype, t));
7544 else
7545 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7546 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7547 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7548 expand_omp_build_assign (&gsi, fd->loop.v, t);
7550 /* The condition is always '<' since the runtime will fill in the low
7551 and high values. */
7552 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7553 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7555 /* Remove GIMPLE_OMP_RETURN. */
7556 gsi = gsi_last_bb (exit_bb);
7557 gsi_remove (&gsi, true);
7559 /* Connect the new blocks. */
7560 remove_edge (FALLTHRU_EDGE (entry_bb));
7562 edge e, ne;
7563 if (!broken_loop)
7565 remove_edge (BRANCH_EDGE (entry_bb));
7566 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7568 e = BRANCH_EDGE (l1_bb);
7569 ne = FALLTHRU_EDGE (l1_bb);
7570 e->flags = EDGE_TRUE_VALUE;
7572 else
7574 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7576 ne = single_succ_edge (l1_bb);
7577 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7580 ne->flags = EDGE_FALSE_VALUE;
7581 e->probability = REG_BR_PROB_BASE * 7 / 8;
7582 ne->probability = REG_BR_PROB_BASE / 8;
7584 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7585 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7586 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7588 if (!broken_loop)
7590 struct loop *loop = alloc_loop ();
7591 loop->header = l1_bb;
7592 loop->latch = cont_bb;
7593 add_loop (loop, l1_bb->loop_father);
7594 loop->safelen = INT_MAX;
7597 /* Pick the correct library function based on the precision of the
7598 induction variable type. */
7599 tree lib_fun = NULL_TREE;
7600 if (TYPE_PRECISION (type) == 32)
7601 lib_fun = cilk_for_32_fndecl;
7602 else if (TYPE_PRECISION (type) == 64)
7603 lib_fun = cilk_for_64_fndecl;
7604 else
7605 gcc_unreachable ();
7607 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7609 /* WS_ARGS contains the library function flavor to call:
7610 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7611 user-defined grain value. If the user does not define one, then zero
7612 is passed in by the parser. */
7613 vec_alloc (region->ws_args, 2);
7614 region->ws_args->quick_push (lib_fun);
7615 region->ws_args->quick_push (fd->chunk_size);
7618 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7619 loop. Given parameters:
7621 for (V = N1; V cond N2; V += STEP) BODY;
7623 where COND is "<" or ">", we generate pseudocode
7625 V = N1;
7626 goto L1;
7628 BODY;
7629 V += STEP;
7631 if (V cond N2) goto L0; else goto L2;
7634 For collapsed loops, given parameters:
7635 collapse(3)
7636 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7637 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7638 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7639 BODY;
7641 we generate pseudocode
7643 if (cond3 is <)
7644 adj = STEP3 - 1;
7645 else
7646 adj = STEP3 + 1;
7647 count3 = (adj + N32 - N31) / STEP3;
7648 if (cond2 is <)
7649 adj = STEP2 - 1;
7650 else
7651 adj = STEP2 + 1;
7652 count2 = (adj + N22 - N21) / STEP2;
7653 if (cond1 is <)
7654 adj = STEP1 - 1;
7655 else
7656 adj = STEP1 + 1;
7657 count1 = (adj + N12 - N11) / STEP1;
7658 count = count1 * count2 * count3;
7659 V = 0;
7660 V1 = N11;
7661 V2 = N21;
7662 V3 = N31;
7663 goto L1;
7665 BODY;
7666 V += 1;
7667 V3 += STEP3;
7668 V2 += (V3 cond3 N32) ? 0 : STEP2;
7669 V3 = (V3 cond3 N32) ? V3 : N31;
7670 V1 += (V2 cond2 N22) ? 0 : STEP1;
7671 V2 = (V2 cond2 N22) ? V2 : N21;
7673 if (V < count) goto L0; else goto L2;
7678 static void
7679 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7681 tree type, t;
7682 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7683 gimple_stmt_iterator gsi;
7684 gimple *stmt;
7685 gcond *cond_stmt;
7686 bool broken_loop = region->cont == NULL;
7687 edge e, ne;
7688 tree *counts = NULL;
7689 int i;
7690 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7691 OMP_CLAUSE_SAFELEN);
7692 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7693 OMP_CLAUSE__SIMDUID_);
7694 tree n1, n2;
7696 type = TREE_TYPE (fd->loop.v);
7697 entry_bb = region->entry;
7698 cont_bb = region->cont;
7699 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7700 gcc_assert (broken_loop
7701 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7702 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7703 if (!broken_loop)
7705 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7706 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7707 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7708 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7710 else
7712 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7713 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7714 l2_bb = single_succ (l1_bb);
7716 exit_bb = region->exit;
7717 l2_dom_bb = NULL;
7719 gsi = gsi_last_bb (entry_bb);
7721 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7722 /* Not needed in SSA form right now. */
7723 gcc_assert (!gimple_in_ssa_p (cfun));
7724 if (fd->collapse > 1)
7726 int first_zero_iter = -1;
7727 basic_block zero_iter_bb = l2_bb;
7729 counts = XALLOCAVEC (tree, fd->collapse);
7730 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7731 zero_iter_bb, first_zero_iter,
7732 l2_dom_bb);
7734 if (l2_dom_bb == NULL)
7735 l2_dom_bb = l1_bb;
7737 n1 = fd->loop.n1;
7738 n2 = fd->loop.n2;
7739 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7741 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7742 OMP_CLAUSE__LOOPTEMP_);
7743 gcc_assert (innerc);
7744 n1 = OMP_CLAUSE_DECL (innerc);
7745 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7746 OMP_CLAUSE__LOOPTEMP_);
7747 gcc_assert (innerc);
7748 n2 = OMP_CLAUSE_DECL (innerc);
7749 expand_omp_build_assign (&gsi, fd->loop.v,
7750 fold_convert (type, n1));
7751 if (fd->collapse > 1)
7753 gsi_prev (&gsi);
7754 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7755 gsi_next (&gsi);
7758 else
7760 expand_omp_build_assign (&gsi, fd->loop.v,
7761 fold_convert (type, fd->loop.n1));
7762 if (fd->collapse > 1)
7763 for (i = 0; i < fd->collapse; i++)
7765 tree itype = TREE_TYPE (fd->loops[i].v);
7766 if (POINTER_TYPE_P (itype))
7767 itype = signed_type_for (itype);
7768 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7769 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7773 /* Remove the GIMPLE_OMP_FOR statement. */
7774 gsi_remove (&gsi, true);
7776 if (!broken_loop)
7778 /* Code to control the increment goes in the CONT_BB. */
7779 gsi = gsi_last_bb (cont_bb);
7780 stmt = gsi_stmt (gsi);
7781 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7783 if (POINTER_TYPE_P (type))
7784 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7785 else
7786 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7787 expand_omp_build_assign (&gsi, fd->loop.v, t);
7789 if (fd->collapse > 1)
7791 i = fd->collapse - 1;
7792 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7794 t = fold_convert (sizetype, fd->loops[i].step);
7795 t = fold_build_pointer_plus (fd->loops[i].v, t);
7797 else
7799 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7800 fd->loops[i].step);
7801 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7802 fd->loops[i].v, t);
7804 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7806 for (i = fd->collapse - 1; i > 0; i--)
7808 tree itype = TREE_TYPE (fd->loops[i].v);
7809 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7810 if (POINTER_TYPE_P (itype2))
7811 itype2 = signed_type_for (itype2);
7812 t = build3 (COND_EXPR, itype2,
7813 build2 (fd->loops[i].cond_code, boolean_type_node,
7814 fd->loops[i].v,
7815 fold_convert (itype, fd->loops[i].n2)),
7816 build_int_cst (itype2, 0),
7817 fold_convert (itype2, fd->loops[i - 1].step));
7818 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7819 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7820 else
7821 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7822 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7824 t = build3 (COND_EXPR, itype,
7825 build2 (fd->loops[i].cond_code, boolean_type_node,
7826 fd->loops[i].v,
7827 fold_convert (itype, fd->loops[i].n2)),
7828 fd->loops[i].v,
7829 fold_convert (itype, fd->loops[i].n1));
7830 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7834 /* Remove GIMPLE_OMP_CONTINUE. */
7835 gsi_remove (&gsi, true);
7838 /* Emit the condition in L1_BB. */
7839 gsi = gsi_start_bb (l1_bb);
7841 t = fold_convert (type, n2);
7842 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7843 false, GSI_CONTINUE_LINKING);
7844 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7845 cond_stmt = gimple_build_cond_empty (t);
7846 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7847 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7848 NULL, NULL)
7849 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7850 NULL, NULL))
7852 gsi = gsi_for_stmt (cond_stmt);
7853 gimple_regimplify_operands (cond_stmt, &gsi);
7856 /* Remove GIMPLE_OMP_RETURN. */
7857 gsi = gsi_last_bb (exit_bb);
7858 gsi_remove (&gsi, true);
7860 /* Connect the new blocks. */
7861 remove_edge (FALLTHRU_EDGE (entry_bb));
7863 if (!broken_loop)
7865 remove_edge (BRANCH_EDGE (entry_bb));
7866 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7868 e = BRANCH_EDGE (l1_bb);
7869 ne = FALLTHRU_EDGE (l1_bb);
7870 e->flags = EDGE_TRUE_VALUE;
7872 else
7874 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7876 ne = single_succ_edge (l1_bb);
7877 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7880 ne->flags = EDGE_FALSE_VALUE;
7881 e->probability = REG_BR_PROB_BASE * 7 / 8;
7882 ne->probability = REG_BR_PROB_BASE / 8;
7884 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7885 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7886 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7888 if (!broken_loop)
7890 struct loop *loop = alloc_loop ();
7891 loop->header = l1_bb;
7892 loop->latch = cont_bb;
7893 add_loop (loop, l1_bb->loop_father);
7894 if (safelen == NULL_TREE)
7895 loop->safelen = INT_MAX;
7896 else
7898 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7899 if (TREE_CODE (safelen) != INTEGER_CST)
7900 loop->safelen = 0;
7901 else if (!tree_fits_uhwi_p (safelen)
7902 || tree_to_uhwi (safelen) > INT_MAX)
7903 loop->safelen = INT_MAX;
7904 else
7905 loop->safelen = tree_to_uhwi (safelen);
7906 if (loop->safelen == 1)
7907 loop->safelen = 0;
7909 if (simduid)
7911 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7912 cfun->has_simduid_loops = true;
7914 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7915 the loop. */
7916 if ((flag_tree_loop_vectorize
7917 || (!global_options_set.x_flag_tree_loop_vectorize
7918 && !global_options_set.x_flag_tree_vectorize))
7919 && flag_tree_loop_optimize
7920 && loop->safelen > 1)
7922 loop->force_vectorize = true;
7923 cfun->has_force_vectorize_loops = true;
7926 else if (simduid)
7927 cfun->has_simduid_loops = true;
7931 /* Expand the OMP loop defined by REGION. */
7933 static void
7934 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
7936 struct omp_for_data fd;
7937 struct omp_for_data_loop *loops;
7939 loops
7940 = (struct omp_for_data_loop *)
7941 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7942 * sizeof (struct omp_for_data_loop));
7943 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7944 &fd, loops);
7945 region->sched_kind = fd.sched_kind;
7947 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7948 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7949 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7950 if (region->cont)
7952 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7953 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7954 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7956 else
7957 /* If there isn't a continue then this is a degerate case where
7958 the introduction of abnormal edges during lowering will prevent
7959 original loops from being detected. Fix that up. */
7960 loops_state_set (LOOPS_NEED_FIXUP);
7962 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7963 expand_omp_simd (region, &fd);
7964 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7965 expand_cilk_for (region, &fd);
7966 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7967 && !fd.have_ordered)
7969 if (fd.chunk_size == NULL)
7970 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7971 else
7972 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7974 else
7976 int fn_index, start_ix, next_ix;
7978 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7979 == GF_OMP_FOR_KIND_FOR);
7980 if (fd.chunk_size == NULL
7981 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7982 fd.chunk_size = integer_zero_node;
7983 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7984 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7985 ? 3 : fd.sched_kind;
7986 fn_index += fd.have_ordered * 4;
7987 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7988 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7989 if (fd.iter_type == long_long_unsigned_type_node)
7991 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7992 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7993 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7994 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7996 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7997 (enum built_in_function) next_ix, inner_stmt);
8000 if (gimple_in_ssa_p (cfun))
8001 update_ssa (TODO_update_ssa_only_virtuals);
8005 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
8007 v = GOMP_sections_start (n);
8009 switch (v)
8011 case 0:
8012 goto L2;
8013 case 1:
8014 section 1;
8015 goto L1;
8016 case 2:
8018 case n:
8020 default:
8021 abort ();
8024 v = GOMP_sections_next ();
8025 goto L0;
8027 reduction;
8029 If this is a combined parallel sections, replace the call to
8030 GOMP_sections_start with call to GOMP_sections_next. */
8032 static void
8033 expand_omp_sections (struct omp_region *region)
8035 tree t, u, vin = NULL, vmain, vnext, l2;
8036 unsigned len;
8037 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
8038 gimple_stmt_iterator si, switch_si;
8039 gomp_sections *sections_stmt;
8040 gimple *stmt;
8041 gomp_continue *cont;
8042 edge_iterator ei;
8043 edge e;
8044 struct omp_region *inner;
8045 unsigned i, casei;
8046 bool exit_reachable = region->cont != NULL;
8048 gcc_assert (region->exit != NULL);
8049 entry_bb = region->entry;
8050 l0_bb = single_succ (entry_bb);
8051 l1_bb = region->cont;
8052 l2_bb = region->exit;
8053 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
8054 l2 = gimple_block_label (l2_bb);
8055 else
8057 /* This can happen if there are reductions. */
8058 len = EDGE_COUNT (l0_bb->succs);
8059 gcc_assert (len > 0);
8060 e = EDGE_SUCC (l0_bb, len - 1);
8061 si = gsi_last_bb (e->dest);
8062 l2 = NULL_TREE;
8063 if (gsi_end_p (si)
8064 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
8065 l2 = gimple_block_label (e->dest);
8066 else
8067 FOR_EACH_EDGE (e, ei, l0_bb->succs)
8069 si = gsi_last_bb (e->dest);
8070 if (gsi_end_p (si)
8071 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
8073 l2 = gimple_block_label (e->dest);
8074 break;
8078 if (exit_reachable)
8079 default_bb = create_empty_bb (l1_bb->prev_bb);
8080 else
8081 default_bb = create_empty_bb (l0_bb);
8083 /* We will build a switch() with enough cases for all the
8084 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
8085 and a default case to abort if something goes wrong. */
8086 len = EDGE_COUNT (l0_bb->succs);
8088 /* Use vec::quick_push on label_vec throughout, since we know the size
8089 in advance. */
8090 auto_vec<tree> label_vec (len);
8092 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
8093 GIMPLE_OMP_SECTIONS statement. */
8094 si = gsi_last_bb (entry_bb);
8095 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
8096 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8097 vin = gimple_omp_sections_control (sections_stmt);
8098 if (!is_combined_parallel (region))
8100 /* If we are not inside a combined parallel+sections region,
8101 call GOMP_sections_start. */
8102 t = build_int_cst (unsigned_type_node, len - 1);
8103 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
8104 stmt = gimple_build_call (u, 1, t);
8106 else
8108 /* Otherwise, call GOMP_sections_next. */
8109 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8110 stmt = gimple_build_call (u, 0);
8112 gimple_call_set_lhs (stmt, vin);
8113 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8114 gsi_remove (&si, true);
8116 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8117 L0_BB. */
8118 switch_si = gsi_last_bb (l0_bb);
8119 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8120 if (exit_reachable)
8122 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8123 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8124 vmain = gimple_omp_continue_control_use (cont);
8125 vnext = gimple_omp_continue_control_def (cont);
8127 else
8129 vmain = vin;
8130 vnext = NULL_TREE;
8133 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8134 label_vec.quick_push (t);
8135 i = 1;
8137 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8138 for (inner = region->inner, casei = 1;
8139 inner;
8140 inner = inner->next, i++, casei++)
8142 basic_block s_entry_bb, s_exit_bb;
8144 /* Skip optional reduction region. */
8145 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8147 --i;
8148 --casei;
8149 continue;
8152 s_entry_bb = inner->entry;
8153 s_exit_bb = inner->exit;
8155 t = gimple_block_label (s_entry_bb);
8156 u = build_int_cst (unsigned_type_node, casei);
8157 u = build_case_label (u, NULL, t);
8158 label_vec.quick_push (u);
8160 si = gsi_last_bb (s_entry_bb);
8161 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8162 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8163 gsi_remove (&si, true);
8164 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8166 if (s_exit_bb == NULL)
8167 continue;
8169 si = gsi_last_bb (s_exit_bb);
8170 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8171 gsi_remove (&si, true);
8173 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8176 /* Error handling code goes in DEFAULT_BB. */
8177 t = gimple_block_label (default_bb);
8178 u = build_case_label (NULL, NULL, t);
8179 make_edge (l0_bb, default_bb, 0);
8180 add_bb_to_loop (default_bb, current_loops->tree_root);
8182 stmt = gimple_build_switch (vmain, u, label_vec);
8183 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8184 gsi_remove (&switch_si, true);
8186 si = gsi_start_bb (default_bb);
8187 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8188 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8190 if (exit_reachable)
8192 tree bfn_decl;
8194 /* Code to get the next section goes in L1_BB. */
8195 si = gsi_last_bb (l1_bb);
8196 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8198 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8199 stmt = gimple_build_call (bfn_decl, 0);
8200 gimple_call_set_lhs (stmt, vnext);
8201 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8202 gsi_remove (&si, true);
8204 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8207 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8208 si = gsi_last_bb (l2_bb);
8209 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8210 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8211 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8212 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8213 else
8214 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8215 stmt = gimple_build_call (t, 0);
8216 if (gimple_omp_return_lhs (gsi_stmt (si)))
8217 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8218 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8219 gsi_remove (&si, true);
8221 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8225 /* Expand code for an OpenMP single directive. We've already expanded
8226 much of the code, here we simply place the GOMP_barrier call. */
8228 static void
8229 expand_omp_single (struct omp_region *region)
8231 basic_block entry_bb, exit_bb;
8232 gimple_stmt_iterator si;
8234 entry_bb = region->entry;
8235 exit_bb = region->exit;
8237 si = gsi_last_bb (entry_bb);
8238 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8239 gsi_remove (&si, true);
8240 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8242 si = gsi_last_bb (exit_bb);
8243 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8245 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8246 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8248 gsi_remove (&si, true);
8249 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8253 /* Generic expansion for OpenMP synchronization directives: master,
8254 ordered and critical. All we need to do here is remove the entry
8255 and exit markers for REGION. */
8257 static void
8258 expand_omp_synch (struct omp_region *region)
8260 basic_block entry_bb, exit_bb;
8261 gimple_stmt_iterator si;
8263 entry_bb = region->entry;
8264 exit_bb = region->exit;
8266 si = gsi_last_bb (entry_bb);
8267 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8268 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8269 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8270 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8271 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8272 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8273 gsi_remove (&si, true);
8274 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8276 if (exit_bb)
8278 si = gsi_last_bb (exit_bb);
8279 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8280 gsi_remove (&si, true);
8281 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8285 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8286 operation as a normal volatile load. */
8288 static bool
8289 expand_omp_atomic_load (basic_block load_bb, tree addr,
8290 tree loaded_val, int index)
8292 enum built_in_function tmpbase;
8293 gimple_stmt_iterator gsi;
8294 basic_block store_bb;
8295 location_t loc;
8296 gimple *stmt;
8297 tree decl, call, type, itype;
8299 gsi = gsi_last_bb (load_bb);
8300 stmt = gsi_stmt (gsi);
8301 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8302 loc = gimple_location (stmt);
8304 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8305 is smaller than word size, then expand_atomic_load assumes that the load
8306 is atomic. We could avoid the builtin entirely in this case. */
8308 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8309 decl = builtin_decl_explicit (tmpbase);
8310 if (decl == NULL_TREE)
8311 return false;
8313 type = TREE_TYPE (loaded_val);
8314 itype = TREE_TYPE (TREE_TYPE (decl));
8316 call = build_call_expr_loc (loc, decl, 2, addr,
8317 build_int_cst (NULL,
8318 gimple_omp_atomic_seq_cst_p (stmt)
8319 ? MEMMODEL_SEQ_CST
8320 : MEMMODEL_RELAXED));
8321 if (!useless_type_conversion_p (type, itype))
8322 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8323 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8325 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8326 gsi_remove (&gsi, true);
8328 store_bb = single_succ (load_bb);
8329 gsi = gsi_last_bb (store_bb);
8330 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8331 gsi_remove (&gsi, true);
8333 if (gimple_in_ssa_p (cfun))
8334 update_ssa (TODO_update_ssa_no_phi);
8336 return true;
8339 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8340 operation as a normal volatile store. */
8342 static bool
8343 expand_omp_atomic_store (basic_block load_bb, tree addr,
8344 tree loaded_val, tree stored_val, int index)
8346 enum built_in_function tmpbase;
8347 gimple_stmt_iterator gsi;
8348 basic_block store_bb = single_succ (load_bb);
8349 location_t loc;
8350 gimple *stmt;
8351 tree decl, call, type, itype;
8352 machine_mode imode;
8353 bool exchange;
8355 gsi = gsi_last_bb (load_bb);
8356 stmt = gsi_stmt (gsi);
8357 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8359 /* If the load value is needed, then this isn't a store but an exchange. */
8360 exchange = gimple_omp_atomic_need_value_p (stmt);
8362 gsi = gsi_last_bb (store_bb);
8363 stmt = gsi_stmt (gsi);
8364 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8365 loc = gimple_location (stmt);
8367 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8368 is smaller than word size, then expand_atomic_store assumes that the store
8369 is atomic. We could avoid the builtin entirely in this case. */
8371 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8372 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8373 decl = builtin_decl_explicit (tmpbase);
8374 if (decl == NULL_TREE)
8375 return false;
8377 type = TREE_TYPE (stored_val);
8379 /* Dig out the type of the function's second argument. */
8380 itype = TREE_TYPE (decl);
8381 itype = TYPE_ARG_TYPES (itype);
8382 itype = TREE_CHAIN (itype);
8383 itype = TREE_VALUE (itype);
8384 imode = TYPE_MODE (itype);
8386 if (exchange && !can_atomic_exchange_p (imode, true))
8387 return false;
8389 if (!useless_type_conversion_p (itype, type))
8390 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8391 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8392 build_int_cst (NULL,
8393 gimple_omp_atomic_seq_cst_p (stmt)
8394 ? MEMMODEL_SEQ_CST
8395 : MEMMODEL_RELAXED));
8396 if (exchange)
8398 if (!useless_type_conversion_p (type, itype))
8399 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8400 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8403 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8404 gsi_remove (&gsi, true);
8406 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8407 gsi = gsi_last_bb (load_bb);
8408 gsi_remove (&gsi, true);
8410 if (gimple_in_ssa_p (cfun))
8411 update_ssa (TODO_update_ssa_no_phi);
8413 return true;
8416 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8417 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8418 size of the data type, and thus usable to find the index of the builtin
8419 decl. Returns false if the expression is not of the proper form. */
8421 static bool
8422 expand_omp_atomic_fetch_op (basic_block load_bb,
8423 tree addr, tree loaded_val,
8424 tree stored_val, int index)
8426 enum built_in_function oldbase, newbase, tmpbase;
8427 tree decl, itype, call;
8428 tree lhs, rhs;
8429 basic_block store_bb = single_succ (load_bb);
8430 gimple_stmt_iterator gsi;
8431 gimple *stmt;
8432 location_t loc;
8433 enum tree_code code;
8434 bool need_old, need_new;
8435 machine_mode imode;
8436 bool seq_cst;
8438 /* We expect to find the following sequences:
8440 load_bb:
8441 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8443 store_bb:
8444 val = tmp OP something; (or: something OP tmp)
8445 GIMPLE_OMP_STORE (val)
8447 ???FIXME: Allow a more flexible sequence.
8448 Perhaps use data flow to pick the statements.
8452 gsi = gsi_after_labels (store_bb);
8453 stmt = gsi_stmt (gsi);
8454 loc = gimple_location (stmt);
8455 if (!is_gimple_assign (stmt))
8456 return false;
8457 gsi_next (&gsi);
8458 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8459 return false;
8460 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8461 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8462 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8463 gcc_checking_assert (!need_old || !need_new);
8465 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8466 return false;
8468 /* Check for one of the supported fetch-op operations. */
8469 code = gimple_assign_rhs_code (stmt);
8470 switch (code)
8472 case PLUS_EXPR:
8473 case POINTER_PLUS_EXPR:
8474 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8475 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8476 break;
8477 case MINUS_EXPR:
8478 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8479 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8480 break;
8481 case BIT_AND_EXPR:
8482 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8483 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8484 break;
8485 case BIT_IOR_EXPR:
8486 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8487 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8488 break;
8489 case BIT_XOR_EXPR:
8490 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8491 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8492 break;
8493 default:
8494 return false;
8497 /* Make sure the expression is of the proper form. */
8498 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8499 rhs = gimple_assign_rhs2 (stmt);
8500 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8501 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8502 rhs = gimple_assign_rhs1 (stmt);
8503 else
8504 return false;
8506 tmpbase = ((enum built_in_function)
8507 ((need_new ? newbase : oldbase) + index + 1));
8508 decl = builtin_decl_explicit (tmpbase);
8509 if (decl == NULL_TREE)
8510 return false;
8511 itype = TREE_TYPE (TREE_TYPE (decl));
8512 imode = TYPE_MODE (itype);
8514 /* We could test all of the various optabs involved, but the fact of the
8515 matter is that (with the exception of i486 vs i586 and xadd) all targets
8516 that support any atomic operaton optab also implements compare-and-swap.
8517 Let optabs.c take care of expanding any compare-and-swap loop. */
8518 if (!can_compare_and_swap_p (imode, true))
8519 return false;
8521 gsi = gsi_last_bb (load_bb);
8522 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8524 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8525 It only requires that the operation happen atomically. Thus we can
8526 use the RELAXED memory model. */
8527 call = build_call_expr_loc (loc, decl, 3, addr,
8528 fold_convert_loc (loc, itype, rhs),
8529 build_int_cst (NULL,
8530 seq_cst ? MEMMODEL_SEQ_CST
8531 : MEMMODEL_RELAXED));
8533 if (need_old || need_new)
8535 lhs = need_old ? loaded_val : stored_val;
8536 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8537 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8539 else
8540 call = fold_convert_loc (loc, void_type_node, call);
8541 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8542 gsi_remove (&gsi, true);
8544 gsi = gsi_last_bb (store_bb);
8545 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8546 gsi_remove (&gsi, true);
8547 gsi = gsi_last_bb (store_bb);
8548 gsi_remove (&gsi, true);
8550 if (gimple_in_ssa_p (cfun))
8551 update_ssa (TODO_update_ssa_no_phi);
8553 return true;
8556 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8558 oldval = *addr;
8559 repeat:
8560 newval = rhs; // with oldval replacing *addr in rhs
8561 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8562 if (oldval != newval)
8563 goto repeat;
8565 INDEX is log2 of the size of the data type, and thus usable to find the
8566 index of the builtin decl. */
8568 static bool
8569 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8570 tree addr, tree loaded_val, tree stored_val,
8571 int index)
8573 tree loadedi, storedi, initial, new_storedi, old_vali;
8574 tree type, itype, cmpxchg, iaddr;
8575 gimple_stmt_iterator si;
8576 basic_block loop_header = single_succ (load_bb);
8577 gimple *phi, *stmt;
8578 edge e;
8579 enum built_in_function fncode;
8581 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8582 order to use the RELAXED memory model effectively. */
8583 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8584 + index + 1);
8585 cmpxchg = builtin_decl_explicit (fncode);
8586 if (cmpxchg == NULL_TREE)
8587 return false;
8588 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8589 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8591 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8592 return false;
8594 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8595 si = gsi_last_bb (load_bb);
8596 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8598 /* For floating-point values, we'll need to view-convert them to integers
8599 so that we can perform the atomic compare and swap. Simplify the
8600 following code by always setting up the "i"ntegral variables. */
8601 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8603 tree iaddr_val;
8605 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8606 true));
8607 iaddr_val
8608 = force_gimple_operand_gsi (&si,
8609 fold_convert (TREE_TYPE (iaddr), addr),
8610 false, NULL_TREE, true, GSI_SAME_STMT);
8611 stmt = gimple_build_assign (iaddr, iaddr_val);
8612 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8613 loadedi = create_tmp_var (itype);
8614 if (gimple_in_ssa_p (cfun))
8615 loadedi = make_ssa_name (loadedi);
8617 else
8619 iaddr = addr;
8620 loadedi = loaded_val;
8623 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8624 tree loaddecl = builtin_decl_explicit (fncode);
8625 if (loaddecl)
8626 initial
8627 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8628 build_call_expr (loaddecl, 2, iaddr,
8629 build_int_cst (NULL_TREE,
8630 MEMMODEL_RELAXED)));
8631 else
8632 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8633 build_int_cst (TREE_TYPE (iaddr), 0));
8635 initial
8636 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8637 GSI_SAME_STMT);
8639 /* Move the value to the LOADEDI temporary. */
8640 if (gimple_in_ssa_p (cfun))
8642 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8643 phi = create_phi_node (loadedi, loop_header);
8644 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8645 initial);
8647 else
8648 gsi_insert_before (&si,
8649 gimple_build_assign (loadedi, initial),
8650 GSI_SAME_STMT);
8651 if (loadedi != loaded_val)
8653 gimple_stmt_iterator gsi2;
8654 tree x;
8656 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8657 gsi2 = gsi_start_bb (loop_header);
8658 if (gimple_in_ssa_p (cfun))
8660 gassign *stmt;
8661 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8662 true, GSI_SAME_STMT);
8663 stmt = gimple_build_assign (loaded_val, x);
8664 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8666 else
8668 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8669 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8670 true, GSI_SAME_STMT);
8673 gsi_remove (&si, true);
8675 si = gsi_last_bb (store_bb);
8676 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8678 if (iaddr == addr)
8679 storedi = stored_val;
8680 else
8681 storedi =
8682 force_gimple_operand_gsi (&si,
8683 build1 (VIEW_CONVERT_EXPR, itype,
8684 stored_val), true, NULL_TREE, true,
8685 GSI_SAME_STMT);
8687 /* Build the compare&swap statement. */
8688 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8689 new_storedi = force_gimple_operand_gsi (&si,
8690 fold_convert (TREE_TYPE (loadedi),
8691 new_storedi),
8692 true, NULL_TREE,
8693 true, GSI_SAME_STMT);
8695 if (gimple_in_ssa_p (cfun))
8696 old_vali = loadedi;
8697 else
8699 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8700 stmt = gimple_build_assign (old_vali, loadedi);
8701 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8703 stmt = gimple_build_assign (loadedi, new_storedi);
8704 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8707 /* Note that we always perform the comparison as an integer, even for
8708 floating point. This allows the atomic operation to properly
8709 succeed even with NaNs and -0.0. */
8710 stmt = gimple_build_cond_empty
8711 (build2 (NE_EXPR, boolean_type_node,
8712 new_storedi, old_vali));
8713 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8715 /* Update cfg. */
8716 e = single_succ_edge (store_bb);
8717 e->flags &= ~EDGE_FALLTHRU;
8718 e->flags |= EDGE_FALSE_VALUE;
8720 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8722 /* Copy the new value to loadedi (we already did that before the condition
8723 if we are not in SSA). */
8724 if (gimple_in_ssa_p (cfun))
8726 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8727 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8730 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8731 gsi_remove (&si, true);
8733 struct loop *loop = alloc_loop ();
8734 loop->header = loop_header;
8735 loop->latch = store_bb;
8736 add_loop (loop, loop_header->loop_father);
8738 if (gimple_in_ssa_p (cfun))
8739 update_ssa (TODO_update_ssa_no_phi);
8741 return true;
8744 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8746 GOMP_atomic_start ();
8747 *addr = rhs;
8748 GOMP_atomic_end ();
8750 The result is not globally atomic, but works so long as all parallel
8751 references are within #pragma omp atomic directives. According to
8752 responses received from omp@openmp.org, appears to be within spec.
8753 Which makes sense, since that's how several other compilers handle
8754 this situation as well.
8755 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8756 expanding. STORED_VAL is the operand of the matching
8757 GIMPLE_OMP_ATOMIC_STORE.
8759 We replace
8760 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8761 loaded_val = *addr;
8763 and replace
8764 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8765 *addr = stored_val;
8768 static bool
8769 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8770 tree addr, tree loaded_val, tree stored_val)
8772 gimple_stmt_iterator si;
8773 gassign *stmt;
8774 tree t;
8776 si = gsi_last_bb (load_bb);
8777 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8779 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8780 t = build_call_expr (t, 0);
8781 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8783 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8784 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8785 gsi_remove (&si, true);
8787 si = gsi_last_bb (store_bb);
8788 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8790 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8791 stored_val);
8792 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8794 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8795 t = build_call_expr (t, 0);
8796 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8797 gsi_remove (&si, true);
8799 if (gimple_in_ssa_p (cfun))
8800 update_ssa (TODO_update_ssa_no_phi);
8801 return true;
8804 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8805 using expand_omp_atomic_fetch_op. If it failed, we try to
8806 call expand_omp_atomic_pipeline, and if it fails too, the
8807 ultimate fallback is wrapping the operation in a mutex
8808 (expand_omp_atomic_mutex). REGION is the atomic region built
8809 by build_omp_regions_1(). */
8811 static void
8812 expand_omp_atomic (struct omp_region *region)
8814 basic_block load_bb = region->entry, store_bb = region->exit;
8815 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8816 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8817 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8818 tree addr = gimple_omp_atomic_load_rhs (load);
8819 tree stored_val = gimple_omp_atomic_store_val (store);
8820 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8821 HOST_WIDE_INT index;
8823 /* Make sure the type is one of the supported sizes. */
8824 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8825 index = exact_log2 (index);
8826 if (index >= 0 && index <= 4)
8828 unsigned int align = TYPE_ALIGN_UNIT (type);
8830 /* __sync builtins require strict data alignment. */
8831 if (exact_log2 (align) >= index)
8833 /* Atomic load. */
8834 if (loaded_val == stored_val
8835 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8836 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8837 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8838 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8839 return;
8841 /* Atomic store. */
8842 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8843 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8844 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8845 && store_bb == single_succ (load_bb)
8846 && first_stmt (store_bb) == store
8847 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8848 stored_val, index))
8849 return;
8851 /* When possible, use specialized atomic update functions. */
8852 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8853 && store_bb == single_succ (load_bb)
8854 && expand_omp_atomic_fetch_op (load_bb, addr,
8855 loaded_val, stored_val, index))
8856 return;
8858 /* If we don't have specialized __sync builtins, try and implement
8859 as a compare and swap loop. */
8860 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8861 loaded_val, stored_val, index))
8862 return;
8866 /* The ultimate fallback is wrapping the operation in a mutex. */
8867 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8871 /* Encode an oacc launc argument. This matches the GOMP_LAUNCH_PACK
8872 macro on gomp-constants.h. We do not check for overflow. */
8874 static tree
8875 oacc_launch_pack (unsigned code, tree device, unsigned op)
8877 tree res;
8879 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
8880 if (device)
8882 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
8883 device, build_int_cst (unsigned_type_node,
8884 GOMP_LAUNCH_DEVICE_SHIFT));
8885 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
8887 return res;
8890 /* Look for compute grid dimension clauses and convert to an attribute
8891 attached to FN. This permits the target-side code to (a) massage
8892 the dimensions, (b) emit that data and (c) optimize. Non-constant
8893 dimensions are pushed onto ARGS.
8895 The attribute value is a TREE_LIST. A set of dimensions is
8896 represented as a list of INTEGER_CST. Those that are runtime
8897 expres are represented as an INTEGER_CST of zero.
8899 TOOO. Normally the attribute will just contain a single such list. If
8900 however it contains a list of lists, this will represent the use of
8901 device_type. Each member of the outer list is an assoc list of
8902 dimensions, keyed by the device type. The first entry will be the
8903 default. Well, that's the plan. */
8905 #define OACC_FN_ATTRIB "oacc function"
8907 /* Replace any existing oacc fn attribute with updated dimensions. */
8909 void
8910 replace_oacc_fn_attrib (tree fn, tree dims)
8912 tree ident = get_identifier (OACC_FN_ATTRIB);
8913 tree attribs = DECL_ATTRIBUTES (fn);
8915 /* If we happen to be present as the first attrib, drop it. */
8916 if (attribs && TREE_PURPOSE (attribs) == ident)
8917 attribs = TREE_CHAIN (attribs);
8918 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
8921 /* Scan CLAUSES for launch dimensions and attach them to the oacc
8922 function attribute. Push any that are non-constant onto the ARGS
8923 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
8925 static void
8926 set_oacc_fn_attrib (tree fn, tree clauses, vec<tree> *args)
8928 /* Must match GOMP_DIM ordering. */
8929 static const omp_clause_code ids[]
8930 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
8931 OMP_CLAUSE_VECTOR_LENGTH };
8932 unsigned ix;
8933 tree dims[GOMP_DIM_MAX];
8934 tree attr = NULL_TREE;
8935 unsigned non_const = 0;
8937 for (ix = GOMP_DIM_MAX; ix--;)
8939 tree clause = find_omp_clause (clauses, ids[ix]);
8940 tree dim = NULL_TREE;
8942 if (clause)
8943 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
8944 dims[ix] = dim;
8945 if (dim && TREE_CODE (dim) != INTEGER_CST)
8947 dim = integer_zero_node;
8948 non_const |= GOMP_DIM_MASK (ix);
8950 attr = tree_cons (NULL_TREE, dim, attr);
8953 replace_oacc_fn_attrib (fn, attr);
8955 if (non_const)
8957 /* Push a dynamic argument set. */
8958 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
8959 NULL_TREE, non_const));
8960 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
8961 if (non_const & GOMP_DIM_MASK (ix))
8962 args->safe_push (dims[ix]);
8966 /* Retrieve the oacc function attrib and return it. Non-oacc
8967 functions will return NULL. */
8969 tree
8970 get_oacc_fn_attrib (tree fn)
8972 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
8975 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8977 static void
8978 expand_omp_target (struct omp_region *region)
8980 basic_block entry_bb, exit_bb, new_bb;
8981 struct function *child_cfun;
8982 tree child_fn, block, t;
8983 gimple_stmt_iterator gsi;
8984 gomp_target *entry_stmt;
8985 gimple *stmt;
8986 edge e;
8987 bool offloaded, data_region;
8989 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8990 new_bb = region->entry;
8992 offloaded = is_gimple_omp_offloaded (entry_stmt);
8993 switch (gimple_omp_target_kind (entry_stmt))
8995 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8996 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8997 case GF_OMP_TARGET_KIND_REGION:
8998 case GF_OMP_TARGET_KIND_UPDATE:
8999 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9000 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9001 data_region = false;
9002 break;
9003 case GF_OMP_TARGET_KIND_DATA:
9004 case GF_OMP_TARGET_KIND_OACC_DATA:
9005 data_region = true;
9006 break;
9007 default:
9008 gcc_unreachable ();
9011 child_fn = NULL_TREE;
9012 child_cfun = NULL;
9013 if (offloaded)
9015 child_fn = gimple_omp_target_child_fn (entry_stmt);
9016 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
9019 /* Supported by expand_omp_taskreg, but not here. */
9020 if (child_cfun != NULL)
9021 gcc_checking_assert (!child_cfun->cfg);
9022 gcc_checking_assert (!gimple_in_ssa_p (cfun));
9024 entry_bb = region->entry;
9025 exit_bb = region->exit;
9027 if (offloaded)
9029 unsigned srcidx, dstidx, num;
9031 /* If the offloading region needs data sent from the parent
9032 function, then the very first statement (except possible
9033 tree profile counter updates) of the offloading body
9034 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
9035 &.OMP_DATA_O is passed as an argument to the child function,
9036 we need to replace it with the argument as seen by the child
9037 function.
9039 In most cases, this will end up being the identity assignment
9040 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
9041 a function call that has been inlined, the original PARM_DECL
9042 .OMP_DATA_I may have been converted into a different local
9043 variable. In which case, we need to keep the assignment. */
9044 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
9045 if (data_arg)
9047 basic_block entry_succ_bb = single_succ (entry_bb);
9048 gimple_stmt_iterator gsi;
9049 tree arg;
9050 gimple *tgtcopy_stmt = NULL;
9051 tree sender = TREE_VEC_ELT (data_arg, 0);
9053 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
9055 gcc_assert (!gsi_end_p (gsi));
9056 stmt = gsi_stmt (gsi);
9057 if (gimple_code (stmt) != GIMPLE_ASSIGN)
9058 continue;
9060 if (gimple_num_ops (stmt) == 2)
9062 tree arg = gimple_assign_rhs1 (stmt);
9064 /* We're ignoring the subcode because we're
9065 effectively doing a STRIP_NOPS. */
9067 if (TREE_CODE (arg) == ADDR_EXPR
9068 && TREE_OPERAND (arg, 0) == sender)
9070 tgtcopy_stmt = stmt;
9071 break;
9076 gcc_assert (tgtcopy_stmt != NULL);
9077 arg = DECL_ARGUMENTS (child_fn);
9079 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
9080 gsi_remove (&gsi, true);
9083 /* Declare local variables needed in CHILD_CFUN. */
9084 block = DECL_INITIAL (child_fn);
9085 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
9086 /* The gimplifier could record temporaries in the offloading block
9087 rather than in containing function's local_decls chain,
9088 which would mean cgraph missed finalizing them. Do it now. */
9089 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
9090 if (TREE_CODE (t) == VAR_DECL
9091 && TREE_STATIC (t)
9092 && !DECL_EXTERNAL (t))
9093 varpool_node::finalize_decl (t);
9094 DECL_SAVED_TREE (child_fn) = NULL;
9095 /* We'll create a CFG for child_fn, so no gimple body is needed. */
9096 gimple_set_body (child_fn, NULL);
9097 TREE_USED (block) = 1;
9099 /* Reset DECL_CONTEXT on function arguments. */
9100 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9101 DECL_CONTEXT (t) = child_fn;
9103 /* Split ENTRY_BB at GIMPLE_*,
9104 so that it can be moved to the child function. */
9105 gsi = gsi_last_bb (entry_bb);
9106 stmt = gsi_stmt (gsi);
9107 gcc_assert (stmt
9108 && gimple_code (stmt) == gimple_code (entry_stmt));
9109 e = split_block (entry_bb, stmt);
9110 gsi_remove (&gsi, true);
9111 entry_bb = e->dest;
9112 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
9114 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
9115 if (exit_bb)
9117 gsi = gsi_last_bb (exit_bb);
9118 gcc_assert (!gsi_end_p (gsi)
9119 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
9120 stmt = gimple_build_return (NULL);
9121 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
9122 gsi_remove (&gsi, true);
9125 /* Move the offloading region into CHILD_CFUN. */
9127 block = gimple_block (entry_stmt);
9129 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
9130 if (exit_bb)
9131 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
9132 /* When the OMP expansion process cannot guarantee an up-to-date
9133 loop tree arrange for the child function to fixup loops. */
9134 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
9135 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
9137 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
9138 num = vec_safe_length (child_cfun->local_decls);
9139 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
9141 t = (*child_cfun->local_decls)[srcidx];
9142 if (DECL_CONTEXT (t) == cfun->decl)
9143 continue;
9144 if (srcidx != dstidx)
9145 (*child_cfun->local_decls)[dstidx] = t;
9146 dstidx++;
9148 if (dstidx != num)
9149 vec_safe_truncate (child_cfun->local_decls, dstidx);
9151 /* Inform the callgraph about the new function. */
9152 child_cfun->curr_properties = cfun->curr_properties;
9153 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
9154 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
9155 cgraph_node *node = cgraph_node::get_create (child_fn);
9156 node->parallelized_function = 1;
9157 cgraph_node::add_new_function (child_fn, true);
9159 #ifdef ENABLE_OFFLOADING
9160 /* Add the new function to the offload table. */
9161 vec_safe_push (offload_funcs, child_fn);
9162 #endif
9164 /* Fix the callgraph edges for child_cfun. Those for cfun will be
9165 fixed in a following pass. */
9166 push_cfun (child_cfun);
9167 cgraph_edge::rebuild_edges ();
9169 #ifdef ENABLE_OFFLOADING
9170 /* Prevent IPA from removing child_fn as unreachable, since there are no
9171 refs from the parent function to child_fn in offload LTO mode. */
9172 cgraph_node::get (child_fn)->mark_force_output ();
9173 #endif
9175 /* Some EH regions might become dead, see PR34608. If
9176 pass_cleanup_cfg isn't the first pass to happen with the
9177 new child, these dead EH edges might cause problems.
9178 Clean them up now. */
9179 if (flag_exceptions)
9181 basic_block bb;
9182 bool changed = false;
9184 FOR_EACH_BB_FN (bb, cfun)
9185 changed |= gimple_purge_dead_eh_edges (bb);
9186 if (changed)
9187 cleanup_tree_cfg ();
9189 #ifdef ENABLE_CHECKING
9190 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
9191 verify_loop_structure ();
9192 #endif
9193 pop_cfun ();
9196 /* Emit a library call to launch the offloading region, or do data
9197 transfers. */
9198 tree t1, t2, t3, t4, device, cond, c, clauses;
9199 enum built_in_function start_ix;
9200 location_t clause_loc;
9202 switch (gimple_omp_target_kind (entry_stmt))
9204 case GF_OMP_TARGET_KIND_REGION:
9205 start_ix = BUILT_IN_GOMP_TARGET;
9206 break;
9207 case GF_OMP_TARGET_KIND_DATA:
9208 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9209 break;
9210 case GF_OMP_TARGET_KIND_UPDATE:
9211 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9212 break;
9213 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9214 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9215 start_ix = BUILT_IN_GOACC_PARALLEL;
9216 break;
9217 case GF_OMP_TARGET_KIND_OACC_DATA:
9218 start_ix = BUILT_IN_GOACC_DATA_START;
9219 break;
9220 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9221 start_ix = BUILT_IN_GOACC_UPDATE;
9222 break;
9223 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9224 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9225 break;
9226 default:
9227 gcc_unreachable ();
9230 clauses = gimple_omp_target_clauses (entry_stmt);
9232 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9233 library choose) and there is no conditional. */
9234 cond = NULL_TREE;
9235 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
9237 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9238 if (c)
9239 cond = OMP_CLAUSE_IF_EXPR (c);
9241 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9242 if (c)
9244 /* Even if we pass it to all library function calls, it is currently only
9245 defined/used for the OpenMP target ones. */
9246 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9247 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9248 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9250 device = OMP_CLAUSE_DEVICE_ID (c);
9251 clause_loc = OMP_CLAUSE_LOCATION (c);
9253 else
9254 clause_loc = gimple_location (entry_stmt);
9256 /* Ensure 'device' is of the correct type. */
9257 device = fold_convert_loc (clause_loc, integer_type_node, device);
9259 /* If we found the clause 'if (cond)', build
9260 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9261 if (cond)
9263 cond = gimple_boolify (cond);
9265 basic_block cond_bb, then_bb, else_bb;
9266 edge e;
9267 tree tmp_var;
9269 tmp_var = create_tmp_var (TREE_TYPE (device));
9270 if (offloaded)
9271 e = split_block_after_labels (new_bb);
9272 else
9274 gsi = gsi_last_bb (new_bb);
9275 gsi_prev (&gsi);
9276 e = split_block (new_bb, gsi_stmt (gsi));
9278 cond_bb = e->src;
9279 new_bb = e->dest;
9280 remove_edge (e);
9282 then_bb = create_empty_bb (cond_bb);
9283 else_bb = create_empty_bb (then_bb);
9284 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9285 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9287 stmt = gimple_build_cond_empty (cond);
9288 gsi = gsi_last_bb (cond_bb);
9289 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9291 gsi = gsi_start_bb (then_bb);
9292 stmt = gimple_build_assign (tmp_var, device);
9293 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9295 gsi = gsi_start_bb (else_bb);
9296 stmt = gimple_build_assign (tmp_var,
9297 build_int_cst (integer_type_node,
9298 GOMP_DEVICE_HOST_FALLBACK));
9299 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9301 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9302 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9303 add_bb_to_loop (then_bb, cond_bb->loop_father);
9304 add_bb_to_loop (else_bb, cond_bb->loop_father);
9305 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9306 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9308 device = tmp_var;
9311 gsi = gsi_last_bb (new_bb);
9312 t = gimple_omp_target_data_arg (entry_stmt);
9313 if (t == NULL)
9315 t1 = size_zero_node;
9316 t2 = build_zero_cst (ptr_type_node);
9317 t3 = t2;
9318 t4 = t2;
9320 else
9322 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9323 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9324 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9325 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9326 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9329 gimple *g;
9330 bool tagging = false;
9331 /* The maximum number used by any start_ix, without varargs. */
9332 auto_vec<tree, 11> args;
9333 args.quick_push (device);
9334 if (offloaded)
9335 args.quick_push (build_fold_addr_expr (child_fn));
9336 switch (start_ix)
9338 case BUILT_IN_GOMP_TARGET:
9339 case BUILT_IN_GOMP_TARGET_DATA:
9340 case BUILT_IN_GOMP_TARGET_UPDATE:
9341 /* This const void * is part of the current ABI, but we're not actually
9342 using it. */
9343 args.quick_push (build_zero_cst (ptr_type_node));
9344 break;
9345 case BUILT_IN_GOACC_DATA_START:
9346 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9347 case BUILT_IN_GOACC_PARALLEL:
9348 case BUILT_IN_GOACC_UPDATE:
9349 break;
9350 default:
9351 gcc_unreachable ();
9353 args.quick_push (t1);
9354 args.quick_push (t2);
9355 args.quick_push (t3);
9356 args.quick_push (t4);
9357 switch (start_ix)
9359 case BUILT_IN_GOACC_DATA_START:
9360 case BUILT_IN_GOMP_TARGET:
9361 case BUILT_IN_GOMP_TARGET_DATA:
9362 case BUILT_IN_GOMP_TARGET_UPDATE:
9363 break;
9364 case BUILT_IN_GOACC_PARALLEL:
9366 set_oacc_fn_attrib (child_fn, clauses, &args);
9367 tagging = true;
9369 /* FALLTHRU */
9370 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9371 case BUILT_IN_GOACC_UPDATE:
9373 tree t_async = NULL_TREE;
9375 /* If present, use the value specified by the respective
9376 clause, making sure that is of the correct type. */
9377 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9378 if (c)
9379 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9380 integer_type_node,
9381 OMP_CLAUSE_ASYNC_EXPR (c));
9382 else if (!tagging)
9383 /* Default values for t_async. */
9384 t_async = fold_convert_loc (gimple_location (entry_stmt),
9385 integer_type_node,
9386 build_int_cst (integer_type_node,
9387 GOMP_ASYNC_SYNC));
9388 if (tagging && t_async)
9390 unsigned HOST_WIDE_INT i_async;
9392 if (TREE_CODE (t_async) == INTEGER_CST)
9394 /* See if we can pack the async arg in to the tag's
9395 operand. */
9396 i_async = TREE_INT_CST_LOW (t_async);
9398 if (i_async < GOMP_LAUNCH_OP_MAX)
9399 t_async = NULL_TREE;
9401 if (t_async)
9402 i_async = GOMP_LAUNCH_OP_MAX;
9403 args.safe_push (oacc_launch_pack
9404 (GOMP_LAUNCH_ASYNC, NULL_TREE, i_async));
9406 if (t_async)
9407 args.safe_push (t_async);
9409 /* Save the argument index, and ... */
9410 unsigned t_wait_idx = args.length ();
9411 unsigned num_waits = 0;
9412 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9413 if (!tagging || c)
9414 /* ... push a placeholder. */
9415 args.safe_push (integer_zero_node);
9417 for (; c; c = OMP_CLAUSE_CHAIN (c))
9418 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9420 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9421 integer_type_node,
9422 OMP_CLAUSE_WAIT_EXPR (c)));
9423 num_waits++;
9426 if (!tagging || num_waits)
9428 tree len;
9430 /* Now that we know the number, update the placeholder. */
9431 if (tagging)
9432 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
9433 else
9434 len = build_int_cst (integer_type_node, num_waits);
9435 len = fold_convert_loc (gimple_location (entry_stmt),
9436 unsigned_type_node, len);
9437 args[t_wait_idx] = len;
9440 break;
9441 default:
9442 gcc_unreachable ();
9444 if (tagging)
9445 /* Push terminal marker - zero. */
9446 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
9448 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
9449 gimple_set_location (g, gimple_location (entry_stmt));
9450 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9451 if (!offloaded)
9453 g = gsi_stmt (gsi);
9454 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9455 gsi_remove (&gsi, true);
9457 if (data_region
9458 && region->exit)
9460 gsi = gsi_last_bb (region->exit);
9461 g = gsi_stmt (gsi);
9462 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9463 gsi_remove (&gsi, true);
9468 /* Expand the parallel region tree rooted at REGION. Expansion
9469 proceeds in depth-first order. Innermost regions are expanded
9470 first. This way, parallel regions that require a new function to
9471 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9472 internal dependencies in their body. */
9474 static void
9475 expand_omp (struct omp_region *region)
9477 while (region)
9479 location_t saved_location;
9480 gimple *inner_stmt = NULL;
9482 /* First, determine whether this is a combined parallel+workshare
9483 region. */
9484 if (region->type == GIMPLE_OMP_PARALLEL)
9485 determine_parallel_type (region);
9487 if (region->type == GIMPLE_OMP_FOR
9488 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9489 inner_stmt = last_stmt (region->inner->entry);
9491 if (region->inner)
9492 expand_omp (region->inner);
9494 saved_location = input_location;
9495 if (gimple_has_location (last_stmt (region->entry)))
9496 input_location = gimple_location (last_stmt (region->entry));
9498 switch (region->type)
9500 case GIMPLE_OMP_PARALLEL:
9501 case GIMPLE_OMP_TASK:
9502 expand_omp_taskreg (region);
9503 break;
9505 case GIMPLE_OMP_FOR:
9506 expand_omp_for (region, inner_stmt);
9507 break;
9509 case GIMPLE_OMP_SECTIONS:
9510 expand_omp_sections (region);
9511 break;
9513 case GIMPLE_OMP_SECTION:
9514 /* Individual omp sections are handled together with their
9515 parent GIMPLE_OMP_SECTIONS region. */
9516 break;
9518 case GIMPLE_OMP_SINGLE:
9519 expand_omp_single (region);
9520 break;
9522 case GIMPLE_OMP_MASTER:
9523 case GIMPLE_OMP_TASKGROUP:
9524 case GIMPLE_OMP_ORDERED:
9525 case GIMPLE_OMP_CRITICAL:
9526 case GIMPLE_OMP_TEAMS:
9527 expand_omp_synch (region);
9528 break;
9530 case GIMPLE_OMP_ATOMIC_LOAD:
9531 expand_omp_atomic (region);
9532 break;
9534 case GIMPLE_OMP_TARGET:
9535 expand_omp_target (region);
9536 break;
9538 default:
9539 gcc_unreachable ();
9542 input_location = saved_location;
9543 region = region->next;
9548 /* Helper for build_omp_regions. Scan the dominator tree starting at
9549 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9550 true, the function ends once a single tree is built (otherwise, whole
9551 forest of OMP constructs may be built). */
9553 static void
9554 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9555 bool single_tree)
9557 gimple_stmt_iterator gsi;
9558 gimple *stmt;
9559 basic_block son;
9561 gsi = gsi_last_bb (bb);
9562 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9564 struct omp_region *region;
9565 enum gimple_code code;
9567 stmt = gsi_stmt (gsi);
9568 code = gimple_code (stmt);
9569 if (code == GIMPLE_OMP_RETURN)
9571 /* STMT is the return point out of region PARENT. Mark it
9572 as the exit point and make PARENT the immediately
9573 enclosing region. */
9574 gcc_assert (parent);
9575 region = parent;
9576 region->exit = bb;
9577 parent = parent->outer;
9579 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9581 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9582 GIMPLE_OMP_RETURN, but matches with
9583 GIMPLE_OMP_ATOMIC_LOAD. */
9584 gcc_assert (parent);
9585 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9586 region = parent;
9587 region->exit = bb;
9588 parent = parent->outer;
9590 else if (code == GIMPLE_OMP_CONTINUE)
9592 gcc_assert (parent);
9593 parent->cont = bb;
9595 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9597 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9598 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9600 else
9602 region = new_omp_region (bb, code, parent);
9603 /* Otherwise... */
9604 if (code == GIMPLE_OMP_TARGET)
9606 switch (gimple_omp_target_kind (stmt))
9608 case GF_OMP_TARGET_KIND_REGION:
9609 case GF_OMP_TARGET_KIND_DATA:
9610 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9611 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9612 case GF_OMP_TARGET_KIND_OACC_DATA:
9613 break;
9614 case GF_OMP_TARGET_KIND_UPDATE:
9615 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9616 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9617 /* ..., other than for those stand-alone directives... */
9618 region = NULL;
9619 break;
9620 default:
9621 gcc_unreachable ();
9624 /* ..., this directive becomes the parent for a new region. */
9625 if (region)
9626 parent = region;
9630 if (single_tree && !parent)
9631 return;
9633 for (son = first_dom_son (CDI_DOMINATORS, bb);
9634 son;
9635 son = next_dom_son (CDI_DOMINATORS, son))
9636 build_omp_regions_1 (son, parent, single_tree);
9639 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9640 root_omp_region. */
9642 static void
9643 build_omp_regions_root (basic_block root)
9645 gcc_assert (root_omp_region == NULL);
9646 build_omp_regions_1 (root, NULL, true);
9647 gcc_assert (root_omp_region != NULL);
9650 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9652 void
9653 omp_expand_local (basic_block head)
9655 build_omp_regions_root (head);
9656 if (dump_file && (dump_flags & TDF_DETAILS))
9658 fprintf (dump_file, "\nOMP region tree\n\n");
9659 dump_omp_region (dump_file, root_omp_region, 0);
9660 fprintf (dump_file, "\n");
9663 remove_exit_barriers (root_omp_region);
9664 expand_omp (root_omp_region);
9666 free_omp_regions ();
9669 /* Scan the CFG and build a tree of OMP regions. Return the root of
9670 the OMP region tree. */
9672 static void
9673 build_omp_regions (void)
9675 gcc_assert (root_omp_region == NULL);
9676 calculate_dominance_info (CDI_DOMINATORS);
9677 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9680 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9682 static unsigned int
9683 execute_expand_omp (void)
9685 build_omp_regions ();
9687 if (!root_omp_region)
9688 return 0;
9690 if (dump_file)
9692 fprintf (dump_file, "\nOMP region tree\n\n");
9693 dump_omp_region (dump_file, root_omp_region, 0);
9694 fprintf (dump_file, "\n");
9697 remove_exit_barriers (root_omp_region);
9699 expand_omp (root_omp_region);
9701 #ifdef ENABLE_CHECKING
9702 if (!loops_state_satisfies_p (LOOPS_NEED_FIXUP))
9703 verify_loop_structure ();
9704 #endif
9705 cleanup_tree_cfg ();
9707 free_omp_regions ();
9709 return 0;
9712 /* OMP expansion -- the default pass, run before creation of SSA form. */
9714 namespace {
9716 const pass_data pass_data_expand_omp =
9718 GIMPLE_PASS, /* type */
9719 "ompexp", /* name */
9720 OPTGROUP_NONE, /* optinfo_flags */
9721 TV_NONE, /* tv_id */
9722 PROP_gimple_any, /* properties_required */
9723 PROP_gimple_eomp, /* properties_provided */
9724 0, /* properties_destroyed */
9725 0, /* todo_flags_start */
9726 0, /* todo_flags_finish */
9729 class pass_expand_omp : public gimple_opt_pass
9731 public:
9732 pass_expand_omp (gcc::context *ctxt)
9733 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9736 /* opt_pass methods: */
9737 virtual unsigned int execute (function *)
9739 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9740 || flag_openmp_simd != 0)
9741 && !seen_error ());
9743 /* This pass always runs, to provide PROP_gimple_eomp.
9744 But often, there is nothing to do. */
9745 if (!gate)
9746 return 0;
9748 return execute_expand_omp ();
9751 }; // class pass_expand_omp
9753 } // anon namespace
9755 gimple_opt_pass *
9756 make_pass_expand_omp (gcc::context *ctxt)
9758 return new pass_expand_omp (ctxt);
9761 namespace {
9763 const pass_data pass_data_expand_omp_ssa =
9765 GIMPLE_PASS, /* type */
9766 "ompexpssa", /* name */
9767 OPTGROUP_NONE, /* optinfo_flags */
9768 TV_NONE, /* tv_id */
9769 PROP_cfg | PROP_ssa, /* properties_required */
9770 PROP_gimple_eomp, /* properties_provided */
9771 0, /* properties_destroyed */
9772 0, /* todo_flags_start */
9773 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9776 class pass_expand_omp_ssa : public gimple_opt_pass
9778 public:
9779 pass_expand_omp_ssa (gcc::context *ctxt)
9780 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9783 /* opt_pass methods: */
9784 virtual bool gate (function *fun)
9786 return !(fun->curr_properties & PROP_gimple_eomp);
9788 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9790 }; // class pass_expand_omp_ssa
9792 } // anon namespace
9794 gimple_opt_pass *
9795 make_pass_expand_omp_ssa (gcc::context *ctxt)
9797 return new pass_expand_omp_ssa (ctxt);
9800 /* Routines to lower OMP directives into OMP-GIMPLE. */
9802 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9803 convert it to gimple. */
9804 static void
9805 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9807 gimple *stmt;
9809 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9811 stmt = gimple_build_assign (dest, op, dest, src);
9812 gimple_seq_add_stmt (seq, stmt);
9813 return;
9816 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9817 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9818 gimplify_assign (t, rdest, seq);
9819 rdest = t;
9821 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9822 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9823 gimplify_assign (t, idest, seq);
9824 idest = t;
9826 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9827 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9828 gimplify_assign (t, rsrc, seq);
9829 rsrc = t;
9831 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9832 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9833 gimplify_assign (t, isrc, seq);
9834 isrc = t;
9836 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9837 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9838 tree result;
9840 if (op == PLUS_EXPR)
9842 stmt = gimple_build_assign (r, op, rdest, rsrc);
9843 gimple_seq_add_stmt (seq, stmt);
9845 stmt = gimple_build_assign (i, op, idest, isrc);
9846 gimple_seq_add_stmt (seq, stmt);
9848 else if (op == MULT_EXPR)
9850 /* Let x = a + ib = dest, y = c + id = src.
9851 x * y = (ac - bd) + i(ad + bc) */
9852 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9853 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9854 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9855 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9857 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9858 gimple_seq_add_stmt (seq, stmt);
9860 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9861 gimple_seq_add_stmt (seq, stmt);
9863 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9864 gimple_seq_add_stmt (seq, stmt);
9866 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9867 gimple_seq_add_stmt (seq, stmt);
9869 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9870 gimple_seq_add_stmt (seq, stmt);
9872 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9873 gimple_seq_add_stmt (seq, stmt);
9875 else
9876 gcc_unreachable ();
9878 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9879 gimplify_assign (dest, result, seq);
9882 /* Helper function to initialize local data for the reduction arrays.
9883 The reduction arrays need to be placed inside the calling function
9884 for accelerators, or else the host won't be able to preform the final
9885 reduction. */
9887 static void
9888 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9889 gimple_seq *stmt_seqp, omp_context *ctx)
9891 tree c, t, oc;
9892 gimple *stmt;
9893 omp_context *octx;
9895 /* Find the innermost OpenACC parallel context. */
9896 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9897 && (gimple_omp_target_kind (ctx->stmt)
9898 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9899 octx = ctx;
9900 else
9901 octx = ctx->outer;
9902 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9903 && (gimple_omp_target_kind (octx->stmt)
9904 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9906 /* Extract the clauses. */
9907 oc = gimple_omp_target_clauses (octx->stmt);
9909 /* Find the last outer clause. */
9910 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9913 /* Allocate arrays for each reduction variable. */
9914 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9916 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9917 continue;
9919 tree var = OMP_CLAUSE_DECL (c);
9920 tree type = get_base_type (var);
9921 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9922 ctx);
9923 tree size, call;
9925 /* Calculate size of the reduction array. */
9926 t = create_tmp_var (TREE_TYPE (nthreads));
9927 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9928 fold_convert (TREE_TYPE (nthreads),
9929 TYPE_SIZE_UNIT (type)));
9930 gimple_seq_add_stmt (stmt_seqp, stmt);
9932 size = create_tmp_var (sizetype);
9933 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9935 /* Now allocate memory for it. */
9936 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9937 stmt = gimple_build_call (call, 1, size);
9938 gimple_call_set_lhs (stmt, array);
9939 gimple_seq_add_stmt (stmt_seqp, stmt);
9941 /* Map this array into the accelerator. */
9943 /* Add the reduction array to the list of clauses. */
9944 tree x = array;
9945 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9946 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9947 OMP_CLAUSE_DECL (t) = x;
9948 OMP_CLAUSE_CHAIN (t) = NULL;
9949 if (oc)
9950 OMP_CLAUSE_CHAIN (oc) = t;
9951 else
9952 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9953 OMP_CLAUSE_SIZE (t) = size;
9954 oc = t;
9958 /* Helper function to process the array of partial reductions. Nthreads
9959 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9960 cannot be used here, because nthreads on the host may be different than
9961 on the accelerator. */
9963 static void
9964 oacc_finalize_reduction_data (tree clauses, tree nthreads,
9965 gimple_seq *stmt_seqp, omp_context *ctx)
9967 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9968 gimple *stmt;
9970 /* Create for loop.
9972 let var = the original reduction variable
9973 let array = reduction variable array
9975 for (i = 0; i < nthreads; i++)
9976 var op= array[i]
9979 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9980 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9981 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9983 /* Create and initialize an index variable. */
9984 tree ix = create_tmp_var (sizetype);
9985 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9986 stmt_seqp);
9988 /* Insert the loop header label here. */
9989 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9991 /* Exit loop if ix >= nthreads. */
9992 x = create_tmp_var (sizetype);
9993 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9994 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9995 gimple_seq_add_stmt (stmt_seqp, stmt);
9997 /* Insert the loop body label here. */
9998 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
10000 /* Collapse each reduction array, one element at a time. */
10001 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10003 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
10004 continue;
10006 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
10008 /* reduction(-:var) sums up the partial results, so it acts
10009 identically to reduction(+:var). */
10010 if (reduction_code == MINUS_EXPR)
10011 reduction_code = PLUS_EXPR;
10013 /* Set up reduction variable var. */
10014 var = OMP_CLAUSE_DECL (c);
10015 type = get_base_type (var);
10016 array = lookup_oacc_reduction (oacc_get_reduction_array_id
10017 (OMP_CLAUSE_DECL (c)), ctx);
10019 /* Calculate the array offset. */
10020 tree offset = create_tmp_var (sizetype);
10021 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
10022 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
10023 gimple_seq_add_stmt (stmt_seqp, stmt);
10025 tree ptr = create_tmp_var (TREE_TYPE (array));
10026 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
10027 gimple_seq_add_stmt (stmt_seqp, stmt);
10029 /* Extract array[ix] into mem. */
10030 tree mem = create_tmp_var (type);
10031 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
10033 /* Find the original reduction variable. */
10034 if (is_reference (var))
10035 var = build_simple_mem_ref (var);
10037 tree t = create_tmp_var (type);
10039 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
10040 gimplify_and_add (unshare_expr(x), stmt_seqp);
10042 /* var = var op mem */
10043 switch (OMP_CLAUSE_REDUCTION_CODE (c))
10045 case TRUTH_ANDIF_EXPR:
10046 case TRUTH_ORIF_EXPR:
10047 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
10048 t, mem);
10049 gimplify_and_add (t, stmt_seqp);
10050 break;
10051 default:
10052 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
10053 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
10054 stmt_seqp);
10057 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
10058 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
10059 gimplify_and_add (unshare_expr(x), stmt_seqp);
10062 /* Increment the induction variable. */
10063 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
10064 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
10065 gimple_seq_add_stmt (stmt_seqp, stmt);
10067 /* Go back to the top of the loop. */
10068 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
10070 /* Place the loop exit label here. */
10071 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
10074 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
10075 scan that for reductions. */
10077 static void
10078 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
10079 gimple_seq *out_stmt_seqp, omp_context *ctx)
10081 gimple_stmt_iterator gsi;
10082 gimple_seq inner = NULL;
10084 /* A collapse clause may have inserted a new bind block. */
10085 gsi = gsi_start (*body);
10086 while (!gsi_end_p (gsi))
10088 gimple *stmt = gsi_stmt (gsi);
10089 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
10091 inner = gimple_bind_body (bind_stmt);
10092 body = &inner;
10093 gsi = gsi_start (*body);
10095 else if (dyn_cast <gomp_for *> (stmt))
10096 break;
10097 else
10098 gsi_next (&gsi);
10101 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10103 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
10104 enter, exit;
10105 bool reduction_found = false;
10107 gimple *stmt = gsi_stmt (gsi);
10109 switch (gimple_code (stmt))
10111 case GIMPLE_OMP_FOR:
10112 clauses = gimple_omp_for_clauses (stmt);
10114 /* Search for a reduction clause. */
10115 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10116 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
10118 reduction_found = true;
10119 break;
10122 if (!reduction_found)
10123 break;
10125 ctx = maybe_lookup_ctx (stmt);
10126 t = NULL_TREE;
10128 /* Extract the number of threads. */
10129 nthreads = create_tmp_var (sizetype);
10130 t = oacc_max_threads (ctx);
10131 gimplify_assign (nthreads, t, in_stmt_seqp);
10133 /* Determine if this is kernel will be executed on the host. */
10134 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
10135 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
10136 stmt = gimple_build_call (call, 0);
10137 gimple_call_set_lhs (stmt, acc_device);
10138 gimple_seq_add_stmt (in_stmt_seqp, stmt);
10140 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
10141 acc_device_host = create_tmp_var (integer_type_node,
10142 ".acc_device_host");
10143 gimplify_assign (acc_device_host,
10144 build_int_cst (integer_type_node,
10145 GOMP_DEVICE_HOST),
10146 in_stmt_seqp);
10148 enter = create_artificial_label (UNKNOWN_LOCATION);
10149 exit = create_artificial_label (UNKNOWN_LOCATION);
10151 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
10152 enter, exit);
10153 gimple_seq_add_stmt (in_stmt_seqp, stmt);
10154 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
10155 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
10156 integer_one_node),
10157 in_stmt_seqp);
10158 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
10160 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
10161 ctx);
10162 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
10163 break;
10164 default:
10165 // Scan for other directives which support reduction here.
10166 break;
10171 /* If ctx is a worksharing context inside of a cancellable parallel
10172 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
10173 and conditional branch to parallel's cancel_label to handle
10174 cancellation in the implicit barrier. */
10176 static void
10177 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
10179 gimple *omp_return = gimple_seq_last_stmt (*body);
10180 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
10181 if (gimple_omp_return_nowait_p (omp_return))
10182 return;
10183 if (ctx->outer
10184 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
10185 && ctx->outer->cancellable)
10187 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
10188 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
10189 tree lhs = create_tmp_var (c_bool_type);
10190 gimple_omp_return_set_lhs (omp_return, lhs);
10191 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10192 gimple *g = gimple_build_cond (NE_EXPR, lhs,
10193 fold_convert (c_bool_type,
10194 boolean_false_node),
10195 ctx->outer->cancel_label, fallthru_label);
10196 gimple_seq_add_stmt (body, g);
10197 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10201 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10202 CTX is the enclosing OMP context for the current statement. */
10204 static void
10205 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10207 tree block, control;
10208 gimple_stmt_iterator tgsi;
10209 gomp_sections *stmt;
10210 gimple *t;
10211 gbind *new_stmt, *bind;
10212 gimple_seq ilist, dlist, olist, new_body;
10214 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
10216 push_gimplify_context ();
10218 dlist = NULL;
10219 ilist = NULL;
10220 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10221 &ilist, &dlist, ctx, NULL);
10223 new_body = gimple_omp_body (stmt);
10224 gimple_omp_set_body (stmt, NULL);
10225 tgsi = gsi_start (new_body);
10226 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10228 omp_context *sctx;
10229 gimple *sec_start;
10231 sec_start = gsi_stmt (tgsi);
10232 sctx = maybe_lookup_ctx (sec_start);
10233 gcc_assert (sctx);
10235 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10236 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10237 GSI_CONTINUE_LINKING);
10238 gimple_omp_set_body (sec_start, NULL);
10240 if (gsi_one_before_end_p (tgsi))
10242 gimple_seq l = NULL;
10243 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10244 &l, ctx);
10245 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10246 gimple_omp_section_set_last (sec_start);
10249 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10250 GSI_CONTINUE_LINKING);
10253 block = make_node (BLOCK);
10254 bind = gimple_build_bind (NULL, new_body, block);
10256 olist = NULL;
10257 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10259 block = make_node (BLOCK);
10260 new_stmt = gimple_build_bind (NULL, NULL, block);
10261 gsi_replace (gsi_p, new_stmt, true);
10263 pop_gimplify_context (new_stmt);
10264 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10265 BLOCK_VARS (block) = gimple_bind_vars (bind);
10266 if (BLOCK_VARS (block))
10267 TREE_USED (block) = 1;
10269 new_body = NULL;
10270 gimple_seq_add_seq (&new_body, ilist);
10271 gimple_seq_add_stmt (&new_body, stmt);
10272 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10273 gimple_seq_add_stmt (&new_body, bind);
10275 control = create_tmp_var (unsigned_type_node, ".section");
10276 t = gimple_build_omp_continue (control, control);
10277 gimple_omp_sections_set_control (stmt, control);
10278 gimple_seq_add_stmt (&new_body, t);
10280 gimple_seq_add_seq (&new_body, olist);
10281 if (ctx->cancellable)
10282 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10283 gimple_seq_add_seq (&new_body, dlist);
10285 new_body = maybe_catch_exception (new_body);
10287 t = gimple_build_omp_return
10288 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10289 OMP_CLAUSE_NOWAIT));
10290 gimple_seq_add_stmt (&new_body, t);
10291 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10293 gimple_bind_set_body (new_stmt, new_body);
10297 /* A subroutine of lower_omp_single. Expand the simple form of
10298 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10300 if (GOMP_single_start ())
10301 BODY;
10302 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10304 FIXME. It may be better to delay expanding the logic of this until
10305 pass_expand_omp. The expanded logic may make the job more difficult
10306 to a synchronization analysis pass. */
10308 static void
10309 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10311 location_t loc = gimple_location (single_stmt);
10312 tree tlabel = create_artificial_label (loc);
10313 tree flabel = create_artificial_label (loc);
10314 gimple *call, *cond;
10315 tree lhs, decl;
10317 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10318 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10319 call = gimple_build_call (decl, 0);
10320 gimple_call_set_lhs (call, lhs);
10321 gimple_seq_add_stmt (pre_p, call);
10323 cond = gimple_build_cond (EQ_EXPR, lhs,
10324 fold_convert_loc (loc, TREE_TYPE (lhs),
10325 boolean_true_node),
10326 tlabel, flabel);
10327 gimple_seq_add_stmt (pre_p, cond);
10328 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10329 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10330 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10334 /* A subroutine of lower_omp_single. Expand the simple form of
10335 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10337 #pragma omp single copyprivate (a, b, c)
10339 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10342 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10344 BODY;
10345 copyout.a = a;
10346 copyout.b = b;
10347 copyout.c = c;
10348 GOMP_single_copy_end (&copyout);
10350 else
10352 a = copyout_p->a;
10353 b = copyout_p->b;
10354 c = copyout_p->c;
10356 GOMP_barrier ();
10359 FIXME. It may be better to delay expanding the logic of this until
10360 pass_expand_omp. The expanded logic may make the job more difficult
10361 to a synchronization analysis pass. */
10363 static void
10364 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10365 omp_context *ctx)
10367 tree ptr_type, t, l0, l1, l2, bfn_decl;
10368 gimple_seq copyin_seq;
10369 location_t loc = gimple_location (single_stmt);
10371 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10373 ptr_type = build_pointer_type (ctx->record_type);
10374 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10376 l0 = create_artificial_label (loc);
10377 l1 = create_artificial_label (loc);
10378 l2 = create_artificial_label (loc);
10380 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10381 t = build_call_expr_loc (loc, bfn_decl, 0);
10382 t = fold_convert_loc (loc, ptr_type, t);
10383 gimplify_assign (ctx->receiver_decl, t, pre_p);
10385 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10386 build_int_cst (ptr_type, 0));
10387 t = build3 (COND_EXPR, void_type_node, t,
10388 build_and_jump (&l0), build_and_jump (&l1));
10389 gimplify_and_add (t, pre_p);
10391 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10393 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10395 copyin_seq = NULL;
10396 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10397 &copyin_seq, ctx);
10399 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10400 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10401 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10402 gimplify_and_add (t, pre_p);
10404 t = build_and_jump (&l2);
10405 gimplify_and_add (t, pre_p);
10407 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10409 gimple_seq_add_seq (pre_p, copyin_seq);
10411 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10415 /* Expand code for an OpenMP single directive. */
10417 static void
10418 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10420 tree block;
10421 gimple *t;
10422 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10423 gbind *bind;
10424 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10426 push_gimplify_context ();
10428 block = make_node (BLOCK);
10429 bind = gimple_build_bind (NULL, NULL, block);
10430 gsi_replace (gsi_p, bind, true);
10431 bind_body = NULL;
10432 dlist = NULL;
10433 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10434 &bind_body, &dlist, ctx, NULL);
10435 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10437 gimple_seq_add_stmt (&bind_body, single_stmt);
10439 if (ctx->record_type)
10440 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10441 else
10442 lower_omp_single_simple (single_stmt, &bind_body);
10444 gimple_omp_set_body (single_stmt, NULL);
10446 gimple_seq_add_seq (&bind_body, dlist);
10448 bind_body = maybe_catch_exception (bind_body);
10450 t = gimple_build_omp_return
10451 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10452 OMP_CLAUSE_NOWAIT));
10453 gimple_seq_add_stmt (&bind_body_tail, t);
10454 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10455 if (ctx->record_type)
10457 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10458 tree clobber = build_constructor (ctx->record_type, NULL);
10459 TREE_THIS_VOLATILE (clobber) = 1;
10460 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10461 clobber), GSI_SAME_STMT);
10463 gimple_seq_add_seq (&bind_body, bind_body_tail);
10464 gimple_bind_set_body (bind, bind_body);
10466 pop_gimplify_context (bind);
10468 gimple_bind_append_vars (bind, ctx->block_vars);
10469 BLOCK_VARS (block) = ctx->block_vars;
10470 if (BLOCK_VARS (block))
10471 TREE_USED (block) = 1;
10475 /* Expand code for an OpenMP master directive. */
10477 static void
10478 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10480 tree block, lab = NULL, x, bfn_decl;
10481 gimple *stmt = gsi_stmt (*gsi_p);
10482 gbind *bind;
10483 location_t loc = gimple_location (stmt);
10484 gimple_seq tseq;
10486 push_gimplify_context ();
10488 block = make_node (BLOCK);
10489 bind = gimple_build_bind (NULL, NULL, block);
10490 gsi_replace (gsi_p, bind, true);
10491 gimple_bind_add_stmt (bind, stmt);
10493 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10494 x = build_call_expr_loc (loc, bfn_decl, 0);
10495 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10496 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10497 tseq = NULL;
10498 gimplify_and_add (x, &tseq);
10499 gimple_bind_add_seq (bind, tseq);
10501 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10502 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10503 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10504 gimple_omp_set_body (stmt, NULL);
10506 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10508 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10510 pop_gimplify_context (bind);
10512 gimple_bind_append_vars (bind, ctx->block_vars);
10513 BLOCK_VARS (block) = ctx->block_vars;
10517 /* Expand code for an OpenMP taskgroup directive. */
10519 static void
10520 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10522 gimple *stmt = gsi_stmt (*gsi_p);
10523 gcall *x;
10524 gbind *bind;
10525 tree block = make_node (BLOCK);
10527 bind = gimple_build_bind (NULL, NULL, block);
10528 gsi_replace (gsi_p, bind, true);
10529 gimple_bind_add_stmt (bind, stmt);
10531 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10533 gimple_bind_add_stmt (bind, x);
10535 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10536 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10537 gimple_omp_set_body (stmt, NULL);
10539 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10541 gimple_bind_append_vars (bind, ctx->block_vars);
10542 BLOCK_VARS (block) = ctx->block_vars;
10546 /* Expand code for an OpenMP ordered directive. */
10548 static void
10549 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10551 tree block;
10552 gimple *stmt = gsi_stmt (*gsi_p);
10553 gcall *x;
10554 gbind *bind;
10556 push_gimplify_context ();
10558 block = make_node (BLOCK);
10559 bind = gimple_build_bind (NULL, NULL, block);
10560 gsi_replace (gsi_p, bind, true);
10561 gimple_bind_add_stmt (bind, stmt);
10563 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10565 gimple_bind_add_stmt (bind, x);
10567 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10568 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10569 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10570 gimple_omp_set_body (stmt, NULL);
10572 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10573 gimple_bind_add_stmt (bind, x);
10575 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10577 pop_gimplify_context (bind);
10579 gimple_bind_append_vars (bind, ctx->block_vars);
10580 BLOCK_VARS (block) = gimple_bind_vars (bind);
10584 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10585 substitution of a couple of function calls. But in the NAMED case,
10586 requires that languages coordinate a symbol name. It is therefore
10587 best put here in common code. */
10589 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10591 static void
10592 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10594 tree block;
10595 tree name, lock, unlock;
10596 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10597 gbind *bind;
10598 location_t loc = gimple_location (stmt);
10599 gimple_seq tbody;
10601 name = gimple_omp_critical_name (stmt);
10602 if (name)
10604 tree decl;
10606 if (!critical_name_mutexes)
10607 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10609 tree *n = critical_name_mutexes->get (name);
10610 if (n == NULL)
10612 char *new_str;
10614 decl = create_tmp_var_raw (ptr_type_node);
10616 new_str = ACONCAT ((".gomp_critical_user_",
10617 IDENTIFIER_POINTER (name), NULL));
10618 DECL_NAME (decl) = get_identifier (new_str);
10619 TREE_PUBLIC (decl) = 1;
10620 TREE_STATIC (decl) = 1;
10621 DECL_COMMON (decl) = 1;
10622 DECL_ARTIFICIAL (decl) = 1;
10623 DECL_IGNORED_P (decl) = 1;
10625 varpool_node::finalize_decl (decl);
10627 critical_name_mutexes->put (name, decl);
10629 else
10630 decl = *n;
10632 /* If '#pragma omp critical' is inside offloaded region or
10633 inside function marked as offloadable, the symbol must be
10634 marked as offloadable too. */
10635 omp_context *octx;
10636 if (cgraph_node::get (current_function_decl)->offloadable)
10637 varpool_node::get_create (decl)->offloadable = 1;
10638 else
10639 for (octx = ctx->outer; octx; octx = octx->outer)
10640 if (is_gimple_omp_offloaded (octx->stmt))
10642 varpool_node::get_create (decl)->offloadable = 1;
10643 break;
10646 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10647 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10649 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10650 unlock = build_call_expr_loc (loc, unlock, 1,
10651 build_fold_addr_expr_loc (loc, decl));
10653 else
10655 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10656 lock = build_call_expr_loc (loc, lock, 0);
10658 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10659 unlock = build_call_expr_loc (loc, unlock, 0);
10662 push_gimplify_context ();
10664 block = make_node (BLOCK);
10665 bind = gimple_build_bind (NULL, NULL, block);
10666 gsi_replace (gsi_p, bind, true);
10667 gimple_bind_add_stmt (bind, stmt);
10669 tbody = gimple_bind_body (bind);
10670 gimplify_and_add (lock, &tbody);
10671 gimple_bind_set_body (bind, tbody);
10673 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10674 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10675 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10676 gimple_omp_set_body (stmt, NULL);
10678 tbody = gimple_bind_body (bind);
10679 gimplify_and_add (unlock, &tbody);
10680 gimple_bind_set_body (bind, tbody);
10682 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10684 pop_gimplify_context (bind);
10685 gimple_bind_append_vars (bind, ctx->block_vars);
10686 BLOCK_VARS (block) = gimple_bind_vars (bind);
10690 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10691 for a lastprivate clause. Given a loop control predicate of (V
10692 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10693 is appended to *DLIST, iterator initialization is appended to
10694 *BODY_P. */
10696 static void
10697 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10698 gimple_seq *dlist, struct omp_context *ctx)
10700 tree clauses, cond, vinit;
10701 enum tree_code cond_code;
10702 gimple_seq stmts;
10704 cond_code = fd->loop.cond_code;
10705 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10707 /* When possible, use a strict equality expression. This can let VRP
10708 type optimizations deduce the value and remove a copy. */
10709 if (tree_fits_shwi_p (fd->loop.step))
10711 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10712 if (step == 1 || step == -1)
10713 cond_code = EQ_EXPR;
10716 tree n2 = fd->loop.n2;
10717 if (fd->collapse > 1
10718 && TREE_CODE (n2) != INTEGER_CST
10719 && gimple_omp_for_combined_into_p (fd->for_stmt)
10720 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10722 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10723 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
10725 struct omp_for_data outer_fd;
10726 extract_omp_for_data (gfor, &outer_fd, NULL);
10727 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10730 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
10732 clauses = gimple_omp_for_clauses (fd->for_stmt);
10733 stmts = NULL;
10734 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10735 if (!gimple_seq_empty_p (stmts))
10737 gimple_seq_add_seq (&stmts, *dlist);
10738 *dlist = stmts;
10740 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10741 vinit = fd->loop.n1;
10742 if (cond_code == EQ_EXPR
10743 && tree_fits_shwi_p (fd->loop.n2)
10744 && ! integer_zerop (fd->loop.n2))
10745 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10746 else
10747 vinit = unshare_expr (vinit);
10749 /* Initialize the iterator variable, so that threads that don't execute
10750 any iterations don't execute the lastprivate clauses by accident. */
10751 gimplify_assign (fd->loop.v, vinit, body_p);
10756 /* Lower code for an OMP loop directive. */
10758 static void
10759 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10761 tree *rhs_p, block;
10762 struct omp_for_data fd, *fdp = NULL;
10763 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10764 gbind *new_stmt;
10765 gimple_seq omp_for_body, body, dlist;
10766 size_t i;
10768 push_gimplify_context ();
10770 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10772 block = make_node (BLOCK);
10773 new_stmt = gimple_build_bind (NULL, NULL, block);
10774 /* Replace at gsi right away, so that 'stmt' is no member
10775 of a sequence anymore as we're going to add to a different
10776 one below. */
10777 gsi_replace (gsi_p, new_stmt, true);
10779 /* Move declaration of temporaries in the loop body before we make
10780 it go away. */
10781 omp_for_body = gimple_omp_body (stmt);
10782 if (!gimple_seq_empty_p (omp_for_body)
10783 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10785 gbind *inner_bind
10786 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10787 tree vars = gimple_bind_vars (inner_bind);
10788 gimple_bind_append_vars (new_stmt, vars);
10789 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10790 keep them on the inner_bind and it's block. */
10791 gimple_bind_set_vars (inner_bind, NULL_TREE);
10792 if (gimple_bind_block (inner_bind))
10793 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10796 if (gimple_omp_for_combined_into_p (stmt))
10798 extract_omp_for_data (stmt, &fd, NULL);
10799 fdp = &fd;
10801 /* We need two temporaries with fd.loop.v type (istart/iend)
10802 and then (fd.collapse - 1) temporaries with the same
10803 type for count2 ... countN-1 vars if not constant. */
10804 size_t count = 2;
10805 tree type = fd.iter_type;
10806 if (fd.collapse > 1
10807 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10808 count += fd.collapse - 1;
10809 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10810 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10811 tree clauses = *pc;
10812 if (parallel_for)
10813 outerc
10814 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10815 OMP_CLAUSE__LOOPTEMP_);
10816 for (i = 0; i < count; i++)
10818 tree temp;
10819 if (parallel_for)
10821 gcc_assert (outerc);
10822 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10823 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10824 OMP_CLAUSE__LOOPTEMP_);
10826 else
10828 temp = create_tmp_var (type);
10829 insert_decl_map (&ctx->outer->cb, temp, temp);
10831 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10832 OMP_CLAUSE_DECL (*pc) = temp;
10833 pc = &OMP_CLAUSE_CHAIN (*pc);
10835 *pc = clauses;
10838 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10839 dlist = NULL;
10840 body = NULL;
10841 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10842 fdp);
10843 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10845 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10847 /* Lower the header expressions. At this point, we can assume that
10848 the header is of the form:
10850 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10852 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10853 using the .omp_data_s mapping, if needed. */
10854 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10856 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10857 if (!is_gimple_min_invariant (*rhs_p))
10858 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10860 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10861 if (!is_gimple_min_invariant (*rhs_p))
10862 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10864 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10865 if (!is_gimple_min_invariant (*rhs_p))
10866 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10869 /* Once lowered, extract the bounds and clauses. */
10870 extract_omp_for_data (stmt, &fd, NULL);
10872 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10874 gimple_seq_add_stmt (&body, stmt);
10875 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10877 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10878 fd.loop.v));
10880 /* After the loop, add exit clauses. */
10881 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10883 if (ctx->cancellable)
10884 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10886 gimple_seq_add_seq (&body, dlist);
10888 body = maybe_catch_exception (body);
10890 /* Region exit marker goes at the end of the loop body. */
10891 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10892 maybe_add_implicit_barrier_cancel (ctx, &body);
10893 pop_gimplify_context (new_stmt);
10895 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10896 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10897 if (BLOCK_VARS (block))
10898 TREE_USED (block) = 1;
10900 gimple_bind_set_body (new_stmt, body);
10901 gimple_omp_set_body (stmt, NULL);
10902 gimple_omp_for_set_pre_body (stmt, NULL);
10905 /* Callback for walk_stmts. Check if the current statement only contains
10906 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10908 static tree
10909 check_combined_parallel (gimple_stmt_iterator *gsi_p,
10910 bool *handled_ops_p,
10911 struct walk_stmt_info *wi)
10913 int *info = (int *) wi->info;
10914 gimple *stmt = gsi_stmt (*gsi_p);
10916 *handled_ops_p = true;
10917 switch (gimple_code (stmt))
10919 WALK_SUBSTMTS;
10921 case GIMPLE_OMP_FOR:
10922 case GIMPLE_OMP_SECTIONS:
10923 *info = *info == 0 ? 1 : -1;
10924 break;
10925 default:
10926 *info = -1;
10927 break;
10929 return NULL;
10932 struct omp_taskcopy_context
10934 /* This field must be at the beginning, as we do "inheritance": Some
10935 callback functions for tree-inline.c (e.g., omp_copy_decl)
10936 receive a copy_body_data pointer that is up-casted to an
10937 omp_context pointer. */
10938 copy_body_data cb;
10939 omp_context *ctx;
10942 static tree
10943 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10945 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10947 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10948 return create_tmp_var (TREE_TYPE (var));
10950 return var;
10953 static tree
10954 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10956 tree name, new_fields = NULL, type, f;
10958 type = lang_hooks.types.make_type (RECORD_TYPE);
10959 name = DECL_NAME (TYPE_NAME (orig_type));
10960 name = build_decl (gimple_location (tcctx->ctx->stmt),
10961 TYPE_DECL, name, type);
10962 TYPE_NAME (type) = name;
10964 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10966 tree new_f = copy_node (f);
10967 DECL_CONTEXT (new_f) = type;
10968 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10969 TREE_CHAIN (new_f) = new_fields;
10970 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10971 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10972 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10973 &tcctx->cb, NULL);
10974 new_fields = new_f;
10975 tcctx->cb.decl_map->put (f, new_f);
10977 TYPE_FIELDS (type) = nreverse (new_fields);
10978 layout_type (type);
10979 return type;
10982 /* Create task copyfn. */
10984 static void
10985 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
10987 struct function *child_cfun;
10988 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10989 tree record_type, srecord_type, bind, list;
10990 bool record_needs_remap = false, srecord_needs_remap = false;
10991 splay_tree_node n;
10992 struct omp_taskcopy_context tcctx;
10993 location_t loc = gimple_location (task_stmt);
10995 child_fn = gimple_omp_task_copy_fn (task_stmt);
10996 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10997 gcc_assert (child_cfun->cfg == NULL);
10998 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
11000 /* Reset DECL_CONTEXT on function arguments. */
11001 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
11002 DECL_CONTEXT (t) = child_fn;
11004 /* Populate the function. */
11005 push_gimplify_context ();
11006 push_cfun (child_cfun);
11008 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
11009 TREE_SIDE_EFFECTS (bind) = 1;
11010 list = NULL;
11011 DECL_SAVED_TREE (child_fn) = bind;
11012 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
11014 /* Remap src and dst argument types if needed. */
11015 record_type = ctx->record_type;
11016 srecord_type = ctx->srecord_type;
11017 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
11018 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
11020 record_needs_remap = true;
11021 break;
11023 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
11024 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
11026 srecord_needs_remap = true;
11027 break;
11030 if (record_needs_remap || srecord_needs_remap)
11032 memset (&tcctx, '\0', sizeof (tcctx));
11033 tcctx.cb.src_fn = ctx->cb.src_fn;
11034 tcctx.cb.dst_fn = child_fn;
11035 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
11036 gcc_checking_assert (tcctx.cb.src_node);
11037 tcctx.cb.dst_node = tcctx.cb.src_node;
11038 tcctx.cb.src_cfun = ctx->cb.src_cfun;
11039 tcctx.cb.copy_decl = task_copyfn_copy_decl;
11040 tcctx.cb.eh_lp_nr = 0;
11041 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
11042 tcctx.cb.decl_map = new hash_map<tree, tree>;
11043 tcctx.ctx = ctx;
11045 if (record_needs_remap)
11046 record_type = task_copyfn_remap_type (&tcctx, record_type);
11047 if (srecord_needs_remap)
11048 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
11050 else
11051 tcctx.cb.decl_map = NULL;
11053 arg = DECL_ARGUMENTS (child_fn);
11054 TREE_TYPE (arg) = build_pointer_type (record_type);
11055 sarg = DECL_CHAIN (arg);
11056 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
11058 /* First pass: initialize temporaries used in record_type and srecord_type
11059 sizes and field offsets. */
11060 if (tcctx.cb.decl_map)
11061 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
11062 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
11064 tree *p;
11066 decl = OMP_CLAUSE_DECL (c);
11067 p = tcctx.cb.decl_map->get (decl);
11068 if (p == NULL)
11069 continue;
11070 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11071 sf = (tree) n->value;
11072 sf = *tcctx.cb.decl_map->get (sf);
11073 src = build_simple_mem_ref_loc (loc, sarg);
11074 src = omp_build_component_ref (src, sf);
11075 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
11076 append_to_statement_list (t, &list);
11079 /* Second pass: copy shared var pointers and copy construct non-VLA
11080 firstprivate vars. */
11081 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
11082 switch (OMP_CLAUSE_CODE (c))
11084 case OMP_CLAUSE_SHARED:
11085 decl = OMP_CLAUSE_DECL (c);
11086 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11087 if (n == NULL)
11088 break;
11089 f = (tree) n->value;
11090 if (tcctx.cb.decl_map)
11091 f = *tcctx.cb.decl_map->get (f);
11092 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11093 sf = (tree) n->value;
11094 if (tcctx.cb.decl_map)
11095 sf = *tcctx.cb.decl_map->get (sf);
11096 src = build_simple_mem_ref_loc (loc, sarg);
11097 src = omp_build_component_ref (src, sf);
11098 dst = build_simple_mem_ref_loc (loc, arg);
11099 dst = omp_build_component_ref (dst, f);
11100 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
11101 append_to_statement_list (t, &list);
11102 break;
11103 case OMP_CLAUSE_FIRSTPRIVATE:
11104 decl = OMP_CLAUSE_DECL (c);
11105 if (is_variable_sized (decl))
11106 break;
11107 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11108 if (n == NULL)
11109 break;
11110 f = (tree) n->value;
11111 if (tcctx.cb.decl_map)
11112 f = *tcctx.cb.decl_map->get (f);
11113 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11114 if (n != NULL)
11116 sf = (tree) n->value;
11117 if (tcctx.cb.decl_map)
11118 sf = *tcctx.cb.decl_map->get (sf);
11119 src = build_simple_mem_ref_loc (loc, sarg);
11120 src = omp_build_component_ref (src, sf);
11121 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
11122 src = build_simple_mem_ref_loc (loc, src);
11124 else
11125 src = decl;
11126 dst = build_simple_mem_ref_loc (loc, arg);
11127 dst = omp_build_component_ref (dst, f);
11128 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11129 append_to_statement_list (t, &list);
11130 break;
11131 case OMP_CLAUSE_PRIVATE:
11132 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
11133 break;
11134 decl = OMP_CLAUSE_DECL (c);
11135 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11136 f = (tree) n->value;
11137 if (tcctx.cb.decl_map)
11138 f = *tcctx.cb.decl_map->get (f);
11139 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11140 if (n != NULL)
11142 sf = (tree) n->value;
11143 if (tcctx.cb.decl_map)
11144 sf = *tcctx.cb.decl_map->get (sf);
11145 src = build_simple_mem_ref_loc (loc, sarg);
11146 src = omp_build_component_ref (src, sf);
11147 if (use_pointer_for_field (decl, NULL))
11148 src = build_simple_mem_ref_loc (loc, src);
11150 else
11151 src = decl;
11152 dst = build_simple_mem_ref_loc (loc, arg);
11153 dst = omp_build_component_ref (dst, f);
11154 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
11155 append_to_statement_list (t, &list);
11156 break;
11157 default:
11158 break;
11161 /* Last pass: handle VLA firstprivates. */
11162 if (tcctx.cb.decl_map)
11163 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
11164 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
11166 tree ind, ptr, df;
11168 decl = OMP_CLAUSE_DECL (c);
11169 if (!is_variable_sized (decl))
11170 continue;
11171 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11172 if (n == NULL)
11173 continue;
11174 f = (tree) n->value;
11175 f = *tcctx.cb.decl_map->get (f);
11176 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
11177 ind = DECL_VALUE_EXPR (decl);
11178 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
11179 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
11180 n = splay_tree_lookup (ctx->sfield_map,
11181 (splay_tree_key) TREE_OPERAND (ind, 0));
11182 sf = (tree) n->value;
11183 sf = *tcctx.cb.decl_map->get (sf);
11184 src = build_simple_mem_ref_loc (loc, sarg);
11185 src = omp_build_component_ref (src, sf);
11186 src = build_simple_mem_ref_loc (loc, src);
11187 dst = build_simple_mem_ref_loc (loc, arg);
11188 dst = omp_build_component_ref (dst, f);
11189 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11190 append_to_statement_list (t, &list);
11191 n = splay_tree_lookup (ctx->field_map,
11192 (splay_tree_key) TREE_OPERAND (ind, 0));
11193 df = (tree) n->value;
11194 df = *tcctx.cb.decl_map->get (df);
11195 ptr = build_simple_mem_ref_loc (loc, arg);
11196 ptr = omp_build_component_ref (ptr, df);
11197 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
11198 build_fold_addr_expr_loc (loc, dst));
11199 append_to_statement_list (t, &list);
11202 t = build1 (RETURN_EXPR, void_type_node, NULL);
11203 append_to_statement_list (t, &list);
11205 if (tcctx.cb.decl_map)
11206 delete tcctx.cb.decl_map;
11207 pop_gimplify_context (NULL);
11208 BIND_EXPR_BODY (bind) = list;
11209 pop_cfun ();
11212 static void
11213 lower_depend_clauses (gimple *stmt, gimple_seq *iseq, gimple_seq *oseq)
11215 tree c, clauses;
11216 gimple *g;
11217 size_t n_in = 0, n_out = 0, idx = 2, i;
11219 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11220 OMP_CLAUSE_DEPEND);
11221 gcc_assert (clauses);
11222 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11223 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11224 switch (OMP_CLAUSE_DEPEND_KIND (c))
11226 case OMP_CLAUSE_DEPEND_IN:
11227 n_in++;
11228 break;
11229 case OMP_CLAUSE_DEPEND_OUT:
11230 case OMP_CLAUSE_DEPEND_INOUT:
11231 n_out++;
11232 break;
11233 default:
11234 gcc_unreachable ();
11236 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11237 tree array = create_tmp_var (type);
11238 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11239 NULL_TREE);
11240 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11241 gimple_seq_add_stmt (iseq, g);
11242 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11243 NULL_TREE);
11244 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11245 gimple_seq_add_stmt (iseq, g);
11246 for (i = 0; i < 2; i++)
11248 if ((i ? n_in : n_out) == 0)
11249 continue;
11250 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11251 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11252 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11254 tree t = OMP_CLAUSE_DECL (c);
11255 t = fold_convert (ptr_type_node, t);
11256 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11257 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11258 NULL_TREE, NULL_TREE);
11259 g = gimple_build_assign (r, t);
11260 gimple_seq_add_stmt (iseq, g);
11263 tree *p = gimple_omp_task_clauses_ptr (stmt);
11264 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11265 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11266 OMP_CLAUSE_CHAIN (c) = *p;
11267 *p = c;
11268 tree clobber = build_constructor (type, NULL);
11269 TREE_THIS_VOLATILE (clobber) = 1;
11270 g = gimple_build_assign (array, clobber);
11271 gimple_seq_add_stmt (oseq, g);
11274 /* Lower the OpenMP parallel or task directive in the current statement
11275 in GSI_P. CTX holds context information for the directive. */
11277 static void
11278 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11280 tree clauses;
11281 tree child_fn, t;
11282 gimple *stmt = gsi_stmt (*gsi_p);
11283 gbind *par_bind, *bind, *dep_bind = NULL;
11284 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11285 location_t loc = gimple_location (stmt);
11287 clauses = gimple_omp_taskreg_clauses (stmt);
11288 par_bind
11289 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11290 par_body = gimple_bind_body (par_bind);
11291 child_fn = ctx->cb.dst_fn;
11292 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11293 && !gimple_omp_parallel_combined_p (stmt))
11295 struct walk_stmt_info wi;
11296 int ws_num = 0;
11298 memset (&wi, 0, sizeof (wi));
11299 wi.info = &ws_num;
11300 wi.val_only = true;
11301 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11302 if (ws_num == 1)
11303 gimple_omp_parallel_set_combined_p (stmt, true);
11305 gimple_seq dep_ilist = NULL;
11306 gimple_seq dep_olist = NULL;
11307 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11308 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11310 push_gimplify_context ();
11311 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11312 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11315 if (ctx->srecord_type)
11316 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11318 push_gimplify_context ();
11320 par_olist = NULL;
11321 par_ilist = NULL;
11322 par_rlist = NULL;
11323 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11324 lower_omp (&par_body, ctx);
11325 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11326 lower_reduction_clauses (clauses, &par_rlist, ctx);
11328 /* Declare all the variables created by mapping and the variables
11329 declared in the scope of the parallel body. */
11330 record_vars_into (ctx->block_vars, child_fn);
11331 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11333 if (ctx->record_type)
11335 ctx->sender_decl
11336 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11337 : ctx->record_type, ".omp_data_o");
11338 DECL_NAMELESS (ctx->sender_decl) = 1;
11339 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11340 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11343 olist = NULL;
11344 ilist = NULL;
11345 lower_send_clauses (clauses, &ilist, &olist, ctx);
11346 lower_send_shared_vars (&ilist, &olist, ctx);
11348 if (ctx->record_type)
11350 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11351 TREE_THIS_VOLATILE (clobber) = 1;
11352 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11353 clobber));
11356 /* Once all the expansions are done, sequence all the different
11357 fragments inside gimple_omp_body. */
11359 new_body = NULL;
11361 if (ctx->record_type)
11363 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11364 /* fixup_child_record_type might have changed receiver_decl's type. */
11365 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11366 gimple_seq_add_stmt (&new_body,
11367 gimple_build_assign (ctx->receiver_decl, t));
11370 gimple_seq_add_seq (&new_body, par_ilist);
11371 gimple_seq_add_seq (&new_body, par_body);
11372 gimple_seq_add_seq (&new_body, par_rlist);
11373 if (ctx->cancellable)
11374 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11375 gimple_seq_add_seq (&new_body, par_olist);
11376 new_body = maybe_catch_exception (new_body);
11377 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
11378 gimple_seq_add_stmt (&new_body,
11379 gimple_build_omp_continue (integer_zero_node,
11380 integer_zero_node));
11381 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11382 gimple_omp_set_body (stmt, new_body);
11384 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11385 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11386 gimple_bind_add_seq (bind, ilist);
11387 gimple_bind_add_stmt (bind, stmt);
11388 gimple_bind_add_seq (bind, olist);
11390 pop_gimplify_context (NULL);
11392 if (dep_bind)
11394 gimple_bind_add_seq (dep_bind, dep_ilist);
11395 gimple_bind_add_stmt (dep_bind, bind);
11396 gimple_bind_add_seq (dep_bind, dep_olist);
11397 pop_gimplify_context (dep_bind);
11401 /* Lower the GIMPLE_OMP_TARGET in the current statement
11402 in GSI_P. CTX holds context information for the directive. */
11404 static void
11405 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11407 tree clauses;
11408 tree child_fn, t, c;
11409 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11410 gbind *tgt_bind, *bind;
11411 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11412 location_t loc = gimple_location (stmt);
11413 bool offloaded, data_region;
11414 unsigned int map_cnt = 0;
11416 offloaded = is_gimple_omp_offloaded (stmt);
11417 switch (gimple_omp_target_kind (stmt))
11419 case GF_OMP_TARGET_KIND_REGION:
11420 case GF_OMP_TARGET_KIND_UPDATE:
11421 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11422 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11423 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11424 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11425 data_region = false;
11426 break;
11427 case GF_OMP_TARGET_KIND_DATA:
11428 case GF_OMP_TARGET_KIND_OACC_DATA:
11429 data_region = true;
11430 break;
11431 default:
11432 gcc_unreachable ();
11435 clauses = gimple_omp_target_clauses (stmt);
11437 tgt_bind = NULL;
11438 tgt_body = NULL;
11439 if (offloaded)
11441 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11442 tgt_body = gimple_bind_body (tgt_bind);
11444 else if (data_region)
11445 tgt_body = gimple_omp_body (stmt);
11446 child_fn = ctx->cb.dst_fn;
11448 push_gimplify_context ();
11450 irlist = NULL;
11451 orlist = NULL;
11452 if (offloaded
11453 && is_gimple_omp_oacc (stmt))
11454 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11456 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11457 switch (OMP_CLAUSE_CODE (c))
11459 tree var, x;
11461 default:
11462 break;
11463 case OMP_CLAUSE_MAP:
11464 #ifdef ENABLE_CHECKING
11465 /* First check what we're prepared to handle in the following. */
11466 switch (OMP_CLAUSE_MAP_KIND (c))
11468 case GOMP_MAP_ALLOC:
11469 case GOMP_MAP_TO:
11470 case GOMP_MAP_FROM:
11471 case GOMP_MAP_TOFROM:
11472 case GOMP_MAP_POINTER:
11473 case GOMP_MAP_TO_PSET:
11474 break;
11475 case GOMP_MAP_FORCE_ALLOC:
11476 case GOMP_MAP_FORCE_TO:
11477 case GOMP_MAP_FORCE_FROM:
11478 case GOMP_MAP_FORCE_TOFROM:
11479 case GOMP_MAP_FORCE_PRESENT:
11480 case GOMP_MAP_FORCE_DEALLOC:
11481 case GOMP_MAP_FORCE_DEVICEPTR:
11482 gcc_assert (is_gimple_omp_oacc (stmt));
11483 break;
11484 default:
11485 gcc_unreachable ();
11487 #endif
11488 /* FALLTHRU */
11489 case OMP_CLAUSE_TO:
11490 case OMP_CLAUSE_FROM:
11491 var = OMP_CLAUSE_DECL (c);
11492 if (!DECL_P (var))
11494 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11495 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11496 map_cnt++;
11497 continue;
11500 if (DECL_SIZE (var)
11501 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11503 tree var2 = DECL_VALUE_EXPR (var);
11504 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11505 var2 = TREE_OPERAND (var2, 0);
11506 gcc_assert (DECL_P (var2));
11507 var = var2;
11510 if (!maybe_lookup_field (var, ctx))
11511 continue;
11513 if (offloaded)
11515 x = build_receiver_ref (var, true, ctx);
11516 tree new_var = lookup_decl (var, ctx);
11517 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11518 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11519 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11520 x = build_simple_mem_ref (x);
11521 SET_DECL_VALUE_EXPR (new_var, x);
11522 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11524 map_cnt++;
11527 if (offloaded)
11529 target_nesting_level++;
11530 lower_omp (&tgt_body, ctx);
11531 target_nesting_level--;
11533 else if (data_region)
11534 lower_omp (&tgt_body, ctx);
11536 if (offloaded)
11538 /* Declare all the variables created by mapping and the variables
11539 declared in the scope of the target body. */
11540 record_vars_into (ctx->block_vars, child_fn);
11541 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11544 olist = NULL;
11545 ilist = NULL;
11546 if (ctx->record_type)
11548 ctx->sender_decl
11549 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11550 DECL_NAMELESS (ctx->sender_decl) = 1;
11551 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11552 t = make_tree_vec (3);
11553 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11554 TREE_VEC_ELT (t, 1)
11555 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11556 ".omp_data_sizes");
11557 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11558 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11559 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11560 tree tkind_type;
11561 int talign_shift;
11562 if (is_gimple_omp_oacc (stmt))
11564 tkind_type = short_unsigned_type_node;
11565 talign_shift = 8;
11567 else
11569 tkind_type = unsigned_char_type_node;
11570 talign_shift = 3;
11572 TREE_VEC_ELT (t, 2)
11573 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11574 ".omp_data_kinds");
11575 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11576 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11577 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11578 gimple_omp_target_set_data_arg (stmt, t);
11580 vec<constructor_elt, va_gc> *vsize;
11581 vec<constructor_elt, va_gc> *vkind;
11582 vec_alloc (vsize, map_cnt);
11583 vec_alloc (vkind, map_cnt);
11584 unsigned int map_idx = 0;
11586 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11587 switch (OMP_CLAUSE_CODE (c))
11589 tree ovar, nc;
11591 default:
11592 break;
11593 case OMP_CLAUSE_MAP:
11594 case OMP_CLAUSE_TO:
11595 case OMP_CLAUSE_FROM:
11596 nc = c;
11597 ovar = OMP_CLAUSE_DECL (c);
11598 if (!DECL_P (ovar))
11600 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11601 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11603 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11604 == get_base_address (ovar));
11605 nc = OMP_CLAUSE_CHAIN (c);
11606 ovar = OMP_CLAUSE_DECL (nc);
11608 else
11610 tree x = build_sender_ref (ovar, ctx);
11611 tree v
11612 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11613 gimplify_assign (x, v, &ilist);
11614 nc = NULL_TREE;
11617 else
11619 if (DECL_SIZE (ovar)
11620 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11622 tree ovar2 = DECL_VALUE_EXPR (ovar);
11623 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11624 ovar2 = TREE_OPERAND (ovar2, 0);
11625 gcc_assert (DECL_P (ovar2));
11626 ovar = ovar2;
11628 if (!maybe_lookup_field (ovar, ctx))
11629 continue;
11632 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11633 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11634 talign = DECL_ALIGN_UNIT (ovar);
11635 if (nc)
11637 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11638 tree x = build_sender_ref (ovar, ctx);
11639 if (maybe_lookup_oacc_reduction (var, ctx))
11641 gcc_checking_assert (offloaded
11642 && is_gimple_omp_oacc (stmt));
11643 gimplify_assign (x, var, &ilist);
11645 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11646 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11647 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11648 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11650 gcc_assert (offloaded);
11651 tree avar
11652 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11653 mark_addressable (avar);
11654 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11655 talign = DECL_ALIGN_UNIT (avar);
11656 avar = build_fold_addr_expr (avar);
11657 gimplify_assign (x, avar, &ilist);
11659 else if (is_gimple_reg (var))
11661 gcc_assert (offloaded);
11662 tree avar = create_tmp_var (TREE_TYPE (var));
11663 mark_addressable (avar);
11664 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11665 if (GOMP_MAP_COPY_TO_P (map_kind)
11666 || map_kind == GOMP_MAP_POINTER
11667 || map_kind == GOMP_MAP_TO_PSET
11668 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11669 gimplify_assign (avar, var, &ilist);
11670 avar = build_fold_addr_expr (avar);
11671 gimplify_assign (x, avar, &ilist);
11672 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11673 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11674 && !TYPE_READONLY (TREE_TYPE (var)))
11676 x = build_sender_ref (ovar, ctx);
11677 x = build_simple_mem_ref (x);
11678 gimplify_assign (var, x, &olist);
11681 else
11683 var = build_fold_addr_expr (var);
11684 gimplify_assign (x, var, &ilist);
11687 tree s = OMP_CLAUSE_SIZE (c);
11688 if (s == NULL_TREE)
11689 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11690 s = fold_convert (size_type_node, s);
11691 tree purpose = size_int (map_idx++);
11692 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11693 if (TREE_CODE (s) != INTEGER_CST)
11694 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11696 unsigned HOST_WIDE_INT tkind;
11697 switch (OMP_CLAUSE_CODE (c))
11699 case OMP_CLAUSE_MAP:
11700 tkind = OMP_CLAUSE_MAP_KIND (c);
11701 break;
11702 case OMP_CLAUSE_TO:
11703 tkind = GOMP_MAP_TO;
11704 break;
11705 case OMP_CLAUSE_FROM:
11706 tkind = GOMP_MAP_FROM;
11707 break;
11708 default:
11709 gcc_unreachable ();
11711 gcc_checking_assert (tkind
11712 < (HOST_WIDE_INT_C (1U) << talign_shift));
11713 talign = ceil_log2 (talign);
11714 tkind |= talign << talign_shift;
11715 gcc_checking_assert (tkind
11716 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11717 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11718 build_int_cstu (tkind_type, tkind));
11719 if (nc && nc != c)
11720 c = nc;
11723 gcc_assert (map_idx == map_cnt);
11725 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11726 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11727 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11728 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11729 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11731 gimple_seq initlist = NULL;
11732 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11733 TREE_VEC_ELT (t, 1)),
11734 &initlist, true, NULL_TREE);
11735 gimple_seq_add_seq (&ilist, initlist);
11737 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11738 NULL);
11739 TREE_THIS_VOLATILE (clobber) = 1;
11740 gimple_seq_add_stmt (&olist,
11741 gimple_build_assign (TREE_VEC_ELT (t, 1),
11742 clobber));
11745 tree clobber = build_constructor (ctx->record_type, NULL);
11746 TREE_THIS_VOLATILE (clobber) = 1;
11747 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11748 clobber));
11751 /* Once all the expansions are done, sequence all the different
11752 fragments inside gimple_omp_body. */
11754 new_body = NULL;
11756 if (offloaded
11757 && ctx->record_type)
11759 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11760 /* fixup_child_record_type might have changed receiver_decl's type. */
11761 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11762 gimple_seq_add_stmt (&new_body,
11763 gimple_build_assign (ctx->receiver_decl, t));
11766 if (offloaded)
11768 gimple_seq_add_seq (&new_body, tgt_body);
11769 new_body = maybe_catch_exception (new_body);
11771 else if (data_region)
11772 new_body = tgt_body;
11773 if (offloaded || data_region)
11775 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11776 gimple_omp_set_body (stmt, new_body);
11779 bind = gimple_build_bind (NULL, NULL,
11780 tgt_bind ? gimple_bind_block (tgt_bind)
11781 : NULL_TREE);
11782 gsi_replace (gsi_p, bind, true);
11783 gimple_bind_add_seq (bind, irlist);
11784 gimple_bind_add_seq (bind, ilist);
11785 gimple_bind_add_stmt (bind, stmt);
11786 gimple_bind_add_seq (bind, olist);
11787 gimple_bind_add_seq (bind, orlist);
11789 pop_gimplify_context (NULL);
11792 /* Expand code for an OpenMP teams directive. */
11794 static void
11795 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11797 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11798 push_gimplify_context ();
11800 tree block = make_node (BLOCK);
11801 gbind *bind = gimple_build_bind (NULL, NULL, block);
11802 gsi_replace (gsi_p, bind, true);
11803 gimple_seq bind_body = NULL;
11804 gimple_seq dlist = NULL;
11805 gimple_seq olist = NULL;
11807 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11808 OMP_CLAUSE_NUM_TEAMS);
11809 if (num_teams == NULL_TREE)
11810 num_teams = build_int_cst (unsigned_type_node, 0);
11811 else
11813 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11814 num_teams = fold_convert (unsigned_type_node, num_teams);
11815 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11817 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11818 OMP_CLAUSE_THREAD_LIMIT);
11819 if (thread_limit == NULL_TREE)
11820 thread_limit = build_int_cst (unsigned_type_node, 0);
11821 else
11823 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11824 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11825 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11826 fb_rvalue);
11829 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11830 &bind_body, &dlist, ctx, NULL);
11831 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11832 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11833 gimple_seq_add_stmt (&bind_body, teams_stmt);
11835 location_t loc = gimple_location (teams_stmt);
11836 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11837 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
11838 gimple_set_location (call, loc);
11839 gimple_seq_add_stmt (&bind_body, call);
11841 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11842 gimple_omp_set_body (teams_stmt, NULL);
11843 gimple_seq_add_seq (&bind_body, olist);
11844 gimple_seq_add_seq (&bind_body, dlist);
11845 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11846 gimple_bind_set_body (bind, bind_body);
11848 pop_gimplify_context (bind);
11850 gimple_bind_append_vars (bind, ctx->block_vars);
11851 BLOCK_VARS (block) = ctx->block_vars;
11852 if (BLOCK_VARS (block))
11853 TREE_USED (block) = 1;
11857 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11858 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11859 of OMP context, but with task_shared_vars set. */
11861 static tree
11862 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11863 void *data)
11865 tree t = *tp;
11867 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11868 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11869 return t;
11871 if (task_shared_vars
11872 && DECL_P (t)
11873 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11874 return t;
11876 /* If a global variable has been privatized, TREE_CONSTANT on
11877 ADDR_EXPR might be wrong. */
11878 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11879 recompute_tree_invariant_for_addr_expr (t);
11881 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11882 return NULL_TREE;
11885 static void
11886 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11888 gimple *stmt = gsi_stmt (*gsi_p);
11889 struct walk_stmt_info wi;
11890 gcall *call_stmt;
11892 if (gimple_has_location (stmt))
11893 input_location = gimple_location (stmt);
11895 if (task_shared_vars)
11896 memset (&wi, '\0', sizeof (wi));
11898 /* If we have issued syntax errors, avoid doing any heavy lifting.
11899 Just replace the OMP directives with a NOP to avoid
11900 confusing RTL expansion. */
11901 if (seen_error () && is_gimple_omp (stmt))
11903 gsi_replace (gsi_p, gimple_build_nop (), true);
11904 return;
11907 switch (gimple_code (stmt))
11909 case GIMPLE_COND:
11911 gcond *cond_stmt = as_a <gcond *> (stmt);
11912 if ((ctx || task_shared_vars)
11913 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11914 lower_omp_regimplify_p,
11915 ctx ? NULL : &wi, NULL)
11916 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11917 lower_omp_regimplify_p,
11918 ctx ? NULL : &wi, NULL)))
11919 gimple_regimplify_operands (cond_stmt, gsi_p);
11921 break;
11922 case GIMPLE_CATCH:
11923 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
11924 break;
11925 case GIMPLE_EH_FILTER:
11926 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
11927 break;
11928 case GIMPLE_TRY:
11929 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11930 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
11931 break;
11932 case GIMPLE_TRANSACTION:
11933 lower_omp (gimple_transaction_body_ptr (
11934 as_a <gtransaction *> (stmt)),
11935 ctx);
11936 break;
11937 case GIMPLE_BIND:
11938 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
11939 break;
11940 case GIMPLE_OMP_PARALLEL:
11941 case GIMPLE_OMP_TASK:
11942 ctx = maybe_lookup_ctx (stmt);
11943 gcc_assert (ctx);
11944 if (ctx->cancellable)
11945 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11946 lower_omp_taskreg (gsi_p, ctx);
11947 break;
11948 case GIMPLE_OMP_FOR:
11949 ctx = maybe_lookup_ctx (stmt);
11950 gcc_assert (ctx);
11951 if (ctx->cancellable)
11952 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11953 lower_omp_for (gsi_p, ctx);
11954 break;
11955 case GIMPLE_OMP_SECTIONS:
11956 ctx = maybe_lookup_ctx (stmt);
11957 gcc_assert (ctx);
11958 if (ctx->cancellable)
11959 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11960 lower_omp_sections (gsi_p, ctx);
11961 break;
11962 case GIMPLE_OMP_SINGLE:
11963 ctx = maybe_lookup_ctx (stmt);
11964 gcc_assert (ctx);
11965 lower_omp_single (gsi_p, ctx);
11966 break;
11967 case GIMPLE_OMP_MASTER:
11968 ctx = maybe_lookup_ctx (stmt);
11969 gcc_assert (ctx);
11970 lower_omp_master (gsi_p, ctx);
11971 break;
11972 case GIMPLE_OMP_TASKGROUP:
11973 ctx = maybe_lookup_ctx (stmt);
11974 gcc_assert (ctx);
11975 lower_omp_taskgroup (gsi_p, ctx);
11976 break;
11977 case GIMPLE_OMP_ORDERED:
11978 ctx = maybe_lookup_ctx (stmt);
11979 gcc_assert (ctx);
11980 lower_omp_ordered (gsi_p, ctx);
11981 break;
11982 case GIMPLE_OMP_CRITICAL:
11983 ctx = maybe_lookup_ctx (stmt);
11984 gcc_assert (ctx);
11985 lower_omp_critical (gsi_p, ctx);
11986 break;
11987 case GIMPLE_OMP_ATOMIC_LOAD:
11988 if ((ctx || task_shared_vars)
11989 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11990 as_a <gomp_atomic_load *> (stmt)),
11991 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11992 gimple_regimplify_operands (stmt, gsi_p);
11993 break;
11994 case GIMPLE_OMP_TARGET:
11995 ctx = maybe_lookup_ctx (stmt);
11996 gcc_assert (ctx);
11997 lower_omp_target (gsi_p, ctx);
11998 break;
11999 case GIMPLE_OMP_TEAMS:
12000 ctx = maybe_lookup_ctx (stmt);
12001 gcc_assert (ctx);
12002 lower_omp_teams (gsi_p, ctx);
12003 break;
12004 case GIMPLE_CALL:
12005 tree fndecl;
12006 call_stmt = as_a <gcall *> (stmt);
12007 fndecl = gimple_call_fndecl (call_stmt);
12008 if (fndecl
12009 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
12010 switch (DECL_FUNCTION_CODE (fndecl))
12012 case BUILT_IN_GOMP_BARRIER:
12013 if (ctx == NULL)
12014 break;
12015 /* FALLTHRU */
12016 case BUILT_IN_GOMP_CANCEL:
12017 case BUILT_IN_GOMP_CANCELLATION_POINT:
12018 omp_context *cctx;
12019 cctx = ctx;
12020 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
12021 cctx = cctx->outer;
12022 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
12023 if (!cctx->cancellable)
12025 if (DECL_FUNCTION_CODE (fndecl)
12026 == BUILT_IN_GOMP_CANCELLATION_POINT)
12028 stmt = gimple_build_nop ();
12029 gsi_replace (gsi_p, stmt, false);
12031 break;
12033 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
12035 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
12036 gimple_call_set_fndecl (call_stmt, fndecl);
12037 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
12039 tree lhs;
12040 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
12041 gimple_call_set_lhs (call_stmt, lhs);
12042 tree fallthru_label;
12043 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
12044 gimple *g;
12045 g = gimple_build_label (fallthru_label);
12046 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
12047 g = gimple_build_cond (NE_EXPR, lhs,
12048 fold_convert (TREE_TYPE (lhs),
12049 boolean_false_node),
12050 cctx->cancel_label, fallthru_label);
12051 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
12052 break;
12053 default:
12054 break;
12056 /* FALLTHRU */
12057 default:
12058 if ((ctx || task_shared_vars)
12059 && walk_gimple_op (stmt, lower_omp_regimplify_p,
12060 ctx ? NULL : &wi))
12062 /* Just remove clobbers, this should happen only if we have
12063 "privatized" local addressable variables in SIMD regions,
12064 the clobber isn't needed in that case and gimplifying address
12065 of the ARRAY_REF into a pointer and creating MEM_REF based
12066 clobber would create worse code than we get with the clobber
12067 dropped. */
12068 if (gimple_clobber_p (stmt))
12070 gsi_replace (gsi_p, gimple_build_nop (), true);
12071 break;
12073 gimple_regimplify_operands (stmt, gsi_p);
12075 break;
12079 static void
12080 lower_omp (gimple_seq *body, omp_context *ctx)
12082 location_t saved_location = input_location;
12083 gimple_stmt_iterator gsi;
12084 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
12085 lower_omp_1 (&gsi, ctx);
12086 /* During gimplification, we haven't folded statments inside offloading
12087 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
12088 if (target_nesting_level || taskreg_nesting_level)
12089 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
12090 fold_stmt (&gsi);
12091 input_location = saved_location;
12094 /* Main entry point. */
12096 static unsigned int
12097 execute_lower_omp (void)
12099 gimple_seq body;
12100 int i;
12101 omp_context *ctx;
12103 /* This pass always runs, to provide PROP_gimple_lomp.
12104 But often, there is nothing to do. */
12105 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
12106 && flag_openmp_simd == 0)
12107 return 0;
12109 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
12110 delete_omp_context);
12112 body = gimple_body (current_function_decl);
12113 scan_omp (&body, NULL);
12114 gcc_assert (taskreg_nesting_level == 0);
12115 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
12116 finish_taskreg_scan (ctx);
12117 taskreg_contexts.release ();
12119 if (all_contexts->root)
12121 if (task_shared_vars)
12122 push_gimplify_context ();
12123 lower_omp (&body, NULL);
12124 if (task_shared_vars)
12125 pop_gimplify_context (NULL);
12128 if (all_contexts)
12130 splay_tree_delete (all_contexts);
12131 all_contexts = NULL;
12133 BITMAP_FREE (task_shared_vars);
12134 return 0;
12137 namespace {
12139 const pass_data pass_data_lower_omp =
12141 GIMPLE_PASS, /* type */
12142 "omplower", /* name */
12143 OPTGROUP_NONE, /* optinfo_flags */
12144 TV_NONE, /* tv_id */
12145 PROP_gimple_any, /* properties_required */
12146 PROP_gimple_lomp, /* properties_provided */
12147 0, /* properties_destroyed */
12148 0, /* todo_flags_start */
12149 0, /* todo_flags_finish */
12152 class pass_lower_omp : public gimple_opt_pass
12154 public:
12155 pass_lower_omp (gcc::context *ctxt)
12156 : gimple_opt_pass (pass_data_lower_omp, ctxt)
12159 /* opt_pass methods: */
12160 virtual unsigned int execute (function *) { return execute_lower_omp (); }
12162 }; // class pass_lower_omp
12164 } // anon namespace
12166 gimple_opt_pass *
12167 make_pass_lower_omp (gcc::context *ctxt)
12169 return new pass_lower_omp (ctxt);
12172 /* The following is a utility to diagnose structured block violations.
12173 It is not part of the "omplower" pass, as that's invoked too late. It
12174 should be invoked by the respective front ends after gimplification. */
12176 static splay_tree all_labels;
12178 /* Check for mismatched contexts and generate an error if needed. Return
12179 true if an error is detected. */
12181 static bool
12182 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
12183 gimple *branch_ctx, gimple *label_ctx)
12185 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
12186 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
12188 if (label_ctx == branch_ctx)
12189 return false;
12191 const char* kind = NULL;
12193 if (flag_cilkplus)
12195 if ((branch_ctx
12196 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12197 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12198 || (label_ctx
12199 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12200 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12201 kind = "Cilk Plus";
12203 if (flag_openacc)
12205 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
12206 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
12208 gcc_checking_assert (kind == NULL);
12209 kind = "OpenACC";
12212 if (kind == NULL)
12214 gcc_checking_assert (flag_openmp);
12215 kind = "OpenMP";
12219 Previously we kept track of the label's entire context in diagnose_sb_[12]
12220 so we could traverse it and issue a correct "exit" or "enter" error
12221 message upon a structured block violation.
12223 We built the context by building a list with tree_cons'ing, but there is
12224 no easy counterpart in gimple tuples. It seems like far too much work
12225 for issuing exit/enter error messages. If someone really misses the
12226 distinct error message... patches welcome.
12229 #if 0
12230 /* Try to avoid confusing the user by producing and error message
12231 with correct "exit" or "enter" verbiage. We prefer "exit"
12232 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12233 if (branch_ctx == NULL)
12234 exit_p = false;
12235 else
12237 while (label_ctx)
12239 if (TREE_VALUE (label_ctx) == branch_ctx)
12241 exit_p = false;
12242 break;
12244 label_ctx = TREE_CHAIN (label_ctx);
12248 if (exit_p)
12249 error ("invalid exit from %s structured block", kind);
12250 else
12251 error ("invalid entry to %s structured block", kind);
12252 #endif
12254 /* If it's obvious we have an invalid entry, be specific about the error. */
12255 if (branch_ctx == NULL)
12256 error ("invalid entry to %s structured block", kind);
12257 else
12259 /* Otherwise, be vague and lazy, but efficient. */
12260 error ("invalid branch to/from %s structured block", kind);
12263 gsi_replace (gsi_p, gimple_build_nop (), false);
12264 return true;
12267 /* Pass 1: Create a minimal tree of structured blocks, and record
12268 where each label is found. */
12270 static tree
12271 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12272 struct walk_stmt_info *wi)
12274 gimple *context = (gimple *) wi->info;
12275 gimple *inner_context;
12276 gimple *stmt = gsi_stmt (*gsi_p);
12278 *handled_ops_p = true;
12280 switch (gimple_code (stmt))
12282 WALK_SUBSTMTS;
12284 case GIMPLE_OMP_PARALLEL:
12285 case GIMPLE_OMP_TASK:
12286 case GIMPLE_OMP_SECTIONS:
12287 case GIMPLE_OMP_SINGLE:
12288 case GIMPLE_OMP_SECTION:
12289 case GIMPLE_OMP_MASTER:
12290 case GIMPLE_OMP_ORDERED:
12291 case GIMPLE_OMP_CRITICAL:
12292 case GIMPLE_OMP_TARGET:
12293 case GIMPLE_OMP_TEAMS:
12294 case GIMPLE_OMP_TASKGROUP:
12295 /* The minimal context here is just the current OMP construct. */
12296 inner_context = stmt;
12297 wi->info = inner_context;
12298 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12299 wi->info = context;
12300 break;
12302 case GIMPLE_OMP_FOR:
12303 inner_context = stmt;
12304 wi->info = inner_context;
12305 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12306 walk them. */
12307 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12308 diagnose_sb_1, NULL, wi);
12309 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12310 wi->info = context;
12311 break;
12313 case GIMPLE_LABEL:
12314 splay_tree_insert (all_labels,
12315 (splay_tree_key) gimple_label_label (
12316 as_a <glabel *> (stmt)),
12317 (splay_tree_value) context);
12318 break;
12320 default:
12321 break;
12324 return NULL_TREE;
12327 /* Pass 2: Check each branch and see if its context differs from that of
12328 the destination label's context. */
12330 static tree
12331 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12332 struct walk_stmt_info *wi)
12334 gimple *context = (gimple *) wi->info;
12335 splay_tree_node n;
12336 gimple *stmt = gsi_stmt (*gsi_p);
12338 *handled_ops_p = true;
12340 switch (gimple_code (stmt))
12342 WALK_SUBSTMTS;
12344 case GIMPLE_OMP_PARALLEL:
12345 case GIMPLE_OMP_TASK:
12346 case GIMPLE_OMP_SECTIONS:
12347 case GIMPLE_OMP_SINGLE:
12348 case GIMPLE_OMP_SECTION:
12349 case GIMPLE_OMP_MASTER:
12350 case GIMPLE_OMP_ORDERED:
12351 case GIMPLE_OMP_CRITICAL:
12352 case GIMPLE_OMP_TARGET:
12353 case GIMPLE_OMP_TEAMS:
12354 case GIMPLE_OMP_TASKGROUP:
12355 wi->info = stmt;
12356 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12357 wi->info = context;
12358 break;
12360 case GIMPLE_OMP_FOR:
12361 wi->info = stmt;
12362 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12363 walk them. */
12364 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12365 diagnose_sb_2, NULL, wi);
12366 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12367 wi->info = context;
12368 break;
12370 case GIMPLE_COND:
12372 gcond *cond_stmt = as_a <gcond *> (stmt);
12373 tree lab = gimple_cond_true_label (cond_stmt);
12374 if (lab)
12376 n = splay_tree_lookup (all_labels,
12377 (splay_tree_key) lab);
12378 diagnose_sb_0 (gsi_p, context,
12379 n ? (gimple *) n->value : NULL);
12381 lab = gimple_cond_false_label (cond_stmt);
12382 if (lab)
12384 n = splay_tree_lookup (all_labels,
12385 (splay_tree_key) lab);
12386 diagnose_sb_0 (gsi_p, context,
12387 n ? (gimple *) n->value : NULL);
12390 break;
12392 case GIMPLE_GOTO:
12394 tree lab = gimple_goto_dest (stmt);
12395 if (TREE_CODE (lab) != LABEL_DECL)
12396 break;
12398 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12399 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
12401 break;
12403 case GIMPLE_SWITCH:
12405 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12406 unsigned int i;
12407 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12409 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12410 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12411 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
12412 break;
12415 break;
12417 case GIMPLE_RETURN:
12418 diagnose_sb_0 (gsi_p, context, NULL);
12419 break;
12421 default:
12422 break;
12425 return NULL_TREE;
12428 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12429 GIMPLE_* codes. */
12430 bool
12431 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12432 int *region_idx)
12434 gimple *last = last_stmt (bb);
12435 enum gimple_code code = gimple_code (last);
12436 struct omp_region *cur_region = *region;
12437 bool fallthru = false;
12439 switch (code)
12441 case GIMPLE_OMP_PARALLEL:
12442 case GIMPLE_OMP_TASK:
12443 case GIMPLE_OMP_FOR:
12444 case GIMPLE_OMP_SINGLE:
12445 case GIMPLE_OMP_TEAMS:
12446 case GIMPLE_OMP_MASTER:
12447 case GIMPLE_OMP_TASKGROUP:
12448 case GIMPLE_OMP_ORDERED:
12449 case GIMPLE_OMP_CRITICAL:
12450 case GIMPLE_OMP_SECTION:
12451 cur_region = new_omp_region (bb, code, cur_region);
12452 fallthru = true;
12453 break;
12455 case GIMPLE_OMP_TARGET:
12456 cur_region = new_omp_region (bb, code, cur_region);
12457 fallthru = true;
12458 switch (gimple_omp_target_kind (last))
12460 case GF_OMP_TARGET_KIND_REGION:
12461 case GF_OMP_TARGET_KIND_DATA:
12462 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12463 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12464 case GF_OMP_TARGET_KIND_OACC_DATA:
12465 break;
12466 case GF_OMP_TARGET_KIND_UPDATE:
12467 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12468 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12469 cur_region = cur_region->outer;
12470 break;
12471 default:
12472 gcc_unreachable ();
12474 break;
12476 case GIMPLE_OMP_SECTIONS:
12477 cur_region = new_omp_region (bb, code, cur_region);
12478 fallthru = true;
12479 break;
12481 case GIMPLE_OMP_SECTIONS_SWITCH:
12482 fallthru = false;
12483 break;
12485 case GIMPLE_OMP_ATOMIC_LOAD:
12486 case GIMPLE_OMP_ATOMIC_STORE:
12487 fallthru = true;
12488 break;
12490 case GIMPLE_OMP_RETURN:
12491 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12492 somewhere other than the next block. This will be
12493 created later. */
12494 cur_region->exit = bb;
12495 if (cur_region->type == GIMPLE_OMP_TASK)
12496 /* Add an edge corresponding to not scheduling the task
12497 immediately. */
12498 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
12499 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12500 cur_region = cur_region->outer;
12501 break;
12503 case GIMPLE_OMP_CONTINUE:
12504 cur_region->cont = bb;
12505 switch (cur_region->type)
12507 case GIMPLE_OMP_FOR:
12508 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12509 succs edges as abnormal to prevent splitting
12510 them. */
12511 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12512 /* Make the loopback edge. */
12513 make_edge (bb, single_succ (cur_region->entry),
12514 EDGE_ABNORMAL);
12516 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12517 corresponds to the case that the body of the loop
12518 is not executed at all. */
12519 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12520 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12521 fallthru = false;
12522 break;
12524 case GIMPLE_OMP_SECTIONS:
12525 /* Wire up the edges into and out of the nested sections. */
12527 basic_block switch_bb = single_succ (cur_region->entry);
12529 struct omp_region *i;
12530 for (i = cur_region->inner; i ; i = i->next)
12532 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12533 make_edge (switch_bb, i->entry, 0);
12534 make_edge (i->exit, bb, EDGE_FALLTHRU);
12537 /* Make the loopback edge to the block with
12538 GIMPLE_OMP_SECTIONS_SWITCH. */
12539 make_edge (bb, switch_bb, 0);
12541 /* Make the edge from the switch to exit. */
12542 make_edge (switch_bb, bb->next_bb, 0);
12543 fallthru = false;
12545 break;
12547 case GIMPLE_OMP_TASK:
12548 fallthru = true;
12549 break;
12551 default:
12552 gcc_unreachable ();
12554 break;
12556 default:
12557 gcc_unreachable ();
12560 if (*region != cur_region)
12562 *region = cur_region;
12563 if (cur_region)
12564 *region_idx = cur_region->entry->index;
12565 else
12566 *region_idx = 0;
12569 return fallthru;
12572 static unsigned int
12573 diagnose_omp_structured_block_errors (void)
12575 struct walk_stmt_info wi;
12576 gimple_seq body = gimple_body (current_function_decl);
12578 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12580 memset (&wi, 0, sizeof (wi));
12581 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12583 memset (&wi, 0, sizeof (wi));
12584 wi.want_locations = true;
12585 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12587 gimple_set_body (current_function_decl, body);
12589 splay_tree_delete (all_labels);
12590 all_labels = NULL;
12592 return 0;
12595 namespace {
12597 const pass_data pass_data_diagnose_omp_blocks =
12599 GIMPLE_PASS, /* type */
12600 "*diagnose_omp_blocks", /* name */
12601 OPTGROUP_NONE, /* optinfo_flags */
12602 TV_NONE, /* tv_id */
12603 PROP_gimple_any, /* properties_required */
12604 0, /* properties_provided */
12605 0, /* properties_destroyed */
12606 0, /* todo_flags_start */
12607 0, /* todo_flags_finish */
12610 class pass_diagnose_omp_blocks : public gimple_opt_pass
12612 public:
12613 pass_diagnose_omp_blocks (gcc::context *ctxt)
12614 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12617 /* opt_pass methods: */
12618 virtual bool gate (function *)
12620 return flag_cilkplus || flag_openacc || flag_openmp;
12622 virtual unsigned int execute (function *)
12624 return diagnose_omp_structured_block_errors ();
12627 }; // class pass_diagnose_omp_blocks
12629 } // anon namespace
12631 gimple_opt_pass *
12632 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12634 return new pass_diagnose_omp_blocks (ctxt);
12637 /* SIMD clone supporting code. */
12639 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12640 of arguments to reserve space for. */
12642 static struct cgraph_simd_clone *
12643 simd_clone_struct_alloc (int nargs)
12645 struct cgraph_simd_clone *clone_info;
12646 size_t len = (sizeof (struct cgraph_simd_clone)
12647 + nargs * sizeof (struct cgraph_simd_clone_arg));
12648 clone_info = (struct cgraph_simd_clone *)
12649 ggc_internal_cleared_alloc (len);
12650 return clone_info;
12653 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12655 static inline void
12656 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12657 struct cgraph_simd_clone *from)
12659 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12660 + ((from->nargs - from->inbranch)
12661 * sizeof (struct cgraph_simd_clone_arg))));
12664 /* Return vector of parameter types of function FNDECL. This uses
12665 TYPE_ARG_TYPES if available, otherwise falls back to types of
12666 DECL_ARGUMENTS types. */
12668 vec<tree>
12669 simd_clone_vector_of_formal_parm_types (tree fndecl)
12671 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12672 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12673 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12674 unsigned int i;
12675 tree arg;
12676 FOR_EACH_VEC_ELT (args, i, arg)
12677 args[i] = TREE_TYPE (args[i]);
12678 return args;
12681 /* Given a simd function in NODE, extract the simd specific
12682 information from the OMP clauses passed in CLAUSES, and return
12683 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12684 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12685 otherwise set to FALSE. */
12687 static struct cgraph_simd_clone *
12688 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12689 bool *inbranch_specified)
12691 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12692 tree t;
12693 int n;
12694 *inbranch_specified = false;
12696 n = args.length ();
12697 if (n > 0 && args.last () == void_type_node)
12698 n--;
12700 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12701 be cloned have a distinctive artificial label in addition to "omp
12702 declare simd". */
12703 bool cilk_clone
12704 = (flag_cilkplus
12705 && lookup_attribute ("cilk simd function",
12706 DECL_ATTRIBUTES (node->decl)));
12708 /* Allocate one more than needed just in case this is an in-branch
12709 clone which will require a mask argument. */
12710 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12711 clone_info->nargs = n;
12712 clone_info->cilk_elemental = cilk_clone;
12714 if (!clauses)
12716 args.release ();
12717 return clone_info;
12719 clauses = TREE_VALUE (clauses);
12720 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12721 return clone_info;
12723 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12725 switch (OMP_CLAUSE_CODE (t))
12727 case OMP_CLAUSE_INBRANCH:
12728 clone_info->inbranch = 1;
12729 *inbranch_specified = true;
12730 break;
12731 case OMP_CLAUSE_NOTINBRANCH:
12732 clone_info->inbranch = 0;
12733 *inbranch_specified = true;
12734 break;
12735 case OMP_CLAUSE_SIMDLEN:
12736 clone_info->simdlen
12737 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12738 break;
12739 case OMP_CLAUSE_LINEAR:
12741 tree decl = OMP_CLAUSE_DECL (t);
12742 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12743 int argno = TREE_INT_CST_LOW (decl);
12744 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12746 clone_info->args[argno].arg_type
12747 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12748 clone_info->args[argno].linear_step = tree_to_shwi (step);
12749 gcc_assert (clone_info->args[argno].linear_step >= 0
12750 && clone_info->args[argno].linear_step < n);
12752 else
12754 if (POINTER_TYPE_P (args[argno]))
12755 step = fold_convert (ssizetype, step);
12756 if (!tree_fits_shwi_p (step))
12758 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12759 "ignoring large linear step");
12760 args.release ();
12761 return NULL;
12763 else if (integer_zerop (step))
12765 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12766 "ignoring zero linear step");
12767 args.release ();
12768 return NULL;
12770 else
12772 clone_info->args[argno].arg_type
12773 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12774 clone_info->args[argno].linear_step = tree_to_shwi (step);
12777 break;
12779 case OMP_CLAUSE_UNIFORM:
12781 tree decl = OMP_CLAUSE_DECL (t);
12782 int argno = tree_to_uhwi (decl);
12783 clone_info->args[argno].arg_type
12784 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12785 break;
12787 case OMP_CLAUSE_ALIGNED:
12789 tree decl = OMP_CLAUSE_DECL (t);
12790 int argno = tree_to_uhwi (decl);
12791 clone_info->args[argno].alignment
12792 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12793 break;
12795 default:
12796 break;
12799 args.release ();
12800 return clone_info;
12803 /* Given a SIMD clone in NODE, calculate the characteristic data
12804 type and return the coresponding type. The characteristic data
12805 type is computed as described in the Intel Vector ABI. */
12807 static tree
12808 simd_clone_compute_base_data_type (struct cgraph_node *node,
12809 struct cgraph_simd_clone *clone_info)
12811 tree type = integer_type_node;
12812 tree fndecl = node->decl;
12814 /* a) For non-void function, the characteristic data type is the
12815 return type. */
12816 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12817 type = TREE_TYPE (TREE_TYPE (fndecl));
12819 /* b) If the function has any non-uniform, non-linear parameters,
12820 then the characteristic data type is the type of the first
12821 such parameter. */
12822 else
12824 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12825 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12826 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12828 type = map[i];
12829 break;
12831 map.release ();
12834 /* c) If the characteristic data type determined by a) or b) above
12835 is struct, union, or class type which is pass-by-value (except
12836 for the type that maps to the built-in complex data type), the
12837 characteristic data type is int. */
12838 if (RECORD_OR_UNION_TYPE_P (type)
12839 && !aggregate_value_p (type, NULL)
12840 && TREE_CODE (type) != COMPLEX_TYPE)
12841 return integer_type_node;
12843 /* d) If none of the above three classes is applicable, the
12844 characteristic data type is int. */
12846 return type;
12848 /* e) For Intel Xeon Phi native and offload compilation, if the
12849 resulting characteristic data type is 8-bit or 16-bit integer
12850 data type, the characteristic data type is int. */
12851 /* Well, we don't handle Xeon Phi yet. */
12854 static tree
12855 simd_clone_mangle (struct cgraph_node *node,
12856 struct cgraph_simd_clone *clone_info)
12858 char vecsize_mangle = clone_info->vecsize_mangle;
12859 char mask = clone_info->inbranch ? 'M' : 'N';
12860 unsigned int simdlen = clone_info->simdlen;
12861 unsigned int n;
12862 pretty_printer pp;
12864 gcc_assert (vecsize_mangle && simdlen);
12866 pp_string (&pp, "_ZGV");
12867 pp_character (&pp, vecsize_mangle);
12868 pp_character (&pp, mask);
12869 pp_decimal_int (&pp, simdlen);
12871 for (n = 0; n < clone_info->nargs; ++n)
12873 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12875 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12876 pp_character (&pp, 'u');
12877 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12879 gcc_assert (arg.linear_step != 0);
12880 pp_character (&pp, 'l');
12881 if (arg.linear_step > 1)
12882 pp_unsigned_wide_integer (&pp, arg.linear_step);
12883 else if (arg.linear_step < 0)
12885 pp_character (&pp, 'n');
12886 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12887 arg.linear_step));
12890 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12892 pp_character (&pp, 's');
12893 pp_unsigned_wide_integer (&pp, arg.linear_step);
12895 else
12896 pp_character (&pp, 'v');
12897 if (arg.alignment)
12899 pp_character (&pp, 'a');
12900 pp_decimal_int (&pp, arg.alignment);
12904 pp_underscore (&pp);
12905 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12906 if (*str == '*')
12907 ++str;
12908 pp_string (&pp, str);
12909 str = pp_formatted_text (&pp);
12911 /* If there already is a SIMD clone with the same mangled name, don't
12912 add another one. This can happen e.g. for
12913 #pragma omp declare simd
12914 #pragma omp declare simd simdlen(8)
12915 int foo (int, int);
12916 if the simdlen is assumed to be 8 for the first one, etc. */
12917 for (struct cgraph_node *clone = node->simd_clones; clone;
12918 clone = clone->simdclone->next_clone)
12919 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12920 str) == 0)
12921 return NULL_TREE;
12923 return get_identifier (str);
12926 /* Create a simd clone of OLD_NODE and return it. */
12928 static struct cgraph_node *
12929 simd_clone_create (struct cgraph_node *old_node)
12931 struct cgraph_node *new_node;
12932 if (old_node->definition)
12934 if (!old_node->has_gimple_body_p ())
12935 return NULL;
12936 old_node->get_body ();
12937 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12938 false, NULL, NULL,
12939 "simdclone");
12941 else
12943 tree old_decl = old_node->decl;
12944 tree new_decl = copy_node (old_node->decl);
12945 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12946 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12947 SET_DECL_RTL (new_decl, NULL);
12948 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12949 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
12950 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
12951 symtab->call_cgraph_insertion_hooks (new_node);
12953 if (new_node == NULL)
12954 return new_node;
12956 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12958 /* The function cgraph_function_versioning () will force the new
12959 symbol local. Undo this, and inherit external visability from
12960 the old node. */
12961 new_node->local.local = old_node->local.local;
12962 new_node->externally_visible = old_node->externally_visible;
12964 return new_node;
12967 /* Adjust the return type of the given function to its appropriate
12968 vector counterpart. Returns a simd array to be used throughout the
12969 function as a return value. */
12971 static tree
12972 simd_clone_adjust_return_type (struct cgraph_node *node)
12974 tree fndecl = node->decl;
12975 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12976 unsigned int veclen;
12977 tree t;
12979 /* Adjust the function return type. */
12980 if (orig_rettype == void_type_node)
12981 return NULL_TREE;
12982 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
12983 t = TREE_TYPE (TREE_TYPE (fndecl));
12984 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
12985 veclen = node->simdclone->vecsize_int;
12986 else
12987 veclen = node->simdclone->vecsize_float;
12988 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
12989 if (veclen > node->simdclone->simdlen)
12990 veclen = node->simdclone->simdlen;
12991 if (POINTER_TYPE_P (t))
12992 t = pointer_sized_int_node;
12993 if (veclen == node->simdclone->simdlen)
12994 t = build_vector_type (t, node->simdclone->simdlen);
12995 else
12997 t = build_vector_type (t, veclen);
12998 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
13000 TREE_TYPE (TREE_TYPE (fndecl)) = t;
13001 if (!node->definition)
13002 return NULL_TREE;
13004 t = DECL_RESULT (fndecl);
13005 /* Adjust the DECL_RESULT. */
13006 gcc_assert (TREE_TYPE (t) != void_type_node);
13007 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
13008 relayout_decl (t);
13010 tree atype = build_array_type_nelts (orig_rettype,
13011 node->simdclone->simdlen);
13012 if (veclen != node->simdclone->simdlen)
13013 return build1 (VIEW_CONVERT_EXPR, atype, t);
13015 /* Set up a SIMD array to use as the return value. */
13016 tree retval = create_tmp_var_raw (atype, "retval");
13017 gimple_add_tmp_var (retval);
13018 return retval;
13021 /* Each vector argument has a corresponding array to be used locally
13022 as part of the eventual loop. Create such temporary array and
13023 return it.
13025 PREFIX is the prefix to be used for the temporary.
13027 TYPE is the inner element type.
13029 SIMDLEN is the number of elements. */
13031 static tree
13032 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
13034 tree atype = build_array_type_nelts (type, simdlen);
13035 tree avar = create_tmp_var_raw (atype, prefix);
13036 gimple_add_tmp_var (avar);
13037 return avar;
13040 /* Modify the function argument types to their corresponding vector
13041 counterparts if appropriate. Also, create one array for each simd
13042 argument to be used locally when using the function arguments as
13043 part of the loop.
13045 NODE is the function whose arguments are to be adjusted.
13047 Returns an adjustment vector that will be filled describing how the
13048 argument types will be adjusted. */
13050 static ipa_parm_adjustment_vec
13051 simd_clone_adjust_argument_types (struct cgraph_node *node)
13053 vec<tree> args;
13054 ipa_parm_adjustment_vec adjustments;
13056 if (node->definition)
13057 args = ipa_get_vector_of_formal_parms (node->decl);
13058 else
13059 args = simd_clone_vector_of_formal_parm_types (node->decl);
13060 adjustments.create (args.length ());
13061 unsigned i, j, veclen;
13062 struct ipa_parm_adjustment adj;
13063 for (i = 0; i < node->simdclone->nargs; ++i)
13065 memset (&adj, 0, sizeof (adj));
13066 tree parm = args[i];
13067 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
13068 adj.base_index = i;
13069 adj.base = parm;
13071 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
13072 node->simdclone->args[i].orig_type = parm_type;
13074 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
13076 /* No adjustment necessary for scalar arguments. */
13077 adj.op = IPA_PARM_OP_COPY;
13079 else
13081 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
13082 veclen = node->simdclone->vecsize_int;
13083 else
13084 veclen = node->simdclone->vecsize_float;
13085 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
13086 if (veclen > node->simdclone->simdlen)
13087 veclen = node->simdclone->simdlen;
13088 adj.arg_prefix = "simd";
13089 if (POINTER_TYPE_P (parm_type))
13090 adj.type = build_vector_type (pointer_sized_int_node, veclen);
13091 else
13092 adj.type = build_vector_type (parm_type, veclen);
13093 node->simdclone->args[i].vector_type = adj.type;
13094 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
13096 adjustments.safe_push (adj);
13097 if (j == veclen)
13099 memset (&adj, 0, sizeof (adj));
13100 adj.op = IPA_PARM_OP_NEW;
13101 adj.arg_prefix = "simd";
13102 adj.base_index = i;
13103 adj.type = node->simdclone->args[i].vector_type;
13107 if (node->definition)
13108 node->simdclone->args[i].simd_array
13109 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
13110 parm_type, node->simdclone->simdlen);
13112 adjustments.safe_push (adj);
13115 if (node->simdclone->inbranch)
13117 tree base_type
13118 = simd_clone_compute_base_data_type (node->simdclone->origin,
13119 node->simdclone);
13121 memset (&adj, 0, sizeof (adj));
13122 adj.op = IPA_PARM_OP_NEW;
13123 adj.arg_prefix = "mask";
13125 adj.base_index = i;
13126 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
13127 veclen = node->simdclone->vecsize_int;
13128 else
13129 veclen = node->simdclone->vecsize_float;
13130 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
13131 if (veclen > node->simdclone->simdlen)
13132 veclen = node->simdclone->simdlen;
13133 if (POINTER_TYPE_P (base_type))
13134 adj.type = build_vector_type (pointer_sized_int_node, veclen);
13135 else
13136 adj.type = build_vector_type (base_type, veclen);
13137 adjustments.safe_push (adj);
13139 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
13140 adjustments.safe_push (adj);
13142 /* We have previously allocated one extra entry for the mask. Use
13143 it and fill it. */
13144 struct cgraph_simd_clone *sc = node->simdclone;
13145 sc->nargs++;
13146 if (node->definition)
13148 sc->args[i].orig_arg
13149 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
13150 sc->args[i].simd_array
13151 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
13153 sc->args[i].orig_type = base_type;
13154 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
13157 if (node->definition)
13158 ipa_modify_formal_parameters (node->decl, adjustments);
13159 else
13161 tree new_arg_types = NULL_TREE, new_reversed;
13162 bool last_parm_void = false;
13163 if (args.length () > 0 && args.last () == void_type_node)
13164 last_parm_void = true;
13166 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
13167 j = adjustments.length ();
13168 for (i = 0; i < j; i++)
13170 struct ipa_parm_adjustment *adj = &adjustments[i];
13171 tree ptype;
13172 if (adj->op == IPA_PARM_OP_COPY)
13173 ptype = args[adj->base_index];
13174 else
13175 ptype = adj->type;
13176 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
13178 new_reversed = nreverse (new_arg_types);
13179 if (last_parm_void)
13181 if (new_reversed)
13182 TREE_CHAIN (new_arg_types) = void_list_node;
13183 else
13184 new_reversed = void_list_node;
13187 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
13188 TYPE_ARG_TYPES (new_type) = new_reversed;
13189 TREE_TYPE (node->decl) = new_type;
13191 adjustments.release ();
13193 args.release ();
13194 return adjustments;
13197 /* Initialize and copy the function arguments in NODE to their
13198 corresponding local simd arrays. Returns a fresh gimple_seq with
13199 the instruction sequence generated. */
13201 static gimple_seq
13202 simd_clone_init_simd_arrays (struct cgraph_node *node,
13203 ipa_parm_adjustment_vec adjustments)
13205 gimple_seq seq = NULL;
13206 unsigned i = 0, j = 0, k;
13208 for (tree arg = DECL_ARGUMENTS (node->decl);
13209 arg;
13210 arg = DECL_CHAIN (arg), i++, j++)
13212 if (adjustments[j].op == IPA_PARM_OP_COPY)
13213 continue;
13215 node->simdclone->args[i].vector_arg = arg;
13217 tree array = node->simdclone->args[i].simd_array;
13218 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13220 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13221 tree ptr = build_fold_addr_expr (array);
13222 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13223 build_int_cst (ptype, 0));
13224 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13225 gimplify_and_add (t, &seq);
13227 else
13229 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13230 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13231 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13233 tree ptr = build_fold_addr_expr (array);
13234 int elemsize;
13235 if (k)
13237 arg = DECL_CHAIN (arg);
13238 j++;
13240 elemsize
13241 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13242 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13243 build_int_cst (ptype, k * elemsize));
13244 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13245 gimplify_and_add (t, &seq);
13249 return seq;
13252 /* Callback info for ipa_simd_modify_stmt_ops below. */
13254 struct modify_stmt_info {
13255 ipa_parm_adjustment_vec adjustments;
13256 gimple *stmt;
13257 /* True if the parent statement was modified by
13258 ipa_simd_modify_stmt_ops. */
13259 bool modified;
13262 /* Callback for walk_gimple_op.
13264 Adjust operands from a given statement as specified in the
13265 adjustments vector in the callback data. */
13267 static tree
13268 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13270 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13271 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13272 tree *orig_tp = tp;
13273 if (TREE_CODE (*tp) == ADDR_EXPR)
13274 tp = &TREE_OPERAND (*tp, 0);
13275 struct ipa_parm_adjustment *cand = NULL;
13276 if (TREE_CODE (*tp) == PARM_DECL)
13277 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13278 else
13280 if (TYPE_P (*tp))
13281 *walk_subtrees = 0;
13284 tree repl = NULL_TREE;
13285 if (cand)
13286 repl = unshare_expr (cand->new_decl);
13287 else
13289 if (tp != orig_tp)
13291 *walk_subtrees = 0;
13292 bool modified = info->modified;
13293 info->modified = false;
13294 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13295 if (!info->modified)
13297 info->modified = modified;
13298 return NULL_TREE;
13300 info->modified = modified;
13301 repl = *tp;
13303 else
13304 return NULL_TREE;
13307 if (tp != orig_tp)
13309 repl = build_fold_addr_expr (repl);
13310 gimple *stmt;
13311 if (is_gimple_debug (info->stmt))
13313 tree vexpr = make_node (DEBUG_EXPR_DECL);
13314 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13315 DECL_ARTIFICIAL (vexpr) = 1;
13316 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13317 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13318 repl = vexpr;
13320 else
13322 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13323 repl = gimple_assign_lhs (stmt);
13325 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13326 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13327 *orig_tp = repl;
13329 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13331 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13332 *tp = vce;
13334 else
13335 *tp = repl;
13337 info->modified = true;
13338 return NULL_TREE;
13341 /* Traverse the function body and perform all modifications as
13342 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13343 modified such that the replacement/reduction value will now be an
13344 offset into the corresponding simd_array.
13346 This function will replace all function argument uses with their
13347 corresponding simd array elements, and ajust the return values
13348 accordingly. */
13350 static void
13351 ipa_simd_modify_function_body (struct cgraph_node *node,
13352 ipa_parm_adjustment_vec adjustments,
13353 tree retval_array, tree iter)
13355 basic_block bb;
13356 unsigned int i, j, l;
13358 /* Re-use the adjustments array, but this time use it to replace
13359 every function argument use to an offset into the corresponding
13360 simd_array. */
13361 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13363 if (!node->simdclone->args[i].vector_arg)
13364 continue;
13366 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13367 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13368 adjustments[j].new_decl
13369 = build4 (ARRAY_REF,
13370 basetype,
13371 node->simdclone->args[i].simd_array,
13372 iter,
13373 NULL_TREE, NULL_TREE);
13374 if (adjustments[j].op == IPA_PARM_OP_NONE
13375 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13376 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13379 l = adjustments.length ();
13380 for (i = 1; i < num_ssa_names; i++)
13382 tree name = ssa_name (i);
13383 if (name
13384 && SSA_NAME_VAR (name)
13385 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13387 for (j = 0; j < l; j++)
13388 if (SSA_NAME_VAR (name) == adjustments[j].base
13389 && adjustments[j].new_decl)
13391 tree base_var;
13392 if (adjustments[j].new_ssa_base == NULL_TREE)
13394 base_var
13395 = copy_var_decl (adjustments[j].base,
13396 DECL_NAME (adjustments[j].base),
13397 TREE_TYPE (adjustments[j].base));
13398 adjustments[j].new_ssa_base = base_var;
13400 else
13401 base_var = adjustments[j].new_ssa_base;
13402 if (SSA_NAME_IS_DEFAULT_DEF (name))
13404 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13405 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13406 tree new_decl = unshare_expr (adjustments[j].new_decl);
13407 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13408 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13409 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13410 gimple *stmt = gimple_build_assign (name, new_decl);
13411 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13413 else
13414 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13419 struct modify_stmt_info info;
13420 info.adjustments = adjustments;
13422 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13424 gimple_stmt_iterator gsi;
13426 gsi = gsi_start_bb (bb);
13427 while (!gsi_end_p (gsi))
13429 gimple *stmt = gsi_stmt (gsi);
13430 info.stmt = stmt;
13431 struct walk_stmt_info wi;
13433 memset (&wi, 0, sizeof (wi));
13434 info.modified = false;
13435 wi.info = &info;
13436 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13438 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13440 tree retval = gimple_return_retval (return_stmt);
13441 if (!retval)
13443 gsi_remove (&gsi, true);
13444 continue;
13447 /* Replace `return foo' with `retval_array[iter] = foo'. */
13448 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13449 retval_array, iter, NULL, NULL);
13450 stmt = gimple_build_assign (ref, retval);
13451 gsi_replace (&gsi, stmt, true);
13452 info.modified = true;
13455 if (info.modified)
13457 update_stmt (stmt);
13458 if (maybe_clean_eh_stmt (stmt))
13459 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13461 gsi_next (&gsi);
13466 /* Adjust the argument types in NODE to their appropriate vector
13467 counterparts. */
13469 static void
13470 simd_clone_adjust (struct cgraph_node *node)
13472 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13474 targetm.simd_clone.adjust (node);
13476 tree retval = simd_clone_adjust_return_type (node);
13477 ipa_parm_adjustment_vec adjustments
13478 = simd_clone_adjust_argument_types (node);
13480 push_gimplify_context ();
13482 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13484 /* Adjust all uses of vector arguments accordingly. Adjust all
13485 return values accordingly. */
13486 tree iter = create_tmp_var (unsigned_type_node, "iter");
13487 tree iter1 = make_ssa_name (iter);
13488 tree iter2 = make_ssa_name (iter);
13489 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13491 /* Initialize the iteration variable. */
13492 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13493 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13494 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13495 /* Insert the SIMD array and iv initialization at function
13496 entry. */
13497 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13499 pop_gimplify_context (NULL);
13501 /* Create a new BB right before the original exit BB, to hold the
13502 iteration increment and the condition/branch. */
13503 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13504 basic_block incr_bb = create_empty_bb (orig_exit);
13505 add_bb_to_loop (incr_bb, body_bb->loop_father);
13506 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13507 flag. Set it now to be a FALLTHRU_EDGE. */
13508 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13509 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13510 for (unsigned i = 0;
13511 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13513 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13514 redirect_edge_succ (e, incr_bb);
13516 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13517 e->probability = REG_BR_PROB_BASE;
13518 gsi = gsi_last_bb (incr_bb);
13519 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13520 build_int_cst (unsigned_type_node, 1));
13521 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13523 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13524 struct loop *loop = alloc_loop ();
13525 cfun->has_force_vectorize_loops = true;
13526 loop->safelen = node->simdclone->simdlen;
13527 loop->force_vectorize = true;
13528 loop->header = body_bb;
13530 /* Branch around the body if the mask applies. */
13531 if (node->simdclone->inbranch)
13533 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13534 tree mask_array
13535 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13536 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13537 tree aref = build4 (ARRAY_REF,
13538 TREE_TYPE (TREE_TYPE (mask_array)),
13539 mask_array, iter1,
13540 NULL, NULL);
13541 g = gimple_build_assign (mask, aref);
13542 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13543 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13544 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13546 aref = build1 (VIEW_CONVERT_EXPR,
13547 build_nonstandard_integer_type (bitsize, 0), mask);
13548 mask = make_ssa_name (TREE_TYPE (aref));
13549 g = gimple_build_assign (mask, aref);
13550 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13553 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13554 NULL, NULL);
13555 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13556 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13557 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13560 /* Generate the condition. */
13561 g = gimple_build_cond (LT_EXPR,
13562 iter2,
13563 build_int_cst (unsigned_type_node,
13564 node->simdclone->simdlen),
13565 NULL, NULL);
13566 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13567 e = split_block (incr_bb, gsi_stmt (gsi));
13568 basic_block latch_bb = e->dest;
13569 basic_block new_exit_bb;
13570 new_exit_bb = split_block_after_labels (latch_bb)->dest;
13571 loop->latch = latch_bb;
13573 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13575 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13576 /* The successor of incr_bb is already pointing to latch_bb; just
13577 change the flags.
13578 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13579 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13581 gphi *phi = create_phi_node (iter1, body_bb);
13582 edge preheader_edge = find_edge (entry_bb, body_bb);
13583 edge latch_edge = single_succ_edge (latch_bb);
13584 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13585 UNKNOWN_LOCATION);
13586 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13588 /* Generate the new return. */
13589 gsi = gsi_last_bb (new_exit_bb);
13590 if (retval
13591 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13592 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13593 retval = TREE_OPERAND (retval, 0);
13594 else if (retval)
13596 retval = build1 (VIEW_CONVERT_EXPR,
13597 TREE_TYPE (TREE_TYPE (node->decl)),
13598 retval);
13599 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13600 false, GSI_CONTINUE_LINKING);
13602 g = gimple_build_return (retval);
13603 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13605 /* Handle aligned clauses by replacing default defs of the aligned
13606 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13607 lhs. Handle linear by adding PHIs. */
13608 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13609 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13610 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
13611 || !is_gimple_reg_type
13612 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
13614 tree orig_arg = node->simdclone->args[i].orig_arg;
13615 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
13616 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
13617 else
13619 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
13620 gimple_add_tmp_var (iter1);
13622 gsi = gsi_after_labels (entry_bb);
13623 g = gimple_build_assign (iter1, orig_arg);
13624 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13625 gsi = gsi_after_labels (body_bb);
13626 g = gimple_build_assign (orig_arg, iter1);
13627 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13629 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13630 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
13631 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13632 == REFERENCE_TYPE
13633 && TREE_ADDRESSABLE
13634 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
13636 tree orig_arg = node->simdclone->args[i].orig_arg;
13637 tree def = ssa_default_def (cfun, orig_arg);
13638 if (def && !has_zero_uses (def))
13640 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
13641 gimple_add_tmp_var (iter1);
13642 gsi = gsi_after_labels (entry_bb);
13643 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
13644 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13645 gsi = gsi_after_labels (body_bb);
13646 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
13647 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13650 else if (node->simdclone->args[i].alignment
13651 && node->simdclone->args[i].arg_type
13652 == SIMD_CLONE_ARG_TYPE_UNIFORM
13653 && (node->simdclone->args[i].alignment
13654 & (node->simdclone->args[i].alignment - 1)) == 0
13655 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13656 == POINTER_TYPE)
13658 unsigned int alignment = node->simdclone->args[i].alignment;
13659 tree orig_arg = node->simdclone->args[i].orig_arg;
13660 tree def = ssa_default_def (cfun, orig_arg);
13661 if (def && !has_zero_uses (def))
13663 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13664 gimple_seq seq = NULL;
13665 bool need_cvt = false;
13666 gcall *call
13667 = gimple_build_call (fn, 2, def, size_int (alignment));
13668 g = call;
13669 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13670 ptr_type_node))
13671 need_cvt = true;
13672 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13673 gimple_call_set_lhs (g, t);
13674 gimple_seq_add_stmt_without_update (&seq, g);
13675 if (need_cvt)
13677 t = make_ssa_name (orig_arg);
13678 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13679 gimple_seq_add_stmt_without_update (&seq, g);
13681 gsi_insert_seq_on_edge_immediate
13682 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13684 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13685 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13686 entry_bb);
13687 node->create_edge (cgraph_node::get_create (fn),
13688 call, entry_bb->count, freq);
13690 imm_use_iterator iter;
13691 use_operand_p use_p;
13692 gimple *use_stmt;
13693 tree repl = gimple_get_lhs (g);
13694 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13695 if (is_gimple_debug (use_stmt) || use_stmt == call)
13696 continue;
13697 else
13698 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13699 SET_USE (use_p, repl);
13702 else if (node->simdclone->args[i].arg_type
13703 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13705 tree orig_arg = node->simdclone->args[i].orig_arg;
13706 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13707 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13708 tree def = NULL_TREE;
13709 if (TREE_ADDRESSABLE (orig_arg))
13711 def = make_ssa_name (TREE_TYPE (orig_arg));
13712 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
13713 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
13714 gsi = gsi_after_labels (entry_bb);
13715 g = gimple_build_assign (def, orig_arg);
13716 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13718 else
13720 def = ssa_default_def (cfun, orig_arg);
13721 if (!def || has_zero_uses (def))
13722 def = NULL_TREE;
13723 else
13725 iter1 = make_ssa_name (orig_arg);
13726 iter2 = make_ssa_name (orig_arg);
13729 if (def)
13731 phi = create_phi_node (iter1, body_bb);
13732 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13733 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13734 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13735 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13736 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13737 ? TREE_TYPE (orig_arg) : sizetype;
13738 tree addcst
13739 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13740 g = gimple_build_assign (iter2, code, iter1, addcst);
13741 gsi = gsi_last_bb (incr_bb);
13742 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13744 imm_use_iterator iter;
13745 use_operand_p use_p;
13746 gimple *use_stmt;
13747 if (TREE_ADDRESSABLE (orig_arg))
13749 gsi = gsi_after_labels (body_bb);
13750 g = gimple_build_assign (orig_arg, iter1);
13751 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13753 else
13754 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13755 if (use_stmt == phi)
13756 continue;
13757 else
13758 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13759 SET_USE (use_p, iter1);
13763 calculate_dominance_info (CDI_DOMINATORS);
13764 add_loop (loop, loop->header->loop_father);
13765 update_ssa (TODO_update_ssa);
13767 pop_cfun ();
13770 /* If the function in NODE is tagged as an elemental SIMD function,
13771 create the appropriate SIMD clones. */
13773 static void
13774 expand_simd_clones (struct cgraph_node *node)
13776 tree attr = lookup_attribute ("omp declare simd",
13777 DECL_ATTRIBUTES (node->decl));
13778 if (attr == NULL_TREE
13779 || node->global.inlined_to
13780 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13781 return;
13783 /* Ignore
13784 #pragma omp declare simd
13785 extern int foo ();
13786 in C, there we don't know the argument types at all. */
13787 if (!node->definition
13788 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13789 return;
13793 /* Start with parsing the "omp declare simd" attribute(s). */
13794 bool inbranch_clause_specified;
13795 struct cgraph_simd_clone *clone_info
13796 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13797 &inbranch_clause_specified);
13798 if (clone_info == NULL)
13799 continue;
13801 int orig_simdlen = clone_info->simdlen;
13802 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13803 /* The target can return 0 (no simd clones should be created),
13804 1 (just one ISA of simd clones should be created) or higher
13805 count of ISA variants. In that case, clone_info is initialized
13806 for the first ISA variant. */
13807 int count
13808 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13809 base_type, 0);
13810 if (count == 0)
13811 continue;
13813 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13814 also create one inbranch and one !inbranch clone of it. */
13815 for (int i = 0; i < count * 2; i++)
13817 struct cgraph_simd_clone *clone = clone_info;
13818 if (inbranch_clause_specified && (i & 1) != 0)
13819 continue;
13821 if (i != 0)
13823 clone = simd_clone_struct_alloc (clone_info->nargs
13824 + ((i & 1) != 0));
13825 simd_clone_struct_copy (clone, clone_info);
13826 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13827 and simd_clone_adjust_argument_types did to the first
13828 clone's info. */
13829 clone->nargs -= clone_info->inbranch;
13830 clone->simdlen = orig_simdlen;
13831 /* And call the target hook again to get the right ISA. */
13832 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13833 base_type,
13834 i / 2);
13835 if ((i & 1) != 0)
13836 clone->inbranch = 1;
13839 /* simd_clone_mangle might fail if such a clone has been created
13840 already. */
13841 tree id = simd_clone_mangle (node, clone);
13842 if (id == NULL_TREE)
13843 continue;
13845 /* Only when we are sure we want to create the clone actually
13846 clone the function (or definitions) or create another
13847 extern FUNCTION_DECL (for prototypes without definitions). */
13848 struct cgraph_node *n = simd_clone_create (node);
13849 if (n == NULL)
13850 continue;
13852 n->simdclone = clone;
13853 clone->origin = node;
13854 clone->next_clone = NULL;
13855 if (node->simd_clones == NULL)
13857 clone->prev_clone = n;
13858 node->simd_clones = n;
13860 else
13862 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13863 clone->prev_clone->simdclone->next_clone = n;
13864 node->simd_clones->simdclone->prev_clone = n;
13866 symtab->change_decl_assembler_name (n->decl, id);
13867 /* And finally adjust the return type, parameters and for
13868 definitions also function body. */
13869 if (node->definition)
13870 simd_clone_adjust (n);
13871 else
13873 simd_clone_adjust_return_type (n);
13874 simd_clone_adjust_argument_types (n);
13878 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13881 /* Entry point for IPA simd clone creation pass. */
13883 static unsigned int
13884 ipa_omp_simd_clone (void)
13886 struct cgraph_node *node;
13887 FOR_EACH_FUNCTION (node)
13888 expand_simd_clones (node);
13889 return 0;
13892 namespace {
13894 const pass_data pass_data_omp_simd_clone =
13896 SIMPLE_IPA_PASS, /* type */
13897 "simdclone", /* name */
13898 OPTGROUP_NONE, /* optinfo_flags */
13899 TV_NONE, /* tv_id */
13900 ( PROP_ssa | PROP_cfg ), /* properties_required */
13901 0, /* properties_provided */
13902 0, /* properties_destroyed */
13903 0, /* todo_flags_start */
13904 0, /* todo_flags_finish */
13907 class pass_omp_simd_clone : public simple_ipa_opt_pass
13909 public:
13910 pass_omp_simd_clone(gcc::context *ctxt)
13911 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13914 /* opt_pass methods: */
13915 virtual bool gate (function *);
13916 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
13919 bool
13920 pass_omp_simd_clone::gate (function *)
13922 return ((flag_openmp || flag_openmp_simd
13923 || flag_cilkplus
13924 || (in_lto_p && !flag_wpa))
13925 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13928 } // anon namespace
13930 simple_ipa_opt_pass *
13931 make_pass_omp_simd_clone (gcc::context *ctxt)
13933 return new pass_omp_simd_clone (ctxt);
13936 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13937 adds their addresses and sizes to constructor-vector V_CTOR. */
13938 static void
13939 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13940 vec<constructor_elt, va_gc> *v_ctor)
13942 unsigned len = vec_safe_length (v_decls);
13943 for (unsigned i = 0; i < len; i++)
13945 tree it = (*v_decls)[i];
13946 bool is_function = TREE_CODE (it) != VAR_DECL;
13948 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13949 if (!is_function)
13950 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13951 fold_convert (const_ptr_type_node,
13952 DECL_SIZE_UNIT (it)));
13956 /* Create new symbols containing (address, size) pairs for global variables,
13957 marked with "omp declare target" attribute, as well as addresses for the
13958 functions, which are outlined offloading regions. */
13959 void
13960 omp_finish_file (void)
13962 unsigned num_funcs = vec_safe_length (offload_funcs);
13963 unsigned num_vars = vec_safe_length (offload_vars);
13965 if (num_funcs == 0 && num_vars == 0)
13966 return;
13968 if (targetm_common.have_named_sections)
13970 vec<constructor_elt, va_gc> *v_f, *v_v;
13971 vec_alloc (v_f, num_funcs);
13972 vec_alloc (v_v, num_vars * 2);
13974 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13975 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13977 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13978 num_vars * 2);
13979 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13980 num_funcs);
13981 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13982 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13983 tree ctor_v = build_constructor (vars_decl_type, v_v);
13984 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13985 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13986 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13987 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13988 get_identifier (".offload_func_table"),
13989 funcs_decl_type);
13990 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13991 get_identifier (".offload_var_table"),
13992 vars_decl_type);
13993 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13994 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13995 otherwise a joint table in a binary will contain padding between
13996 tables from multiple object files. */
13997 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13998 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13999 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
14000 DECL_INITIAL (funcs_decl) = ctor_f;
14001 DECL_INITIAL (vars_decl) = ctor_v;
14002 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
14003 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
14005 varpool_node::finalize_decl (vars_decl);
14006 varpool_node::finalize_decl (funcs_decl);
14008 else
14010 for (unsigned i = 0; i < num_funcs; i++)
14012 tree it = (*offload_funcs)[i];
14013 targetm.record_offload_symbol (it);
14015 for (unsigned i = 0; i < num_vars; i++)
14017 tree it = (*offload_vars)[i];
14018 targetm.record_offload_symbol (it);
14023 /* Validate and update the dimensions for offloaded FN. ATTRS is the
14024 raw attribute. DIMS is an array of dimensions, which is returned.
14025 Returns the function level dimensionality -- the level at which an
14026 offload routine wishes to partition a loop. */
14028 static int
14029 oacc_validate_dims (tree fn, tree attrs, int *dims)
14031 tree purpose[GOMP_DIM_MAX];
14032 unsigned ix;
14033 tree pos = TREE_VALUE (attrs);
14034 int fn_level = -1;
14036 /* Make sure the attribute creator attached the dimension
14037 information. */
14038 gcc_assert (pos);
14040 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
14042 purpose[ix] = TREE_PURPOSE (pos);
14044 if (purpose[ix])
14046 if (integer_zerop (purpose[ix]))
14047 fn_level = ix + 1;
14048 else if (fn_level < 0)
14049 fn_level = ix;
14052 tree val = TREE_VALUE (pos);
14053 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
14054 pos = TREE_CHAIN (pos);
14057 bool changed = targetm.goacc.validate_dims (fn, dims, fn_level);
14059 /* Default anything left to 1. */
14060 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
14061 if (dims[ix] < 0)
14063 dims[ix] = 1;
14064 changed = true;
14067 if (changed)
14069 /* Replace the attribute with new values. */
14070 pos = NULL_TREE;
14071 for (ix = GOMP_DIM_MAX; ix--;)
14072 pos = tree_cons (purpose[ix],
14073 build_int_cst (integer_type_node, dims[ix]),
14074 pos);
14075 replace_oacc_fn_attrib (fn, pos);
14078 return fn_level;
14081 /* Main entry point for oacc transformations which run on the device
14082 compiler after LTO, so we know what the target device is at this
14083 point (including the host fallback). */
14085 static unsigned int
14086 execute_oacc_device_lower ()
14088 tree attrs = get_oacc_fn_attrib (current_function_decl);
14089 int dims[GOMP_DIM_MAX];
14091 if (!attrs)
14092 /* Not an offloaded function. */
14093 return 0;
14095 oacc_validate_dims (current_function_decl, attrs, dims);
14097 return 0;
14100 /* Default launch dimension validator. Force everything to 1. A
14101 backend that wants to provide larger dimensions must override this
14102 hook. */
14104 bool
14105 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
14106 int ARG_UNUSED (fn_level))
14108 bool changed = false;
14110 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
14112 if (dims[ix] != 1)
14114 dims[ix] = 1;
14115 changed = true;
14119 return changed;
14122 namespace {
14124 const pass_data pass_data_oacc_device_lower =
14126 GIMPLE_PASS, /* type */
14127 "oaccdevlow", /* name */
14128 OPTGROUP_NONE, /* optinfo_flags */
14129 TV_NONE, /* tv_id */
14130 PROP_cfg, /* properties_required */
14131 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
14132 0, /* properties_destroyed */
14133 0, /* todo_flags_start */
14134 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
14137 class pass_oacc_device_lower : public gimple_opt_pass
14139 public:
14140 pass_oacc_device_lower (gcc::context *ctxt)
14141 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
14144 /* opt_pass methods: */
14145 virtual unsigned int execute (function *)
14147 bool gate = (flag_openacc != 0 && !seen_error ());
14149 if (!gate)
14150 return 0;
14152 return execute_oacc_device_lower ();
14155 }; // class pass_oacc_transform
14157 } // anon namespace
14159 gimple_opt_pass *
14160 make_pass_oacc_device_lower (gcc::context *ctxt)
14162 return new pass_oacc_device_lower (ctxt);
14165 #include "gt-omp-low.h"