Check int_size_in_bytes in ix86_return_in_memory
[official-gcc.git] / gcc / omp-low.c
blob2517f1873cda90acd97a6adffaf62f55dbd12fb5
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 "tree.h"
30 #include "gimple.h"
31 #include "rtl.h"
32 #include "ssa.h"
33 #include "alias.h"
34 #include "fold-const.h"
35 #include "stor-layout.h"
36 #include "cfganal.h"
37 #include "internal-fn.h"
38 #include "gimple-fold.h"
39 #include "gimplify.h"
40 #include "gimple-iterator.h"
41 #include "gimplify-me.h"
42 #include "gimple-walk.h"
43 #include "tree-iterator.h"
44 #include "tree-inline.h"
45 #include "langhooks.h"
46 #include "diagnostic-core.h"
47 #include "cgraph.h"
48 #include "tree-cfg.h"
49 #include "tree-into-ssa.h"
50 #include "flags.h"
51 #include "insn-config.h"
52 #include "expmed.h"
53 #include "dojump.h"
54 #include "explow.h"
55 #include "calls.h"
56 #include "emit-rtl.h"
57 #include "varasm.h"
58 #include "stmt.h"
59 #include "expr.h"
60 #include "tree-dfa.h"
61 #include "tree-ssa.h"
62 #include "tree-pass.h"
63 #include "except.h"
64 #include "splay-tree.h"
65 #include "insn-codes.h"
66 #include "optabs.h"
67 #include "cfgloop.h"
68 #include "target.h"
69 #include "common/common-target.h"
70 #include "omp-low.h"
71 #include "gimple-low.h"
72 #include "tree-cfgcleanup.h"
73 #include "pretty-print.h"
74 #include "alloc-pool.h"
75 #include "symbol-summary.h"
76 #include "ipa-prop.h"
77 #include "tree-nested.h"
78 #include "tree-eh.h"
79 #include "cilk.h"
80 #include "context.h"
81 #include "lto-section-names.h"
82 #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 typedef 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;
206 } omp_context;
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 x = omp_build_component_ref (x, field);
1130 if (by_ref)
1131 x = build_simple_mem_ref (x);
1133 return x;
1136 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1137 of a parallel, this is a component reference; for workshare constructs
1138 this is some variable. */
1140 static tree
1141 build_outer_var_ref (tree var, omp_context *ctx)
1143 tree x;
1145 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1146 x = var;
1147 else if (is_variable_sized (var))
1149 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1150 x = build_outer_var_ref (x, ctx);
1151 x = build_simple_mem_ref (x);
1153 else if (is_taskreg_ctx (ctx))
1155 bool by_ref = use_pointer_for_field (var, NULL);
1156 x = build_receiver_ref (var, by_ref, ctx);
1158 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1159 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1161 /* #pragma omp simd isn't a worksharing construct, and can reference even
1162 private vars in its linear etc. clauses. */
1163 x = NULL_TREE;
1164 if (ctx->outer && is_taskreg_ctx (ctx))
1165 x = lookup_decl (var, ctx->outer);
1166 else if (ctx->outer)
1167 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1168 if (x == NULL_TREE)
1169 x = var;
1171 else if (ctx->outer)
1172 x = lookup_decl (var, ctx->outer);
1173 else if (is_reference (var))
1174 /* This can happen with orphaned constructs. If var is reference, it is
1175 possible it is shared and as such valid. */
1176 x = var;
1177 else
1178 gcc_unreachable ();
1180 if (is_reference (var))
1181 x = build_simple_mem_ref (x);
1183 return x;
1186 /* Build tree nodes to access the field for VAR on the sender side. */
1188 static tree
1189 build_sender_ref (tree var, omp_context *ctx)
1191 tree field = lookup_sfield (var, ctx);
1192 return omp_build_component_ref (ctx->sender_decl, field);
1195 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1197 static void
1198 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1200 tree field, type, sfield = NULL_TREE;
1202 gcc_assert ((mask & 1) == 0
1203 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1204 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1205 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1206 gcc_assert ((mask & 3) == 3
1207 || !is_gimple_omp_oacc (ctx->stmt));
1209 type = TREE_TYPE (var);
1210 if (mask & 4)
1212 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1213 type = build_pointer_type (build_pointer_type (type));
1215 else if (by_ref)
1216 type = build_pointer_type (type);
1217 else if ((mask & 3) == 1 && is_reference (var))
1218 type = TREE_TYPE (type);
1220 field = build_decl (DECL_SOURCE_LOCATION (var),
1221 FIELD_DECL, DECL_NAME (var), type);
1223 /* Remember what variable this field was created for. This does have a
1224 side effect of making dwarf2out ignore this member, so for helpful
1225 debugging we clear it later in delete_omp_context. */
1226 DECL_ABSTRACT_ORIGIN (field) = var;
1227 if (type == TREE_TYPE (var))
1229 DECL_ALIGN (field) = DECL_ALIGN (var);
1230 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1231 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1233 else
1234 DECL_ALIGN (field) = TYPE_ALIGN (type);
1236 if ((mask & 3) == 3)
1238 insert_field_into_struct (ctx->record_type, field);
1239 if (ctx->srecord_type)
1241 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1242 FIELD_DECL, DECL_NAME (var), type);
1243 DECL_ABSTRACT_ORIGIN (sfield) = var;
1244 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1245 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1246 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1247 insert_field_into_struct (ctx->srecord_type, sfield);
1250 else
1252 if (ctx->srecord_type == NULL_TREE)
1254 tree t;
1256 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1257 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1258 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1260 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1261 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1262 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1263 insert_field_into_struct (ctx->srecord_type, sfield);
1264 splay_tree_insert (ctx->sfield_map,
1265 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1266 (splay_tree_value) sfield);
1269 sfield = field;
1270 insert_field_into_struct ((mask & 1) ? ctx->record_type
1271 : ctx->srecord_type, field);
1274 if (mask & 1)
1275 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1276 (splay_tree_value) field);
1277 if ((mask & 2) && ctx->sfield_map)
1278 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1279 (splay_tree_value) sfield);
1282 static tree
1283 install_var_local (tree var, omp_context *ctx)
1285 tree new_var = omp_copy_decl_1 (var, ctx);
1286 insert_decl_map (&ctx->cb, var, new_var);
1287 return new_var;
1290 /* Adjust the replacement for DECL in CTX for the new context. This means
1291 copying the DECL_VALUE_EXPR, and fixing up the type. */
1293 static void
1294 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1296 tree new_decl, size;
1298 new_decl = lookup_decl (decl, ctx);
1300 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1302 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1303 && DECL_HAS_VALUE_EXPR_P (decl))
1305 tree ve = DECL_VALUE_EXPR (decl);
1306 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1307 SET_DECL_VALUE_EXPR (new_decl, ve);
1308 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1311 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1313 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1314 if (size == error_mark_node)
1315 size = TYPE_SIZE (TREE_TYPE (new_decl));
1316 DECL_SIZE (new_decl) = size;
1318 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1319 if (size == error_mark_node)
1320 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1321 DECL_SIZE_UNIT (new_decl) = size;
1325 /* The callback for remap_decl. Search all containing contexts for a
1326 mapping of the variable; this avoids having to duplicate the splay
1327 tree ahead of time. We know a mapping doesn't already exist in the
1328 given context. Create new mappings to implement default semantics. */
1330 static tree
1331 omp_copy_decl (tree var, copy_body_data *cb)
1333 omp_context *ctx = (omp_context *) cb;
1334 tree new_var;
1336 if (TREE_CODE (var) == LABEL_DECL)
1338 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1339 DECL_CONTEXT (new_var) = current_function_decl;
1340 insert_decl_map (&ctx->cb, var, new_var);
1341 return new_var;
1344 while (!is_taskreg_ctx (ctx))
1346 ctx = ctx->outer;
1347 if (ctx == NULL)
1348 return var;
1349 new_var = maybe_lookup_decl (var, ctx);
1350 if (new_var)
1351 return new_var;
1354 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1355 return var;
1357 return error_mark_node;
1361 /* Debugging dumps for parallel regions. */
1362 void dump_omp_region (FILE *, struct omp_region *, int);
1363 void debug_omp_region (struct omp_region *);
1364 void debug_all_omp_regions (void);
1366 /* Dump the parallel region tree rooted at REGION. */
1368 void
1369 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1371 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1372 gimple_code_name[region->type]);
1374 if (region->inner)
1375 dump_omp_region (file, region->inner, indent + 4);
1377 if (region->cont)
1379 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1380 region->cont->index);
1383 if (region->exit)
1384 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1385 region->exit->index);
1386 else
1387 fprintf (file, "%*s[no exit marker]\n", indent, "");
1389 if (region->next)
1390 dump_omp_region (file, region->next, indent);
1393 DEBUG_FUNCTION void
1394 debug_omp_region (struct omp_region *region)
1396 dump_omp_region (stderr, region, 0);
1399 DEBUG_FUNCTION void
1400 debug_all_omp_regions (void)
1402 dump_omp_region (stderr, root_omp_region, 0);
1406 /* Create a new parallel region starting at STMT inside region PARENT. */
1408 static struct omp_region *
1409 new_omp_region (basic_block bb, enum gimple_code type,
1410 struct omp_region *parent)
1412 struct omp_region *region = XCNEW (struct omp_region);
1414 region->outer = parent;
1415 region->entry = bb;
1416 region->type = type;
1418 if (parent)
1420 /* This is a nested region. Add it to the list of inner
1421 regions in PARENT. */
1422 region->next = parent->inner;
1423 parent->inner = region;
1425 else
1427 /* This is a toplevel region. Add it to the list of toplevel
1428 regions in ROOT_OMP_REGION. */
1429 region->next = root_omp_region;
1430 root_omp_region = region;
1433 return region;
1436 /* Release the memory associated with the region tree rooted at REGION. */
1438 static void
1439 free_omp_region_1 (struct omp_region *region)
1441 struct omp_region *i, *n;
1443 for (i = region->inner; i ; i = n)
1445 n = i->next;
1446 free_omp_region_1 (i);
1449 free (region);
1452 /* Release the memory for the entire omp region tree. */
1454 void
1455 free_omp_regions (void)
1457 struct omp_region *r, *n;
1458 for (r = root_omp_region; r ; r = n)
1460 n = r->next;
1461 free_omp_region_1 (r);
1463 root_omp_region = NULL;
1467 /* Create a new context, with OUTER_CTX being the surrounding context. */
1469 static omp_context *
1470 new_omp_context (gimple stmt, omp_context *outer_ctx)
1472 omp_context *ctx = XCNEW (omp_context);
1474 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1475 (splay_tree_value) ctx);
1476 ctx->stmt = stmt;
1478 if (outer_ctx)
1480 ctx->outer = outer_ctx;
1481 ctx->cb = outer_ctx->cb;
1482 ctx->cb.block = NULL;
1483 ctx->depth = outer_ctx->depth + 1;
1484 ctx->reduction_map = outer_ctx->reduction_map;
1486 else
1488 ctx->cb.src_fn = current_function_decl;
1489 ctx->cb.dst_fn = current_function_decl;
1490 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1491 gcc_checking_assert (ctx->cb.src_node);
1492 ctx->cb.dst_node = ctx->cb.src_node;
1493 ctx->cb.src_cfun = cfun;
1494 ctx->cb.copy_decl = omp_copy_decl;
1495 ctx->cb.eh_lp_nr = 0;
1496 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1497 ctx->depth = 1;
1500 ctx->cb.decl_map = new hash_map<tree, tree>;
1502 return ctx;
1505 static gimple_seq maybe_catch_exception (gimple_seq);
1507 /* Finalize task copyfn. */
1509 static void
1510 finalize_task_copyfn (gomp_task *task_stmt)
1512 struct function *child_cfun;
1513 tree child_fn;
1514 gimple_seq seq = NULL, new_seq;
1515 gbind *bind;
1517 child_fn = gimple_omp_task_copy_fn (task_stmt);
1518 if (child_fn == NULL_TREE)
1519 return;
1521 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1522 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1524 push_cfun (child_cfun);
1525 bind = gimplify_body (child_fn, false);
1526 gimple_seq_add_stmt (&seq, bind);
1527 new_seq = maybe_catch_exception (seq);
1528 if (new_seq != seq)
1530 bind = gimple_build_bind (NULL, new_seq, NULL);
1531 seq = NULL;
1532 gimple_seq_add_stmt (&seq, bind);
1534 gimple_set_body (child_fn, seq);
1535 pop_cfun ();
1537 /* Inform the callgraph about the new function. */
1538 cgraph_node *node = cgraph_node::get_create (child_fn);
1539 node->parallelized_function = 1;
1540 cgraph_node::add_new_function (child_fn, false);
1543 /* Destroy a omp_context data structures. Called through the splay tree
1544 value delete callback. */
1546 static void
1547 delete_omp_context (splay_tree_value value)
1549 omp_context *ctx = (omp_context *) value;
1551 delete ctx->cb.decl_map;
1553 if (ctx->field_map)
1554 splay_tree_delete (ctx->field_map);
1555 if (ctx->sfield_map)
1556 splay_tree_delete (ctx->sfield_map);
1557 /* Reduction map is copied to nested contexts, so only delete it in the
1558 owner. */
1559 if (ctx->reduction_map
1560 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1561 && is_gimple_omp_offloaded (ctx->stmt)
1562 && is_gimple_omp_oacc (ctx->stmt))
1563 splay_tree_delete (ctx->reduction_map);
1565 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1566 it produces corrupt debug information. */
1567 if (ctx->record_type)
1569 tree t;
1570 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1571 DECL_ABSTRACT_ORIGIN (t) = NULL;
1573 if (ctx->srecord_type)
1575 tree t;
1576 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1577 DECL_ABSTRACT_ORIGIN (t) = NULL;
1580 if (is_task_ctx (ctx))
1581 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1583 XDELETE (ctx);
1586 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1587 context. */
1589 static void
1590 fixup_child_record_type (omp_context *ctx)
1592 tree f, type = ctx->record_type;
1594 /* ??? It isn't sufficient to just call remap_type here, because
1595 variably_modified_type_p doesn't work the way we expect for
1596 record types. Testing each field for whether it needs remapping
1597 and creating a new record by hand works, however. */
1598 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1599 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1600 break;
1601 if (f)
1603 tree name, new_fields = NULL;
1605 type = lang_hooks.types.make_type (RECORD_TYPE);
1606 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1607 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1608 TYPE_DECL, name, type);
1609 TYPE_NAME (type) = name;
1611 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1613 tree new_f = copy_node (f);
1614 DECL_CONTEXT (new_f) = type;
1615 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1616 DECL_CHAIN (new_f) = new_fields;
1617 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1618 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1619 &ctx->cb, NULL);
1620 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1621 &ctx->cb, NULL);
1622 new_fields = new_f;
1624 /* Arrange to be able to look up the receiver field
1625 given the sender field. */
1626 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1627 (splay_tree_value) new_f);
1629 TYPE_FIELDS (type) = nreverse (new_fields);
1630 layout_type (type);
1633 TREE_TYPE (ctx->receiver_decl)
1634 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1637 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1638 specified by CLAUSES. */
1640 static void
1641 scan_sharing_clauses (tree clauses, omp_context *ctx)
1643 tree c, decl;
1644 bool scan_array_reductions = false;
1646 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1648 bool by_ref;
1650 switch (OMP_CLAUSE_CODE (c))
1652 case OMP_CLAUSE_PRIVATE:
1653 decl = OMP_CLAUSE_DECL (c);
1654 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1655 goto do_private;
1656 else if (!is_variable_sized (decl))
1657 install_var_local (decl, ctx);
1658 break;
1660 case OMP_CLAUSE_SHARED:
1661 decl = OMP_CLAUSE_DECL (c);
1662 /* Ignore shared directives in teams construct. */
1663 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1665 /* Global variables don't need to be copied,
1666 the receiver side will use them directly. */
1667 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1668 if (is_global_var (odecl))
1669 break;
1670 insert_decl_map (&ctx->cb, decl, odecl);
1671 break;
1673 gcc_assert (is_taskreg_ctx (ctx));
1674 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1675 || !is_variable_sized (decl));
1676 /* Global variables don't need to be copied,
1677 the receiver side will use them directly. */
1678 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1679 break;
1680 by_ref = use_pointer_for_field (decl, ctx);
1681 if (! TREE_READONLY (decl)
1682 || TREE_ADDRESSABLE (decl)
1683 || by_ref
1684 || is_reference (decl))
1686 install_var_field (decl, by_ref, 3, ctx);
1687 install_var_local (decl, ctx);
1688 break;
1690 /* We don't need to copy const scalar vars back. */
1691 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1692 goto do_private;
1694 case OMP_CLAUSE_LASTPRIVATE:
1695 /* Let the corresponding firstprivate clause create
1696 the variable. */
1697 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1698 break;
1699 /* FALLTHRU */
1701 case OMP_CLAUSE_FIRSTPRIVATE:
1702 if (is_gimple_omp_oacc (ctx->stmt))
1704 sorry ("clause not supported yet");
1705 break;
1707 /* FALLTHRU */
1708 case OMP_CLAUSE_REDUCTION:
1709 case OMP_CLAUSE_LINEAR:
1710 decl = OMP_CLAUSE_DECL (c);
1711 do_private:
1712 if (is_variable_sized (decl))
1714 if (is_task_ctx (ctx))
1715 install_var_field (decl, false, 1, ctx);
1716 break;
1718 else if (is_taskreg_ctx (ctx))
1720 bool global
1721 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1722 by_ref = use_pointer_for_field (decl, NULL);
1724 if (is_task_ctx (ctx)
1725 && (global || by_ref || is_reference (decl)))
1727 install_var_field (decl, false, 1, ctx);
1728 if (!global)
1729 install_var_field (decl, by_ref, 2, ctx);
1731 else if (!global)
1732 install_var_field (decl, by_ref, 3, ctx);
1734 install_var_local (decl, ctx);
1735 if (is_gimple_omp_oacc (ctx->stmt)
1736 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1738 /* Create a decl for the reduction array. */
1739 tree var = OMP_CLAUSE_DECL (c);
1740 tree type = get_base_type (var);
1741 tree ptype = build_pointer_type (type);
1742 tree array = create_tmp_var (ptype,
1743 oacc_get_reduction_array_id (var));
1744 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1745 install_var_field (array, true, 3, c);
1746 install_var_local (array, c);
1748 /* Insert it into the current context. */
1749 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1750 oacc_get_reduction_array_id (var),
1751 (splay_tree_value) array);
1752 splay_tree_insert (ctx->reduction_map,
1753 (splay_tree_key) array,
1754 (splay_tree_value) array);
1756 break;
1758 case OMP_CLAUSE__LOOPTEMP_:
1759 gcc_assert (is_parallel_ctx (ctx));
1760 decl = OMP_CLAUSE_DECL (c);
1761 install_var_field (decl, false, 3, ctx);
1762 install_var_local (decl, ctx);
1763 break;
1765 case OMP_CLAUSE_COPYPRIVATE:
1766 case OMP_CLAUSE_COPYIN:
1767 decl = OMP_CLAUSE_DECL (c);
1768 by_ref = use_pointer_for_field (decl, NULL);
1769 install_var_field (decl, by_ref, 3, ctx);
1770 break;
1772 case OMP_CLAUSE_DEFAULT:
1773 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1774 break;
1776 case OMP_CLAUSE_FINAL:
1777 case OMP_CLAUSE_IF:
1778 case OMP_CLAUSE_NUM_THREADS:
1779 case OMP_CLAUSE_NUM_TEAMS:
1780 case OMP_CLAUSE_THREAD_LIMIT:
1781 case OMP_CLAUSE_DEVICE:
1782 case OMP_CLAUSE_SCHEDULE:
1783 case OMP_CLAUSE_DIST_SCHEDULE:
1784 case OMP_CLAUSE_DEPEND:
1785 case OMP_CLAUSE__CILK_FOR_COUNT_:
1786 case OMP_CLAUSE_NUM_GANGS:
1787 case OMP_CLAUSE_NUM_WORKERS:
1788 case OMP_CLAUSE_VECTOR_LENGTH:
1789 if (ctx->outer)
1790 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1791 break;
1793 case OMP_CLAUSE_TO:
1794 case OMP_CLAUSE_FROM:
1795 case OMP_CLAUSE_MAP:
1796 if (ctx->outer)
1797 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1798 decl = OMP_CLAUSE_DECL (c);
1799 /* Global variables with "omp declare target" attribute
1800 don't need to be copied, the receiver side will use them
1801 directly. */
1802 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1803 && DECL_P (decl)
1804 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1805 && varpool_node::get_create (decl)->offloadable)
1806 break;
1807 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1808 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
1810 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1811 not offloaded; there is nothing to map for those. */
1812 if (!is_gimple_omp_offloaded (ctx->stmt)
1813 && !POINTER_TYPE_P (TREE_TYPE (decl))
1814 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
1815 break;
1817 if (DECL_P (decl))
1819 if (DECL_SIZE (decl)
1820 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1822 tree decl2 = DECL_VALUE_EXPR (decl);
1823 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1824 decl2 = TREE_OPERAND (decl2, 0);
1825 gcc_assert (DECL_P (decl2));
1826 install_var_field (decl2, true, 3, ctx);
1827 install_var_local (decl2, ctx);
1828 install_var_local (decl, ctx);
1830 else
1832 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1833 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1834 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1835 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1836 install_var_field (decl, true, 7, ctx);
1837 else
1838 install_var_field (decl, true, 3, ctx);
1839 if (is_gimple_omp_offloaded (ctx->stmt))
1840 install_var_local (decl, ctx);
1843 else
1845 tree base = get_base_address (decl);
1846 tree nc = OMP_CLAUSE_CHAIN (c);
1847 if (DECL_P (base)
1848 && nc != NULL_TREE
1849 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1850 && OMP_CLAUSE_DECL (nc) == base
1851 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1852 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1854 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1855 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1857 else
1859 if (ctx->outer)
1861 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1862 decl = OMP_CLAUSE_DECL (c);
1864 gcc_assert (!splay_tree_lookup (ctx->field_map,
1865 (splay_tree_key) decl));
1866 tree field
1867 = build_decl (OMP_CLAUSE_LOCATION (c),
1868 FIELD_DECL, NULL_TREE, ptr_type_node);
1869 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1870 insert_field_into_struct (ctx->record_type, field);
1871 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1872 (splay_tree_value) field);
1875 break;
1877 case OMP_CLAUSE_NOWAIT:
1878 case OMP_CLAUSE_ORDERED:
1879 case OMP_CLAUSE_COLLAPSE:
1880 case OMP_CLAUSE_UNTIED:
1881 case OMP_CLAUSE_MERGEABLE:
1882 case OMP_CLAUSE_PROC_BIND:
1883 case OMP_CLAUSE_SAFELEN:
1884 case OMP_CLAUSE_ASYNC:
1885 case OMP_CLAUSE_WAIT:
1886 case OMP_CLAUSE_GANG:
1887 case OMP_CLAUSE_WORKER:
1888 case OMP_CLAUSE_VECTOR:
1889 break;
1891 case OMP_CLAUSE_ALIGNED:
1892 decl = OMP_CLAUSE_DECL (c);
1893 if (is_global_var (decl)
1894 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1895 install_var_local (decl, ctx);
1896 break;
1898 case OMP_CLAUSE_DEVICE_RESIDENT:
1899 case OMP_CLAUSE_USE_DEVICE:
1900 case OMP_CLAUSE__CACHE_:
1901 case OMP_CLAUSE_INDEPENDENT:
1902 case OMP_CLAUSE_AUTO:
1903 case OMP_CLAUSE_SEQ:
1904 sorry ("Clause not supported yet");
1905 break;
1907 default:
1908 gcc_unreachable ();
1912 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1914 switch (OMP_CLAUSE_CODE (c))
1916 case OMP_CLAUSE_LASTPRIVATE:
1917 /* Let the corresponding firstprivate clause create
1918 the variable. */
1919 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1920 scan_array_reductions = true;
1921 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1922 break;
1923 /* FALLTHRU */
1925 case OMP_CLAUSE_FIRSTPRIVATE:
1926 if (is_gimple_omp_oacc (ctx->stmt))
1928 sorry ("clause not supported yet");
1929 break;
1931 /* FALLTHRU */
1932 case OMP_CLAUSE_PRIVATE:
1933 case OMP_CLAUSE_REDUCTION:
1934 case OMP_CLAUSE_LINEAR:
1935 decl = OMP_CLAUSE_DECL (c);
1936 if (is_variable_sized (decl))
1937 install_var_local (decl, ctx);
1938 fixup_remapped_decl (decl, ctx,
1939 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1940 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1941 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1942 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1943 scan_array_reductions = true;
1944 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1945 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1946 scan_array_reductions = true;
1947 break;
1949 case OMP_CLAUSE_SHARED:
1950 /* Ignore shared directives in teams construct. */
1951 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1952 break;
1953 decl = OMP_CLAUSE_DECL (c);
1954 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1955 fixup_remapped_decl (decl, ctx, false);
1956 break;
1958 case OMP_CLAUSE_MAP:
1959 if (!is_gimple_omp_offloaded (ctx->stmt))
1960 break;
1961 decl = OMP_CLAUSE_DECL (c);
1962 if (DECL_P (decl)
1963 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1964 && varpool_node::get_create (decl)->offloadable)
1965 break;
1966 if (DECL_P (decl))
1968 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1969 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1970 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1972 tree new_decl = lookup_decl (decl, ctx);
1973 TREE_TYPE (new_decl)
1974 = remap_type (TREE_TYPE (decl), &ctx->cb);
1976 else if (DECL_SIZE (decl)
1977 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1979 tree decl2 = DECL_VALUE_EXPR (decl);
1980 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1981 decl2 = TREE_OPERAND (decl2, 0);
1982 gcc_assert (DECL_P (decl2));
1983 fixup_remapped_decl (decl2, ctx, false);
1984 fixup_remapped_decl (decl, ctx, true);
1986 else
1987 fixup_remapped_decl (decl, ctx, false);
1989 break;
1991 case OMP_CLAUSE_COPYPRIVATE:
1992 case OMP_CLAUSE_COPYIN:
1993 case OMP_CLAUSE_DEFAULT:
1994 case OMP_CLAUSE_IF:
1995 case OMP_CLAUSE_NUM_THREADS:
1996 case OMP_CLAUSE_NUM_TEAMS:
1997 case OMP_CLAUSE_THREAD_LIMIT:
1998 case OMP_CLAUSE_DEVICE:
1999 case OMP_CLAUSE_SCHEDULE:
2000 case OMP_CLAUSE_DIST_SCHEDULE:
2001 case OMP_CLAUSE_NOWAIT:
2002 case OMP_CLAUSE_ORDERED:
2003 case OMP_CLAUSE_COLLAPSE:
2004 case OMP_CLAUSE_UNTIED:
2005 case OMP_CLAUSE_FINAL:
2006 case OMP_CLAUSE_MERGEABLE:
2007 case OMP_CLAUSE_PROC_BIND:
2008 case OMP_CLAUSE_SAFELEN:
2009 case OMP_CLAUSE_ALIGNED:
2010 case OMP_CLAUSE_DEPEND:
2011 case OMP_CLAUSE__LOOPTEMP_:
2012 case OMP_CLAUSE_TO:
2013 case OMP_CLAUSE_FROM:
2014 case OMP_CLAUSE__CILK_FOR_COUNT_:
2015 case OMP_CLAUSE_ASYNC:
2016 case OMP_CLAUSE_WAIT:
2017 case OMP_CLAUSE_NUM_GANGS:
2018 case OMP_CLAUSE_NUM_WORKERS:
2019 case OMP_CLAUSE_VECTOR_LENGTH:
2020 case OMP_CLAUSE_GANG:
2021 case OMP_CLAUSE_WORKER:
2022 case OMP_CLAUSE_VECTOR:
2023 break;
2025 case OMP_CLAUSE_DEVICE_RESIDENT:
2026 case OMP_CLAUSE_USE_DEVICE:
2027 case OMP_CLAUSE__CACHE_:
2028 case OMP_CLAUSE_INDEPENDENT:
2029 case OMP_CLAUSE_AUTO:
2030 case OMP_CLAUSE_SEQ:
2031 sorry ("Clause not supported yet");
2032 break;
2034 default:
2035 gcc_unreachable ();
2039 gcc_checking_assert (!scan_array_reductions
2040 || !is_gimple_omp_oacc (ctx->stmt));
2041 if (scan_array_reductions)
2042 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2043 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2044 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2046 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2047 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2049 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2050 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2051 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2052 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2053 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2054 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2057 /* Create a new name for omp child function. Returns an identifier. If
2058 IS_CILK_FOR is true then the suffix for the child function is
2059 "_cilk_for_fn." */
2061 static tree
2062 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2064 if (is_cilk_for)
2065 return clone_function_name (current_function_decl, "_cilk_for_fn");
2066 return clone_function_name (current_function_decl,
2067 task_copy ? "_omp_cpyfn" : "_omp_fn");
2070 /* Returns the type of the induction variable for the child function for
2071 _Cilk_for and the types for _high and _low variables based on TYPE. */
2073 static tree
2074 cilk_for_check_loop_diff_type (tree type)
2076 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2078 if (TYPE_UNSIGNED (type))
2079 return uint32_type_node;
2080 else
2081 return integer_type_node;
2083 else
2085 if (TYPE_UNSIGNED (type))
2086 return uint64_type_node;
2087 else
2088 return long_long_integer_type_node;
2092 /* Build a decl for the omp child function. It'll not contain a body
2093 yet, just the bare decl. */
2095 static void
2096 create_omp_child_function (omp_context *ctx, bool task_copy)
2098 tree decl, type, name, t;
2100 tree cilk_for_count
2101 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2102 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2103 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2104 tree cilk_var_type = NULL_TREE;
2106 name = create_omp_child_function_name (task_copy,
2107 cilk_for_count != NULL_TREE);
2108 if (task_copy)
2109 type = build_function_type_list (void_type_node, ptr_type_node,
2110 ptr_type_node, NULL_TREE);
2111 else if (cilk_for_count)
2113 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2114 cilk_var_type = cilk_for_check_loop_diff_type (type);
2115 type = build_function_type_list (void_type_node, ptr_type_node,
2116 cilk_var_type, cilk_var_type, NULL_TREE);
2118 else
2119 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2121 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2123 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2124 || !task_copy);
2125 if (!task_copy)
2126 ctx->cb.dst_fn = decl;
2127 else
2128 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2130 TREE_STATIC (decl) = 1;
2131 TREE_USED (decl) = 1;
2132 DECL_ARTIFICIAL (decl) = 1;
2133 DECL_IGNORED_P (decl) = 0;
2134 TREE_PUBLIC (decl) = 0;
2135 DECL_UNINLINABLE (decl) = 1;
2136 DECL_EXTERNAL (decl) = 0;
2137 DECL_CONTEXT (decl) = NULL_TREE;
2138 DECL_INITIAL (decl) = make_node (BLOCK);
2139 if (cgraph_node::get (current_function_decl)->offloadable)
2140 cgraph_node::get_create (decl)->offloadable = 1;
2141 else
2143 omp_context *octx;
2144 for (octx = ctx; octx; octx = octx->outer)
2145 if (is_gimple_omp_offloaded (octx->stmt))
2147 cgraph_node::get_create (decl)->offloadable = 1;
2148 #ifdef ENABLE_OFFLOADING
2149 g->have_offload = true;
2150 #endif
2151 break;
2155 if (cgraph_node::get_create (decl)->offloadable
2156 && !lookup_attribute ("omp declare target",
2157 DECL_ATTRIBUTES (current_function_decl)))
2158 DECL_ATTRIBUTES (decl)
2159 = tree_cons (get_identifier ("omp target entrypoint"),
2160 NULL_TREE, DECL_ATTRIBUTES (decl));
2162 t = build_decl (DECL_SOURCE_LOCATION (decl),
2163 RESULT_DECL, NULL_TREE, void_type_node);
2164 DECL_ARTIFICIAL (t) = 1;
2165 DECL_IGNORED_P (t) = 1;
2166 DECL_CONTEXT (t) = decl;
2167 DECL_RESULT (decl) = t;
2169 /* _Cilk_for's child function requires two extra parameters called
2170 __low and __high that are set the by Cilk runtime when it calls this
2171 function. */
2172 if (cilk_for_count)
2174 t = build_decl (DECL_SOURCE_LOCATION (decl),
2175 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2176 DECL_ARTIFICIAL (t) = 1;
2177 DECL_NAMELESS (t) = 1;
2178 DECL_ARG_TYPE (t) = ptr_type_node;
2179 DECL_CONTEXT (t) = current_function_decl;
2180 TREE_USED (t) = 1;
2181 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2182 DECL_ARGUMENTS (decl) = t;
2184 t = build_decl (DECL_SOURCE_LOCATION (decl),
2185 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2186 DECL_ARTIFICIAL (t) = 1;
2187 DECL_NAMELESS (t) = 1;
2188 DECL_ARG_TYPE (t) = ptr_type_node;
2189 DECL_CONTEXT (t) = current_function_decl;
2190 TREE_USED (t) = 1;
2191 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2192 DECL_ARGUMENTS (decl) = t;
2195 tree data_name = get_identifier (".omp_data_i");
2196 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2197 ptr_type_node);
2198 DECL_ARTIFICIAL (t) = 1;
2199 DECL_NAMELESS (t) = 1;
2200 DECL_ARG_TYPE (t) = ptr_type_node;
2201 DECL_CONTEXT (t) = current_function_decl;
2202 TREE_USED (t) = 1;
2203 if (cilk_for_count)
2204 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2205 DECL_ARGUMENTS (decl) = t;
2206 if (!task_copy)
2207 ctx->receiver_decl = t;
2208 else
2210 t = build_decl (DECL_SOURCE_LOCATION (decl),
2211 PARM_DECL, get_identifier (".omp_data_o"),
2212 ptr_type_node);
2213 DECL_ARTIFICIAL (t) = 1;
2214 DECL_NAMELESS (t) = 1;
2215 DECL_ARG_TYPE (t) = ptr_type_node;
2216 DECL_CONTEXT (t) = current_function_decl;
2217 TREE_USED (t) = 1;
2218 TREE_ADDRESSABLE (t) = 1;
2219 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2220 DECL_ARGUMENTS (decl) = t;
2223 /* Allocate memory for the function structure. The call to
2224 allocate_struct_function clobbers CFUN, so we need to restore
2225 it afterward. */
2226 push_struct_function (decl);
2227 cfun->function_end_locus = gimple_location (ctx->stmt);
2228 pop_cfun ();
2231 /* Callback for walk_gimple_seq. Check if combined parallel
2232 contains gimple_omp_for_combined_into_p OMP_FOR. */
2234 static tree
2235 find_combined_for (gimple_stmt_iterator *gsi_p,
2236 bool *handled_ops_p,
2237 struct walk_stmt_info *wi)
2239 gimple stmt = gsi_stmt (*gsi_p);
2241 *handled_ops_p = true;
2242 switch (gimple_code (stmt))
2244 WALK_SUBSTMTS;
2246 case GIMPLE_OMP_FOR:
2247 if (gimple_omp_for_combined_into_p (stmt)
2248 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2250 wi->info = stmt;
2251 return integer_zero_node;
2253 break;
2254 default:
2255 break;
2257 return NULL;
2260 /* Scan an OpenMP parallel directive. */
2262 static void
2263 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2265 omp_context *ctx;
2266 tree name;
2267 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2269 /* Ignore parallel directives with empty bodies, unless there
2270 are copyin clauses. */
2271 if (optimize > 0
2272 && empty_body_p (gimple_omp_body (stmt))
2273 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2274 OMP_CLAUSE_COPYIN) == NULL)
2276 gsi_replace (gsi, gimple_build_nop (), false);
2277 return;
2280 if (gimple_omp_parallel_combined_p (stmt))
2282 struct walk_stmt_info wi;
2284 memset (&wi, 0, sizeof (wi));
2285 wi.val_only = true;
2286 walk_gimple_seq (gimple_omp_body (stmt),
2287 find_combined_for, NULL, &wi);
2288 if (wi.info)
2290 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2291 struct omp_for_data fd;
2292 extract_omp_for_data (for_stmt, &fd, NULL);
2293 /* We need two temporaries with fd.loop.v type (istart/iend)
2294 and then (fd.collapse - 1) temporaries with the same
2295 type for count2 ... countN-1 vars if not constant. */
2296 size_t count = 2, i;
2297 tree type = fd.iter_type;
2298 if (fd.collapse > 1
2299 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2300 count += fd.collapse - 1;
2301 for (i = 0; i < count; i++)
2303 tree temp = create_tmp_var (type);
2304 tree c = build_omp_clause (UNKNOWN_LOCATION,
2305 OMP_CLAUSE__LOOPTEMP_);
2306 insert_decl_map (&outer_ctx->cb, temp, temp);
2307 OMP_CLAUSE_DECL (c) = temp;
2308 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2309 gimple_omp_parallel_set_clauses (stmt, c);
2314 ctx = new_omp_context (stmt, outer_ctx);
2315 taskreg_contexts.safe_push (ctx);
2316 if (taskreg_nesting_level > 1)
2317 ctx->is_nested = true;
2318 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2319 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2320 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2321 name = create_tmp_var_name (".omp_data_s");
2322 name = build_decl (gimple_location (stmt),
2323 TYPE_DECL, name, ctx->record_type);
2324 DECL_ARTIFICIAL (name) = 1;
2325 DECL_NAMELESS (name) = 1;
2326 TYPE_NAME (ctx->record_type) = name;
2327 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2328 create_omp_child_function (ctx, false);
2329 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2331 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2332 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2334 if (TYPE_FIELDS (ctx->record_type) == NULL)
2335 ctx->record_type = ctx->receiver_decl = NULL;
2338 /* Scan an OpenMP task directive. */
2340 static void
2341 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2343 omp_context *ctx;
2344 tree name, t;
2345 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2347 /* Ignore task directives with empty bodies. */
2348 if (optimize > 0
2349 && empty_body_p (gimple_omp_body (stmt)))
2351 gsi_replace (gsi, gimple_build_nop (), false);
2352 return;
2355 ctx = new_omp_context (stmt, outer_ctx);
2356 taskreg_contexts.safe_push (ctx);
2357 if (taskreg_nesting_level > 1)
2358 ctx->is_nested = true;
2359 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2360 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2361 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2362 name = create_tmp_var_name (".omp_data_s");
2363 name = build_decl (gimple_location (stmt),
2364 TYPE_DECL, name, ctx->record_type);
2365 DECL_ARTIFICIAL (name) = 1;
2366 DECL_NAMELESS (name) = 1;
2367 TYPE_NAME (ctx->record_type) = name;
2368 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2369 create_omp_child_function (ctx, false);
2370 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2372 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2374 if (ctx->srecord_type)
2376 name = create_tmp_var_name (".omp_data_a");
2377 name = build_decl (gimple_location (stmt),
2378 TYPE_DECL, name, ctx->srecord_type);
2379 DECL_ARTIFICIAL (name) = 1;
2380 DECL_NAMELESS (name) = 1;
2381 TYPE_NAME (ctx->srecord_type) = name;
2382 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2383 create_omp_child_function (ctx, true);
2386 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2388 if (TYPE_FIELDS (ctx->record_type) == NULL)
2390 ctx->record_type = ctx->receiver_decl = NULL;
2391 t = build_int_cst (long_integer_type_node, 0);
2392 gimple_omp_task_set_arg_size (stmt, t);
2393 t = build_int_cst (long_integer_type_node, 1);
2394 gimple_omp_task_set_arg_align (stmt, t);
2399 /* If any decls have been made addressable during scan_omp,
2400 adjust their fields if needed, and layout record types
2401 of parallel/task constructs. */
2403 static void
2404 finish_taskreg_scan (omp_context *ctx)
2406 if (ctx->record_type == NULL_TREE)
2407 return;
2409 /* If any task_shared_vars were needed, verify all
2410 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2411 statements if use_pointer_for_field hasn't changed
2412 because of that. If it did, update field types now. */
2413 if (task_shared_vars)
2415 tree c;
2417 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2418 c; c = OMP_CLAUSE_CHAIN (c))
2419 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2421 tree decl = OMP_CLAUSE_DECL (c);
2423 /* Global variables don't need to be copied,
2424 the receiver side will use them directly. */
2425 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2426 continue;
2427 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2428 || !use_pointer_for_field (decl, ctx))
2429 continue;
2430 tree field = lookup_field (decl, ctx);
2431 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2432 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2433 continue;
2434 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2435 TREE_THIS_VOLATILE (field) = 0;
2436 DECL_USER_ALIGN (field) = 0;
2437 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2438 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2439 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2440 if (ctx->srecord_type)
2442 tree sfield = lookup_sfield (decl, ctx);
2443 TREE_TYPE (sfield) = TREE_TYPE (field);
2444 TREE_THIS_VOLATILE (sfield) = 0;
2445 DECL_USER_ALIGN (sfield) = 0;
2446 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2447 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2448 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2453 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2455 layout_type (ctx->record_type);
2456 fixup_child_record_type (ctx);
2458 else
2460 location_t loc = gimple_location (ctx->stmt);
2461 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2462 /* Move VLA fields to the end. */
2463 p = &TYPE_FIELDS (ctx->record_type);
2464 while (*p)
2465 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2466 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2468 *q = *p;
2469 *p = TREE_CHAIN (*p);
2470 TREE_CHAIN (*q) = NULL_TREE;
2471 q = &TREE_CHAIN (*q);
2473 else
2474 p = &DECL_CHAIN (*p);
2475 *p = vla_fields;
2476 layout_type (ctx->record_type);
2477 fixup_child_record_type (ctx);
2478 if (ctx->srecord_type)
2479 layout_type (ctx->srecord_type);
2480 tree t = fold_convert_loc (loc, long_integer_type_node,
2481 TYPE_SIZE_UNIT (ctx->record_type));
2482 gimple_omp_task_set_arg_size (ctx->stmt, t);
2483 t = build_int_cst (long_integer_type_node,
2484 TYPE_ALIGN_UNIT (ctx->record_type));
2485 gimple_omp_task_set_arg_align (ctx->stmt, t);
2490 static omp_context *
2491 enclosing_target_ctx (omp_context *ctx)
2493 while (ctx != NULL
2494 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2495 ctx = ctx->outer;
2496 gcc_assert (ctx != NULL);
2497 return ctx;
2500 static bool
2501 oacc_loop_or_target_p (gimple stmt)
2503 enum gimple_code outer_type = gimple_code (stmt);
2504 return ((outer_type == GIMPLE_OMP_TARGET
2505 && ((gimple_omp_target_kind (stmt)
2506 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2507 || (gimple_omp_target_kind (stmt)
2508 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2509 || (outer_type == GIMPLE_OMP_FOR
2510 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2513 /* Scan a GIMPLE_OMP_FOR. */
2515 static void
2516 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2518 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
2519 omp_context *ctx;
2520 size_t i;
2521 tree clauses = gimple_omp_for_clauses (stmt);
2523 if (outer_ctx)
2524 outer_type = gimple_code (outer_ctx->stmt);
2526 ctx = new_omp_context (stmt, outer_ctx);
2528 if (is_gimple_omp_oacc (stmt))
2530 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2531 ctx->gwv_this = outer_ctx->gwv_this;
2532 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2534 int val;
2535 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2536 val = MASK_GANG;
2537 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2538 val = MASK_WORKER;
2539 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2540 val = MASK_VECTOR;
2541 else
2542 continue;
2543 ctx->gwv_this |= val;
2544 if (!outer_ctx)
2546 /* Skip; not nested inside a region. */
2547 continue;
2549 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2551 /* Skip; not nested inside an OpenACC region. */
2552 continue;
2554 if (outer_type == GIMPLE_OMP_FOR)
2555 outer_ctx->gwv_below |= val;
2556 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2558 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2559 if (gimple_omp_target_kind (enclosing->stmt)
2560 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2561 error_at (gimple_location (stmt),
2562 "no arguments allowed to gang, worker and vector clauses inside parallel");
2567 scan_sharing_clauses (clauses, ctx);
2569 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2570 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2572 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2573 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2574 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2575 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2577 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2579 if (is_gimple_omp_oacc (stmt))
2581 if (ctx->gwv_this & ctx->gwv_below)
2582 error_at (gimple_location (stmt),
2583 "gang, worker and vector may occur only once in a loop nest");
2584 else if (ctx->gwv_below != 0
2585 && ctx->gwv_this > ctx->gwv_below)
2586 error_at (gimple_location (stmt),
2587 "gang, worker and vector must occur in this order in a loop nest");
2588 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2589 outer_ctx->gwv_below |= ctx->gwv_below;
2593 /* Scan an OpenMP sections directive. */
2595 static void
2596 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2598 omp_context *ctx;
2600 ctx = new_omp_context (stmt, outer_ctx);
2601 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2602 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2605 /* Scan an OpenMP single directive. */
2607 static void
2608 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2610 omp_context *ctx;
2611 tree name;
2613 ctx = new_omp_context (stmt, outer_ctx);
2614 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2615 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2616 name = create_tmp_var_name (".omp_copy_s");
2617 name = build_decl (gimple_location (stmt),
2618 TYPE_DECL, name, ctx->record_type);
2619 TYPE_NAME (ctx->record_type) = name;
2621 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2622 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2624 if (TYPE_FIELDS (ctx->record_type) == NULL)
2625 ctx->record_type = NULL;
2626 else
2627 layout_type (ctx->record_type);
2630 /* Scan a GIMPLE_OMP_TARGET. */
2632 static void
2633 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2635 omp_context *ctx;
2636 tree name;
2637 bool offloaded = is_gimple_omp_offloaded (stmt);
2638 tree clauses = gimple_omp_target_clauses (stmt);
2640 ctx = new_omp_context (stmt, outer_ctx);
2641 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2642 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2643 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2644 name = create_tmp_var_name (".omp_data_t");
2645 name = build_decl (gimple_location (stmt),
2646 TYPE_DECL, name, ctx->record_type);
2647 DECL_ARTIFICIAL (name) = 1;
2648 DECL_NAMELESS (name) = 1;
2649 TYPE_NAME (ctx->record_type) = name;
2650 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2651 if (offloaded)
2653 if (is_gimple_omp_oacc (stmt))
2654 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2655 0, 0);
2657 create_omp_child_function (ctx, false);
2658 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2661 if (is_gimple_omp_oacc (stmt))
2663 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2665 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2666 ctx->gwv_this |= MASK_GANG;
2667 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2668 ctx->gwv_this |= MASK_WORKER;
2669 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2670 ctx->gwv_this |= MASK_VECTOR;
2674 scan_sharing_clauses (clauses, ctx);
2675 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2677 if (TYPE_FIELDS (ctx->record_type) == NULL)
2678 ctx->record_type = ctx->receiver_decl = NULL;
2679 else
2681 TYPE_FIELDS (ctx->record_type)
2682 = nreverse (TYPE_FIELDS (ctx->record_type));
2683 #ifdef ENABLE_CHECKING
2684 tree field;
2685 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2686 for (field = TYPE_FIELDS (ctx->record_type);
2687 field;
2688 field = DECL_CHAIN (field))
2689 gcc_assert (DECL_ALIGN (field) == align);
2690 #endif
2691 layout_type (ctx->record_type);
2692 if (offloaded)
2693 fixup_child_record_type (ctx);
2697 /* Scan an OpenMP teams directive. */
2699 static void
2700 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2702 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2703 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2704 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2707 /* Check nesting restrictions. */
2708 static bool
2709 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2711 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2712 inside an OpenACC CTX. */
2713 if (!(is_gimple_omp (stmt)
2714 && is_gimple_omp_oacc (stmt)))
2716 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2717 if (is_gimple_omp (ctx_->stmt)
2718 && is_gimple_omp_oacc (ctx_->stmt))
2720 error_at (gimple_location (stmt),
2721 "non-OpenACC construct inside of OpenACC region");
2722 return false;
2726 if (ctx != NULL)
2728 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2729 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2731 error_at (gimple_location (stmt),
2732 "OpenMP constructs may not be nested inside simd region");
2733 return false;
2735 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2737 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2738 || (gimple_omp_for_kind (stmt)
2739 != GF_OMP_FOR_KIND_DISTRIBUTE))
2740 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2742 error_at (gimple_location (stmt),
2743 "only distribute or parallel constructs are allowed to "
2744 "be closely nested inside teams construct");
2745 return false;
2749 switch (gimple_code (stmt))
2751 case GIMPLE_OMP_FOR:
2752 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2753 return true;
2754 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2756 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2758 error_at (gimple_location (stmt),
2759 "distribute construct must be closely nested inside "
2760 "teams construct");
2761 return false;
2763 return true;
2765 /* FALLTHRU */
2766 case GIMPLE_CALL:
2767 if (is_gimple_call (stmt)
2768 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2769 == BUILT_IN_GOMP_CANCEL
2770 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2771 == BUILT_IN_GOMP_CANCELLATION_POINT))
2773 const char *bad = NULL;
2774 const char *kind = NULL;
2775 if (ctx == NULL)
2777 error_at (gimple_location (stmt), "orphaned %qs construct",
2778 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2779 == BUILT_IN_GOMP_CANCEL
2780 ? "#pragma omp cancel"
2781 : "#pragma omp cancellation point");
2782 return false;
2784 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2785 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2786 : 0)
2788 case 1:
2789 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2790 bad = "#pragma omp parallel";
2791 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2792 == BUILT_IN_GOMP_CANCEL
2793 && !integer_zerop (gimple_call_arg (stmt, 1)))
2794 ctx->cancellable = true;
2795 kind = "parallel";
2796 break;
2797 case 2:
2798 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2799 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2800 bad = "#pragma omp for";
2801 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2802 == BUILT_IN_GOMP_CANCEL
2803 && !integer_zerop (gimple_call_arg (stmt, 1)))
2805 ctx->cancellable = true;
2806 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2807 OMP_CLAUSE_NOWAIT))
2808 warning_at (gimple_location (stmt), 0,
2809 "%<#pragma omp cancel for%> inside "
2810 "%<nowait%> for construct");
2811 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2812 OMP_CLAUSE_ORDERED))
2813 warning_at (gimple_location (stmt), 0,
2814 "%<#pragma omp cancel for%> inside "
2815 "%<ordered%> for construct");
2817 kind = "for";
2818 break;
2819 case 4:
2820 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2821 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2822 bad = "#pragma omp sections";
2823 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2824 == BUILT_IN_GOMP_CANCEL
2825 && !integer_zerop (gimple_call_arg (stmt, 1)))
2827 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2829 ctx->cancellable = true;
2830 if (find_omp_clause (gimple_omp_sections_clauses
2831 (ctx->stmt),
2832 OMP_CLAUSE_NOWAIT))
2833 warning_at (gimple_location (stmt), 0,
2834 "%<#pragma omp cancel sections%> inside "
2835 "%<nowait%> sections construct");
2837 else
2839 gcc_assert (ctx->outer
2840 && gimple_code (ctx->outer->stmt)
2841 == GIMPLE_OMP_SECTIONS);
2842 ctx->outer->cancellable = true;
2843 if (find_omp_clause (gimple_omp_sections_clauses
2844 (ctx->outer->stmt),
2845 OMP_CLAUSE_NOWAIT))
2846 warning_at (gimple_location (stmt), 0,
2847 "%<#pragma omp cancel sections%> inside "
2848 "%<nowait%> sections construct");
2851 kind = "sections";
2852 break;
2853 case 8:
2854 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2855 bad = "#pragma omp task";
2856 else
2857 ctx->cancellable = true;
2858 kind = "taskgroup";
2859 break;
2860 default:
2861 error_at (gimple_location (stmt), "invalid arguments");
2862 return false;
2864 if (bad)
2866 error_at (gimple_location (stmt),
2867 "%<%s %s%> construct not closely nested inside of %qs",
2868 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2869 == BUILT_IN_GOMP_CANCEL
2870 ? "#pragma omp cancel"
2871 : "#pragma omp cancellation point", kind, bad);
2872 return false;
2875 /* FALLTHRU */
2876 case GIMPLE_OMP_SECTIONS:
2877 case GIMPLE_OMP_SINGLE:
2878 for (; ctx != NULL; ctx = ctx->outer)
2879 switch (gimple_code (ctx->stmt))
2881 case GIMPLE_OMP_FOR:
2882 case GIMPLE_OMP_SECTIONS:
2883 case GIMPLE_OMP_SINGLE:
2884 case GIMPLE_OMP_ORDERED:
2885 case GIMPLE_OMP_MASTER:
2886 case GIMPLE_OMP_TASK:
2887 case GIMPLE_OMP_CRITICAL:
2888 if (is_gimple_call (stmt))
2890 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2891 != BUILT_IN_GOMP_BARRIER)
2892 return true;
2893 error_at (gimple_location (stmt),
2894 "barrier region may not be closely nested inside "
2895 "of work-sharing, critical, ordered, master or "
2896 "explicit task region");
2897 return false;
2899 error_at (gimple_location (stmt),
2900 "work-sharing region may not be closely nested inside "
2901 "of work-sharing, critical, ordered, master or explicit "
2902 "task region");
2903 return false;
2904 case GIMPLE_OMP_PARALLEL:
2905 return true;
2906 default:
2907 break;
2909 break;
2910 case GIMPLE_OMP_MASTER:
2911 for (; ctx != NULL; ctx = ctx->outer)
2912 switch (gimple_code (ctx->stmt))
2914 case GIMPLE_OMP_FOR:
2915 case GIMPLE_OMP_SECTIONS:
2916 case GIMPLE_OMP_SINGLE:
2917 case GIMPLE_OMP_TASK:
2918 error_at (gimple_location (stmt),
2919 "master region may not be closely nested inside "
2920 "of work-sharing or explicit task region");
2921 return false;
2922 case GIMPLE_OMP_PARALLEL:
2923 return true;
2924 default:
2925 break;
2927 break;
2928 case GIMPLE_OMP_ORDERED:
2929 for (; ctx != NULL; ctx = ctx->outer)
2930 switch (gimple_code (ctx->stmt))
2932 case GIMPLE_OMP_CRITICAL:
2933 case GIMPLE_OMP_TASK:
2934 error_at (gimple_location (stmt),
2935 "ordered region may not be closely nested inside "
2936 "of critical or explicit task region");
2937 return false;
2938 case GIMPLE_OMP_FOR:
2939 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2940 OMP_CLAUSE_ORDERED) == NULL)
2942 error_at (gimple_location (stmt),
2943 "ordered region must be closely nested inside "
2944 "a loop region with an ordered clause");
2945 return false;
2947 return true;
2948 case GIMPLE_OMP_PARALLEL:
2949 error_at (gimple_location (stmt),
2950 "ordered region must be closely nested inside "
2951 "a loop region with an ordered clause");
2952 return false;
2953 default:
2954 break;
2956 break;
2957 case GIMPLE_OMP_CRITICAL:
2959 tree this_stmt_name
2960 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2961 for (; ctx != NULL; ctx = ctx->outer)
2962 if (gomp_critical *other_crit
2963 = dyn_cast <gomp_critical *> (ctx->stmt))
2964 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2966 error_at (gimple_location (stmt),
2967 "critical region may not be nested inside a critical "
2968 "region with the same name");
2969 return false;
2972 break;
2973 case GIMPLE_OMP_TEAMS:
2974 if (ctx == NULL
2975 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2976 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2978 error_at (gimple_location (stmt),
2979 "teams construct not closely nested inside of target "
2980 "region");
2981 return false;
2983 break;
2984 case GIMPLE_OMP_TARGET:
2985 for (; ctx != NULL; ctx = ctx->outer)
2987 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2989 if (is_gimple_omp (stmt)
2990 && is_gimple_omp_oacc (stmt)
2991 && is_gimple_omp (ctx->stmt))
2993 error_at (gimple_location (stmt),
2994 "OpenACC construct inside of non-OpenACC region");
2995 return false;
2997 continue;
3000 const char *stmt_name, *ctx_stmt_name;
3001 switch (gimple_omp_target_kind (stmt))
3003 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3004 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3005 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3006 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3007 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3008 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3009 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3010 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3011 default: gcc_unreachable ();
3013 switch (gimple_omp_target_kind (ctx->stmt))
3015 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3016 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3017 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3018 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3019 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3020 default: gcc_unreachable ();
3023 /* OpenACC/OpenMP mismatch? */
3024 if (is_gimple_omp_oacc (stmt)
3025 != is_gimple_omp_oacc (ctx->stmt))
3027 error_at (gimple_location (stmt),
3028 "%s %s construct inside of %s %s region",
3029 (is_gimple_omp_oacc (stmt)
3030 ? "OpenACC" : "OpenMP"), stmt_name,
3031 (is_gimple_omp_oacc (ctx->stmt)
3032 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3033 return false;
3035 if (is_gimple_omp_offloaded (ctx->stmt))
3037 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3038 if (is_gimple_omp_oacc (ctx->stmt))
3040 error_at (gimple_location (stmt),
3041 "%s construct inside of %s region",
3042 stmt_name, ctx_stmt_name);
3043 return false;
3045 else
3047 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3048 warning_at (gimple_location (stmt), 0,
3049 "%s construct inside of %s region",
3050 stmt_name, ctx_stmt_name);
3054 break;
3055 default:
3056 break;
3058 return true;
3062 /* Helper function scan_omp.
3064 Callback for walk_tree or operators in walk_gimple_stmt used to
3065 scan for OMP directives in TP. */
3067 static tree
3068 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3070 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3071 omp_context *ctx = (omp_context *) wi->info;
3072 tree t = *tp;
3074 switch (TREE_CODE (t))
3076 case VAR_DECL:
3077 case PARM_DECL:
3078 case LABEL_DECL:
3079 case RESULT_DECL:
3080 if (ctx)
3081 *tp = remap_decl (t, &ctx->cb);
3082 break;
3084 default:
3085 if (ctx && TYPE_P (t))
3086 *tp = remap_type (t, &ctx->cb);
3087 else if (!DECL_P (t))
3089 *walk_subtrees = 1;
3090 if (ctx)
3092 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3093 if (tem != TREE_TYPE (t))
3095 if (TREE_CODE (t) == INTEGER_CST)
3096 *tp = wide_int_to_tree (tem, t);
3097 else
3098 TREE_TYPE (t) = tem;
3102 break;
3105 return NULL_TREE;
3108 /* Return true if FNDECL is a setjmp or a longjmp. */
3110 static bool
3111 setjmp_or_longjmp_p (const_tree fndecl)
3113 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3114 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3115 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3116 return true;
3118 tree declname = DECL_NAME (fndecl);
3119 if (!declname)
3120 return false;
3121 const char *name = IDENTIFIER_POINTER (declname);
3122 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3126 /* Helper function for scan_omp.
3128 Callback for walk_gimple_stmt used to scan for OMP directives in
3129 the current statement in GSI. */
3131 static tree
3132 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3133 struct walk_stmt_info *wi)
3135 gimple stmt = gsi_stmt (*gsi);
3136 omp_context *ctx = (omp_context *) wi->info;
3138 if (gimple_has_location (stmt))
3139 input_location = gimple_location (stmt);
3141 /* Check the nesting restrictions. */
3142 bool remove = false;
3143 if (is_gimple_omp (stmt))
3144 remove = !check_omp_nesting_restrictions (stmt, ctx);
3145 else if (is_gimple_call (stmt))
3147 tree fndecl = gimple_call_fndecl (stmt);
3148 if (fndecl)
3150 if (setjmp_or_longjmp_p (fndecl)
3151 && ctx
3152 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3153 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3155 remove = true;
3156 error_at (gimple_location (stmt),
3157 "setjmp/longjmp inside simd construct");
3159 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3160 switch (DECL_FUNCTION_CODE (fndecl))
3162 case BUILT_IN_GOMP_BARRIER:
3163 case BUILT_IN_GOMP_CANCEL:
3164 case BUILT_IN_GOMP_CANCELLATION_POINT:
3165 case BUILT_IN_GOMP_TASKYIELD:
3166 case BUILT_IN_GOMP_TASKWAIT:
3167 case BUILT_IN_GOMP_TASKGROUP_START:
3168 case BUILT_IN_GOMP_TASKGROUP_END:
3169 remove = !check_omp_nesting_restrictions (stmt, ctx);
3170 break;
3171 default:
3172 break;
3176 if (remove)
3178 stmt = gimple_build_nop ();
3179 gsi_replace (gsi, stmt, false);
3182 *handled_ops_p = true;
3184 switch (gimple_code (stmt))
3186 case GIMPLE_OMP_PARALLEL:
3187 taskreg_nesting_level++;
3188 scan_omp_parallel (gsi, ctx);
3189 taskreg_nesting_level--;
3190 break;
3192 case GIMPLE_OMP_TASK:
3193 taskreg_nesting_level++;
3194 scan_omp_task (gsi, ctx);
3195 taskreg_nesting_level--;
3196 break;
3198 case GIMPLE_OMP_FOR:
3199 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3200 break;
3202 case GIMPLE_OMP_SECTIONS:
3203 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3204 break;
3206 case GIMPLE_OMP_SINGLE:
3207 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3208 break;
3210 case GIMPLE_OMP_SECTION:
3211 case GIMPLE_OMP_MASTER:
3212 case GIMPLE_OMP_TASKGROUP:
3213 case GIMPLE_OMP_ORDERED:
3214 case GIMPLE_OMP_CRITICAL:
3215 ctx = new_omp_context (stmt, ctx);
3216 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3217 break;
3219 case GIMPLE_OMP_TARGET:
3220 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3221 break;
3223 case GIMPLE_OMP_TEAMS:
3224 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3225 break;
3227 case GIMPLE_BIND:
3229 tree var;
3231 *handled_ops_p = false;
3232 if (ctx)
3233 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3234 var ;
3235 var = DECL_CHAIN (var))
3236 insert_decl_map (&ctx->cb, var, var);
3238 break;
3239 default:
3240 *handled_ops_p = false;
3241 break;
3244 return NULL_TREE;
3248 /* Scan all the statements starting at the current statement. CTX
3249 contains context information about the OMP directives and
3250 clauses found during the scan. */
3252 static void
3253 scan_omp (gimple_seq *body_p, omp_context *ctx)
3255 location_t saved_location;
3256 struct walk_stmt_info wi;
3258 memset (&wi, 0, sizeof (wi));
3259 wi.info = ctx;
3260 wi.want_locations = true;
3262 saved_location = input_location;
3263 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3264 input_location = saved_location;
3267 /* Re-gimplification and code generation routines. */
3269 /* Build a call to GOMP_barrier. */
3271 static gimple
3272 build_omp_barrier (tree lhs)
3274 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3275 : BUILT_IN_GOMP_BARRIER);
3276 gcall *g = gimple_build_call (fndecl, 0);
3277 if (lhs)
3278 gimple_call_set_lhs (g, lhs);
3279 return g;
3282 /* If a context was created for STMT when it was scanned, return it. */
3284 static omp_context *
3285 maybe_lookup_ctx (gimple stmt)
3287 splay_tree_node n;
3288 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3289 return n ? (omp_context *) n->value : NULL;
3293 /* Find the mapping for DECL in CTX or the immediately enclosing
3294 context that has a mapping for DECL.
3296 If CTX is a nested parallel directive, we may have to use the decl
3297 mappings created in CTX's parent context. Suppose that we have the
3298 following parallel nesting (variable UIDs showed for clarity):
3300 iD.1562 = 0;
3301 #omp parallel shared(iD.1562) -> outer parallel
3302 iD.1562 = iD.1562 + 1;
3304 #omp parallel shared (iD.1562) -> inner parallel
3305 iD.1562 = iD.1562 - 1;
3307 Each parallel structure will create a distinct .omp_data_s structure
3308 for copying iD.1562 in/out of the directive:
3310 outer parallel .omp_data_s.1.i -> iD.1562
3311 inner parallel .omp_data_s.2.i -> iD.1562
3313 A shared variable mapping will produce a copy-out operation before
3314 the parallel directive and a copy-in operation after it. So, in
3315 this case we would have:
3317 iD.1562 = 0;
3318 .omp_data_o.1.i = iD.1562;
3319 #omp parallel shared(iD.1562) -> outer parallel
3320 .omp_data_i.1 = &.omp_data_o.1
3321 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3323 .omp_data_o.2.i = iD.1562; -> **
3324 #omp parallel shared(iD.1562) -> inner parallel
3325 .omp_data_i.2 = &.omp_data_o.2
3326 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3329 ** This is a problem. The symbol iD.1562 cannot be referenced
3330 inside the body of the outer parallel region. But since we are
3331 emitting this copy operation while expanding the inner parallel
3332 directive, we need to access the CTX structure of the outer
3333 parallel directive to get the correct mapping:
3335 .omp_data_o.2.i = .omp_data_i.1->i
3337 Since there may be other workshare or parallel directives enclosing
3338 the parallel directive, it may be necessary to walk up the context
3339 parent chain. This is not a problem in general because nested
3340 parallelism happens only rarely. */
3342 static tree
3343 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3345 tree t;
3346 omp_context *up;
3348 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3349 t = maybe_lookup_decl (decl, up);
3351 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3353 return t ? t : decl;
3357 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3358 in outer contexts. */
3360 static tree
3361 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3363 tree t = NULL;
3364 omp_context *up;
3366 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3367 t = maybe_lookup_decl (decl, up);
3369 return t ? t : decl;
3373 /* Construct the initialization value for reduction CLAUSE. */
3375 tree
3376 omp_reduction_init (tree clause, tree type)
3378 location_t loc = OMP_CLAUSE_LOCATION (clause);
3379 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
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
3415 gcc_assert (INTEGRAL_TYPE_P (type));
3416 return TYPE_MIN_VALUE (type);
3419 case MIN_EXPR:
3420 if (SCALAR_FLOAT_TYPE_P (type))
3422 REAL_VALUE_TYPE max;
3423 if (HONOR_INFINITIES (type))
3424 real_inf (&max);
3425 else
3426 real_maxval (&max, 0, TYPE_MODE (type));
3427 return build_real (type, max);
3429 else
3431 gcc_assert (INTEGRAL_TYPE_P (type));
3432 return TYPE_MAX_VALUE (type);
3435 default:
3436 gcc_unreachable ();
3440 /* Return alignment to be assumed for var in CLAUSE, which should be
3441 OMP_CLAUSE_ALIGNED. */
3443 static tree
3444 omp_clause_aligned_alignment (tree clause)
3446 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3447 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3449 /* Otherwise return implementation defined alignment. */
3450 unsigned int al = 1;
3451 machine_mode mode, vmode;
3452 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3453 if (vs)
3454 vs = 1 << floor_log2 (vs);
3455 static enum mode_class classes[]
3456 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3457 for (int i = 0; i < 4; i += 2)
3458 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3459 mode != VOIDmode;
3460 mode = GET_MODE_WIDER_MODE (mode))
3462 vmode = targetm.vectorize.preferred_simd_mode (mode);
3463 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3464 continue;
3465 while (vs
3466 && GET_MODE_SIZE (vmode) < vs
3467 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3468 vmode = GET_MODE_2XWIDER_MODE (vmode);
3470 tree type = lang_hooks.types.type_for_mode (mode, 1);
3471 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3472 continue;
3473 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3474 / GET_MODE_SIZE (mode));
3475 if (TYPE_MODE (type) != vmode)
3476 continue;
3477 if (TYPE_ALIGN_UNIT (type) > al)
3478 al = TYPE_ALIGN_UNIT (type);
3480 return build_int_cst (integer_type_node, al);
3483 /* Return maximum possible vectorization factor for the target. */
3485 static int
3486 omp_max_vf (void)
3488 if (!optimize
3489 || optimize_debug
3490 || !flag_tree_loop_optimize
3491 || (!flag_tree_loop_vectorize
3492 && (global_options_set.x_flag_tree_loop_vectorize
3493 || global_options_set.x_flag_tree_vectorize)))
3494 return 1;
3496 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3497 if (vs)
3499 vs = 1 << floor_log2 (vs);
3500 return vs;
3502 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3503 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3504 return GET_MODE_NUNITS (vqimode);
3505 return 1;
3508 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3509 privatization. */
3511 static bool
3512 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3513 tree &idx, tree &lane, tree &ivar, tree &lvar)
3515 if (max_vf == 0)
3517 max_vf = omp_max_vf ();
3518 if (max_vf > 1)
3520 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3521 OMP_CLAUSE_SAFELEN);
3522 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3523 max_vf = 1;
3524 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3525 max_vf) == -1)
3526 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3528 if (max_vf > 1)
3530 idx = create_tmp_var (unsigned_type_node);
3531 lane = create_tmp_var (unsigned_type_node);
3534 if (max_vf == 1)
3535 return false;
3537 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3538 tree avar = create_tmp_var_raw (atype);
3539 if (TREE_ADDRESSABLE (new_var))
3540 TREE_ADDRESSABLE (avar) = 1;
3541 DECL_ATTRIBUTES (avar)
3542 = tree_cons (get_identifier ("omp simd array"), NULL,
3543 DECL_ATTRIBUTES (avar));
3544 gimple_add_tmp_var (avar);
3545 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3546 NULL_TREE, NULL_TREE);
3547 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3548 NULL_TREE, NULL_TREE);
3549 if (DECL_P (new_var))
3551 SET_DECL_VALUE_EXPR (new_var, lvar);
3552 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3554 return true;
3557 /* Helper function of lower_rec_input_clauses. For a reference
3558 in simd reduction, add an underlying variable it will reference. */
3560 static void
3561 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3563 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3564 if (TREE_CONSTANT (z))
3566 const char *name = NULL;
3567 if (DECL_NAME (new_vard))
3568 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3570 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3571 gimple_add_tmp_var (z);
3572 TREE_ADDRESSABLE (z) = 1;
3573 z = build_fold_addr_expr_loc (loc, z);
3574 gimplify_assign (new_vard, z, ilist);
3578 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3579 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3580 private variables. Initialization statements go in ILIST, while calls
3581 to destructors go in DLIST. */
3583 static void
3584 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3585 omp_context *ctx, struct omp_for_data *fd)
3587 tree c, dtor, copyin_seq, x, ptr;
3588 bool copyin_by_ref = false;
3589 bool lastprivate_firstprivate = false;
3590 bool reduction_omp_orig_ref = false;
3591 int pass;
3592 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3593 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3594 int max_vf = 0;
3595 tree lane = NULL_TREE, idx = NULL_TREE;
3596 tree ivar = NULL_TREE, lvar = NULL_TREE;
3597 gimple_seq llist[2] = { NULL, NULL };
3599 copyin_seq = NULL;
3601 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3602 with data sharing clauses referencing variable sized vars. That
3603 is unnecessarily hard to support and very unlikely to result in
3604 vectorized code anyway. */
3605 if (is_simd)
3606 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3607 switch (OMP_CLAUSE_CODE (c))
3609 case OMP_CLAUSE_LINEAR:
3610 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3611 max_vf = 1;
3612 /* FALLTHRU */
3613 case OMP_CLAUSE_REDUCTION:
3614 case OMP_CLAUSE_PRIVATE:
3615 case OMP_CLAUSE_FIRSTPRIVATE:
3616 case OMP_CLAUSE_LASTPRIVATE:
3617 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3618 max_vf = 1;
3619 break;
3620 default:
3621 continue;
3624 /* Do all the fixed sized types in the first pass, and the variable sized
3625 types in the second pass. This makes sure that the scalar arguments to
3626 the variable sized types are processed before we use them in the
3627 variable sized operations. */
3628 for (pass = 0; pass < 2; ++pass)
3630 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3632 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3633 tree var, new_var;
3634 bool by_ref;
3635 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3637 switch (c_kind)
3639 case OMP_CLAUSE_PRIVATE:
3640 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3641 continue;
3642 break;
3643 case OMP_CLAUSE_SHARED:
3644 /* Ignore shared directives in teams construct. */
3645 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3646 continue;
3647 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3649 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3650 continue;
3652 case OMP_CLAUSE_FIRSTPRIVATE:
3653 case OMP_CLAUSE_COPYIN:
3654 case OMP_CLAUSE_LINEAR:
3655 break;
3656 case OMP_CLAUSE_REDUCTION:
3657 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3658 reduction_omp_orig_ref = true;
3659 break;
3660 case OMP_CLAUSE__LOOPTEMP_:
3661 /* Handle _looptemp_ clauses only on parallel. */
3662 if (fd)
3663 continue;
3664 break;
3665 case OMP_CLAUSE_LASTPRIVATE:
3666 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3668 lastprivate_firstprivate = true;
3669 if (pass != 0)
3670 continue;
3672 /* Even without corresponding firstprivate, if
3673 decl is Fortran allocatable, it needs outer var
3674 reference. */
3675 else if (pass == 0
3676 && lang_hooks.decls.omp_private_outer_ref
3677 (OMP_CLAUSE_DECL (c)))
3678 lastprivate_firstprivate = true;
3679 break;
3680 case OMP_CLAUSE_ALIGNED:
3681 if (pass == 0)
3682 continue;
3683 var = OMP_CLAUSE_DECL (c);
3684 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3685 && !is_global_var (var))
3687 new_var = maybe_lookup_decl (var, ctx);
3688 if (new_var == NULL_TREE)
3689 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3690 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3691 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3692 omp_clause_aligned_alignment (c));
3693 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3694 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3695 gimplify_and_add (x, ilist);
3697 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3698 && is_global_var (var))
3700 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3701 new_var = lookup_decl (var, ctx);
3702 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3703 t = build_fold_addr_expr_loc (clause_loc, t);
3704 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3705 t = build_call_expr_loc (clause_loc, t2, 2, t,
3706 omp_clause_aligned_alignment (c));
3707 t = fold_convert_loc (clause_loc, ptype, t);
3708 x = create_tmp_var (ptype);
3709 t = build2 (MODIFY_EXPR, ptype, x, t);
3710 gimplify_and_add (t, ilist);
3711 t = build_simple_mem_ref_loc (clause_loc, x);
3712 SET_DECL_VALUE_EXPR (new_var, t);
3713 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3715 continue;
3716 default:
3717 continue;
3720 new_var = var = OMP_CLAUSE_DECL (c);
3721 if (c_kind != OMP_CLAUSE_COPYIN)
3722 new_var = lookup_decl (var, ctx);
3724 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3726 if (pass != 0)
3727 continue;
3729 else if (is_variable_sized (var))
3731 /* For variable sized types, we need to allocate the
3732 actual storage here. Call alloca and store the
3733 result in the pointer decl that we created elsewhere. */
3734 if (pass == 0)
3735 continue;
3737 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3739 gcall *stmt;
3740 tree tmp, atmp;
3742 ptr = DECL_VALUE_EXPR (new_var);
3743 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3744 ptr = TREE_OPERAND (ptr, 0);
3745 gcc_assert (DECL_P (ptr));
3746 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3748 /* void *tmp = __builtin_alloca */
3749 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3750 stmt = gimple_build_call (atmp, 1, x);
3751 tmp = create_tmp_var_raw (ptr_type_node);
3752 gimple_add_tmp_var (tmp);
3753 gimple_call_set_lhs (stmt, tmp);
3755 gimple_seq_add_stmt (ilist, stmt);
3757 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3758 gimplify_assign (ptr, x, ilist);
3761 else if (is_reference (var))
3763 /* For references that are being privatized for Fortran,
3764 allocate new backing storage for the new pointer
3765 variable. This allows us to avoid changing all the
3766 code that expects a pointer to something that expects
3767 a direct variable. */
3768 if (pass == 0)
3769 continue;
3771 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3772 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3774 x = build_receiver_ref (var, false, ctx);
3775 x = build_fold_addr_expr_loc (clause_loc, x);
3777 else if (TREE_CONSTANT (x))
3779 /* For reduction in SIMD loop, defer adding the
3780 initialization of the reference, because if we decide
3781 to use SIMD array for it, the initilization could cause
3782 expansion ICE. */
3783 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3784 x = NULL_TREE;
3785 else
3787 const char *name = NULL;
3788 if (DECL_NAME (var))
3789 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3791 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3792 name);
3793 gimple_add_tmp_var (x);
3794 TREE_ADDRESSABLE (x) = 1;
3795 x = build_fold_addr_expr_loc (clause_loc, x);
3798 else
3800 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3801 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3804 if (x)
3806 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3807 gimplify_assign (new_var, x, ilist);
3810 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3812 else if (c_kind == OMP_CLAUSE_REDUCTION
3813 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3815 if (pass == 0)
3816 continue;
3818 else if (pass != 0)
3819 continue;
3821 switch (OMP_CLAUSE_CODE (c))
3823 case OMP_CLAUSE_SHARED:
3824 /* Ignore shared directives in teams construct. */
3825 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3826 continue;
3827 /* Shared global vars are just accessed directly. */
3828 if (is_global_var (new_var))
3829 break;
3830 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3831 needs to be delayed until after fixup_child_record_type so
3832 that we get the correct type during the dereference. */
3833 by_ref = use_pointer_for_field (var, ctx);
3834 x = build_receiver_ref (var, by_ref, ctx);
3835 SET_DECL_VALUE_EXPR (new_var, x);
3836 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3838 /* ??? If VAR is not passed by reference, and the variable
3839 hasn't been initialized yet, then we'll get a warning for
3840 the store into the omp_data_s structure. Ideally, we'd be
3841 able to notice this and not store anything at all, but
3842 we're generating code too early. Suppress the warning. */
3843 if (!by_ref)
3844 TREE_NO_WARNING (var) = 1;
3845 break;
3847 case OMP_CLAUSE_LASTPRIVATE:
3848 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3849 break;
3850 /* FALLTHRU */
3852 case OMP_CLAUSE_PRIVATE:
3853 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3854 x = build_outer_var_ref (var, ctx);
3855 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3857 if (is_task_ctx (ctx))
3858 x = build_receiver_ref (var, false, ctx);
3859 else
3860 x = build_outer_var_ref (var, ctx);
3862 else
3863 x = NULL;
3864 do_private:
3865 tree nx;
3866 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3867 if (is_simd)
3869 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3870 if ((TREE_ADDRESSABLE (new_var) || nx || y
3871 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3872 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3873 idx, lane, ivar, lvar))
3875 if (nx)
3876 x = lang_hooks.decls.omp_clause_default_ctor
3877 (c, unshare_expr (ivar), x);
3878 if (nx && x)
3879 gimplify_and_add (x, &llist[0]);
3880 if (y)
3882 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3883 if (y)
3885 gimple_seq tseq = NULL;
3887 dtor = y;
3888 gimplify_stmt (&dtor, &tseq);
3889 gimple_seq_add_seq (&llist[1], tseq);
3892 break;
3895 if (nx)
3896 gimplify_and_add (nx, ilist);
3897 /* FALLTHRU */
3899 do_dtor:
3900 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3901 if (x)
3903 gimple_seq tseq = NULL;
3905 dtor = x;
3906 gimplify_stmt (&dtor, &tseq);
3907 gimple_seq_add_seq (dlist, tseq);
3909 break;
3911 case OMP_CLAUSE_LINEAR:
3912 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3913 goto do_firstprivate;
3914 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3915 x = NULL;
3916 else
3917 x = build_outer_var_ref (var, ctx);
3918 goto do_private;
3920 case OMP_CLAUSE_FIRSTPRIVATE:
3921 if (is_task_ctx (ctx))
3923 if (is_reference (var) || is_variable_sized (var))
3924 goto do_dtor;
3925 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3926 ctx))
3927 || use_pointer_for_field (var, NULL))
3929 x = build_receiver_ref (var, false, ctx);
3930 SET_DECL_VALUE_EXPR (new_var, x);
3931 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3932 goto do_dtor;
3935 do_firstprivate:
3936 x = build_outer_var_ref (var, ctx);
3937 if (is_simd)
3939 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3940 && gimple_omp_for_combined_into_p (ctx->stmt))
3942 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3943 tree stept = TREE_TYPE (t);
3944 tree ct = find_omp_clause (clauses,
3945 OMP_CLAUSE__LOOPTEMP_);
3946 gcc_assert (ct);
3947 tree l = OMP_CLAUSE_DECL (ct);
3948 tree n1 = fd->loop.n1;
3949 tree step = fd->loop.step;
3950 tree itype = TREE_TYPE (l);
3951 if (POINTER_TYPE_P (itype))
3952 itype = signed_type_for (itype);
3953 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3954 if (TYPE_UNSIGNED (itype)
3955 && fd->loop.cond_code == GT_EXPR)
3956 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3957 fold_build1 (NEGATE_EXPR, itype, l),
3958 fold_build1 (NEGATE_EXPR,
3959 itype, step));
3960 else
3961 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3962 t = fold_build2 (MULT_EXPR, stept,
3963 fold_convert (stept, l), t);
3965 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3967 x = lang_hooks.decls.omp_clause_linear_ctor
3968 (c, new_var, x, t);
3969 gimplify_and_add (x, ilist);
3970 goto do_dtor;
3973 if (POINTER_TYPE_P (TREE_TYPE (x)))
3974 x = fold_build2 (POINTER_PLUS_EXPR,
3975 TREE_TYPE (x), x, t);
3976 else
3977 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3980 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3981 || TREE_ADDRESSABLE (new_var))
3982 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3983 idx, lane, ivar, lvar))
3985 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3987 tree iv = create_tmp_var (TREE_TYPE (new_var));
3988 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
3989 gimplify_and_add (x, ilist);
3990 gimple_stmt_iterator gsi
3991 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
3992 gassign *g
3993 = gimple_build_assign (unshare_expr (lvar), iv);
3994 gsi_insert_before_without_update (&gsi, g,
3995 GSI_SAME_STMT);
3996 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3997 enum tree_code code = PLUS_EXPR;
3998 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
3999 code = POINTER_PLUS_EXPR;
4000 g = gimple_build_assign (iv, code, iv, t);
4001 gsi_insert_before_without_update (&gsi, g,
4002 GSI_SAME_STMT);
4003 break;
4005 x = lang_hooks.decls.omp_clause_copy_ctor
4006 (c, unshare_expr (ivar), x);
4007 gimplify_and_add (x, &llist[0]);
4008 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4009 if (x)
4011 gimple_seq tseq = NULL;
4013 dtor = x;
4014 gimplify_stmt (&dtor, &tseq);
4015 gimple_seq_add_seq (&llist[1], tseq);
4017 break;
4020 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4021 gimplify_and_add (x, ilist);
4022 goto do_dtor;
4024 case OMP_CLAUSE__LOOPTEMP_:
4025 gcc_assert (is_parallel_ctx (ctx));
4026 x = build_outer_var_ref (var, ctx);
4027 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4028 gimplify_and_add (x, ilist);
4029 break;
4031 case OMP_CLAUSE_COPYIN:
4032 by_ref = use_pointer_for_field (var, NULL);
4033 x = build_receiver_ref (var, by_ref, ctx);
4034 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4035 append_to_statement_list (x, &copyin_seq);
4036 copyin_by_ref |= by_ref;
4037 break;
4039 case OMP_CLAUSE_REDUCTION:
4040 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4042 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4043 gimple tseq;
4044 x = build_outer_var_ref (var, ctx);
4046 if (is_reference (var)
4047 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4048 TREE_TYPE (x)))
4049 x = build_fold_addr_expr_loc (clause_loc, x);
4050 SET_DECL_VALUE_EXPR (placeholder, x);
4051 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4052 tree new_vard = new_var;
4053 if (is_reference (var))
4055 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4056 new_vard = TREE_OPERAND (new_var, 0);
4057 gcc_assert (DECL_P (new_vard));
4059 if (is_simd
4060 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4061 idx, lane, ivar, lvar))
4063 if (new_vard == new_var)
4065 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4066 SET_DECL_VALUE_EXPR (new_var, ivar);
4068 else
4070 SET_DECL_VALUE_EXPR (new_vard,
4071 build_fold_addr_expr (ivar));
4072 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4074 x = lang_hooks.decls.omp_clause_default_ctor
4075 (c, unshare_expr (ivar),
4076 build_outer_var_ref (var, ctx));
4077 if (x)
4078 gimplify_and_add (x, &llist[0]);
4079 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4081 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4082 lower_omp (&tseq, ctx);
4083 gimple_seq_add_seq (&llist[0], tseq);
4085 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4086 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4087 lower_omp (&tseq, ctx);
4088 gimple_seq_add_seq (&llist[1], tseq);
4089 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4090 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4091 if (new_vard == new_var)
4092 SET_DECL_VALUE_EXPR (new_var, lvar);
4093 else
4094 SET_DECL_VALUE_EXPR (new_vard,
4095 build_fold_addr_expr (lvar));
4096 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4097 if (x)
4099 tseq = NULL;
4100 dtor = x;
4101 gimplify_stmt (&dtor, &tseq);
4102 gimple_seq_add_seq (&llist[1], tseq);
4104 break;
4106 /* If this is a reference to constant size reduction var
4107 with placeholder, we haven't emitted the initializer
4108 for it because it is undesirable if SIMD arrays are used.
4109 But if they aren't used, we need to emit the deferred
4110 initialization now. */
4111 else if (is_reference (var) && is_simd)
4112 handle_simd_reference (clause_loc, new_vard, ilist);
4113 x = lang_hooks.decls.omp_clause_default_ctor
4114 (c, unshare_expr (new_var),
4115 build_outer_var_ref (var, ctx));
4116 if (x)
4117 gimplify_and_add (x, ilist);
4118 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4120 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4121 lower_omp (&tseq, ctx);
4122 gimple_seq_add_seq (ilist, tseq);
4124 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4125 if (is_simd)
4127 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4128 lower_omp (&tseq, ctx);
4129 gimple_seq_add_seq (dlist, tseq);
4130 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4132 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4133 goto do_dtor;
4135 else
4137 x = omp_reduction_init (c, TREE_TYPE (new_var));
4138 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4139 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4141 /* reduction(-:var) sums up the partial results, so it
4142 acts identically to reduction(+:var). */
4143 if (code == MINUS_EXPR)
4144 code = PLUS_EXPR;
4146 tree new_vard = new_var;
4147 if (is_simd && is_reference (var))
4149 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4150 new_vard = TREE_OPERAND (new_var, 0);
4151 gcc_assert (DECL_P (new_vard));
4153 if (is_simd
4154 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4155 idx, lane, ivar, lvar))
4157 tree ref = build_outer_var_ref (var, ctx);
4159 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4161 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4162 ref = build_outer_var_ref (var, ctx);
4163 gimplify_assign (ref, x, &llist[1]);
4165 if (new_vard != new_var)
4167 SET_DECL_VALUE_EXPR (new_vard,
4168 build_fold_addr_expr (lvar));
4169 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4172 else
4174 if (is_reference (var) && is_simd)
4175 handle_simd_reference (clause_loc, new_vard, ilist);
4176 gimplify_assign (new_var, x, ilist);
4177 if (is_simd)
4179 tree ref = build_outer_var_ref (var, ctx);
4181 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4182 ref = build_outer_var_ref (var, ctx);
4183 gimplify_assign (ref, x, dlist);
4187 break;
4189 default:
4190 gcc_unreachable ();
4195 if (lane)
4197 tree uid = create_tmp_var (ptr_type_node, "simduid");
4198 /* Don't want uninit warnings on simduid, it is always uninitialized,
4199 but we use it not for the value, but for the DECL_UID only. */
4200 TREE_NO_WARNING (uid) = 1;
4201 gimple g
4202 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4203 gimple_call_set_lhs (g, lane);
4204 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4205 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4206 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4207 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4208 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4209 gimple_omp_for_set_clauses (ctx->stmt, c);
4210 g = gimple_build_assign (lane, INTEGER_CST,
4211 build_int_cst (unsigned_type_node, 0));
4212 gimple_seq_add_stmt (ilist, g);
4213 for (int i = 0; i < 2; i++)
4214 if (llist[i])
4216 tree vf = create_tmp_var (unsigned_type_node);
4217 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4218 gimple_call_set_lhs (g, vf);
4219 gimple_seq *seq = i == 0 ? ilist : dlist;
4220 gimple_seq_add_stmt (seq, g);
4221 tree t = build_int_cst (unsigned_type_node, 0);
4222 g = gimple_build_assign (idx, INTEGER_CST, t);
4223 gimple_seq_add_stmt (seq, g);
4224 tree body = create_artificial_label (UNKNOWN_LOCATION);
4225 tree header = create_artificial_label (UNKNOWN_LOCATION);
4226 tree end = create_artificial_label (UNKNOWN_LOCATION);
4227 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4228 gimple_seq_add_stmt (seq, gimple_build_label (body));
4229 gimple_seq_add_seq (seq, llist[i]);
4230 t = build_int_cst (unsigned_type_node, 1);
4231 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4232 gimple_seq_add_stmt (seq, g);
4233 gimple_seq_add_stmt (seq, gimple_build_label (header));
4234 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4235 gimple_seq_add_stmt (seq, g);
4236 gimple_seq_add_stmt (seq, gimple_build_label (end));
4240 /* The copyin sequence is not to be executed by the main thread, since
4241 that would result in self-copies. Perhaps not visible to scalars,
4242 but it certainly is to C++ operator=. */
4243 if (copyin_seq)
4245 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4247 x = build2 (NE_EXPR, boolean_type_node, x,
4248 build_int_cst (TREE_TYPE (x), 0));
4249 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4250 gimplify_and_add (x, ilist);
4253 /* If any copyin variable is passed by reference, we must ensure the
4254 master thread doesn't modify it before it is copied over in all
4255 threads. Similarly for variables in both firstprivate and
4256 lastprivate clauses we need to ensure the lastprivate copying
4257 happens after firstprivate copying in all threads. And similarly
4258 for UDRs if initializer expression refers to omp_orig. */
4259 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4261 /* Don't add any barrier for #pragma omp simd or
4262 #pragma omp distribute. */
4263 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4264 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4265 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4268 /* If max_vf is non-zero, then we can use only a vectorization factor
4269 up to the max_vf we chose. So stick it into the safelen clause. */
4270 if (max_vf)
4272 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4273 OMP_CLAUSE_SAFELEN);
4274 if (c == NULL_TREE
4275 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4276 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4277 max_vf) == 1))
4279 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4280 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4281 max_vf);
4282 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4283 gimple_omp_for_set_clauses (ctx->stmt, c);
4289 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4290 both parallel and workshare constructs. PREDICATE may be NULL if it's
4291 always true. */
4293 static void
4294 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4295 omp_context *ctx)
4297 tree x, c, label = NULL, orig_clauses = clauses;
4298 bool par_clauses = false;
4299 tree simduid = NULL, lastlane = NULL;
4301 /* Early exit if there are no lastprivate or linear clauses. */
4302 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4303 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4304 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4305 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4306 break;
4307 if (clauses == NULL)
4309 /* If this was a workshare clause, see if it had been combined
4310 with its parallel. In that case, look for the clauses on the
4311 parallel statement itself. */
4312 if (is_parallel_ctx (ctx))
4313 return;
4315 ctx = ctx->outer;
4316 if (ctx == NULL || !is_parallel_ctx (ctx))
4317 return;
4319 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4320 OMP_CLAUSE_LASTPRIVATE);
4321 if (clauses == NULL)
4322 return;
4323 par_clauses = true;
4326 if (predicate)
4328 gcond *stmt;
4329 tree label_true, arm1, arm2;
4331 label = create_artificial_label (UNKNOWN_LOCATION);
4332 label_true = create_artificial_label (UNKNOWN_LOCATION);
4333 arm1 = TREE_OPERAND (predicate, 0);
4334 arm2 = TREE_OPERAND (predicate, 1);
4335 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4336 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4337 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4338 label_true, label);
4339 gimple_seq_add_stmt (stmt_list, stmt);
4340 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4343 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4344 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4346 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4347 if (simduid)
4348 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4351 for (c = clauses; c ;)
4353 tree var, new_var;
4354 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4356 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4357 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4358 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4360 var = OMP_CLAUSE_DECL (c);
4361 new_var = lookup_decl (var, ctx);
4363 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4365 tree val = DECL_VALUE_EXPR (new_var);
4366 if (TREE_CODE (val) == ARRAY_REF
4367 && VAR_P (TREE_OPERAND (val, 0))
4368 && lookup_attribute ("omp simd array",
4369 DECL_ATTRIBUTES (TREE_OPERAND (val,
4370 0))))
4372 if (lastlane == NULL)
4374 lastlane = create_tmp_var (unsigned_type_node);
4375 gcall *g
4376 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4377 2, simduid,
4378 TREE_OPERAND (val, 1));
4379 gimple_call_set_lhs (g, lastlane);
4380 gimple_seq_add_stmt (stmt_list, g);
4382 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4383 TREE_OPERAND (val, 0), lastlane,
4384 NULL_TREE, NULL_TREE);
4388 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4389 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4391 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4392 gimple_seq_add_seq (stmt_list,
4393 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4394 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4396 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4397 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4399 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4400 gimple_seq_add_seq (stmt_list,
4401 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4402 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4405 x = build_outer_var_ref (var, ctx);
4406 if (is_reference (var))
4407 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4408 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4409 gimplify_and_add (x, stmt_list);
4411 c = OMP_CLAUSE_CHAIN (c);
4412 if (c == NULL && !par_clauses)
4414 /* If this was a workshare clause, see if it had been combined
4415 with its parallel. In that case, continue looking for the
4416 clauses also on the parallel statement itself. */
4417 if (is_parallel_ctx (ctx))
4418 break;
4420 ctx = ctx->outer;
4421 if (ctx == NULL || !is_parallel_ctx (ctx))
4422 break;
4424 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4425 OMP_CLAUSE_LASTPRIVATE);
4426 par_clauses = true;
4430 if (label)
4431 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4434 static void
4435 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4436 tree tid, tree var, tree new_var)
4438 /* The atomic add at the end of the sum creates unnecessary
4439 write contention on accelerators. To work around this,
4440 create an array to store the partial reductions. Later, in
4441 lower_omp_for (for openacc), the values of array will be
4442 combined. */
4444 tree t = NULL_TREE, array, x;
4445 tree type = get_base_type (var);
4446 gimple stmt;
4448 /* Now insert the partial reductions into the array. */
4450 /* Find the reduction array. */
4452 tree ptype = build_pointer_type (type);
4454 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4455 t = build_receiver_ref (t, false, ctx->outer);
4457 array = create_tmp_var (ptype);
4458 gimplify_assign (array, t, stmt_seqp);
4460 tree ptr = create_tmp_var (TREE_TYPE (array));
4462 /* Find the reduction array. */
4464 /* testing a unary conversion. */
4465 tree offset = create_tmp_var (sizetype);
4466 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4467 stmt_seqp);
4468 t = create_tmp_var (sizetype);
4469 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4470 stmt_seqp);
4471 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4472 gimple_seq_add_stmt (stmt_seqp, stmt);
4474 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4475 of adding sizeof(var) to the array? */
4476 ptr = create_tmp_var (ptype);
4477 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4478 offset);
4479 gimple_seq_add_stmt (stmt_seqp, stmt);
4481 /* Move the local sum to gfc$sum[i]. */
4482 x = unshare_expr (build_simple_mem_ref (ptr));
4483 stmt = gimplify_assign (x, new_var, stmt_seqp);
4486 /* Generate code to implement the REDUCTION clauses. */
4488 static void
4489 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4491 gimple_seq sub_seq = NULL;
4492 gimple stmt;
4493 tree x, c, tid = NULL_TREE;
4494 int count = 0;
4496 /* SIMD reductions are handled in lower_rec_input_clauses. */
4497 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4498 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4499 return;
4501 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4502 update in that case, otherwise use a lock. */
4503 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4504 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4506 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4508 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4509 count = -1;
4510 break;
4512 count++;
4515 if (count == 0)
4516 return;
4518 /* Initialize thread info for OpenACC. */
4519 if (is_gimple_omp_oacc (ctx->stmt))
4521 /* Get the current thread id. */
4522 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4523 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4524 gimple stmt = gimple_build_call (call, 0);
4525 gimple_call_set_lhs (stmt, tid);
4526 gimple_seq_add_stmt (stmt_seqp, stmt);
4529 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4531 tree var, ref, new_var;
4532 enum tree_code code;
4533 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4535 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4536 continue;
4538 var = OMP_CLAUSE_DECL (c);
4539 new_var = lookup_decl (var, ctx);
4540 if (is_reference (var))
4541 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4542 ref = build_outer_var_ref (var, ctx);
4543 code = OMP_CLAUSE_REDUCTION_CODE (c);
4545 /* reduction(-:var) sums up the partial results, so it acts
4546 identically to reduction(+:var). */
4547 if (code == MINUS_EXPR)
4548 code = PLUS_EXPR;
4550 if (is_gimple_omp_oacc (ctx->stmt))
4552 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4554 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4556 else if (count == 1)
4558 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4560 addr = save_expr (addr);
4561 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4562 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4563 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4564 gimplify_and_add (x, stmt_seqp);
4565 return;
4567 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4569 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4571 if (is_reference (var)
4572 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4573 TREE_TYPE (ref)))
4574 ref = build_fold_addr_expr_loc (clause_loc, ref);
4575 SET_DECL_VALUE_EXPR (placeholder, ref);
4576 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4577 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4578 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4579 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4580 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4582 else
4584 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4585 ref = build_outer_var_ref (var, ctx);
4586 gimplify_assign (ref, x, &sub_seq);
4590 if (is_gimple_omp_oacc (ctx->stmt))
4591 return;
4593 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4595 gimple_seq_add_stmt (stmt_seqp, stmt);
4597 gimple_seq_add_seq (stmt_seqp, sub_seq);
4599 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4601 gimple_seq_add_stmt (stmt_seqp, stmt);
4605 /* Generate code to implement the COPYPRIVATE clauses. */
4607 static void
4608 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4609 omp_context *ctx)
4611 tree c;
4613 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4615 tree var, new_var, ref, x;
4616 bool by_ref;
4617 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4619 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4620 continue;
4622 var = OMP_CLAUSE_DECL (c);
4623 by_ref = use_pointer_for_field (var, NULL);
4625 ref = build_sender_ref (var, ctx);
4626 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4627 if (by_ref)
4629 x = build_fold_addr_expr_loc (clause_loc, new_var);
4630 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4632 gimplify_assign (ref, x, slist);
4634 ref = build_receiver_ref (var, false, ctx);
4635 if (by_ref)
4637 ref = fold_convert_loc (clause_loc,
4638 build_pointer_type (TREE_TYPE (new_var)),
4639 ref);
4640 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4642 if (is_reference (var))
4644 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4645 ref = build_simple_mem_ref_loc (clause_loc, ref);
4646 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4648 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4649 gimplify_and_add (x, rlist);
4654 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4655 and REDUCTION from the sender (aka parent) side. */
4657 static void
4658 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4659 omp_context *ctx)
4661 tree c;
4663 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4665 tree val, ref, x, var;
4666 bool by_ref, do_in = false, do_out = false;
4667 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4669 switch (OMP_CLAUSE_CODE (c))
4671 case OMP_CLAUSE_PRIVATE:
4672 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4673 break;
4674 continue;
4675 case OMP_CLAUSE_FIRSTPRIVATE:
4676 case OMP_CLAUSE_COPYIN:
4677 case OMP_CLAUSE_LASTPRIVATE:
4678 case OMP_CLAUSE_REDUCTION:
4679 case OMP_CLAUSE__LOOPTEMP_:
4680 break;
4681 default:
4682 continue;
4685 val = OMP_CLAUSE_DECL (c);
4686 var = lookup_decl_in_outer_ctx (val, ctx);
4688 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4689 && is_global_var (var))
4690 continue;
4691 if (is_variable_sized (val))
4692 continue;
4693 by_ref = use_pointer_for_field (val, NULL);
4695 switch (OMP_CLAUSE_CODE (c))
4697 case OMP_CLAUSE_PRIVATE:
4698 case OMP_CLAUSE_FIRSTPRIVATE:
4699 case OMP_CLAUSE_COPYIN:
4700 case OMP_CLAUSE__LOOPTEMP_:
4701 do_in = true;
4702 break;
4704 case OMP_CLAUSE_LASTPRIVATE:
4705 if (by_ref || is_reference (val))
4707 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4708 continue;
4709 do_in = true;
4711 else
4713 do_out = true;
4714 if (lang_hooks.decls.omp_private_outer_ref (val))
4715 do_in = true;
4717 break;
4719 case OMP_CLAUSE_REDUCTION:
4720 do_in = true;
4721 do_out = !(by_ref || is_reference (val));
4722 break;
4724 default:
4725 gcc_unreachable ();
4728 if (do_in)
4730 ref = build_sender_ref (val, ctx);
4731 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4732 gimplify_assign (ref, x, ilist);
4733 if (is_task_ctx (ctx))
4734 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4737 if (do_out)
4739 ref = build_sender_ref (val, ctx);
4740 gimplify_assign (var, ref, olist);
4745 /* Generate code to implement SHARED from the sender (aka parent)
4746 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4747 list things that got automatically shared. */
4749 static void
4750 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4752 tree var, ovar, nvar, f, x, record_type;
4754 if (ctx->record_type == NULL)
4755 return;
4757 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4758 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4760 ovar = DECL_ABSTRACT_ORIGIN (f);
4761 nvar = maybe_lookup_decl (ovar, ctx);
4762 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4763 continue;
4765 /* If CTX is a nested parallel directive. Find the immediately
4766 enclosing parallel or workshare construct that contains a
4767 mapping for OVAR. */
4768 var = lookup_decl_in_outer_ctx (ovar, ctx);
4770 if (use_pointer_for_field (ovar, ctx))
4772 x = build_sender_ref (ovar, ctx);
4773 var = build_fold_addr_expr (var);
4774 gimplify_assign (x, var, ilist);
4776 else
4778 x = build_sender_ref (ovar, ctx);
4779 gimplify_assign (x, var, ilist);
4781 if (!TREE_READONLY (var)
4782 /* We don't need to receive a new reference to a result
4783 or parm decl. In fact we may not store to it as we will
4784 invalidate any pending RSO and generate wrong gimple
4785 during inlining. */
4786 && !((TREE_CODE (var) == RESULT_DECL
4787 || TREE_CODE (var) == PARM_DECL)
4788 && DECL_BY_REFERENCE (var)))
4790 x = build_sender_ref (ovar, ctx);
4791 gimplify_assign (var, x, olist);
4798 /* A convenience function to build an empty GIMPLE_COND with just the
4799 condition. */
4801 static gcond *
4802 gimple_build_cond_empty (tree cond)
4804 enum tree_code pred_code;
4805 tree lhs, rhs;
4807 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4808 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4812 /* Build the function calls to GOMP_parallel_start etc to actually
4813 generate the parallel operation. REGION is the parallel region
4814 being expanded. BB is the block where to insert the code. WS_ARGS
4815 will be set if this is a call to a combined parallel+workshare
4816 construct, it contains the list of additional arguments needed by
4817 the workshare construct. */
4819 static void
4820 expand_parallel_call (struct omp_region *region, basic_block bb,
4821 gomp_parallel *entry_stmt,
4822 vec<tree, va_gc> *ws_args)
4824 tree t, t1, t2, val, cond, c, clauses, flags;
4825 gimple_stmt_iterator gsi;
4826 gimple stmt;
4827 enum built_in_function start_ix;
4828 int start_ix2;
4829 location_t clause_loc;
4830 vec<tree, va_gc> *args;
4832 clauses = gimple_omp_parallel_clauses (entry_stmt);
4834 /* Determine what flavor of GOMP_parallel we will be
4835 emitting. */
4836 start_ix = BUILT_IN_GOMP_PARALLEL;
4837 if (is_combined_parallel (region))
4839 switch (region->inner->type)
4841 case GIMPLE_OMP_FOR:
4842 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4843 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4844 + (region->inner->sched_kind
4845 == OMP_CLAUSE_SCHEDULE_RUNTIME
4846 ? 3 : region->inner->sched_kind));
4847 start_ix = (enum built_in_function)start_ix2;
4848 break;
4849 case GIMPLE_OMP_SECTIONS:
4850 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4851 break;
4852 default:
4853 gcc_unreachable ();
4857 /* By default, the value of NUM_THREADS is zero (selected at run time)
4858 and there is no conditional. */
4859 cond = NULL_TREE;
4860 val = build_int_cst (unsigned_type_node, 0);
4861 flags = build_int_cst (unsigned_type_node, 0);
4863 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4864 if (c)
4865 cond = OMP_CLAUSE_IF_EXPR (c);
4867 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4868 if (c)
4870 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4871 clause_loc = OMP_CLAUSE_LOCATION (c);
4873 else
4874 clause_loc = gimple_location (entry_stmt);
4876 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4877 if (c)
4878 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4880 /* Ensure 'val' is of the correct type. */
4881 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4883 /* If we found the clause 'if (cond)', build either
4884 (cond != 0) or (cond ? val : 1u). */
4885 if (cond)
4887 cond = gimple_boolify (cond);
4889 if (integer_zerop (val))
4890 val = fold_build2_loc (clause_loc,
4891 EQ_EXPR, unsigned_type_node, cond,
4892 build_int_cst (TREE_TYPE (cond), 0));
4893 else
4895 basic_block cond_bb, then_bb, else_bb;
4896 edge e, e_then, e_else;
4897 tree tmp_then, tmp_else, tmp_join, tmp_var;
4899 tmp_var = create_tmp_var (TREE_TYPE (val));
4900 if (gimple_in_ssa_p (cfun))
4902 tmp_then = make_ssa_name (tmp_var);
4903 tmp_else = make_ssa_name (tmp_var);
4904 tmp_join = make_ssa_name (tmp_var);
4906 else
4908 tmp_then = tmp_var;
4909 tmp_else = tmp_var;
4910 tmp_join = tmp_var;
4913 e = split_block_after_labels (bb);
4914 cond_bb = e->src;
4915 bb = e->dest;
4916 remove_edge (e);
4918 then_bb = create_empty_bb (cond_bb);
4919 else_bb = create_empty_bb (then_bb);
4920 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4921 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4923 stmt = gimple_build_cond_empty (cond);
4924 gsi = gsi_start_bb (cond_bb);
4925 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4927 gsi = gsi_start_bb (then_bb);
4928 stmt = gimple_build_assign (tmp_then, val);
4929 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4931 gsi = gsi_start_bb (else_bb);
4932 stmt = gimple_build_assign
4933 (tmp_else, build_int_cst (unsigned_type_node, 1));
4934 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4936 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4937 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4938 add_bb_to_loop (then_bb, cond_bb->loop_father);
4939 add_bb_to_loop (else_bb, cond_bb->loop_father);
4940 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4941 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4943 if (gimple_in_ssa_p (cfun))
4945 gphi *phi = create_phi_node (tmp_join, bb);
4946 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4947 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4950 val = tmp_join;
4953 gsi = gsi_start_bb (bb);
4954 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4955 false, GSI_CONTINUE_LINKING);
4958 gsi = gsi_last_bb (bb);
4959 t = gimple_omp_parallel_data_arg (entry_stmt);
4960 if (t == NULL)
4961 t1 = null_pointer_node;
4962 else
4963 t1 = build_fold_addr_expr (t);
4964 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4966 vec_alloc (args, 4 + vec_safe_length (ws_args));
4967 args->quick_push (t2);
4968 args->quick_push (t1);
4969 args->quick_push (val);
4970 if (ws_args)
4971 args->splice (*ws_args);
4972 args->quick_push (flags);
4974 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4975 builtin_decl_explicit (start_ix), args);
4977 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4978 false, GSI_CONTINUE_LINKING);
4981 /* Insert a function call whose name is FUNC_NAME with the information from
4982 ENTRY_STMT into the basic_block BB. */
4984 static void
4985 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
4986 vec <tree, va_gc> *ws_args)
4988 tree t, t1, t2;
4989 gimple_stmt_iterator gsi;
4990 vec <tree, va_gc> *args;
4992 gcc_assert (vec_safe_length (ws_args) == 2);
4993 tree func_name = (*ws_args)[0];
4994 tree grain = (*ws_args)[1];
4996 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
4997 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
4998 gcc_assert (count != NULL_TREE);
4999 count = OMP_CLAUSE_OPERAND (count, 0);
5001 gsi = gsi_last_bb (bb);
5002 t = gimple_omp_parallel_data_arg (entry_stmt);
5003 if (t == NULL)
5004 t1 = null_pointer_node;
5005 else
5006 t1 = build_fold_addr_expr (t);
5007 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5009 vec_alloc (args, 4);
5010 args->quick_push (t2);
5011 args->quick_push (t1);
5012 args->quick_push (count);
5013 args->quick_push (grain);
5014 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5016 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5017 GSI_CONTINUE_LINKING);
5020 /* Build the function call to GOMP_task to actually
5021 generate the task operation. BB is the block where to insert the code. */
5023 static void
5024 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5026 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5027 gimple_stmt_iterator gsi;
5028 location_t loc = gimple_location (entry_stmt);
5030 clauses = gimple_omp_task_clauses (entry_stmt);
5032 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5033 if (c)
5034 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5035 else
5036 cond = boolean_true_node;
5038 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5039 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5040 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5041 flags = build_int_cst (unsigned_type_node,
5042 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5044 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5045 if (c)
5047 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5048 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5049 build_int_cst (unsigned_type_node, 2),
5050 build_int_cst (unsigned_type_node, 0));
5051 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5053 if (depend)
5054 depend = OMP_CLAUSE_DECL (depend);
5055 else
5056 depend = build_int_cst (ptr_type_node, 0);
5058 gsi = gsi_last_bb (bb);
5059 t = gimple_omp_task_data_arg (entry_stmt);
5060 if (t == NULL)
5061 t2 = null_pointer_node;
5062 else
5063 t2 = build_fold_addr_expr_loc (loc, t);
5064 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5065 t = gimple_omp_task_copy_fn (entry_stmt);
5066 if (t == NULL)
5067 t3 = null_pointer_node;
5068 else
5069 t3 = build_fold_addr_expr_loc (loc, t);
5071 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5072 8, t1, t2, t3,
5073 gimple_omp_task_arg_size (entry_stmt),
5074 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5075 depend);
5077 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5078 false, GSI_CONTINUE_LINKING);
5082 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5083 catch handler and return it. This prevents programs from violating the
5084 structured block semantics with throws. */
5086 static gimple_seq
5087 maybe_catch_exception (gimple_seq body)
5089 gimple g;
5090 tree decl;
5092 if (!flag_exceptions)
5093 return body;
5095 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5096 decl = lang_hooks.eh_protect_cleanup_actions ();
5097 else
5098 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5100 g = gimple_build_eh_must_not_throw (decl);
5101 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5102 GIMPLE_TRY_CATCH);
5104 return gimple_seq_alloc_with_stmt (g);
5107 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5109 static tree
5110 vec2chain (vec<tree, va_gc> *v)
5112 tree chain = NULL_TREE, t;
5113 unsigned ix;
5115 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5117 DECL_CHAIN (t) = chain;
5118 chain = t;
5121 return chain;
5125 /* Remove barriers in REGION->EXIT's block. Note that this is only
5126 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5127 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5128 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5129 removed. */
5131 static void
5132 remove_exit_barrier (struct omp_region *region)
5134 gimple_stmt_iterator gsi;
5135 basic_block exit_bb;
5136 edge_iterator ei;
5137 edge e;
5138 gimple stmt;
5139 int any_addressable_vars = -1;
5141 exit_bb = region->exit;
5143 /* If the parallel region doesn't return, we don't have REGION->EXIT
5144 block at all. */
5145 if (! exit_bb)
5146 return;
5148 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5149 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5150 statements that can appear in between are extremely limited -- no
5151 memory operations at all. Here, we allow nothing at all, so the
5152 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5153 gsi = gsi_last_bb (exit_bb);
5154 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5155 gsi_prev (&gsi);
5156 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5157 return;
5159 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5161 gsi = gsi_last_bb (e->src);
5162 if (gsi_end_p (gsi))
5163 continue;
5164 stmt = gsi_stmt (gsi);
5165 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5166 && !gimple_omp_return_nowait_p (stmt))
5168 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5169 in many cases. If there could be tasks queued, the barrier
5170 might be needed to let the tasks run before some local
5171 variable of the parallel that the task uses as shared
5172 runs out of scope. The task can be spawned either
5173 from within current function (this would be easy to check)
5174 or from some function it calls and gets passed an address
5175 of such a variable. */
5176 if (any_addressable_vars < 0)
5178 gomp_parallel *parallel_stmt
5179 = as_a <gomp_parallel *> (last_stmt (region->entry));
5180 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5181 tree local_decls, block, decl;
5182 unsigned ix;
5184 any_addressable_vars = 0;
5185 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5186 if (TREE_ADDRESSABLE (decl))
5188 any_addressable_vars = 1;
5189 break;
5191 for (block = gimple_block (stmt);
5192 !any_addressable_vars
5193 && block
5194 && TREE_CODE (block) == BLOCK;
5195 block = BLOCK_SUPERCONTEXT (block))
5197 for (local_decls = BLOCK_VARS (block);
5198 local_decls;
5199 local_decls = DECL_CHAIN (local_decls))
5200 if (TREE_ADDRESSABLE (local_decls))
5202 any_addressable_vars = 1;
5203 break;
5205 if (block == gimple_block (parallel_stmt))
5206 break;
5209 if (!any_addressable_vars)
5210 gimple_omp_return_set_nowait (stmt);
5215 static void
5216 remove_exit_barriers (struct omp_region *region)
5218 if (region->type == GIMPLE_OMP_PARALLEL)
5219 remove_exit_barrier (region);
5221 if (region->inner)
5223 region = region->inner;
5224 remove_exit_barriers (region);
5225 while (region->next)
5227 region = region->next;
5228 remove_exit_barriers (region);
5233 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5234 calls. These can't be declared as const functions, but
5235 within one parallel body they are constant, so they can be
5236 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5237 which are declared const. Similarly for task body, except
5238 that in untied task omp_get_thread_num () can change at any task
5239 scheduling point. */
5241 static void
5242 optimize_omp_library_calls (gimple entry_stmt)
5244 basic_block bb;
5245 gimple_stmt_iterator gsi;
5246 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5247 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5248 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5249 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5250 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5251 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5252 OMP_CLAUSE_UNTIED) != NULL);
5254 FOR_EACH_BB_FN (bb, cfun)
5255 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5257 gimple call = gsi_stmt (gsi);
5258 tree decl;
5260 if (is_gimple_call (call)
5261 && (decl = gimple_call_fndecl (call))
5262 && DECL_EXTERNAL (decl)
5263 && TREE_PUBLIC (decl)
5264 && DECL_INITIAL (decl) == NULL)
5266 tree built_in;
5268 if (DECL_NAME (decl) == thr_num_id)
5270 /* In #pragma omp task untied omp_get_thread_num () can change
5271 during the execution of the task region. */
5272 if (untied_task)
5273 continue;
5274 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5276 else if (DECL_NAME (decl) == num_thr_id)
5277 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5278 else
5279 continue;
5281 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5282 || gimple_call_num_args (call) != 0)
5283 continue;
5285 if (flag_exceptions && !TREE_NOTHROW (decl))
5286 continue;
5288 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5289 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5290 TREE_TYPE (TREE_TYPE (built_in))))
5291 continue;
5293 gimple_call_set_fndecl (call, built_in);
5298 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5299 regimplified. */
5301 static tree
5302 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5304 tree t = *tp;
5306 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5307 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5308 return t;
5310 if (TREE_CODE (t) == ADDR_EXPR)
5311 recompute_tree_invariant_for_addr_expr (t);
5313 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5314 return NULL_TREE;
5317 /* Prepend TO = FROM assignment before *GSI_P. */
5319 static void
5320 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5322 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5323 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5324 true, GSI_SAME_STMT);
5325 gimple stmt = gimple_build_assign (to, from);
5326 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5327 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5328 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5330 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5331 gimple_regimplify_operands (stmt, &gsi);
5335 /* Expand the OpenMP parallel or task directive starting at REGION. */
5337 static void
5338 expand_omp_taskreg (struct omp_region *region)
5340 basic_block entry_bb, exit_bb, new_bb;
5341 struct function *child_cfun;
5342 tree child_fn, block, t;
5343 gimple_stmt_iterator gsi;
5344 gimple entry_stmt, stmt;
5345 edge e;
5346 vec<tree, va_gc> *ws_args;
5348 entry_stmt = last_stmt (region->entry);
5349 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5350 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5352 entry_bb = region->entry;
5353 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
5354 exit_bb = region->cont;
5355 else
5356 exit_bb = region->exit;
5358 bool is_cilk_for
5359 = (flag_cilkplus
5360 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5361 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5362 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5364 if (is_cilk_for)
5365 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5366 and the inner statement contains the name of the built-in function
5367 and grain. */
5368 ws_args = region->inner->ws_args;
5369 else if (is_combined_parallel (region))
5370 ws_args = region->ws_args;
5371 else
5372 ws_args = NULL;
5374 if (child_cfun->cfg)
5376 /* Due to inlining, it may happen that we have already outlined
5377 the region, in which case all we need to do is make the
5378 sub-graph unreachable and emit the parallel call. */
5379 edge entry_succ_e, exit_succ_e;
5381 entry_succ_e = single_succ_edge (entry_bb);
5383 gsi = gsi_last_bb (entry_bb);
5384 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5385 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5386 gsi_remove (&gsi, true);
5388 new_bb = entry_bb;
5389 if (exit_bb)
5391 exit_succ_e = single_succ_edge (exit_bb);
5392 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5394 remove_edge_and_dominated_blocks (entry_succ_e);
5396 else
5398 unsigned srcidx, dstidx, num;
5400 /* If the parallel region needs data sent from the parent
5401 function, then the very first statement (except possible
5402 tree profile counter updates) of the parallel body
5403 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5404 &.OMP_DATA_O is passed as an argument to the child function,
5405 we need to replace it with the argument as seen by the child
5406 function.
5408 In most cases, this will end up being the identity assignment
5409 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5410 a function call that has been inlined, the original PARM_DECL
5411 .OMP_DATA_I may have been converted into a different local
5412 variable. In which case, we need to keep the assignment. */
5413 if (gimple_omp_taskreg_data_arg (entry_stmt))
5415 basic_block entry_succ_bb
5416 = single_succ_p (entry_bb) ? single_succ (entry_bb)
5417 : FALLTHRU_EDGE (entry_bb)->dest;
5418 tree arg, narg;
5419 gimple parcopy_stmt = NULL;
5421 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5423 gimple stmt;
5425 gcc_assert (!gsi_end_p (gsi));
5426 stmt = gsi_stmt (gsi);
5427 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5428 continue;
5430 if (gimple_num_ops (stmt) == 2)
5432 tree arg = gimple_assign_rhs1 (stmt);
5434 /* We're ignore the subcode because we're
5435 effectively doing a STRIP_NOPS. */
5437 if (TREE_CODE (arg) == ADDR_EXPR
5438 && TREE_OPERAND (arg, 0)
5439 == gimple_omp_taskreg_data_arg (entry_stmt))
5441 parcopy_stmt = stmt;
5442 break;
5447 gcc_assert (parcopy_stmt != NULL);
5448 arg = DECL_ARGUMENTS (child_fn);
5450 if (!gimple_in_ssa_p (cfun))
5452 if (gimple_assign_lhs (parcopy_stmt) == arg)
5453 gsi_remove (&gsi, true);
5454 else
5456 /* ?? Is setting the subcode really necessary ?? */
5457 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5458 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5461 else
5463 /* If we are in ssa form, we must load the value from the default
5464 definition of the argument. That should not be defined now,
5465 since the argument is not used uninitialized. */
5466 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5467 narg = make_ssa_name (arg, gimple_build_nop ());
5468 set_ssa_default_def (cfun, arg, narg);
5469 /* ?? Is setting the subcode really necessary ?? */
5470 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5471 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5472 update_stmt (parcopy_stmt);
5476 /* Declare local variables needed in CHILD_CFUN. */
5477 block = DECL_INITIAL (child_fn);
5478 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5479 /* The gimplifier could record temporaries in parallel/task block
5480 rather than in containing function's local_decls chain,
5481 which would mean cgraph missed finalizing them. Do it now. */
5482 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5483 if (TREE_CODE (t) == VAR_DECL
5484 && TREE_STATIC (t)
5485 && !DECL_EXTERNAL (t))
5486 varpool_node::finalize_decl (t);
5487 DECL_SAVED_TREE (child_fn) = NULL;
5488 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5489 gimple_set_body (child_fn, NULL);
5490 TREE_USED (block) = 1;
5492 /* Reset DECL_CONTEXT on function arguments. */
5493 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5494 DECL_CONTEXT (t) = child_fn;
5496 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5497 so that it can be moved to the child function. */
5498 gsi = gsi_last_bb (entry_bb);
5499 stmt = gsi_stmt (gsi);
5500 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5501 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5502 e = split_block (entry_bb, stmt);
5503 gsi_remove (&gsi, true);
5504 entry_bb = e->dest;
5505 edge e2 = NULL;
5506 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5507 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5508 else
5510 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
5511 gcc_assert (e2->dest == region->exit);
5512 remove_edge (BRANCH_EDGE (entry_bb));
5513 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
5514 gsi = gsi_last_bb (region->exit);
5515 gcc_assert (!gsi_end_p (gsi)
5516 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5517 gsi_remove (&gsi, true);
5520 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5521 if (exit_bb)
5523 gsi = gsi_last_bb (exit_bb);
5524 gcc_assert (!gsi_end_p (gsi)
5525 && (gimple_code (gsi_stmt (gsi))
5526 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
5527 stmt = gimple_build_return (NULL);
5528 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5529 gsi_remove (&gsi, true);
5532 /* Move the parallel region into CHILD_CFUN. */
5534 if (gimple_in_ssa_p (cfun))
5536 init_tree_ssa (child_cfun);
5537 init_ssa_operands (child_cfun);
5538 child_cfun->gimple_df->in_ssa_p = true;
5539 block = NULL_TREE;
5541 else
5542 block = gimple_block (entry_stmt);
5544 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5545 if (exit_bb)
5546 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5547 if (e2)
5549 basic_block dest_bb = e2->dest;
5550 if (!exit_bb)
5551 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
5552 remove_edge (e2);
5553 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
5555 /* When the OMP expansion process cannot guarantee an up-to-date
5556 loop tree arrange for the child function to fixup loops. */
5557 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5558 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5560 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5561 num = vec_safe_length (child_cfun->local_decls);
5562 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5564 t = (*child_cfun->local_decls)[srcidx];
5565 if (DECL_CONTEXT (t) == cfun->decl)
5566 continue;
5567 if (srcidx != dstidx)
5568 (*child_cfun->local_decls)[dstidx] = t;
5569 dstidx++;
5571 if (dstidx != num)
5572 vec_safe_truncate (child_cfun->local_decls, dstidx);
5574 /* Inform the callgraph about the new function. */
5575 child_cfun->curr_properties = cfun->curr_properties;
5576 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
5577 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
5578 cgraph_node *node = cgraph_node::get_create (child_fn);
5579 node->parallelized_function = 1;
5580 cgraph_node::add_new_function (child_fn, true);
5582 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5583 fixed in a following pass. */
5584 push_cfun (child_cfun);
5585 if (optimize)
5586 optimize_omp_library_calls (entry_stmt);
5587 cgraph_edge::rebuild_edges ();
5589 /* Some EH regions might become dead, see PR34608. If
5590 pass_cleanup_cfg isn't the first pass to happen with the
5591 new child, these dead EH edges might cause problems.
5592 Clean them up now. */
5593 if (flag_exceptions)
5595 basic_block bb;
5596 bool changed = false;
5598 FOR_EACH_BB_FN (bb, cfun)
5599 changed |= gimple_purge_dead_eh_edges (bb);
5600 if (changed)
5601 cleanup_tree_cfg ();
5603 if (gimple_in_ssa_p (cfun))
5604 update_ssa (TODO_update_ssa);
5605 pop_cfun ();
5608 /* Emit a library call to launch the children threads. */
5609 if (is_cilk_for)
5610 expand_cilk_for_call (new_bb,
5611 as_a <gomp_parallel *> (entry_stmt), ws_args);
5612 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5613 expand_parallel_call (region, new_bb,
5614 as_a <gomp_parallel *> (entry_stmt), ws_args);
5615 else
5616 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5617 if (gimple_in_ssa_p (cfun))
5618 update_ssa (TODO_update_ssa_only_virtuals);
5622 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5623 of the combined collapse > 1 loop constructs, generate code like:
5624 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5625 if (cond3 is <)
5626 adj = STEP3 - 1;
5627 else
5628 adj = STEP3 + 1;
5629 count3 = (adj + N32 - N31) / STEP3;
5630 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5631 if (cond2 is <)
5632 adj = STEP2 - 1;
5633 else
5634 adj = STEP2 + 1;
5635 count2 = (adj + N22 - N21) / STEP2;
5636 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5637 if (cond1 is <)
5638 adj = STEP1 - 1;
5639 else
5640 adj = STEP1 + 1;
5641 count1 = (adj + N12 - N11) / STEP1;
5642 count = count1 * count2 * count3;
5643 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5644 count = 0;
5645 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5646 of the combined loop constructs, just initialize COUNTS array
5647 from the _looptemp_ clauses. */
5649 /* NOTE: It *could* be better to moosh all of the BBs together,
5650 creating one larger BB with all the computation and the unexpected
5651 jump at the end. I.e.
5653 bool zero3, zero2, zero1, zero;
5655 zero3 = N32 c3 N31;
5656 count3 = (N32 - N31) /[cl] STEP3;
5657 zero2 = N22 c2 N21;
5658 count2 = (N22 - N21) /[cl] STEP2;
5659 zero1 = N12 c1 N11;
5660 count1 = (N12 - N11) /[cl] STEP1;
5661 zero = zero3 || zero2 || zero1;
5662 count = count1 * count2 * count3;
5663 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5665 After all, we expect the zero=false, and thus we expect to have to
5666 evaluate all of the comparison expressions, so short-circuiting
5667 oughtn't be a win. Since the condition isn't protecting a
5668 denominator, we're not concerned about divide-by-zero, so we can
5669 fully evaluate count even if a numerator turned out to be wrong.
5671 It seems like putting this all together would create much better
5672 scheduling opportunities, and less pressure on the chip's branch
5673 predictor. */
5675 static void
5676 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5677 basic_block &entry_bb, tree *counts,
5678 basic_block &zero_iter_bb, int &first_zero_iter,
5679 basic_block &l2_dom_bb)
5681 tree t, type = TREE_TYPE (fd->loop.v);
5682 edge e, ne;
5683 int i;
5685 /* Collapsed loops need work for expansion into SSA form. */
5686 gcc_assert (!gimple_in_ssa_p (cfun));
5688 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5689 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5691 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5692 isn't supposed to be handled, as the inner loop doesn't
5693 use it. */
5694 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5695 OMP_CLAUSE__LOOPTEMP_);
5696 gcc_assert (innerc);
5697 for (i = 0; i < fd->collapse; i++)
5699 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5700 OMP_CLAUSE__LOOPTEMP_);
5701 gcc_assert (innerc);
5702 if (i)
5703 counts[i] = OMP_CLAUSE_DECL (innerc);
5704 else
5705 counts[0] = NULL_TREE;
5707 return;
5710 for (i = 0; i < fd->collapse; i++)
5712 tree itype = TREE_TYPE (fd->loops[i].v);
5714 if (SSA_VAR_P (fd->loop.n2)
5715 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5716 fold_convert (itype, fd->loops[i].n1),
5717 fold_convert (itype, fd->loops[i].n2)))
5718 == NULL_TREE || !integer_onep (t)))
5720 gcond *cond_stmt;
5721 tree n1, n2;
5722 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5723 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5724 true, GSI_SAME_STMT);
5725 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5726 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5727 true, GSI_SAME_STMT);
5728 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5729 NULL_TREE, NULL_TREE);
5730 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5731 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5732 expand_omp_regimplify_p, NULL, NULL)
5733 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5734 expand_omp_regimplify_p, NULL, NULL))
5736 *gsi = gsi_for_stmt (cond_stmt);
5737 gimple_regimplify_operands (cond_stmt, gsi);
5739 e = split_block (entry_bb, cond_stmt);
5740 if (zero_iter_bb == NULL)
5742 gassign *assign_stmt;
5743 first_zero_iter = i;
5744 zero_iter_bb = create_empty_bb (entry_bb);
5745 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5746 *gsi = gsi_after_labels (zero_iter_bb);
5747 assign_stmt = gimple_build_assign (fd->loop.n2,
5748 build_zero_cst (type));
5749 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5750 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5751 entry_bb);
5753 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5754 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5755 e->flags = EDGE_TRUE_VALUE;
5756 e->probability = REG_BR_PROB_BASE - ne->probability;
5757 if (l2_dom_bb == NULL)
5758 l2_dom_bb = entry_bb;
5759 entry_bb = e->dest;
5760 *gsi = gsi_last_bb (entry_bb);
5763 if (POINTER_TYPE_P (itype))
5764 itype = signed_type_for (itype);
5765 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5766 ? -1 : 1));
5767 t = fold_build2 (PLUS_EXPR, itype,
5768 fold_convert (itype, fd->loops[i].step), t);
5769 t = fold_build2 (PLUS_EXPR, itype, t,
5770 fold_convert (itype, fd->loops[i].n2));
5771 t = fold_build2 (MINUS_EXPR, itype, t,
5772 fold_convert (itype, fd->loops[i].n1));
5773 /* ?? We could probably use CEIL_DIV_EXPR instead of
5774 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5775 generate the same code in the end because generically we
5776 don't know that the values involved must be negative for
5777 GT?? */
5778 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5779 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5780 fold_build1 (NEGATE_EXPR, itype, t),
5781 fold_build1 (NEGATE_EXPR, itype,
5782 fold_convert (itype,
5783 fd->loops[i].step)));
5784 else
5785 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5786 fold_convert (itype, fd->loops[i].step));
5787 t = fold_convert (type, t);
5788 if (TREE_CODE (t) == INTEGER_CST)
5789 counts[i] = t;
5790 else
5792 counts[i] = create_tmp_reg (type, ".count");
5793 expand_omp_build_assign (gsi, counts[i], t);
5795 if (SSA_VAR_P (fd->loop.n2))
5797 if (i == 0)
5798 t = counts[0];
5799 else
5800 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5801 expand_omp_build_assign (gsi, fd->loop.n2, t);
5807 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5808 T = V;
5809 V3 = N31 + (T % count3) * STEP3;
5810 T = T / count3;
5811 V2 = N21 + (T % count2) * STEP2;
5812 T = T / count2;
5813 V1 = N11 + T * STEP1;
5814 if this loop doesn't have an inner loop construct combined with it.
5815 If it does have an inner loop construct combined with it and the
5816 iteration count isn't known constant, store values from counts array
5817 into its _looptemp_ temporaries instead. */
5819 static void
5820 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5821 tree *counts, gimple inner_stmt, tree startvar)
5823 int i;
5824 if (gimple_omp_for_combined_p (fd->for_stmt))
5826 /* If fd->loop.n2 is constant, then no propagation of the counts
5827 is needed, they are constant. */
5828 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5829 return;
5831 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5832 ? gimple_omp_parallel_clauses (inner_stmt)
5833 : gimple_omp_for_clauses (inner_stmt);
5834 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5835 isn't supposed to be handled, as the inner loop doesn't
5836 use it. */
5837 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5838 gcc_assert (innerc);
5839 for (i = 0; i < fd->collapse; i++)
5841 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5842 OMP_CLAUSE__LOOPTEMP_);
5843 gcc_assert (innerc);
5844 if (i)
5846 tree tem = OMP_CLAUSE_DECL (innerc);
5847 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5848 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5849 false, GSI_CONTINUE_LINKING);
5850 gassign *stmt = gimple_build_assign (tem, t);
5851 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5854 return;
5857 tree type = TREE_TYPE (fd->loop.v);
5858 tree tem = create_tmp_reg (type, ".tem");
5859 gassign *stmt = gimple_build_assign (tem, startvar);
5860 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5862 for (i = fd->collapse - 1; i >= 0; i--)
5864 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5865 itype = vtype;
5866 if (POINTER_TYPE_P (vtype))
5867 itype = signed_type_for (vtype);
5868 if (i != 0)
5869 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5870 else
5871 t = tem;
5872 t = fold_convert (itype, t);
5873 t = fold_build2 (MULT_EXPR, itype, t,
5874 fold_convert (itype, fd->loops[i].step));
5875 if (POINTER_TYPE_P (vtype))
5876 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5877 else
5878 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5879 t = force_gimple_operand_gsi (gsi, t,
5880 DECL_P (fd->loops[i].v)
5881 && TREE_ADDRESSABLE (fd->loops[i].v),
5882 NULL_TREE, false,
5883 GSI_CONTINUE_LINKING);
5884 stmt = gimple_build_assign (fd->loops[i].v, t);
5885 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5886 if (i != 0)
5888 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5889 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5890 false, GSI_CONTINUE_LINKING);
5891 stmt = gimple_build_assign (tem, t);
5892 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5898 /* Helper function for expand_omp_for_*. Generate code like:
5899 L10:
5900 V3 += STEP3;
5901 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5902 L11:
5903 V3 = N31;
5904 V2 += STEP2;
5905 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5906 L12:
5907 V2 = N21;
5908 V1 += STEP1;
5909 goto BODY_BB; */
5911 static basic_block
5912 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5913 basic_block body_bb)
5915 basic_block last_bb, bb, collapse_bb = NULL;
5916 int i;
5917 gimple_stmt_iterator gsi;
5918 edge e;
5919 tree t;
5920 gimple stmt;
5922 last_bb = cont_bb;
5923 for (i = fd->collapse - 1; i >= 0; i--)
5925 tree vtype = TREE_TYPE (fd->loops[i].v);
5927 bb = create_empty_bb (last_bb);
5928 add_bb_to_loop (bb, last_bb->loop_father);
5929 gsi = gsi_start_bb (bb);
5931 if (i < fd->collapse - 1)
5933 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5934 e->probability = REG_BR_PROB_BASE / 8;
5936 t = fd->loops[i + 1].n1;
5937 t = force_gimple_operand_gsi (&gsi, t,
5938 DECL_P (fd->loops[i + 1].v)
5939 && TREE_ADDRESSABLE (fd->loops[i
5940 + 1].v),
5941 NULL_TREE, false,
5942 GSI_CONTINUE_LINKING);
5943 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5944 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5946 else
5947 collapse_bb = bb;
5949 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5951 if (POINTER_TYPE_P (vtype))
5952 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5953 else
5954 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5955 t = force_gimple_operand_gsi (&gsi, t,
5956 DECL_P (fd->loops[i].v)
5957 && TREE_ADDRESSABLE (fd->loops[i].v),
5958 NULL_TREE, false, GSI_CONTINUE_LINKING);
5959 stmt = gimple_build_assign (fd->loops[i].v, t);
5960 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5962 if (i > 0)
5964 t = fd->loops[i].n2;
5965 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5966 false, GSI_CONTINUE_LINKING);
5967 tree v = fd->loops[i].v;
5968 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5969 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5970 false, GSI_CONTINUE_LINKING);
5971 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5972 stmt = gimple_build_cond_empty (t);
5973 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5974 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5975 e->probability = REG_BR_PROB_BASE * 7 / 8;
5977 else
5978 make_edge (bb, body_bb, EDGE_FALLTHRU);
5979 last_bb = bb;
5982 return collapse_bb;
5986 /* A subroutine of expand_omp_for. Generate code for a parallel
5987 loop with any schedule. Given parameters:
5989 for (V = N1; V cond N2; V += STEP) BODY;
5991 where COND is "<" or ">", we generate pseudocode
5993 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5994 if (more) goto L0; else goto L3;
5996 V = istart0;
5997 iend = iend0;
5999 BODY;
6000 V += STEP;
6001 if (V cond iend) goto L1; else goto L2;
6003 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6006 If this is a combined omp parallel loop, instead of the call to
6007 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6008 If this is gimple_omp_for_combined_p loop, then instead of assigning
6009 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6010 inner GIMPLE_OMP_FOR and V += STEP; and
6011 if (V cond iend) goto L1; else goto L2; are removed.
6013 For collapsed loops, given parameters:
6014 collapse(3)
6015 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6016 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6017 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6018 BODY;
6020 we generate pseudocode
6022 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6023 if (cond3 is <)
6024 adj = STEP3 - 1;
6025 else
6026 adj = STEP3 + 1;
6027 count3 = (adj + N32 - N31) / STEP3;
6028 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6029 if (cond2 is <)
6030 adj = STEP2 - 1;
6031 else
6032 adj = STEP2 + 1;
6033 count2 = (adj + N22 - N21) / STEP2;
6034 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6035 if (cond1 is <)
6036 adj = STEP1 - 1;
6037 else
6038 adj = STEP1 + 1;
6039 count1 = (adj + N12 - N11) / STEP1;
6040 count = count1 * count2 * count3;
6041 goto Z1;
6043 count = 0;
6045 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6046 if (more) goto L0; else goto L3;
6048 V = istart0;
6049 T = V;
6050 V3 = N31 + (T % count3) * STEP3;
6051 T = T / count3;
6052 V2 = N21 + (T % count2) * STEP2;
6053 T = T / count2;
6054 V1 = N11 + T * STEP1;
6055 iend = iend0;
6057 BODY;
6058 V += 1;
6059 if (V < iend) goto L10; else goto L2;
6060 L10:
6061 V3 += STEP3;
6062 if (V3 cond3 N32) goto L1; else goto L11;
6063 L11:
6064 V3 = N31;
6065 V2 += STEP2;
6066 if (V2 cond2 N22) goto L1; else goto L12;
6067 L12:
6068 V2 = N21;
6069 V1 += STEP1;
6070 goto L1;
6072 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6077 static void
6078 expand_omp_for_generic (struct omp_region *region,
6079 struct omp_for_data *fd,
6080 enum built_in_function start_fn,
6081 enum built_in_function next_fn,
6082 gimple inner_stmt)
6084 tree type, istart0, iend0, iend;
6085 tree t, vmain, vback, bias = NULL_TREE;
6086 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6087 basic_block l2_bb = NULL, l3_bb = NULL;
6088 gimple_stmt_iterator gsi;
6089 gassign *assign_stmt;
6090 bool in_combined_parallel = is_combined_parallel (region);
6091 bool broken_loop = region->cont == NULL;
6092 edge e, ne;
6093 tree *counts = NULL;
6094 int i;
6096 gcc_assert (!broken_loop || !in_combined_parallel);
6097 gcc_assert (fd->iter_type == long_integer_type_node
6098 || !in_combined_parallel);
6100 type = TREE_TYPE (fd->loop.v);
6101 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6102 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6103 TREE_ADDRESSABLE (istart0) = 1;
6104 TREE_ADDRESSABLE (iend0) = 1;
6106 /* See if we need to bias by LLONG_MIN. */
6107 if (fd->iter_type == long_long_unsigned_type_node
6108 && TREE_CODE (type) == INTEGER_TYPE
6109 && !TYPE_UNSIGNED (type))
6111 tree n1, n2;
6113 if (fd->loop.cond_code == LT_EXPR)
6115 n1 = fd->loop.n1;
6116 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6118 else
6120 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6121 n2 = fd->loop.n1;
6123 if (TREE_CODE (n1) != INTEGER_CST
6124 || TREE_CODE (n2) != INTEGER_CST
6125 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6126 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6129 entry_bb = region->entry;
6130 cont_bb = region->cont;
6131 collapse_bb = NULL;
6132 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6133 gcc_assert (broken_loop
6134 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6135 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6136 l1_bb = single_succ (l0_bb);
6137 if (!broken_loop)
6139 l2_bb = create_empty_bb (cont_bb);
6140 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6141 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6143 else
6144 l2_bb = NULL;
6145 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6146 exit_bb = region->exit;
6148 gsi = gsi_last_bb (entry_bb);
6150 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6151 if (fd->collapse > 1)
6153 int first_zero_iter = -1;
6154 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6156 counts = XALLOCAVEC (tree, fd->collapse);
6157 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6158 zero_iter_bb, first_zero_iter,
6159 l2_dom_bb);
6161 if (zero_iter_bb)
6163 /* Some counts[i] vars might be uninitialized if
6164 some loop has zero iterations. But the body shouldn't
6165 be executed in that case, so just avoid uninit warnings. */
6166 for (i = first_zero_iter; i < fd->collapse; i++)
6167 if (SSA_VAR_P (counts[i]))
6168 TREE_NO_WARNING (counts[i]) = 1;
6169 gsi_prev (&gsi);
6170 e = split_block (entry_bb, gsi_stmt (gsi));
6171 entry_bb = e->dest;
6172 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6173 gsi = gsi_last_bb (entry_bb);
6174 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6175 get_immediate_dominator (CDI_DOMINATORS,
6176 zero_iter_bb));
6179 if (in_combined_parallel)
6181 /* In a combined parallel loop, emit a call to
6182 GOMP_loop_foo_next. */
6183 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6184 build_fold_addr_expr (istart0),
6185 build_fold_addr_expr (iend0));
6187 else
6189 tree t0, t1, t2, t3, t4;
6190 /* If this is not a combined parallel loop, emit a call to
6191 GOMP_loop_foo_start in ENTRY_BB. */
6192 t4 = build_fold_addr_expr (iend0);
6193 t3 = build_fold_addr_expr (istart0);
6194 t2 = fold_convert (fd->iter_type, fd->loop.step);
6195 t1 = fd->loop.n2;
6196 t0 = fd->loop.n1;
6197 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6199 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6200 OMP_CLAUSE__LOOPTEMP_);
6201 gcc_assert (innerc);
6202 t0 = OMP_CLAUSE_DECL (innerc);
6203 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6204 OMP_CLAUSE__LOOPTEMP_);
6205 gcc_assert (innerc);
6206 t1 = OMP_CLAUSE_DECL (innerc);
6208 if (POINTER_TYPE_P (TREE_TYPE (t0))
6209 && TYPE_PRECISION (TREE_TYPE (t0))
6210 != TYPE_PRECISION (fd->iter_type))
6212 /* Avoid casting pointers to integer of a different size. */
6213 tree itype = signed_type_for (type);
6214 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6215 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6217 else
6219 t1 = fold_convert (fd->iter_type, t1);
6220 t0 = fold_convert (fd->iter_type, t0);
6222 if (bias)
6224 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6225 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6227 if (fd->iter_type == long_integer_type_node)
6229 if (fd->chunk_size)
6231 t = fold_convert (fd->iter_type, fd->chunk_size);
6232 t = build_call_expr (builtin_decl_explicit (start_fn),
6233 6, t0, t1, t2, t, t3, t4);
6235 else
6236 t = build_call_expr (builtin_decl_explicit (start_fn),
6237 5, t0, t1, t2, t3, t4);
6239 else
6241 tree t5;
6242 tree c_bool_type;
6243 tree bfn_decl;
6245 /* The GOMP_loop_ull_*start functions have additional boolean
6246 argument, true for < loops and false for > loops.
6247 In Fortran, the C bool type can be different from
6248 boolean_type_node. */
6249 bfn_decl = builtin_decl_explicit (start_fn);
6250 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6251 t5 = build_int_cst (c_bool_type,
6252 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6253 if (fd->chunk_size)
6255 tree bfn_decl = builtin_decl_explicit (start_fn);
6256 t = fold_convert (fd->iter_type, fd->chunk_size);
6257 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6259 else
6260 t = build_call_expr (builtin_decl_explicit (start_fn),
6261 6, t5, t0, t1, t2, t3, t4);
6264 if (TREE_TYPE (t) != boolean_type_node)
6265 t = fold_build2 (NE_EXPR, boolean_type_node,
6266 t, build_int_cst (TREE_TYPE (t), 0));
6267 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6268 true, GSI_SAME_STMT);
6269 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6271 /* Remove the GIMPLE_OMP_FOR statement. */
6272 gsi_remove (&gsi, true);
6274 /* Iteration setup for sequential loop goes in L0_BB. */
6275 tree startvar = fd->loop.v;
6276 tree endvar = NULL_TREE;
6278 if (gimple_omp_for_combined_p (fd->for_stmt))
6280 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6281 && gimple_omp_for_kind (inner_stmt)
6282 == GF_OMP_FOR_KIND_SIMD);
6283 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6284 OMP_CLAUSE__LOOPTEMP_);
6285 gcc_assert (innerc);
6286 startvar = OMP_CLAUSE_DECL (innerc);
6287 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6288 OMP_CLAUSE__LOOPTEMP_);
6289 gcc_assert (innerc);
6290 endvar = OMP_CLAUSE_DECL (innerc);
6293 gsi = gsi_start_bb (l0_bb);
6294 t = istart0;
6295 if (bias)
6296 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6297 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6298 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6299 t = fold_convert (TREE_TYPE (startvar), t);
6300 t = force_gimple_operand_gsi (&gsi, t,
6301 DECL_P (startvar)
6302 && TREE_ADDRESSABLE (startvar),
6303 NULL_TREE, false, GSI_CONTINUE_LINKING);
6304 assign_stmt = gimple_build_assign (startvar, t);
6305 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6307 t = iend0;
6308 if (bias)
6309 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6310 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6311 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6312 t = fold_convert (TREE_TYPE (startvar), t);
6313 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6314 false, GSI_CONTINUE_LINKING);
6315 if (endvar)
6317 assign_stmt = gimple_build_assign (endvar, iend);
6318 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6319 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6320 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6321 else
6322 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6323 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6325 if (fd->collapse > 1)
6326 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6328 if (!broken_loop)
6330 /* Code to control the increment and predicate for the sequential
6331 loop goes in the CONT_BB. */
6332 gsi = gsi_last_bb (cont_bb);
6333 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6334 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6335 vmain = gimple_omp_continue_control_use (cont_stmt);
6336 vback = gimple_omp_continue_control_def (cont_stmt);
6338 if (!gimple_omp_for_combined_p (fd->for_stmt))
6340 if (POINTER_TYPE_P (type))
6341 t = fold_build_pointer_plus (vmain, fd->loop.step);
6342 else
6343 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6344 t = force_gimple_operand_gsi (&gsi, t,
6345 DECL_P (vback)
6346 && TREE_ADDRESSABLE (vback),
6347 NULL_TREE, true, GSI_SAME_STMT);
6348 assign_stmt = gimple_build_assign (vback, t);
6349 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6351 t = build2 (fd->loop.cond_code, boolean_type_node,
6352 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6353 iend);
6354 gcond *cond_stmt = gimple_build_cond_empty (t);
6355 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6358 /* Remove GIMPLE_OMP_CONTINUE. */
6359 gsi_remove (&gsi, true);
6361 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6362 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6364 /* Emit code to get the next parallel iteration in L2_BB. */
6365 gsi = gsi_start_bb (l2_bb);
6367 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6368 build_fold_addr_expr (istart0),
6369 build_fold_addr_expr (iend0));
6370 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6371 false, GSI_CONTINUE_LINKING);
6372 if (TREE_TYPE (t) != boolean_type_node)
6373 t = fold_build2 (NE_EXPR, boolean_type_node,
6374 t, build_int_cst (TREE_TYPE (t), 0));
6375 gcond *cond_stmt = gimple_build_cond_empty (t);
6376 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6379 /* Add the loop cleanup function. */
6380 gsi = gsi_last_bb (exit_bb);
6381 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6382 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6383 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6384 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6385 else
6386 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6387 gcall *call_stmt = gimple_build_call (t, 0);
6388 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6389 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6390 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6391 gsi_remove (&gsi, true);
6393 /* Connect the new blocks. */
6394 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6395 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6397 if (!broken_loop)
6399 gimple_seq phis;
6401 e = find_edge (cont_bb, l3_bb);
6402 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6404 phis = phi_nodes (l3_bb);
6405 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6407 gimple phi = gsi_stmt (gsi);
6408 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6409 PHI_ARG_DEF_FROM_EDGE (phi, e));
6411 remove_edge (e);
6413 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6414 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6415 e = find_edge (cont_bb, l1_bb);
6416 if (gimple_omp_for_combined_p (fd->for_stmt))
6418 remove_edge (e);
6419 e = NULL;
6421 else if (fd->collapse > 1)
6423 remove_edge (e);
6424 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6426 else
6427 e->flags = EDGE_TRUE_VALUE;
6428 if (e)
6430 e->probability = REG_BR_PROB_BASE * 7 / 8;
6431 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6433 else
6435 e = find_edge (cont_bb, l2_bb);
6436 e->flags = EDGE_FALLTHRU;
6438 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6440 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6441 recompute_dominator (CDI_DOMINATORS, l2_bb));
6442 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6443 recompute_dominator (CDI_DOMINATORS, l3_bb));
6444 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6445 recompute_dominator (CDI_DOMINATORS, l0_bb));
6446 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6447 recompute_dominator (CDI_DOMINATORS, l1_bb));
6449 struct loop *outer_loop = alloc_loop ();
6450 outer_loop->header = l0_bb;
6451 outer_loop->latch = l2_bb;
6452 add_loop (outer_loop, l0_bb->loop_father);
6454 if (!gimple_omp_for_combined_p (fd->for_stmt))
6456 struct loop *loop = alloc_loop ();
6457 loop->header = l1_bb;
6458 /* The loop may have multiple latches. */
6459 add_loop (loop, outer_loop);
6465 /* A subroutine of expand_omp_for. Generate code for a parallel
6466 loop with static schedule and no specified chunk size. Given
6467 parameters:
6469 for (V = N1; V cond N2; V += STEP) BODY;
6471 where COND is "<" or ">", we generate pseudocode
6473 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6474 if (cond is <)
6475 adj = STEP - 1;
6476 else
6477 adj = STEP + 1;
6478 if ((__typeof (V)) -1 > 0 && cond is >)
6479 n = -(adj + N2 - N1) / -STEP;
6480 else
6481 n = (adj + N2 - N1) / STEP;
6482 q = n / nthreads;
6483 tt = n % nthreads;
6484 if (threadid < tt) goto L3; else goto L4;
6486 tt = 0;
6487 q = q + 1;
6489 s0 = q * threadid + tt;
6490 e0 = s0 + q;
6491 V = s0 * STEP + N1;
6492 if (s0 >= e0) goto L2; else goto L0;
6494 e = e0 * STEP + N1;
6496 BODY;
6497 V += STEP;
6498 if (V cond e) goto L1;
6502 static void
6503 expand_omp_for_static_nochunk (struct omp_region *region,
6504 struct omp_for_data *fd,
6505 gimple inner_stmt)
6507 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6508 tree type, itype, vmain, vback;
6509 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6510 basic_block body_bb, cont_bb, collapse_bb = NULL;
6511 basic_block fin_bb;
6512 gimple_stmt_iterator gsi;
6513 edge ep;
6514 bool broken_loop = region->cont == NULL;
6515 tree *counts = NULL;
6516 tree n1, n2, step;
6518 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6519 != GF_OMP_FOR_KIND_OACC_LOOP)
6520 || !inner_stmt);
6522 itype = type = TREE_TYPE (fd->loop.v);
6523 if (POINTER_TYPE_P (type))
6524 itype = signed_type_for (type);
6526 entry_bb = region->entry;
6527 cont_bb = region->cont;
6528 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6529 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6530 gcc_assert (broken_loop
6531 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6532 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6533 body_bb = single_succ (seq_start_bb);
6534 if (!broken_loop)
6536 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6537 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6539 exit_bb = region->exit;
6541 /* Iteration space partitioning goes in ENTRY_BB. */
6542 gsi = gsi_last_bb (entry_bb);
6543 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6545 if (fd->collapse > 1)
6547 int first_zero_iter = -1;
6548 basic_block l2_dom_bb = NULL;
6550 counts = XALLOCAVEC (tree, fd->collapse);
6551 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6552 fin_bb, first_zero_iter,
6553 l2_dom_bb);
6554 t = NULL_TREE;
6556 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6557 t = integer_one_node;
6558 else
6559 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6560 fold_convert (type, fd->loop.n1),
6561 fold_convert (type, fd->loop.n2));
6562 if (fd->collapse == 1
6563 && TYPE_UNSIGNED (type)
6564 && (t == NULL_TREE || !integer_onep (t)))
6566 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6567 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6568 true, GSI_SAME_STMT);
6569 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6570 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6571 true, GSI_SAME_STMT);
6572 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6573 NULL_TREE, NULL_TREE);
6574 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6575 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6576 expand_omp_regimplify_p, NULL, NULL)
6577 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6578 expand_omp_regimplify_p, NULL, NULL))
6580 gsi = gsi_for_stmt (cond_stmt);
6581 gimple_regimplify_operands (cond_stmt, &gsi);
6583 ep = split_block (entry_bb, cond_stmt);
6584 ep->flags = EDGE_TRUE_VALUE;
6585 entry_bb = ep->dest;
6586 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6587 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6588 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6589 if (gimple_in_ssa_p (cfun))
6591 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6592 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6593 !gsi_end_p (gpi); gsi_next (&gpi))
6595 gphi *phi = gpi.phi ();
6596 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6597 ep, UNKNOWN_LOCATION);
6600 gsi = gsi_last_bb (entry_bb);
6603 switch (gimple_omp_for_kind (fd->for_stmt))
6605 case GF_OMP_FOR_KIND_FOR:
6606 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6607 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6608 break;
6609 case GF_OMP_FOR_KIND_DISTRIBUTE:
6610 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6611 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6612 break;
6613 case GF_OMP_FOR_KIND_OACC_LOOP:
6614 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6615 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6616 break;
6617 default:
6618 gcc_unreachable ();
6620 nthreads = build_call_expr (nthreads, 0);
6621 nthreads = fold_convert (itype, nthreads);
6622 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6623 true, GSI_SAME_STMT);
6624 threadid = build_call_expr (threadid, 0);
6625 threadid = fold_convert (itype, threadid);
6626 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6627 true, GSI_SAME_STMT);
6629 n1 = fd->loop.n1;
6630 n2 = fd->loop.n2;
6631 step = fd->loop.step;
6632 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6634 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6635 OMP_CLAUSE__LOOPTEMP_);
6636 gcc_assert (innerc);
6637 n1 = OMP_CLAUSE_DECL (innerc);
6638 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6639 OMP_CLAUSE__LOOPTEMP_);
6640 gcc_assert (innerc);
6641 n2 = OMP_CLAUSE_DECL (innerc);
6643 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6644 true, NULL_TREE, true, GSI_SAME_STMT);
6645 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6646 true, NULL_TREE, true, GSI_SAME_STMT);
6647 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6648 true, NULL_TREE, true, GSI_SAME_STMT);
6650 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6651 t = fold_build2 (PLUS_EXPR, itype, step, t);
6652 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6653 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6654 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6655 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6656 fold_build1 (NEGATE_EXPR, itype, t),
6657 fold_build1 (NEGATE_EXPR, itype, step));
6658 else
6659 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6660 t = fold_convert (itype, t);
6661 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6663 q = create_tmp_reg (itype, "q");
6664 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6665 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6666 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6668 tt = create_tmp_reg (itype, "tt");
6669 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6670 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6671 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6673 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6674 gcond *cond_stmt = gimple_build_cond_empty (t);
6675 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6677 second_bb = split_block (entry_bb, cond_stmt)->dest;
6678 gsi = gsi_last_bb (second_bb);
6679 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6681 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6682 GSI_SAME_STMT);
6683 gassign *assign_stmt
6684 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6685 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6687 third_bb = split_block (second_bb, assign_stmt)->dest;
6688 gsi = gsi_last_bb (third_bb);
6689 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6691 t = build2 (MULT_EXPR, itype, q, threadid);
6692 t = build2 (PLUS_EXPR, itype, t, tt);
6693 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6695 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6696 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6698 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6699 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6701 /* Remove the GIMPLE_OMP_FOR statement. */
6702 gsi_remove (&gsi, true);
6704 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6705 gsi = gsi_start_bb (seq_start_bb);
6707 tree startvar = fd->loop.v;
6708 tree endvar = NULL_TREE;
6710 if (gimple_omp_for_combined_p (fd->for_stmt))
6712 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6713 ? gimple_omp_parallel_clauses (inner_stmt)
6714 : gimple_omp_for_clauses (inner_stmt);
6715 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6716 gcc_assert (innerc);
6717 startvar = OMP_CLAUSE_DECL (innerc);
6718 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6719 OMP_CLAUSE__LOOPTEMP_);
6720 gcc_assert (innerc);
6721 endvar = OMP_CLAUSE_DECL (innerc);
6723 t = fold_convert (itype, s0);
6724 t = fold_build2 (MULT_EXPR, itype, t, step);
6725 if (POINTER_TYPE_P (type))
6726 t = fold_build_pointer_plus (n1, t);
6727 else
6728 t = fold_build2 (PLUS_EXPR, type, t, n1);
6729 t = fold_convert (TREE_TYPE (startvar), t);
6730 t = force_gimple_operand_gsi (&gsi, t,
6731 DECL_P (startvar)
6732 && TREE_ADDRESSABLE (startvar),
6733 NULL_TREE, false, GSI_CONTINUE_LINKING);
6734 assign_stmt = gimple_build_assign (startvar, t);
6735 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6737 t = fold_convert (itype, e0);
6738 t = fold_build2 (MULT_EXPR, itype, t, step);
6739 if (POINTER_TYPE_P (type))
6740 t = fold_build_pointer_plus (n1, t);
6741 else
6742 t = fold_build2 (PLUS_EXPR, type, t, n1);
6743 t = fold_convert (TREE_TYPE (startvar), t);
6744 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6745 false, GSI_CONTINUE_LINKING);
6746 if (endvar)
6748 assign_stmt = gimple_build_assign (endvar, e);
6749 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6750 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6751 assign_stmt = gimple_build_assign (fd->loop.v, e);
6752 else
6753 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6754 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6756 if (fd->collapse > 1)
6757 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6759 if (!broken_loop)
6761 /* The code controlling the sequential loop replaces the
6762 GIMPLE_OMP_CONTINUE. */
6763 gsi = gsi_last_bb (cont_bb);
6764 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6765 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6766 vmain = gimple_omp_continue_control_use (cont_stmt);
6767 vback = gimple_omp_continue_control_def (cont_stmt);
6769 if (!gimple_omp_for_combined_p (fd->for_stmt))
6771 if (POINTER_TYPE_P (type))
6772 t = fold_build_pointer_plus (vmain, step);
6773 else
6774 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6775 t = force_gimple_operand_gsi (&gsi, t,
6776 DECL_P (vback)
6777 && TREE_ADDRESSABLE (vback),
6778 NULL_TREE, true, GSI_SAME_STMT);
6779 assign_stmt = gimple_build_assign (vback, t);
6780 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6782 t = build2 (fd->loop.cond_code, boolean_type_node,
6783 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6784 ? t : vback, e);
6785 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6788 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6789 gsi_remove (&gsi, true);
6791 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6792 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6795 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6796 gsi = gsi_last_bb (exit_bb);
6797 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6799 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6800 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6801 gcc_checking_assert (t == NULL_TREE);
6802 else
6803 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6805 gsi_remove (&gsi, true);
6807 /* Connect all the blocks. */
6808 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6809 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6810 ep = find_edge (entry_bb, second_bb);
6811 ep->flags = EDGE_TRUE_VALUE;
6812 ep->probability = REG_BR_PROB_BASE / 4;
6813 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6814 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6816 if (!broken_loop)
6818 ep = find_edge (cont_bb, body_bb);
6819 if (gimple_omp_for_combined_p (fd->for_stmt))
6821 remove_edge (ep);
6822 ep = NULL;
6824 else if (fd->collapse > 1)
6826 remove_edge (ep);
6827 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6829 else
6830 ep->flags = EDGE_TRUE_VALUE;
6831 find_edge (cont_bb, fin_bb)->flags
6832 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6835 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6836 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6837 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6839 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6840 recompute_dominator (CDI_DOMINATORS, body_bb));
6841 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6842 recompute_dominator (CDI_DOMINATORS, fin_bb));
6844 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6846 struct loop *loop = alloc_loop ();
6847 loop->header = body_bb;
6848 if (collapse_bb == NULL)
6849 loop->latch = cont_bb;
6850 add_loop (loop, body_bb->loop_father);
6855 /* A subroutine of expand_omp_for. Generate code for a parallel
6856 loop with static schedule and a specified chunk size. Given
6857 parameters:
6859 for (V = N1; V cond N2; V += STEP) BODY;
6861 where COND is "<" or ">", we generate pseudocode
6863 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6864 if (cond is <)
6865 adj = STEP - 1;
6866 else
6867 adj = STEP + 1;
6868 if ((__typeof (V)) -1 > 0 && cond is >)
6869 n = -(adj + N2 - N1) / -STEP;
6870 else
6871 n = (adj + N2 - N1) / STEP;
6872 trip = 0;
6873 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6874 here so that V is defined
6875 if the loop is not entered
6877 s0 = (trip * nthreads + threadid) * CHUNK;
6878 e0 = min(s0 + CHUNK, n);
6879 if (s0 < n) goto L1; else goto L4;
6881 V = s0 * STEP + N1;
6882 e = e0 * STEP + N1;
6884 BODY;
6885 V += STEP;
6886 if (V cond e) goto L2; else goto L3;
6888 trip += 1;
6889 goto L0;
6893 static void
6894 expand_omp_for_static_chunk (struct omp_region *region,
6895 struct omp_for_data *fd, gimple inner_stmt)
6897 tree n, s0, e0, e, t;
6898 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6899 tree type, itype, vmain, vback, vextra;
6900 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6901 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6902 gimple_stmt_iterator gsi;
6903 edge se;
6904 bool broken_loop = region->cont == NULL;
6905 tree *counts = NULL;
6906 tree n1, n2, step;
6908 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6909 != GF_OMP_FOR_KIND_OACC_LOOP)
6910 || !inner_stmt);
6912 itype = type = TREE_TYPE (fd->loop.v);
6913 if (POINTER_TYPE_P (type))
6914 itype = signed_type_for (type);
6916 entry_bb = region->entry;
6917 se = split_block (entry_bb, last_stmt (entry_bb));
6918 entry_bb = se->src;
6919 iter_part_bb = se->dest;
6920 cont_bb = region->cont;
6921 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6922 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6923 gcc_assert (broken_loop
6924 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6925 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6926 body_bb = single_succ (seq_start_bb);
6927 if (!broken_loop)
6929 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6930 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6931 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6933 exit_bb = region->exit;
6935 /* Trip and adjustment setup goes in ENTRY_BB. */
6936 gsi = gsi_last_bb (entry_bb);
6937 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6939 if (fd->collapse > 1)
6941 int first_zero_iter = -1;
6942 basic_block l2_dom_bb = NULL;
6944 counts = XALLOCAVEC (tree, fd->collapse);
6945 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6946 fin_bb, first_zero_iter,
6947 l2_dom_bb);
6948 t = NULL_TREE;
6950 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6951 t = integer_one_node;
6952 else
6953 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6954 fold_convert (type, fd->loop.n1),
6955 fold_convert (type, fd->loop.n2));
6956 if (fd->collapse == 1
6957 && TYPE_UNSIGNED (type)
6958 && (t == NULL_TREE || !integer_onep (t)))
6960 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6961 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6962 true, GSI_SAME_STMT);
6963 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6964 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6965 true, GSI_SAME_STMT);
6966 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6967 NULL_TREE, NULL_TREE);
6968 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6969 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6970 expand_omp_regimplify_p, NULL, NULL)
6971 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6972 expand_omp_regimplify_p, NULL, NULL))
6974 gsi = gsi_for_stmt (cond_stmt);
6975 gimple_regimplify_operands (cond_stmt, &gsi);
6977 se = split_block (entry_bb, cond_stmt);
6978 se->flags = EDGE_TRUE_VALUE;
6979 entry_bb = se->dest;
6980 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6981 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6982 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6983 if (gimple_in_ssa_p (cfun))
6985 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6986 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6987 !gsi_end_p (gpi); gsi_next (&gpi))
6989 gphi *phi = gpi.phi ();
6990 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6991 se, UNKNOWN_LOCATION);
6994 gsi = gsi_last_bb (entry_bb);
6997 switch (gimple_omp_for_kind (fd->for_stmt))
6999 case GF_OMP_FOR_KIND_FOR:
7000 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7001 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7002 break;
7003 case GF_OMP_FOR_KIND_DISTRIBUTE:
7004 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7005 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7006 break;
7007 case GF_OMP_FOR_KIND_OACC_LOOP:
7008 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7009 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7010 break;
7011 default:
7012 gcc_unreachable ();
7014 nthreads = build_call_expr (nthreads, 0);
7015 nthreads = fold_convert (itype, nthreads);
7016 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7017 true, GSI_SAME_STMT);
7018 threadid = build_call_expr (threadid, 0);
7019 threadid = fold_convert (itype, threadid);
7020 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7021 true, GSI_SAME_STMT);
7023 n1 = fd->loop.n1;
7024 n2 = fd->loop.n2;
7025 step = fd->loop.step;
7026 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7028 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7029 OMP_CLAUSE__LOOPTEMP_);
7030 gcc_assert (innerc);
7031 n1 = OMP_CLAUSE_DECL (innerc);
7032 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7033 OMP_CLAUSE__LOOPTEMP_);
7034 gcc_assert (innerc);
7035 n2 = OMP_CLAUSE_DECL (innerc);
7037 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7038 true, NULL_TREE, true, GSI_SAME_STMT);
7039 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7040 true, NULL_TREE, true, GSI_SAME_STMT);
7041 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7042 true, NULL_TREE, true, GSI_SAME_STMT);
7043 fd->chunk_size
7044 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7045 true, NULL_TREE, true, GSI_SAME_STMT);
7047 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7048 t = fold_build2 (PLUS_EXPR, itype, step, t);
7049 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7050 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7051 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7052 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7053 fold_build1 (NEGATE_EXPR, itype, t),
7054 fold_build1 (NEGATE_EXPR, itype, step));
7055 else
7056 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7057 t = fold_convert (itype, t);
7058 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7059 true, GSI_SAME_STMT);
7061 trip_var = create_tmp_reg (itype, ".trip");
7062 if (gimple_in_ssa_p (cfun))
7064 trip_init = make_ssa_name (trip_var);
7065 trip_main = make_ssa_name (trip_var);
7066 trip_back = make_ssa_name (trip_var);
7068 else
7070 trip_init = trip_var;
7071 trip_main = trip_var;
7072 trip_back = trip_var;
7075 gassign *assign_stmt
7076 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7077 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7079 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7080 t = fold_build2 (MULT_EXPR, itype, t, step);
7081 if (POINTER_TYPE_P (type))
7082 t = fold_build_pointer_plus (n1, t);
7083 else
7084 t = fold_build2 (PLUS_EXPR, type, t, n1);
7085 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7086 true, GSI_SAME_STMT);
7088 /* Remove the GIMPLE_OMP_FOR. */
7089 gsi_remove (&gsi, true);
7091 /* Iteration space partitioning goes in ITER_PART_BB. */
7092 gsi = gsi_last_bb (iter_part_bb);
7094 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7095 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7096 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7097 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7098 false, GSI_CONTINUE_LINKING);
7100 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7101 t = fold_build2 (MIN_EXPR, itype, t, n);
7102 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7103 false, GSI_CONTINUE_LINKING);
7105 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7106 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7108 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7109 gsi = gsi_start_bb (seq_start_bb);
7111 tree startvar = fd->loop.v;
7112 tree endvar = NULL_TREE;
7114 if (gimple_omp_for_combined_p (fd->for_stmt))
7116 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7117 ? gimple_omp_parallel_clauses (inner_stmt)
7118 : gimple_omp_for_clauses (inner_stmt);
7119 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7120 gcc_assert (innerc);
7121 startvar = OMP_CLAUSE_DECL (innerc);
7122 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7123 OMP_CLAUSE__LOOPTEMP_);
7124 gcc_assert (innerc);
7125 endvar = OMP_CLAUSE_DECL (innerc);
7128 t = fold_convert (itype, s0);
7129 t = fold_build2 (MULT_EXPR, itype, t, step);
7130 if (POINTER_TYPE_P (type))
7131 t = fold_build_pointer_plus (n1, t);
7132 else
7133 t = fold_build2 (PLUS_EXPR, type, t, n1);
7134 t = fold_convert (TREE_TYPE (startvar), t);
7135 t = force_gimple_operand_gsi (&gsi, t,
7136 DECL_P (startvar)
7137 && TREE_ADDRESSABLE (startvar),
7138 NULL_TREE, false, GSI_CONTINUE_LINKING);
7139 assign_stmt = gimple_build_assign (startvar, t);
7140 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7142 t = fold_convert (itype, e0);
7143 t = fold_build2 (MULT_EXPR, itype, t, step);
7144 if (POINTER_TYPE_P (type))
7145 t = fold_build_pointer_plus (n1, t);
7146 else
7147 t = fold_build2 (PLUS_EXPR, type, t, n1);
7148 t = fold_convert (TREE_TYPE (startvar), t);
7149 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7150 false, GSI_CONTINUE_LINKING);
7151 if (endvar)
7153 assign_stmt = gimple_build_assign (endvar, e);
7154 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7155 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7156 assign_stmt = gimple_build_assign (fd->loop.v, e);
7157 else
7158 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7159 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7161 if (fd->collapse > 1)
7162 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7164 if (!broken_loop)
7166 /* The code controlling the sequential loop goes in CONT_BB,
7167 replacing the GIMPLE_OMP_CONTINUE. */
7168 gsi = gsi_last_bb (cont_bb);
7169 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7170 vmain = gimple_omp_continue_control_use (cont_stmt);
7171 vback = gimple_omp_continue_control_def (cont_stmt);
7173 if (!gimple_omp_for_combined_p (fd->for_stmt))
7175 if (POINTER_TYPE_P (type))
7176 t = fold_build_pointer_plus (vmain, step);
7177 else
7178 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7179 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7180 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7181 true, GSI_SAME_STMT);
7182 assign_stmt = gimple_build_assign (vback, t);
7183 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7185 t = build2 (fd->loop.cond_code, boolean_type_node,
7186 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7187 ? t : vback, e);
7188 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7191 /* Remove GIMPLE_OMP_CONTINUE. */
7192 gsi_remove (&gsi, true);
7194 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7195 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7197 /* Trip update code goes into TRIP_UPDATE_BB. */
7198 gsi = gsi_start_bb (trip_update_bb);
7200 t = build_int_cst (itype, 1);
7201 t = build2 (PLUS_EXPR, itype, trip_main, t);
7202 assign_stmt = gimple_build_assign (trip_back, t);
7203 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7206 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7207 gsi = gsi_last_bb (exit_bb);
7208 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7210 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7211 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7212 gcc_checking_assert (t == NULL_TREE);
7213 else
7214 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7216 gsi_remove (&gsi, true);
7218 /* Connect the new blocks. */
7219 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7220 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7222 if (!broken_loop)
7224 se = find_edge (cont_bb, body_bb);
7225 if (gimple_omp_for_combined_p (fd->for_stmt))
7227 remove_edge (se);
7228 se = NULL;
7230 else if (fd->collapse > 1)
7232 remove_edge (se);
7233 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7235 else
7236 se->flags = EDGE_TRUE_VALUE;
7237 find_edge (cont_bb, trip_update_bb)->flags
7238 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7240 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7243 if (gimple_in_ssa_p (cfun))
7245 gphi_iterator psi;
7246 gphi *phi;
7247 edge re, ene;
7248 edge_var_map *vm;
7249 size_t i;
7251 gcc_assert (fd->collapse == 1 && !broken_loop);
7253 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7254 remove arguments of the phi nodes in fin_bb. We need to create
7255 appropriate phi nodes in iter_part_bb instead. */
7256 se = single_pred_edge (fin_bb);
7257 re = single_succ_edge (trip_update_bb);
7258 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7259 ene = single_succ_edge (entry_bb);
7261 psi = gsi_start_phis (fin_bb);
7262 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7263 gsi_next (&psi), ++i)
7265 gphi *nphi;
7266 source_location locus;
7268 phi = psi.phi ();
7269 t = gimple_phi_result (phi);
7270 gcc_assert (t == redirect_edge_var_map_result (vm));
7271 nphi = create_phi_node (t, iter_part_bb);
7273 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7274 locus = gimple_phi_arg_location_from_edge (phi, se);
7276 /* A special case -- fd->loop.v is not yet computed in
7277 iter_part_bb, we need to use vextra instead. */
7278 if (t == fd->loop.v)
7279 t = vextra;
7280 add_phi_arg (nphi, t, ene, locus);
7281 locus = redirect_edge_var_map_location (vm);
7282 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7284 gcc_assert (gsi_end_p (psi) && i == head->length ());
7285 redirect_edge_var_map_clear (re);
7286 while (1)
7288 psi = gsi_start_phis (fin_bb);
7289 if (gsi_end_p (psi))
7290 break;
7291 remove_phi_node (&psi, false);
7294 /* Make phi node for trip. */
7295 phi = create_phi_node (trip_main, iter_part_bb);
7296 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7297 UNKNOWN_LOCATION);
7298 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7299 UNKNOWN_LOCATION);
7302 if (!broken_loop)
7303 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7304 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7305 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7306 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7307 recompute_dominator (CDI_DOMINATORS, fin_bb));
7308 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7309 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7310 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7311 recompute_dominator (CDI_DOMINATORS, body_bb));
7313 if (!broken_loop)
7315 struct loop *trip_loop = alloc_loop ();
7316 trip_loop->header = iter_part_bb;
7317 trip_loop->latch = trip_update_bb;
7318 add_loop (trip_loop, iter_part_bb->loop_father);
7320 if (!gimple_omp_for_combined_p (fd->for_stmt))
7322 struct loop *loop = alloc_loop ();
7323 loop->header = body_bb;
7324 if (collapse_bb == NULL)
7325 loop->latch = cont_bb;
7326 add_loop (loop, trip_loop);
7331 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7332 Given parameters:
7333 for (V = N1; V cond N2; V += STEP) BODY;
7335 where COND is "<" or ">" or "!=", we generate pseudocode
7337 for (ind_var = low; ind_var < high; ind_var++)
7339 V = n1 + (ind_var * STEP)
7341 <BODY>
7344 In the above pseudocode, low and high are function parameters of the
7345 child function. In the function below, we are inserting a temp.
7346 variable that will be making a call to two OMP functions that will not be
7347 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7348 with _Cilk_for). These functions are replaced with low and high
7349 by the function that handles taskreg. */
7352 static void
7353 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7355 bool broken_loop = region->cont == NULL;
7356 basic_block entry_bb = region->entry;
7357 basic_block cont_bb = region->cont;
7359 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7360 gcc_assert (broken_loop
7361 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7362 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7363 basic_block l1_bb, l2_bb;
7365 if (!broken_loop)
7367 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7368 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7369 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7370 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7372 else
7374 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7375 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7376 l2_bb = single_succ (l1_bb);
7378 basic_block exit_bb = region->exit;
7379 basic_block l2_dom_bb = NULL;
7381 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7383 /* Below statements until the "tree high_val = ..." are pseudo statements
7384 used to pass information to be used by expand_omp_taskreg.
7385 low_val and high_val will be replaced by the __low and __high
7386 parameter from the child function.
7388 The call_exprs part is a place-holder, it is mainly used
7389 to distinctly identify to the top-level part that this is
7390 where we should put low and high (reasoning given in header
7391 comment). */
7393 tree child_fndecl
7394 = gimple_omp_parallel_child_fn (
7395 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7396 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7397 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7399 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7400 high_val = t;
7401 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7402 low_val = t;
7404 gcc_assert (low_val && high_val);
7406 tree type = TREE_TYPE (low_val);
7407 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7408 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7410 /* Not needed in SSA form right now. */
7411 gcc_assert (!gimple_in_ssa_p (cfun));
7412 if (l2_dom_bb == NULL)
7413 l2_dom_bb = l1_bb;
7415 tree n1 = low_val;
7416 tree n2 = high_val;
7418 gimple stmt = gimple_build_assign (ind_var, n1);
7420 /* Replace the GIMPLE_OMP_FOR statement. */
7421 gsi_replace (&gsi, stmt, true);
7423 if (!broken_loop)
7425 /* Code to control the increment goes in the CONT_BB. */
7426 gsi = gsi_last_bb (cont_bb);
7427 stmt = gsi_stmt (gsi);
7428 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7429 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7430 build_one_cst (type));
7432 /* Replace GIMPLE_OMP_CONTINUE. */
7433 gsi_replace (&gsi, stmt, true);
7436 /* Emit the condition in L1_BB. */
7437 gsi = gsi_after_labels (l1_bb);
7438 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7439 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7440 fd->loop.step);
7441 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7442 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7443 fd->loop.n1, fold_convert (sizetype, t));
7444 else
7445 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7446 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7447 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7448 expand_omp_build_assign (&gsi, fd->loop.v, t);
7450 /* The condition is always '<' since the runtime will fill in the low
7451 and high values. */
7452 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7453 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7455 /* Remove GIMPLE_OMP_RETURN. */
7456 gsi = gsi_last_bb (exit_bb);
7457 gsi_remove (&gsi, true);
7459 /* Connect the new blocks. */
7460 remove_edge (FALLTHRU_EDGE (entry_bb));
7462 edge e, ne;
7463 if (!broken_loop)
7465 remove_edge (BRANCH_EDGE (entry_bb));
7466 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7468 e = BRANCH_EDGE (l1_bb);
7469 ne = FALLTHRU_EDGE (l1_bb);
7470 e->flags = EDGE_TRUE_VALUE;
7472 else
7474 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7476 ne = single_succ_edge (l1_bb);
7477 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7480 ne->flags = EDGE_FALSE_VALUE;
7481 e->probability = REG_BR_PROB_BASE * 7 / 8;
7482 ne->probability = REG_BR_PROB_BASE / 8;
7484 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7485 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7486 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7488 if (!broken_loop)
7490 struct loop *loop = alloc_loop ();
7491 loop->header = l1_bb;
7492 loop->latch = cont_bb;
7493 add_loop (loop, l1_bb->loop_father);
7494 loop->safelen = INT_MAX;
7497 /* Pick the correct library function based on the precision of the
7498 induction variable type. */
7499 tree lib_fun = NULL_TREE;
7500 if (TYPE_PRECISION (type) == 32)
7501 lib_fun = cilk_for_32_fndecl;
7502 else if (TYPE_PRECISION (type) == 64)
7503 lib_fun = cilk_for_64_fndecl;
7504 else
7505 gcc_unreachable ();
7507 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7509 /* WS_ARGS contains the library function flavor to call:
7510 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7511 user-defined grain value. If the user does not define one, then zero
7512 is passed in by the parser. */
7513 vec_alloc (region->ws_args, 2);
7514 region->ws_args->quick_push (lib_fun);
7515 region->ws_args->quick_push (fd->chunk_size);
7518 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7519 loop. Given parameters:
7521 for (V = N1; V cond N2; V += STEP) BODY;
7523 where COND is "<" or ">", we generate pseudocode
7525 V = N1;
7526 goto L1;
7528 BODY;
7529 V += STEP;
7531 if (V cond N2) goto L0; else goto L2;
7534 For collapsed loops, given parameters:
7535 collapse(3)
7536 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7537 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7538 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7539 BODY;
7541 we generate pseudocode
7543 if (cond3 is <)
7544 adj = STEP3 - 1;
7545 else
7546 adj = STEP3 + 1;
7547 count3 = (adj + N32 - N31) / STEP3;
7548 if (cond2 is <)
7549 adj = STEP2 - 1;
7550 else
7551 adj = STEP2 + 1;
7552 count2 = (adj + N22 - N21) / STEP2;
7553 if (cond1 is <)
7554 adj = STEP1 - 1;
7555 else
7556 adj = STEP1 + 1;
7557 count1 = (adj + N12 - N11) / STEP1;
7558 count = count1 * count2 * count3;
7559 V = 0;
7560 V1 = N11;
7561 V2 = N21;
7562 V3 = N31;
7563 goto L1;
7565 BODY;
7566 V += 1;
7567 V3 += STEP3;
7568 V2 += (V3 cond3 N32) ? 0 : STEP2;
7569 V3 = (V3 cond3 N32) ? V3 : N31;
7570 V1 += (V2 cond2 N22) ? 0 : STEP1;
7571 V2 = (V2 cond2 N22) ? V2 : N21;
7573 if (V < count) goto L0; else goto L2;
7578 static void
7579 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7581 tree type, t;
7582 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7583 gimple_stmt_iterator gsi;
7584 gimple stmt;
7585 gcond *cond_stmt;
7586 bool broken_loop = region->cont == NULL;
7587 edge e, ne;
7588 tree *counts = NULL;
7589 int i;
7590 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7591 OMP_CLAUSE_SAFELEN);
7592 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7593 OMP_CLAUSE__SIMDUID_);
7594 tree n1, n2;
7596 type = TREE_TYPE (fd->loop.v);
7597 entry_bb = region->entry;
7598 cont_bb = region->cont;
7599 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7600 gcc_assert (broken_loop
7601 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7602 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7603 if (!broken_loop)
7605 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7606 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7607 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7608 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7610 else
7612 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7613 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7614 l2_bb = single_succ (l1_bb);
7616 exit_bb = region->exit;
7617 l2_dom_bb = NULL;
7619 gsi = gsi_last_bb (entry_bb);
7621 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7622 /* Not needed in SSA form right now. */
7623 gcc_assert (!gimple_in_ssa_p (cfun));
7624 if (fd->collapse > 1)
7626 int first_zero_iter = -1;
7627 basic_block zero_iter_bb = l2_bb;
7629 counts = XALLOCAVEC (tree, fd->collapse);
7630 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7631 zero_iter_bb, first_zero_iter,
7632 l2_dom_bb);
7634 if (l2_dom_bb == NULL)
7635 l2_dom_bb = l1_bb;
7637 n1 = fd->loop.n1;
7638 n2 = fd->loop.n2;
7639 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7641 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7642 OMP_CLAUSE__LOOPTEMP_);
7643 gcc_assert (innerc);
7644 n1 = OMP_CLAUSE_DECL (innerc);
7645 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7646 OMP_CLAUSE__LOOPTEMP_);
7647 gcc_assert (innerc);
7648 n2 = OMP_CLAUSE_DECL (innerc);
7649 expand_omp_build_assign (&gsi, fd->loop.v,
7650 fold_convert (type, n1));
7651 if (fd->collapse > 1)
7653 gsi_prev (&gsi);
7654 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7655 gsi_next (&gsi);
7658 else
7660 expand_omp_build_assign (&gsi, fd->loop.v,
7661 fold_convert (type, fd->loop.n1));
7662 if (fd->collapse > 1)
7663 for (i = 0; i < fd->collapse; i++)
7665 tree itype = TREE_TYPE (fd->loops[i].v);
7666 if (POINTER_TYPE_P (itype))
7667 itype = signed_type_for (itype);
7668 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7669 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7673 /* Remove the GIMPLE_OMP_FOR statement. */
7674 gsi_remove (&gsi, true);
7676 if (!broken_loop)
7678 /* Code to control the increment goes in the CONT_BB. */
7679 gsi = gsi_last_bb (cont_bb);
7680 stmt = gsi_stmt (gsi);
7681 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7683 if (POINTER_TYPE_P (type))
7684 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7685 else
7686 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7687 expand_omp_build_assign (&gsi, fd->loop.v, t);
7689 if (fd->collapse > 1)
7691 i = fd->collapse - 1;
7692 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7694 t = fold_convert (sizetype, fd->loops[i].step);
7695 t = fold_build_pointer_plus (fd->loops[i].v, t);
7697 else
7699 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7700 fd->loops[i].step);
7701 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7702 fd->loops[i].v, t);
7704 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7706 for (i = fd->collapse - 1; i > 0; i--)
7708 tree itype = TREE_TYPE (fd->loops[i].v);
7709 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7710 if (POINTER_TYPE_P (itype2))
7711 itype2 = signed_type_for (itype2);
7712 t = build3 (COND_EXPR, itype2,
7713 build2 (fd->loops[i].cond_code, boolean_type_node,
7714 fd->loops[i].v,
7715 fold_convert (itype, fd->loops[i].n2)),
7716 build_int_cst (itype2, 0),
7717 fold_convert (itype2, fd->loops[i - 1].step));
7718 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7719 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7720 else
7721 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7722 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7724 t = build3 (COND_EXPR, itype,
7725 build2 (fd->loops[i].cond_code, boolean_type_node,
7726 fd->loops[i].v,
7727 fold_convert (itype, fd->loops[i].n2)),
7728 fd->loops[i].v,
7729 fold_convert (itype, fd->loops[i].n1));
7730 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7734 /* Remove GIMPLE_OMP_CONTINUE. */
7735 gsi_remove (&gsi, true);
7738 /* Emit the condition in L1_BB. */
7739 gsi = gsi_start_bb (l1_bb);
7741 t = fold_convert (type, n2);
7742 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7743 false, GSI_CONTINUE_LINKING);
7744 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7745 cond_stmt = gimple_build_cond_empty (t);
7746 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7747 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7748 NULL, NULL)
7749 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7750 NULL, NULL))
7752 gsi = gsi_for_stmt (cond_stmt);
7753 gimple_regimplify_operands (cond_stmt, &gsi);
7756 /* Remove GIMPLE_OMP_RETURN. */
7757 gsi = gsi_last_bb (exit_bb);
7758 gsi_remove (&gsi, true);
7760 /* Connect the new blocks. */
7761 remove_edge (FALLTHRU_EDGE (entry_bb));
7763 if (!broken_loop)
7765 remove_edge (BRANCH_EDGE (entry_bb));
7766 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7768 e = BRANCH_EDGE (l1_bb);
7769 ne = FALLTHRU_EDGE (l1_bb);
7770 e->flags = EDGE_TRUE_VALUE;
7772 else
7774 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7776 ne = single_succ_edge (l1_bb);
7777 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7780 ne->flags = EDGE_FALSE_VALUE;
7781 e->probability = REG_BR_PROB_BASE * 7 / 8;
7782 ne->probability = REG_BR_PROB_BASE / 8;
7784 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7785 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7786 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7788 if (!broken_loop)
7790 struct loop *loop = alloc_loop ();
7791 loop->header = l1_bb;
7792 loop->latch = cont_bb;
7793 add_loop (loop, l1_bb->loop_father);
7794 if (safelen == NULL_TREE)
7795 loop->safelen = INT_MAX;
7796 else
7798 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7799 if (TREE_CODE (safelen) != INTEGER_CST)
7800 loop->safelen = 0;
7801 else if (!tree_fits_uhwi_p (safelen)
7802 || tree_to_uhwi (safelen) > INT_MAX)
7803 loop->safelen = INT_MAX;
7804 else
7805 loop->safelen = tree_to_uhwi (safelen);
7806 if (loop->safelen == 1)
7807 loop->safelen = 0;
7809 if (simduid)
7811 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7812 cfun->has_simduid_loops = true;
7814 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7815 the loop. */
7816 if ((flag_tree_loop_vectorize
7817 || (!global_options_set.x_flag_tree_loop_vectorize
7818 && !global_options_set.x_flag_tree_vectorize))
7819 && flag_tree_loop_optimize
7820 && loop->safelen > 1)
7822 loop->force_vectorize = true;
7823 cfun->has_force_vectorize_loops = true;
7826 else if (simduid)
7827 cfun->has_simduid_loops = true;
7831 /* Expand the OMP loop defined by REGION. */
7833 static void
7834 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7836 struct omp_for_data fd;
7837 struct omp_for_data_loop *loops;
7839 loops
7840 = (struct omp_for_data_loop *)
7841 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7842 * sizeof (struct omp_for_data_loop));
7843 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7844 &fd, loops);
7845 region->sched_kind = fd.sched_kind;
7847 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7848 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7849 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7850 if (region->cont)
7852 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7853 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7854 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7856 else
7857 /* If there isn't a continue then this is a degerate case where
7858 the introduction of abnormal edges during lowering will prevent
7859 original loops from being detected. Fix that up. */
7860 loops_state_set (LOOPS_NEED_FIXUP);
7862 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7863 expand_omp_simd (region, &fd);
7864 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7865 expand_cilk_for (region, &fd);
7866 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7867 && !fd.have_ordered)
7869 if (fd.chunk_size == NULL)
7870 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7871 else
7872 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7874 else
7876 int fn_index, start_ix, next_ix;
7878 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7879 == GF_OMP_FOR_KIND_FOR);
7880 if (fd.chunk_size == NULL
7881 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7882 fd.chunk_size = integer_zero_node;
7883 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7884 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7885 ? 3 : fd.sched_kind;
7886 fn_index += fd.have_ordered * 4;
7887 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7888 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7889 if (fd.iter_type == long_long_unsigned_type_node)
7891 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7892 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7893 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7894 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7896 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7897 (enum built_in_function) next_ix, inner_stmt);
7900 if (gimple_in_ssa_p (cfun))
7901 update_ssa (TODO_update_ssa_only_virtuals);
7905 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7907 v = GOMP_sections_start (n);
7909 switch (v)
7911 case 0:
7912 goto L2;
7913 case 1:
7914 section 1;
7915 goto L1;
7916 case 2:
7918 case n:
7920 default:
7921 abort ();
7924 v = GOMP_sections_next ();
7925 goto L0;
7927 reduction;
7929 If this is a combined parallel sections, replace the call to
7930 GOMP_sections_start with call to GOMP_sections_next. */
7932 static void
7933 expand_omp_sections (struct omp_region *region)
7935 tree t, u, vin = NULL, vmain, vnext, l2;
7936 unsigned len;
7937 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7938 gimple_stmt_iterator si, switch_si;
7939 gomp_sections *sections_stmt;
7940 gimple stmt;
7941 gomp_continue *cont;
7942 edge_iterator ei;
7943 edge e;
7944 struct omp_region *inner;
7945 unsigned i, casei;
7946 bool exit_reachable = region->cont != NULL;
7948 gcc_assert (region->exit != NULL);
7949 entry_bb = region->entry;
7950 l0_bb = single_succ (entry_bb);
7951 l1_bb = region->cont;
7952 l2_bb = region->exit;
7953 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7954 l2 = gimple_block_label (l2_bb);
7955 else
7957 /* This can happen if there are reductions. */
7958 len = EDGE_COUNT (l0_bb->succs);
7959 gcc_assert (len > 0);
7960 e = EDGE_SUCC (l0_bb, len - 1);
7961 si = gsi_last_bb (e->dest);
7962 l2 = NULL_TREE;
7963 if (gsi_end_p (si)
7964 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7965 l2 = gimple_block_label (e->dest);
7966 else
7967 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7969 si = gsi_last_bb (e->dest);
7970 if (gsi_end_p (si)
7971 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7973 l2 = gimple_block_label (e->dest);
7974 break;
7978 if (exit_reachable)
7979 default_bb = create_empty_bb (l1_bb->prev_bb);
7980 else
7981 default_bb = create_empty_bb (l0_bb);
7983 /* We will build a switch() with enough cases for all the
7984 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7985 and a default case to abort if something goes wrong. */
7986 len = EDGE_COUNT (l0_bb->succs);
7988 /* Use vec::quick_push on label_vec throughout, since we know the size
7989 in advance. */
7990 auto_vec<tree> label_vec (len);
7992 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7993 GIMPLE_OMP_SECTIONS statement. */
7994 si = gsi_last_bb (entry_bb);
7995 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
7996 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7997 vin = gimple_omp_sections_control (sections_stmt);
7998 if (!is_combined_parallel (region))
8000 /* If we are not inside a combined parallel+sections region,
8001 call GOMP_sections_start. */
8002 t = build_int_cst (unsigned_type_node, len - 1);
8003 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
8004 stmt = gimple_build_call (u, 1, t);
8006 else
8008 /* Otherwise, call GOMP_sections_next. */
8009 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8010 stmt = gimple_build_call (u, 0);
8012 gimple_call_set_lhs (stmt, vin);
8013 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8014 gsi_remove (&si, true);
8016 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8017 L0_BB. */
8018 switch_si = gsi_last_bb (l0_bb);
8019 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8020 if (exit_reachable)
8022 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8023 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8024 vmain = gimple_omp_continue_control_use (cont);
8025 vnext = gimple_omp_continue_control_def (cont);
8027 else
8029 vmain = vin;
8030 vnext = NULL_TREE;
8033 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8034 label_vec.quick_push (t);
8035 i = 1;
8037 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8038 for (inner = region->inner, casei = 1;
8039 inner;
8040 inner = inner->next, i++, casei++)
8042 basic_block s_entry_bb, s_exit_bb;
8044 /* Skip optional reduction region. */
8045 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8047 --i;
8048 --casei;
8049 continue;
8052 s_entry_bb = inner->entry;
8053 s_exit_bb = inner->exit;
8055 t = gimple_block_label (s_entry_bb);
8056 u = build_int_cst (unsigned_type_node, casei);
8057 u = build_case_label (u, NULL, t);
8058 label_vec.quick_push (u);
8060 si = gsi_last_bb (s_entry_bb);
8061 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8062 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8063 gsi_remove (&si, true);
8064 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8066 if (s_exit_bb == NULL)
8067 continue;
8069 si = gsi_last_bb (s_exit_bb);
8070 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8071 gsi_remove (&si, true);
8073 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8076 /* Error handling code goes in DEFAULT_BB. */
8077 t = gimple_block_label (default_bb);
8078 u = build_case_label (NULL, NULL, t);
8079 make_edge (l0_bb, default_bb, 0);
8080 add_bb_to_loop (default_bb, current_loops->tree_root);
8082 stmt = gimple_build_switch (vmain, u, label_vec);
8083 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8084 gsi_remove (&switch_si, true);
8086 si = gsi_start_bb (default_bb);
8087 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8088 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8090 if (exit_reachable)
8092 tree bfn_decl;
8094 /* Code to get the next section goes in L1_BB. */
8095 si = gsi_last_bb (l1_bb);
8096 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8098 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8099 stmt = gimple_build_call (bfn_decl, 0);
8100 gimple_call_set_lhs (stmt, vnext);
8101 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8102 gsi_remove (&si, true);
8104 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8107 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8108 si = gsi_last_bb (l2_bb);
8109 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8110 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8111 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8112 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8113 else
8114 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8115 stmt = gimple_build_call (t, 0);
8116 if (gimple_omp_return_lhs (gsi_stmt (si)))
8117 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8118 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8119 gsi_remove (&si, true);
8121 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8125 /* Expand code for an OpenMP single directive. We've already expanded
8126 much of the code, here we simply place the GOMP_barrier call. */
8128 static void
8129 expand_omp_single (struct omp_region *region)
8131 basic_block entry_bb, exit_bb;
8132 gimple_stmt_iterator si;
8134 entry_bb = region->entry;
8135 exit_bb = region->exit;
8137 si = gsi_last_bb (entry_bb);
8138 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8139 gsi_remove (&si, true);
8140 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8142 si = gsi_last_bb (exit_bb);
8143 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8145 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8146 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8148 gsi_remove (&si, true);
8149 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8153 /* Generic expansion for OpenMP synchronization directives: master,
8154 ordered and critical. All we need to do here is remove the entry
8155 and exit markers for REGION. */
8157 static void
8158 expand_omp_synch (struct omp_region *region)
8160 basic_block entry_bb, exit_bb;
8161 gimple_stmt_iterator si;
8163 entry_bb = region->entry;
8164 exit_bb = region->exit;
8166 si = gsi_last_bb (entry_bb);
8167 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8168 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8169 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8170 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8171 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8172 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8173 gsi_remove (&si, true);
8174 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8176 if (exit_bb)
8178 si = gsi_last_bb (exit_bb);
8179 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8180 gsi_remove (&si, true);
8181 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8185 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8186 operation as a normal volatile load. */
8188 static bool
8189 expand_omp_atomic_load (basic_block load_bb, tree addr,
8190 tree loaded_val, int index)
8192 enum built_in_function tmpbase;
8193 gimple_stmt_iterator gsi;
8194 basic_block store_bb;
8195 location_t loc;
8196 gimple stmt;
8197 tree decl, call, type, itype;
8199 gsi = gsi_last_bb (load_bb);
8200 stmt = gsi_stmt (gsi);
8201 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8202 loc = gimple_location (stmt);
8204 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8205 is smaller than word size, then expand_atomic_load assumes that the load
8206 is atomic. We could avoid the builtin entirely in this case. */
8208 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8209 decl = builtin_decl_explicit (tmpbase);
8210 if (decl == NULL_TREE)
8211 return false;
8213 type = TREE_TYPE (loaded_val);
8214 itype = TREE_TYPE (TREE_TYPE (decl));
8216 call = build_call_expr_loc (loc, decl, 2, addr,
8217 build_int_cst (NULL,
8218 gimple_omp_atomic_seq_cst_p (stmt)
8219 ? MEMMODEL_SEQ_CST
8220 : MEMMODEL_RELAXED));
8221 if (!useless_type_conversion_p (type, itype))
8222 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8223 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8225 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8226 gsi_remove (&gsi, true);
8228 store_bb = single_succ (load_bb);
8229 gsi = gsi_last_bb (store_bb);
8230 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8231 gsi_remove (&gsi, true);
8233 if (gimple_in_ssa_p (cfun))
8234 update_ssa (TODO_update_ssa_no_phi);
8236 return true;
8239 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8240 operation as a normal volatile store. */
8242 static bool
8243 expand_omp_atomic_store (basic_block load_bb, tree addr,
8244 tree loaded_val, tree stored_val, int index)
8246 enum built_in_function tmpbase;
8247 gimple_stmt_iterator gsi;
8248 basic_block store_bb = single_succ (load_bb);
8249 location_t loc;
8250 gimple stmt;
8251 tree decl, call, type, itype;
8252 machine_mode imode;
8253 bool exchange;
8255 gsi = gsi_last_bb (load_bb);
8256 stmt = gsi_stmt (gsi);
8257 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8259 /* If the load value is needed, then this isn't a store but an exchange. */
8260 exchange = gimple_omp_atomic_need_value_p (stmt);
8262 gsi = gsi_last_bb (store_bb);
8263 stmt = gsi_stmt (gsi);
8264 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8265 loc = gimple_location (stmt);
8267 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8268 is smaller than word size, then expand_atomic_store assumes that the store
8269 is atomic. We could avoid the builtin entirely in this case. */
8271 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8272 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8273 decl = builtin_decl_explicit (tmpbase);
8274 if (decl == NULL_TREE)
8275 return false;
8277 type = TREE_TYPE (stored_val);
8279 /* Dig out the type of the function's second argument. */
8280 itype = TREE_TYPE (decl);
8281 itype = TYPE_ARG_TYPES (itype);
8282 itype = TREE_CHAIN (itype);
8283 itype = TREE_VALUE (itype);
8284 imode = TYPE_MODE (itype);
8286 if (exchange && !can_atomic_exchange_p (imode, true))
8287 return false;
8289 if (!useless_type_conversion_p (itype, type))
8290 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8291 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8292 build_int_cst (NULL,
8293 gimple_omp_atomic_seq_cst_p (stmt)
8294 ? MEMMODEL_SEQ_CST
8295 : MEMMODEL_RELAXED));
8296 if (exchange)
8298 if (!useless_type_conversion_p (type, itype))
8299 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8300 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8303 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8304 gsi_remove (&gsi, true);
8306 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8307 gsi = gsi_last_bb (load_bb);
8308 gsi_remove (&gsi, true);
8310 if (gimple_in_ssa_p (cfun))
8311 update_ssa (TODO_update_ssa_no_phi);
8313 return true;
8316 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8317 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8318 size of the data type, and thus usable to find the index of the builtin
8319 decl. Returns false if the expression is not of the proper form. */
8321 static bool
8322 expand_omp_atomic_fetch_op (basic_block load_bb,
8323 tree addr, tree loaded_val,
8324 tree stored_val, int index)
8326 enum built_in_function oldbase, newbase, tmpbase;
8327 tree decl, itype, call;
8328 tree lhs, rhs;
8329 basic_block store_bb = single_succ (load_bb);
8330 gimple_stmt_iterator gsi;
8331 gimple stmt;
8332 location_t loc;
8333 enum tree_code code;
8334 bool need_old, need_new;
8335 machine_mode imode;
8336 bool seq_cst;
8338 /* We expect to find the following sequences:
8340 load_bb:
8341 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8343 store_bb:
8344 val = tmp OP something; (or: something OP tmp)
8345 GIMPLE_OMP_STORE (val)
8347 ???FIXME: Allow a more flexible sequence.
8348 Perhaps use data flow to pick the statements.
8352 gsi = gsi_after_labels (store_bb);
8353 stmt = gsi_stmt (gsi);
8354 loc = gimple_location (stmt);
8355 if (!is_gimple_assign (stmt))
8356 return false;
8357 gsi_next (&gsi);
8358 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8359 return false;
8360 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8361 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8362 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8363 gcc_checking_assert (!need_old || !need_new);
8365 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8366 return false;
8368 /* Check for one of the supported fetch-op operations. */
8369 code = gimple_assign_rhs_code (stmt);
8370 switch (code)
8372 case PLUS_EXPR:
8373 case POINTER_PLUS_EXPR:
8374 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8375 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8376 break;
8377 case MINUS_EXPR:
8378 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8379 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8380 break;
8381 case BIT_AND_EXPR:
8382 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8383 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8384 break;
8385 case BIT_IOR_EXPR:
8386 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8387 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8388 break;
8389 case BIT_XOR_EXPR:
8390 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8391 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8392 break;
8393 default:
8394 return false;
8397 /* Make sure the expression is of the proper form. */
8398 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8399 rhs = gimple_assign_rhs2 (stmt);
8400 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8401 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8402 rhs = gimple_assign_rhs1 (stmt);
8403 else
8404 return false;
8406 tmpbase = ((enum built_in_function)
8407 ((need_new ? newbase : oldbase) + index + 1));
8408 decl = builtin_decl_explicit (tmpbase);
8409 if (decl == NULL_TREE)
8410 return false;
8411 itype = TREE_TYPE (TREE_TYPE (decl));
8412 imode = TYPE_MODE (itype);
8414 /* We could test all of the various optabs involved, but the fact of the
8415 matter is that (with the exception of i486 vs i586 and xadd) all targets
8416 that support any atomic operaton optab also implements compare-and-swap.
8417 Let optabs.c take care of expanding any compare-and-swap loop. */
8418 if (!can_compare_and_swap_p (imode, true))
8419 return false;
8421 gsi = gsi_last_bb (load_bb);
8422 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8424 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8425 It only requires that the operation happen atomically. Thus we can
8426 use the RELAXED memory model. */
8427 call = build_call_expr_loc (loc, decl, 3, addr,
8428 fold_convert_loc (loc, itype, rhs),
8429 build_int_cst (NULL,
8430 seq_cst ? MEMMODEL_SEQ_CST
8431 : MEMMODEL_RELAXED));
8433 if (need_old || need_new)
8435 lhs = need_old ? loaded_val : stored_val;
8436 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8437 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8439 else
8440 call = fold_convert_loc (loc, void_type_node, call);
8441 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8442 gsi_remove (&gsi, true);
8444 gsi = gsi_last_bb (store_bb);
8445 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8446 gsi_remove (&gsi, true);
8447 gsi = gsi_last_bb (store_bb);
8448 gsi_remove (&gsi, true);
8450 if (gimple_in_ssa_p (cfun))
8451 update_ssa (TODO_update_ssa_no_phi);
8453 return true;
8456 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8458 oldval = *addr;
8459 repeat:
8460 newval = rhs; // with oldval replacing *addr in rhs
8461 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8462 if (oldval != newval)
8463 goto repeat;
8465 INDEX is log2 of the size of the data type, and thus usable to find the
8466 index of the builtin decl. */
8468 static bool
8469 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8470 tree addr, tree loaded_val, tree stored_val,
8471 int index)
8473 tree loadedi, storedi, initial, new_storedi, old_vali;
8474 tree type, itype, cmpxchg, iaddr;
8475 gimple_stmt_iterator si;
8476 basic_block loop_header = single_succ (load_bb);
8477 gimple phi, stmt;
8478 edge e;
8479 enum built_in_function fncode;
8481 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8482 order to use the RELAXED memory model effectively. */
8483 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8484 + index + 1);
8485 cmpxchg = builtin_decl_explicit (fncode);
8486 if (cmpxchg == NULL_TREE)
8487 return false;
8488 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8489 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8491 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8492 return false;
8494 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8495 si = gsi_last_bb (load_bb);
8496 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8498 /* For floating-point values, we'll need to view-convert them to integers
8499 so that we can perform the atomic compare and swap. Simplify the
8500 following code by always setting up the "i"ntegral variables. */
8501 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8503 tree iaddr_val;
8505 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8506 true));
8507 iaddr_val
8508 = force_gimple_operand_gsi (&si,
8509 fold_convert (TREE_TYPE (iaddr), addr),
8510 false, NULL_TREE, true, GSI_SAME_STMT);
8511 stmt = gimple_build_assign (iaddr, iaddr_val);
8512 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8513 loadedi = create_tmp_var (itype);
8514 if (gimple_in_ssa_p (cfun))
8515 loadedi = make_ssa_name (loadedi);
8517 else
8519 iaddr = addr;
8520 loadedi = loaded_val;
8523 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8524 tree loaddecl = builtin_decl_explicit (fncode);
8525 if (loaddecl)
8526 initial
8527 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8528 build_call_expr (loaddecl, 2, iaddr,
8529 build_int_cst (NULL_TREE,
8530 MEMMODEL_RELAXED)));
8531 else
8532 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8533 build_int_cst (TREE_TYPE (iaddr), 0));
8535 initial
8536 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8537 GSI_SAME_STMT);
8539 /* Move the value to the LOADEDI temporary. */
8540 if (gimple_in_ssa_p (cfun))
8542 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8543 phi = create_phi_node (loadedi, loop_header);
8544 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8545 initial);
8547 else
8548 gsi_insert_before (&si,
8549 gimple_build_assign (loadedi, initial),
8550 GSI_SAME_STMT);
8551 if (loadedi != loaded_val)
8553 gimple_stmt_iterator gsi2;
8554 tree x;
8556 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8557 gsi2 = gsi_start_bb (loop_header);
8558 if (gimple_in_ssa_p (cfun))
8560 gassign *stmt;
8561 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8562 true, GSI_SAME_STMT);
8563 stmt = gimple_build_assign (loaded_val, x);
8564 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8566 else
8568 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8569 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8570 true, GSI_SAME_STMT);
8573 gsi_remove (&si, true);
8575 si = gsi_last_bb (store_bb);
8576 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8578 if (iaddr == addr)
8579 storedi = stored_val;
8580 else
8581 storedi =
8582 force_gimple_operand_gsi (&si,
8583 build1 (VIEW_CONVERT_EXPR, itype,
8584 stored_val), true, NULL_TREE, true,
8585 GSI_SAME_STMT);
8587 /* Build the compare&swap statement. */
8588 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8589 new_storedi = force_gimple_operand_gsi (&si,
8590 fold_convert (TREE_TYPE (loadedi),
8591 new_storedi),
8592 true, NULL_TREE,
8593 true, GSI_SAME_STMT);
8595 if (gimple_in_ssa_p (cfun))
8596 old_vali = loadedi;
8597 else
8599 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8600 stmt = gimple_build_assign (old_vali, loadedi);
8601 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8603 stmt = gimple_build_assign (loadedi, new_storedi);
8604 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8607 /* Note that we always perform the comparison as an integer, even for
8608 floating point. This allows the atomic operation to properly
8609 succeed even with NaNs and -0.0. */
8610 stmt = gimple_build_cond_empty
8611 (build2 (NE_EXPR, boolean_type_node,
8612 new_storedi, old_vali));
8613 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8615 /* Update cfg. */
8616 e = single_succ_edge (store_bb);
8617 e->flags &= ~EDGE_FALLTHRU;
8618 e->flags |= EDGE_FALSE_VALUE;
8620 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8622 /* Copy the new value to loadedi (we already did that before the condition
8623 if we are not in SSA). */
8624 if (gimple_in_ssa_p (cfun))
8626 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8627 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8630 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8631 gsi_remove (&si, true);
8633 struct loop *loop = alloc_loop ();
8634 loop->header = loop_header;
8635 loop->latch = store_bb;
8636 add_loop (loop, loop_header->loop_father);
8638 if (gimple_in_ssa_p (cfun))
8639 update_ssa (TODO_update_ssa_no_phi);
8641 return true;
8644 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8646 GOMP_atomic_start ();
8647 *addr = rhs;
8648 GOMP_atomic_end ();
8650 The result is not globally atomic, but works so long as all parallel
8651 references are within #pragma omp atomic directives. According to
8652 responses received from omp@openmp.org, appears to be within spec.
8653 Which makes sense, since that's how several other compilers handle
8654 this situation as well.
8655 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8656 expanding. STORED_VAL is the operand of the matching
8657 GIMPLE_OMP_ATOMIC_STORE.
8659 We replace
8660 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8661 loaded_val = *addr;
8663 and replace
8664 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8665 *addr = stored_val;
8668 static bool
8669 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8670 tree addr, tree loaded_val, tree stored_val)
8672 gimple_stmt_iterator si;
8673 gassign *stmt;
8674 tree t;
8676 si = gsi_last_bb (load_bb);
8677 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8679 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8680 t = build_call_expr (t, 0);
8681 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8683 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8684 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8685 gsi_remove (&si, true);
8687 si = gsi_last_bb (store_bb);
8688 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8690 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8691 stored_val);
8692 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8694 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8695 t = build_call_expr (t, 0);
8696 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8697 gsi_remove (&si, true);
8699 if (gimple_in_ssa_p (cfun))
8700 update_ssa (TODO_update_ssa_no_phi);
8701 return true;
8704 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8705 using expand_omp_atomic_fetch_op. If it failed, we try to
8706 call expand_omp_atomic_pipeline, and if it fails too, the
8707 ultimate fallback is wrapping the operation in a mutex
8708 (expand_omp_atomic_mutex). REGION is the atomic region built
8709 by build_omp_regions_1(). */
8711 static void
8712 expand_omp_atomic (struct omp_region *region)
8714 basic_block load_bb = region->entry, store_bb = region->exit;
8715 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8716 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8717 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8718 tree addr = gimple_omp_atomic_load_rhs (load);
8719 tree stored_val = gimple_omp_atomic_store_val (store);
8720 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8721 HOST_WIDE_INT index;
8723 /* Make sure the type is one of the supported sizes. */
8724 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8725 index = exact_log2 (index);
8726 if (index >= 0 && index <= 4)
8728 unsigned int align = TYPE_ALIGN_UNIT (type);
8730 /* __sync builtins require strict data alignment. */
8731 if (exact_log2 (align) >= index)
8733 /* Atomic load. */
8734 if (loaded_val == stored_val
8735 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8736 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8737 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8738 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8739 return;
8741 /* Atomic store. */
8742 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8743 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8744 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8745 && store_bb == single_succ (load_bb)
8746 && first_stmt (store_bb) == store
8747 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8748 stored_val, index))
8749 return;
8751 /* When possible, use specialized atomic update functions. */
8752 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8753 && store_bb == single_succ (load_bb)
8754 && expand_omp_atomic_fetch_op (load_bb, addr,
8755 loaded_val, stored_val, index))
8756 return;
8758 /* If we don't have specialized __sync builtins, try and implement
8759 as a compare and swap loop. */
8760 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8761 loaded_val, stored_val, index))
8762 return;
8766 /* The ultimate fallback is wrapping the operation in a mutex. */
8767 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8771 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8773 static void
8774 expand_omp_target (struct omp_region *region)
8776 basic_block entry_bb, exit_bb, new_bb;
8777 struct function *child_cfun;
8778 tree child_fn, block, t;
8779 gimple_stmt_iterator gsi;
8780 gomp_target *entry_stmt;
8781 gimple stmt;
8782 edge e;
8783 bool offloaded, data_region;
8785 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8786 new_bb = region->entry;
8788 offloaded = is_gimple_omp_offloaded (entry_stmt);
8789 switch (gimple_omp_target_kind (entry_stmt))
8791 case GF_OMP_TARGET_KIND_REGION:
8792 case GF_OMP_TARGET_KIND_UPDATE:
8793 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8794 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8795 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8796 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8797 data_region = false;
8798 break;
8799 case GF_OMP_TARGET_KIND_DATA:
8800 case GF_OMP_TARGET_KIND_OACC_DATA:
8801 data_region = true;
8802 break;
8803 default:
8804 gcc_unreachable ();
8807 child_fn = NULL_TREE;
8808 child_cfun = NULL;
8809 if (offloaded)
8811 child_fn = gimple_omp_target_child_fn (entry_stmt);
8812 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8815 /* Supported by expand_omp_taskreg, but not here. */
8816 if (child_cfun != NULL)
8817 gcc_checking_assert (!child_cfun->cfg);
8818 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8820 entry_bb = region->entry;
8821 exit_bb = region->exit;
8823 if (offloaded)
8825 unsigned srcidx, dstidx, num;
8827 /* If the offloading region needs data sent from the parent
8828 function, then the very first statement (except possible
8829 tree profile counter updates) of the offloading body
8830 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8831 &.OMP_DATA_O is passed as an argument to the child function,
8832 we need to replace it with the argument as seen by the child
8833 function.
8835 In most cases, this will end up being the identity assignment
8836 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8837 a function call that has been inlined, the original PARM_DECL
8838 .OMP_DATA_I may have been converted into a different local
8839 variable. In which case, we need to keep the assignment. */
8840 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8841 if (data_arg)
8843 basic_block entry_succ_bb = single_succ (entry_bb);
8844 gimple_stmt_iterator gsi;
8845 tree arg;
8846 gimple tgtcopy_stmt = NULL;
8847 tree sender = TREE_VEC_ELT (data_arg, 0);
8849 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8851 gcc_assert (!gsi_end_p (gsi));
8852 stmt = gsi_stmt (gsi);
8853 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8854 continue;
8856 if (gimple_num_ops (stmt) == 2)
8858 tree arg = gimple_assign_rhs1 (stmt);
8860 /* We're ignoring the subcode because we're
8861 effectively doing a STRIP_NOPS. */
8863 if (TREE_CODE (arg) == ADDR_EXPR
8864 && TREE_OPERAND (arg, 0) == sender)
8866 tgtcopy_stmt = stmt;
8867 break;
8872 gcc_assert (tgtcopy_stmt != NULL);
8873 arg = DECL_ARGUMENTS (child_fn);
8875 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8876 gsi_remove (&gsi, true);
8879 /* Declare local variables needed in CHILD_CFUN. */
8880 block = DECL_INITIAL (child_fn);
8881 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8882 /* The gimplifier could record temporaries in the offloading block
8883 rather than in containing function's local_decls chain,
8884 which would mean cgraph missed finalizing them. Do it now. */
8885 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8886 if (TREE_CODE (t) == VAR_DECL
8887 && TREE_STATIC (t)
8888 && !DECL_EXTERNAL (t))
8889 varpool_node::finalize_decl (t);
8890 DECL_SAVED_TREE (child_fn) = NULL;
8891 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8892 gimple_set_body (child_fn, NULL);
8893 TREE_USED (block) = 1;
8895 /* Reset DECL_CONTEXT on function arguments. */
8896 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8897 DECL_CONTEXT (t) = child_fn;
8899 /* Split ENTRY_BB at GIMPLE_*,
8900 so that it can be moved to the child function. */
8901 gsi = gsi_last_bb (entry_bb);
8902 stmt = gsi_stmt (gsi);
8903 gcc_assert (stmt
8904 && gimple_code (stmt) == gimple_code (entry_stmt));
8905 e = split_block (entry_bb, stmt);
8906 gsi_remove (&gsi, true);
8907 entry_bb = e->dest;
8908 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8910 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8911 if (exit_bb)
8913 gsi = gsi_last_bb (exit_bb);
8914 gcc_assert (!gsi_end_p (gsi)
8915 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8916 stmt = gimple_build_return (NULL);
8917 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8918 gsi_remove (&gsi, true);
8921 /* Move the offloading region into CHILD_CFUN. */
8923 block = gimple_block (entry_stmt);
8925 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8926 if (exit_bb)
8927 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8928 /* When the OMP expansion process cannot guarantee an up-to-date
8929 loop tree arrange for the child function to fixup loops. */
8930 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8931 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8933 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8934 num = vec_safe_length (child_cfun->local_decls);
8935 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8937 t = (*child_cfun->local_decls)[srcidx];
8938 if (DECL_CONTEXT (t) == cfun->decl)
8939 continue;
8940 if (srcidx != dstidx)
8941 (*child_cfun->local_decls)[dstidx] = t;
8942 dstidx++;
8944 if (dstidx != num)
8945 vec_safe_truncate (child_cfun->local_decls, dstidx);
8947 /* Inform the callgraph about the new function. */
8948 child_cfun->curr_properties = cfun->curr_properties;
8949 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
8950 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
8951 cgraph_node *node = cgraph_node::get_create (child_fn);
8952 node->parallelized_function = 1;
8953 cgraph_node::add_new_function (child_fn, true);
8955 #ifdef ENABLE_OFFLOADING
8956 /* Add the new function to the offload table. */
8957 vec_safe_push (offload_funcs, child_fn);
8958 #endif
8960 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8961 fixed in a following pass. */
8962 push_cfun (child_cfun);
8963 cgraph_edge::rebuild_edges ();
8965 #ifdef ENABLE_OFFLOADING
8966 /* Prevent IPA from removing child_fn as unreachable, since there are no
8967 refs from the parent function to child_fn in offload LTO mode. */
8968 cgraph_node::get (child_fn)->mark_force_output ();
8969 #endif
8971 /* Some EH regions might become dead, see PR34608. If
8972 pass_cleanup_cfg isn't the first pass to happen with the
8973 new child, these dead EH edges might cause problems.
8974 Clean them up now. */
8975 if (flag_exceptions)
8977 basic_block bb;
8978 bool changed = false;
8980 FOR_EACH_BB_FN (bb, cfun)
8981 changed |= gimple_purge_dead_eh_edges (bb);
8982 if (changed)
8983 cleanup_tree_cfg ();
8985 pop_cfun ();
8988 /* Emit a library call to launch the offloading region, or do data
8989 transfers. */
8990 tree t1, t2, t3, t4, device, cond, c, clauses;
8991 enum built_in_function start_ix;
8992 location_t clause_loc;
8994 switch (gimple_omp_target_kind (entry_stmt))
8996 case GF_OMP_TARGET_KIND_REGION:
8997 start_ix = BUILT_IN_GOMP_TARGET;
8998 break;
8999 case GF_OMP_TARGET_KIND_DATA:
9000 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9001 break;
9002 case GF_OMP_TARGET_KIND_UPDATE:
9003 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9004 break;
9005 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9006 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9007 start_ix = BUILT_IN_GOACC_PARALLEL;
9008 break;
9009 case GF_OMP_TARGET_KIND_OACC_DATA:
9010 start_ix = BUILT_IN_GOACC_DATA_START;
9011 break;
9012 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9013 start_ix = BUILT_IN_GOACC_UPDATE;
9014 break;
9015 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9016 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9017 break;
9018 default:
9019 gcc_unreachable ();
9022 clauses = gimple_omp_target_clauses (entry_stmt);
9024 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9025 library choose) and there is no conditional. */
9026 cond = NULL_TREE;
9027 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
9029 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9030 if (c)
9031 cond = OMP_CLAUSE_IF_EXPR (c);
9033 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9034 if (c)
9036 /* Even if we pass it to all library function calls, it is currently only
9037 defined/used for the OpenMP target ones. */
9038 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9039 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9040 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9042 device = OMP_CLAUSE_DEVICE_ID (c);
9043 clause_loc = OMP_CLAUSE_LOCATION (c);
9045 else
9046 clause_loc = gimple_location (entry_stmt);
9048 /* Ensure 'device' is of the correct type. */
9049 device = fold_convert_loc (clause_loc, integer_type_node, device);
9051 /* If we found the clause 'if (cond)', build
9052 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9053 if (cond)
9055 cond = gimple_boolify (cond);
9057 basic_block cond_bb, then_bb, else_bb;
9058 edge e;
9059 tree tmp_var;
9061 tmp_var = create_tmp_var (TREE_TYPE (device));
9062 if (offloaded)
9063 e = split_block_after_labels (new_bb);
9064 else
9066 gsi = gsi_last_bb (new_bb);
9067 gsi_prev (&gsi);
9068 e = split_block (new_bb, gsi_stmt (gsi));
9070 cond_bb = e->src;
9071 new_bb = e->dest;
9072 remove_edge (e);
9074 then_bb = create_empty_bb (cond_bb);
9075 else_bb = create_empty_bb (then_bb);
9076 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9077 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9079 stmt = gimple_build_cond_empty (cond);
9080 gsi = gsi_last_bb (cond_bb);
9081 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9083 gsi = gsi_start_bb (then_bb);
9084 stmt = gimple_build_assign (tmp_var, device);
9085 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9087 gsi = gsi_start_bb (else_bb);
9088 stmt = gimple_build_assign (tmp_var,
9089 build_int_cst (integer_type_node,
9090 GOMP_DEVICE_HOST_FALLBACK));
9091 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9093 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9094 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9095 add_bb_to_loop (then_bb, cond_bb->loop_father);
9096 add_bb_to_loop (else_bb, cond_bb->loop_father);
9097 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9098 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9100 device = tmp_var;
9103 gsi = gsi_last_bb (new_bb);
9104 t = gimple_omp_target_data_arg (entry_stmt);
9105 if (t == NULL)
9107 t1 = size_zero_node;
9108 t2 = build_zero_cst (ptr_type_node);
9109 t3 = t2;
9110 t4 = t2;
9112 else
9114 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9115 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9116 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9117 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9118 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9121 gimple g;
9122 /* The maximum number used by any start_ix, without varargs. */
9123 auto_vec<tree, 11> args;
9124 args.quick_push (device);
9125 if (offloaded)
9126 args.quick_push (build_fold_addr_expr (child_fn));
9127 switch (start_ix)
9129 case BUILT_IN_GOMP_TARGET:
9130 case BUILT_IN_GOMP_TARGET_DATA:
9131 case BUILT_IN_GOMP_TARGET_UPDATE:
9132 /* This const void * is part of the current ABI, but we're not actually
9133 using it. */
9134 args.quick_push (build_zero_cst (ptr_type_node));
9135 break;
9136 case BUILT_IN_GOACC_DATA_START:
9137 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9138 case BUILT_IN_GOACC_PARALLEL:
9139 case BUILT_IN_GOACC_UPDATE:
9140 break;
9141 default:
9142 gcc_unreachable ();
9144 args.quick_push (t1);
9145 args.quick_push (t2);
9146 args.quick_push (t3);
9147 args.quick_push (t4);
9148 switch (start_ix)
9150 case BUILT_IN_GOACC_DATA_START:
9151 case BUILT_IN_GOMP_TARGET:
9152 case BUILT_IN_GOMP_TARGET_DATA:
9153 case BUILT_IN_GOMP_TARGET_UPDATE:
9154 break;
9155 case BUILT_IN_GOACC_PARALLEL:
9157 tree t_num_gangs, t_num_workers, t_vector_length;
9159 /* Default values for num_gangs, num_workers, and vector_length. */
9160 t_num_gangs = t_num_workers = t_vector_length
9161 = fold_convert_loc (gimple_location (entry_stmt),
9162 integer_type_node, integer_one_node);
9163 /* ..., but if present, use the value specified by the respective
9164 clause, making sure that are of the correct type. */
9165 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9166 if (c)
9167 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9168 integer_type_node,
9169 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9170 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9171 if (c)
9172 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9173 integer_type_node,
9174 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9175 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9176 if (c)
9177 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9178 integer_type_node,
9179 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9180 args.quick_push (t_num_gangs);
9181 args.quick_push (t_num_workers);
9182 args.quick_push (t_vector_length);
9184 /* FALLTHRU */
9185 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9186 case BUILT_IN_GOACC_UPDATE:
9188 tree t_async;
9189 int t_wait_idx;
9191 /* Default values for t_async. */
9192 t_async = fold_convert_loc (gimple_location (entry_stmt),
9193 integer_type_node,
9194 build_int_cst (integer_type_node,
9195 GOMP_ASYNC_SYNC));
9196 /* ..., but if present, use the value specified by the respective
9197 clause, making sure that is of the correct type. */
9198 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9199 if (c)
9200 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9201 integer_type_node,
9202 OMP_CLAUSE_ASYNC_EXPR (c));
9204 args.quick_push (t_async);
9205 /* Save the index, and... */
9206 t_wait_idx = args.length ();
9207 /* ... push a default value. */
9208 args.quick_push (fold_convert_loc (gimple_location (entry_stmt),
9209 integer_type_node,
9210 integer_zero_node));
9211 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9212 if (c)
9214 int n = 0;
9216 for (; c; c = OMP_CLAUSE_CHAIN (c))
9218 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9220 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9221 integer_type_node,
9222 OMP_CLAUSE_WAIT_EXPR (c)));
9223 n++;
9227 /* Now that we know the number, replace the default value. */
9228 args.ordered_remove (t_wait_idx);
9229 args.quick_insert (t_wait_idx,
9230 fold_convert_loc (gimple_location (entry_stmt),
9231 integer_type_node,
9232 build_int_cst (integer_type_node, n)));
9235 break;
9236 default:
9237 gcc_unreachable ();
9240 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
9241 gimple_set_location (g, gimple_location (entry_stmt));
9242 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9243 if (!offloaded)
9245 g = gsi_stmt (gsi);
9246 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9247 gsi_remove (&gsi, true);
9249 if (data_region
9250 && region->exit)
9252 gsi = gsi_last_bb (region->exit);
9253 g = gsi_stmt (gsi);
9254 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9255 gsi_remove (&gsi, true);
9260 /* Expand the parallel region tree rooted at REGION. Expansion
9261 proceeds in depth-first order. Innermost regions are expanded
9262 first. This way, parallel regions that require a new function to
9263 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9264 internal dependencies in their body. */
9266 static void
9267 expand_omp (struct omp_region *region)
9269 while (region)
9271 location_t saved_location;
9272 gimple inner_stmt = NULL;
9274 /* First, determine whether this is a combined parallel+workshare
9275 region. */
9276 if (region->type == GIMPLE_OMP_PARALLEL)
9277 determine_parallel_type (region);
9279 if (region->type == GIMPLE_OMP_FOR
9280 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9281 inner_stmt = last_stmt (region->inner->entry);
9283 if (region->inner)
9284 expand_omp (region->inner);
9286 saved_location = input_location;
9287 if (gimple_has_location (last_stmt (region->entry)))
9288 input_location = gimple_location (last_stmt (region->entry));
9290 switch (region->type)
9292 case GIMPLE_OMP_PARALLEL:
9293 case GIMPLE_OMP_TASK:
9294 expand_omp_taskreg (region);
9295 break;
9297 case GIMPLE_OMP_FOR:
9298 expand_omp_for (region, inner_stmt);
9299 break;
9301 case GIMPLE_OMP_SECTIONS:
9302 expand_omp_sections (region);
9303 break;
9305 case GIMPLE_OMP_SECTION:
9306 /* Individual omp sections are handled together with their
9307 parent GIMPLE_OMP_SECTIONS region. */
9308 break;
9310 case GIMPLE_OMP_SINGLE:
9311 expand_omp_single (region);
9312 break;
9314 case GIMPLE_OMP_MASTER:
9315 case GIMPLE_OMP_TASKGROUP:
9316 case GIMPLE_OMP_ORDERED:
9317 case GIMPLE_OMP_CRITICAL:
9318 case GIMPLE_OMP_TEAMS:
9319 expand_omp_synch (region);
9320 break;
9322 case GIMPLE_OMP_ATOMIC_LOAD:
9323 expand_omp_atomic (region);
9324 break;
9326 case GIMPLE_OMP_TARGET:
9327 expand_omp_target (region);
9328 break;
9330 default:
9331 gcc_unreachable ();
9334 input_location = saved_location;
9335 region = region->next;
9340 /* Helper for build_omp_regions. Scan the dominator tree starting at
9341 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9342 true, the function ends once a single tree is built (otherwise, whole
9343 forest of OMP constructs may be built). */
9345 static void
9346 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9347 bool single_tree)
9349 gimple_stmt_iterator gsi;
9350 gimple stmt;
9351 basic_block son;
9353 gsi = gsi_last_bb (bb);
9354 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9356 struct omp_region *region;
9357 enum gimple_code code;
9359 stmt = gsi_stmt (gsi);
9360 code = gimple_code (stmt);
9361 if (code == GIMPLE_OMP_RETURN)
9363 /* STMT is the return point out of region PARENT. Mark it
9364 as the exit point and make PARENT the immediately
9365 enclosing region. */
9366 gcc_assert (parent);
9367 region = parent;
9368 region->exit = bb;
9369 parent = parent->outer;
9371 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9373 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9374 GIMPLE_OMP_RETURN, but matches with
9375 GIMPLE_OMP_ATOMIC_LOAD. */
9376 gcc_assert (parent);
9377 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9378 region = parent;
9379 region->exit = bb;
9380 parent = parent->outer;
9382 else if (code == GIMPLE_OMP_CONTINUE)
9384 gcc_assert (parent);
9385 parent->cont = bb;
9387 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9389 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9390 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9392 else
9394 region = new_omp_region (bb, code, parent);
9395 /* Otherwise... */
9396 if (code == GIMPLE_OMP_TARGET)
9398 switch (gimple_omp_target_kind (stmt))
9400 case GF_OMP_TARGET_KIND_REGION:
9401 case GF_OMP_TARGET_KIND_DATA:
9402 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9403 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9404 case GF_OMP_TARGET_KIND_OACC_DATA:
9405 break;
9406 case GF_OMP_TARGET_KIND_UPDATE:
9407 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9408 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9409 /* ..., other than for those stand-alone directives... */
9410 region = NULL;
9411 break;
9412 default:
9413 gcc_unreachable ();
9416 /* ..., this directive becomes the parent for a new region. */
9417 if (region)
9418 parent = region;
9422 if (single_tree && !parent)
9423 return;
9425 for (son = first_dom_son (CDI_DOMINATORS, bb);
9426 son;
9427 son = next_dom_son (CDI_DOMINATORS, son))
9428 build_omp_regions_1 (son, parent, single_tree);
9431 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9432 root_omp_region. */
9434 static void
9435 build_omp_regions_root (basic_block root)
9437 gcc_assert (root_omp_region == NULL);
9438 build_omp_regions_1 (root, NULL, true);
9439 gcc_assert (root_omp_region != NULL);
9442 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9444 void
9445 omp_expand_local (basic_block head)
9447 build_omp_regions_root (head);
9448 if (dump_file && (dump_flags & TDF_DETAILS))
9450 fprintf (dump_file, "\nOMP region tree\n\n");
9451 dump_omp_region (dump_file, root_omp_region, 0);
9452 fprintf (dump_file, "\n");
9455 remove_exit_barriers (root_omp_region);
9456 expand_omp (root_omp_region);
9458 free_omp_regions ();
9461 /* Scan the CFG and build a tree of OMP regions. Return the root of
9462 the OMP region tree. */
9464 static void
9465 build_omp_regions (void)
9467 gcc_assert (root_omp_region == NULL);
9468 calculate_dominance_info (CDI_DOMINATORS);
9469 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9472 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9474 static unsigned int
9475 execute_expand_omp (void)
9477 build_omp_regions ();
9479 if (!root_omp_region)
9480 return 0;
9482 if (dump_file)
9484 fprintf (dump_file, "\nOMP region tree\n\n");
9485 dump_omp_region (dump_file, root_omp_region, 0);
9486 fprintf (dump_file, "\n");
9489 remove_exit_barriers (root_omp_region);
9491 expand_omp (root_omp_region);
9493 cleanup_tree_cfg ();
9495 free_omp_regions ();
9497 return 0;
9500 /* OMP expansion -- the default pass, run before creation of SSA form. */
9502 namespace {
9504 const pass_data pass_data_expand_omp =
9506 GIMPLE_PASS, /* type */
9507 "ompexp", /* name */
9508 OPTGROUP_NONE, /* optinfo_flags */
9509 TV_NONE, /* tv_id */
9510 PROP_gimple_any, /* properties_required */
9511 PROP_gimple_eomp, /* properties_provided */
9512 0, /* properties_destroyed */
9513 0, /* todo_flags_start */
9514 0, /* todo_flags_finish */
9517 class pass_expand_omp : public gimple_opt_pass
9519 public:
9520 pass_expand_omp (gcc::context *ctxt)
9521 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9524 /* opt_pass methods: */
9525 virtual unsigned int execute (function *)
9527 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9528 || flag_openmp_simd != 0)
9529 && !seen_error ());
9531 /* This pass always runs, to provide PROP_gimple_eomp.
9532 But often, there is nothing to do. */
9533 if (!gate)
9534 return 0;
9536 return execute_expand_omp ();
9539 }; // class pass_expand_omp
9541 } // anon namespace
9543 gimple_opt_pass *
9544 make_pass_expand_omp (gcc::context *ctxt)
9546 return new pass_expand_omp (ctxt);
9549 namespace {
9551 const pass_data pass_data_expand_omp_ssa =
9553 GIMPLE_PASS, /* type */
9554 "ompexpssa", /* name */
9555 OPTGROUP_NONE, /* optinfo_flags */
9556 TV_NONE, /* tv_id */
9557 PROP_cfg | PROP_ssa, /* properties_required */
9558 PROP_gimple_eomp, /* properties_provided */
9559 0, /* properties_destroyed */
9560 0, /* todo_flags_start */
9561 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9564 class pass_expand_omp_ssa : public gimple_opt_pass
9566 public:
9567 pass_expand_omp_ssa (gcc::context *ctxt)
9568 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9571 /* opt_pass methods: */
9572 virtual bool gate (function *fun)
9574 return !(fun->curr_properties & PROP_gimple_eomp);
9576 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9578 }; // class pass_expand_omp_ssa
9580 } // anon namespace
9582 gimple_opt_pass *
9583 make_pass_expand_omp_ssa (gcc::context *ctxt)
9585 return new pass_expand_omp_ssa (ctxt);
9588 /* Routines to lower OMP directives into OMP-GIMPLE. */
9590 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9591 convert it to gimple. */
9592 static void
9593 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9595 gimple stmt;
9597 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9599 stmt = gimple_build_assign (dest, op, dest, src);
9600 gimple_seq_add_stmt (seq, stmt);
9601 return;
9604 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9605 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9606 gimplify_assign (t, rdest, seq);
9607 rdest = t;
9609 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9610 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9611 gimplify_assign (t, idest, seq);
9612 idest = t;
9614 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9615 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9616 gimplify_assign (t, rsrc, seq);
9617 rsrc = t;
9619 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9620 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9621 gimplify_assign (t, isrc, seq);
9622 isrc = t;
9624 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9625 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9626 tree result;
9628 if (op == PLUS_EXPR)
9630 stmt = gimple_build_assign (r, op, rdest, rsrc);
9631 gimple_seq_add_stmt (seq, stmt);
9633 stmt = gimple_build_assign (i, op, idest, isrc);
9634 gimple_seq_add_stmt (seq, stmt);
9636 else if (op == MULT_EXPR)
9638 /* Let x = a + ib = dest, y = c + id = src.
9639 x * y = (ac - bd) + i(ad + bc) */
9640 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9641 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9642 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9643 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9645 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9646 gimple_seq_add_stmt (seq, stmt);
9648 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9649 gimple_seq_add_stmt (seq, stmt);
9651 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9652 gimple_seq_add_stmt (seq, stmt);
9654 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9655 gimple_seq_add_stmt (seq, stmt);
9657 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9658 gimple_seq_add_stmt (seq, stmt);
9660 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9661 gimple_seq_add_stmt (seq, stmt);
9663 else
9664 gcc_unreachable ();
9666 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9667 gimplify_assign (dest, result, seq);
9670 /* Helper function to initialize local data for the reduction arrays.
9671 The reduction arrays need to be placed inside the calling function
9672 for accelerators, or else the host won't be able to preform the final
9673 reduction. */
9675 static void
9676 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9677 gimple_seq *stmt_seqp, omp_context *ctx)
9679 tree c, t, oc;
9680 gimple stmt;
9681 omp_context *octx;
9683 /* Find the innermost OpenACC parallel context. */
9684 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9685 && (gimple_omp_target_kind (ctx->stmt)
9686 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9687 octx = ctx;
9688 else
9689 octx = ctx->outer;
9690 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9691 && (gimple_omp_target_kind (octx->stmt)
9692 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9694 /* Extract the clauses. */
9695 oc = gimple_omp_target_clauses (octx->stmt);
9697 /* Find the last outer clause. */
9698 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9701 /* Allocate arrays for each reduction variable. */
9702 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9704 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9705 continue;
9707 tree var = OMP_CLAUSE_DECL (c);
9708 tree type = get_base_type (var);
9709 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9710 ctx);
9711 tree size, call;
9713 /* Calculate size of the reduction array. */
9714 t = create_tmp_var (TREE_TYPE (nthreads));
9715 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9716 fold_convert (TREE_TYPE (nthreads),
9717 TYPE_SIZE_UNIT (type)));
9718 gimple_seq_add_stmt (stmt_seqp, stmt);
9720 size = create_tmp_var (sizetype);
9721 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9723 /* Now allocate memory for it. */
9724 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9725 stmt = gimple_build_call (call, 1, size);
9726 gimple_call_set_lhs (stmt, array);
9727 gimple_seq_add_stmt (stmt_seqp, stmt);
9729 /* Map this array into the accelerator. */
9731 /* Add the reduction array to the list of clauses. */
9732 tree x = array;
9733 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9734 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9735 OMP_CLAUSE_DECL (t) = x;
9736 OMP_CLAUSE_CHAIN (t) = NULL;
9737 if (oc)
9738 OMP_CLAUSE_CHAIN (oc) = t;
9739 else
9740 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9741 OMP_CLAUSE_SIZE (t) = size;
9742 oc = t;
9746 /* Helper function to process the array of partial reductions. Nthreads
9747 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9748 cannot be used here, because nthreads on the host may be different than
9749 on the accelerator. */
9751 static void
9752 oacc_finalize_reduction_data (tree clauses, tree nthreads,
9753 gimple_seq *stmt_seqp, omp_context *ctx)
9755 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9756 gimple stmt;
9758 /* Create for loop.
9760 let var = the original reduction variable
9761 let array = reduction variable array
9763 for (i = 0; i < nthreads; i++)
9764 var op= array[i]
9767 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9768 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9769 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9771 /* Create and initialize an index variable. */
9772 tree ix = create_tmp_var (sizetype);
9773 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9774 stmt_seqp);
9776 /* Insert the loop header label here. */
9777 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9779 /* Exit loop if ix >= nthreads. */
9780 x = create_tmp_var (sizetype);
9781 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9782 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9783 gimple_seq_add_stmt (stmt_seqp, stmt);
9785 /* Insert the loop body label here. */
9786 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9788 /* Collapse each reduction array, one element at a time. */
9789 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9791 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9792 continue;
9794 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9796 /* reduction(-:var) sums up the partial results, so it acts
9797 identically to reduction(+:var). */
9798 if (reduction_code == MINUS_EXPR)
9799 reduction_code = PLUS_EXPR;
9801 /* Set up reduction variable var. */
9802 var = OMP_CLAUSE_DECL (c);
9803 type = get_base_type (var);
9804 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9805 (OMP_CLAUSE_DECL (c)), ctx);
9807 /* Calculate the array offset. */
9808 tree offset = create_tmp_var (sizetype);
9809 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9810 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9811 gimple_seq_add_stmt (stmt_seqp, stmt);
9813 tree ptr = create_tmp_var (TREE_TYPE (array));
9814 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9815 gimple_seq_add_stmt (stmt_seqp, stmt);
9817 /* Extract array[ix] into mem. */
9818 tree mem = create_tmp_var (type);
9819 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9821 /* Find the original reduction variable. */
9822 if (is_reference (var))
9823 var = build_simple_mem_ref (var);
9825 tree t = create_tmp_var (type);
9827 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9828 gimplify_and_add (unshare_expr(x), stmt_seqp);
9830 /* var = var op mem */
9831 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9833 case TRUTH_ANDIF_EXPR:
9834 case TRUTH_ORIF_EXPR:
9835 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9836 t, mem);
9837 gimplify_and_add (t, stmt_seqp);
9838 break;
9839 default:
9840 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9841 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9842 stmt_seqp);
9845 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9846 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9847 gimplify_and_add (unshare_expr(x), stmt_seqp);
9850 /* Increment the induction variable. */
9851 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9852 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9853 gimple_seq_add_stmt (stmt_seqp, stmt);
9855 /* Go back to the top of the loop. */
9856 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9858 /* Place the loop exit label here. */
9859 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9862 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9863 scan that for reductions. */
9865 static void
9866 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9867 gimple_seq *out_stmt_seqp, omp_context *ctx)
9869 gimple_stmt_iterator gsi;
9870 gimple_seq inner = NULL;
9872 /* A collapse clause may have inserted a new bind block. */
9873 gsi = gsi_start (*body);
9874 while (!gsi_end_p (gsi))
9876 gimple stmt = gsi_stmt (gsi);
9877 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9879 inner = gimple_bind_body (bind_stmt);
9880 body = &inner;
9881 gsi = gsi_start (*body);
9883 else if (dyn_cast <gomp_for *> (stmt))
9884 break;
9885 else
9886 gsi_next (&gsi);
9889 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9891 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9892 enter, exit;
9893 bool reduction_found = false;
9895 gimple stmt = gsi_stmt (gsi);
9897 switch (gimple_code (stmt))
9899 case GIMPLE_OMP_FOR:
9900 clauses = gimple_omp_for_clauses (stmt);
9902 /* Search for a reduction clause. */
9903 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9904 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9906 reduction_found = true;
9907 break;
9910 if (!reduction_found)
9911 break;
9913 ctx = maybe_lookup_ctx (stmt);
9914 t = NULL_TREE;
9916 /* Extract the number of threads. */
9917 nthreads = create_tmp_var (sizetype);
9918 t = oacc_max_threads (ctx);
9919 gimplify_assign (nthreads, t, in_stmt_seqp);
9921 /* Determine if this is kernel will be executed on the host. */
9922 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9923 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9924 stmt = gimple_build_call (call, 0);
9925 gimple_call_set_lhs (stmt, acc_device);
9926 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9928 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9929 acc_device_host = create_tmp_var (integer_type_node,
9930 ".acc_device_host");
9931 gimplify_assign (acc_device_host,
9932 build_int_cst (integer_type_node,
9933 GOMP_DEVICE_HOST),
9934 in_stmt_seqp);
9936 enter = create_artificial_label (UNKNOWN_LOCATION);
9937 exit = create_artificial_label (UNKNOWN_LOCATION);
9939 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9940 enter, exit);
9941 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9942 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9943 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9944 integer_one_node),
9945 in_stmt_seqp);
9946 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9948 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9949 gimplify_assign (acc_device_host,
9950 build_int_cst (integer_type_node,
9951 GOMP_DEVICE_HOST_NONSHM),
9952 in_stmt_seqp);
9954 enter = create_artificial_label (UNKNOWN_LOCATION);
9955 exit = create_artificial_label (UNKNOWN_LOCATION);
9957 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9958 enter, exit);
9959 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9960 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9961 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9962 integer_one_node),
9963 in_stmt_seqp);
9964 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9966 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9967 ctx);
9968 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9969 break;
9970 default:
9971 // Scan for other directives which support reduction here.
9972 break;
9977 /* If ctx is a worksharing context inside of a cancellable parallel
9978 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9979 and conditional branch to parallel's cancel_label to handle
9980 cancellation in the implicit barrier. */
9982 static void
9983 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9985 gimple omp_return = gimple_seq_last_stmt (*body);
9986 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
9987 if (gimple_omp_return_nowait_p (omp_return))
9988 return;
9989 if (ctx->outer
9990 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
9991 && ctx->outer->cancellable)
9993 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
9994 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
9995 tree lhs = create_tmp_var (c_bool_type);
9996 gimple_omp_return_set_lhs (omp_return, lhs);
9997 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
9998 gimple g = gimple_build_cond (NE_EXPR, lhs,
9999 fold_convert (c_bool_type,
10000 boolean_false_node),
10001 ctx->outer->cancel_label, fallthru_label);
10002 gimple_seq_add_stmt (body, g);
10003 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10007 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10008 CTX is the enclosing OMP context for the current statement. */
10010 static void
10011 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10013 tree block, control;
10014 gimple_stmt_iterator tgsi;
10015 gomp_sections *stmt;
10016 gimple t;
10017 gbind *new_stmt, *bind;
10018 gimple_seq ilist, dlist, olist, new_body;
10020 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
10022 push_gimplify_context ();
10024 dlist = NULL;
10025 ilist = NULL;
10026 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10027 &ilist, &dlist, ctx, NULL);
10029 new_body = gimple_omp_body (stmt);
10030 gimple_omp_set_body (stmt, NULL);
10031 tgsi = gsi_start (new_body);
10032 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10034 omp_context *sctx;
10035 gimple sec_start;
10037 sec_start = gsi_stmt (tgsi);
10038 sctx = maybe_lookup_ctx (sec_start);
10039 gcc_assert (sctx);
10041 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10042 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10043 GSI_CONTINUE_LINKING);
10044 gimple_omp_set_body (sec_start, NULL);
10046 if (gsi_one_before_end_p (tgsi))
10048 gimple_seq l = NULL;
10049 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10050 &l, ctx);
10051 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10052 gimple_omp_section_set_last (sec_start);
10055 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10056 GSI_CONTINUE_LINKING);
10059 block = make_node (BLOCK);
10060 bind = gimple_build_bind (NULL, new_body, block);
10062 olist = NULL;
10063 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10065 block = make_node (BLOCK);
10066 new_stmt = gimple_build_bind (NULL, NULL, block);
10067 gsi_replace (gsi_p, new_stmt, true);
10069 pop_gimplify_context (new_stmt);
10070 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10071 BLOCK_VARS (block) = gimple_bind_vars (bind);
10072 if (BLOCK_VARS (block))
10073 TREE_USED (block) = 1;
10075 new_body = NULL;
10076 gimple_seq_add_seq (&new_body, ilist);
10077 gimple_seq_add_stmt (&new_body, stmt);
10078 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10079 gimple_seq_add_stmt (&new_body, bind);
10081 control = create_tmp_var (unsigned_type_node, ".section");
10082 t = gimple_build_omp_continue (control, control);
10083 gimple_omp_sections_set_control (stmt, control);
10084 gimple_seq_add_stmt (&new_body, t);
10086 gimple_seq_add_seq (&new_body, olist);
10087 if (ctx->cancellable)
10088 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10089 gimple_seq_add_seq (&new_body, dlist);
10091 new_body = maybe_catch_exception (new_body);
10093 t = gimple_build_omp_return
10094 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10095 OMP_CLAUSE_NOWAIT));
10096 gimple_seq_add_stmt (&new_body, t);
10097 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10099 gimple_bind_set_body (new_stmt, new_body);
10103 /* A subroutine of lower_omp_single. Expand the simple form of
10104 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10106 if (GOMP_single_start ())
10107 BODY;
10108 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10110 FIXME. It may be better to delay expanding the logic of this until
10111 pass_expand_omp. The expanded logic may make the job more difficult
10112 to a synchronization analysis pass. */
10114 static void
10115 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10117 location_t loc = gimple_location (single_stmt);
10118 tree tlabel = create_artificial_label (loc);
10119 tree flabel = create_artificial_label (loc);
10120 gimple call, cond;
10121 tree lhs, decl;
10123 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10124 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10125 call = gimple_build_call (decl, 0);
10126 gimple_call_set_lhs (call, lhs);
10127 gimple_seq_add_stmt (pre_p, call);
10129 cond = gimple_build_cond (EQ_EXPR, lhs,
10130 fold_convert_loc (loc, TREE_TYPE (lhs),
10131 boolean_true_node),
10132 tlabel, flabel);
10133 gimple_seq_add_stmt (pre_p, cond);
10134 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10135 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10136 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10140 /* A subroutine of lower_omp_single. Expand the simple form of
10141 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10143 #pragma omp single copyprivate (a, b, c)
10145 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10148 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10150 BODY;
10151 copyout.a = a;
10152 copyout.b = b;
10153 copyout.c = c;
10154 GOMP_single_copy_end (&copyout);
10156 else
10158 a = copyout_p->a;
10159 b = copyout_p->b;
10160 c = copyout_p->c;
10162 GOMP_barrier ();
10165 FIXME. It may be better to delay expanding the logic of this until
10166 pass_expand_omp. The expanded logic may make the job more difficult
10167 to a synchronization analysis pass. */
10169 static void
10170 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10171 omp_context *ctx)
10173 tree ptr_type, t, l0, l1, l2, bfn_decl;
10174 gimple_seq copyin_seq;
10175 location_t loc = gimple_location (single_stmt);
10177 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10179 ptr_type = build_pointer_type (ctx->record_type);
10180 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10182 l0 = create_artificial_label (loc);
10183 l1 = create_artificial_label (loc);
10184 l2 = create_artificial_label (loc);
10186 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10187 t = build_call_expr_loc (loc, bfn_decl, 0);
10188 t = fold_convert_loc (loc, ptr_type, t);
10189 gimplify_assign (ctx->receiver_decl, t, pre_p);
10191 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10192 build_int_cst (ptr_type, 0));
10193 t = build3 (COND_EXPR, void_type_node, t,
10194 build_and_jump (&l0), build_and_jump (&l1));
10195 gimplify_and_add (t, pre_p);
10197 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10199 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10201 copyin_seq = NULL;
10202 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10203 &copyin_seq, ctx);
10205 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10206 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10207 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10208 gimplify_and_add (t, pre_p);
10210 t = build_and_jump (&l2);
10211 gimplify_and_add (t, pre_p);
10213 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10215 gimple_seq_add_seq (pre_p, copyin_seq);
10217 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10221 /* Expand code for an OpenMP single directive. */
10223 static void
10224 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10226 tree block;
10227 gimple t;
10228 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10229 gbind *bind;
10230 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10232 push_gimplify_context ();
10234 block = make_node (BLOCK);
10235 bind = gimple_build_bind (NULL, NULL, block);
10236 gsi_replace (gsi_p, bind, true);
10237 bind_body = NULL;
10238 dlist = NULL;
10239 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10240 &bind_body, &dlist, ctx, NULL);
10241 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10243 gimple_seq_add_stmt (&bind_body, single_stmt);
10245 if (ctx->record_type)
10246 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10247 else
10248 lower_omp_single_simple (single_stmt, &bind_body);
10250 gimple_omp_set_body (single_stmt, NULL);
10252 gimple_seq_add_seq (&bind_body, dlist);
10254 bind_body = maybe_catch_exception (bind_body);
10256 t = gimple_build_omp_return
10257 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10258 OMP_CLAUSE_NOWAIT));
10259 gimple_seq_add_stmt (&bind_body_tail, t);
10260 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10261 if (ctx->record_type)
10263 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10264 tree clobber = build_constructor (ctx->record_type, NULL);
10265 TREE_THIS_VOLATILE (clobber) = 1;
10266 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10267 clobber), GSI_SAME_STMT);
10269 gimple_seq_add_seq (&bind_body, bind_body_tail);
10270 gimple_bind_set_body (bind, bind_body);
10272 pop_gimplify_context (bind);
10274 gimple_bind_append_vars (bind, ctx->block_vars);
10275 BLOCK_VARS (block) = ctx->block_vars;
10276 if (BLOCK_VARS (block))
10277 TREE_USED (block) = 1;
10281 /* Expand code for an OpenMP master directive. */
10283 static void
10284 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10286 tree block, lab = NULL, x, bfn_decl;
10287 gimple stmt = gsi_stmt (*gsi_p);
10288 gbind *bind;
10289 location_t loc = gimple_location (stmt);
10290 gimple_seq tseq;
10292 push_gimplify_context ();
10294 block = make_node (BLOCK);
10295 bind = gimple_build_bind (NULL, NULL, block);
10296 gsi_replace (gsi_p, bind, true);
10297 gimple_bind_add_stmt (bind, stmt);
10299 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10300 x = build_call_expr_loc (loc, bfn_decl, 0);
10301 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10302 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10303 tseq = NULL;
10304 gimplify_and_add (x, &tseq);
10305 gimple_bind_add_seq (bind, tseq);
10307 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10308 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10309 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10310 gimple_omp_set_body (stmt, NULL);
10312 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10314 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10316 pop_gimplify_context (bind);
10318 gimple_bind_append_vars (bind, ctx->block_vars);
10319 BLOCK_VARS (block) = ctx->block_vars;
10323 /* Expand code for an OpenMP taskgroup directive. */
10325 static void
10326 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10328 gimple stmt = gsi_stmt (*gsi_p);
10329 gcall *x;
10330 gbind *bind;
10331 tree block = make_node (BLOCK);
10333 bind = gimple_build_bind (NULL, NULL, block);
10334 gsi_replace (gsi_p, bind, true);
10335 gimple_bind_add_stmt (bind, stmt);
10337 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10339 gimple_bind_add_stmt (bind, x);
10341 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10342 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10343 gimple_omp_set_body (stmt, NULL);
10345 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10347 gimple_bind_append_vars (bind, ctx->block_vars);
10348 BLOCK_VARS (block) = ctx->block_vars;
10352 /* Expand code for an OpenMP ordered directive. */
10354 static void
10355 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10357 tree block;
10358 gimple stmt = gsi_stmt (*gsi_p);
10359 gcall *x;
10360 gbind *bind;
10362 push_gimplify_context ();
10364 block = make_node (BLOCK);
10365 bind = gimple_build_bind (NULL, NULL, block);
10366 gsi_replace (gsi_p, bind, true);
10367 gimple_bind_add_stmt (bind, stmt);
10369 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10371 gimple_bind_add_stmt (bind, x);
10373 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10374 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10375 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10376 gimple_omp_set_body (stmt, NULL);
10378 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10379 gimple_bind_add_stmt (bind, x);
10381 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10383 pop_gimplify_context (bind);
10385 gimple_bind_append_vars (bind, ctx->block_vars);
10386 BLOCK_VARS (block) = gimple_bind_vars (bind);
10390 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10391 substitution of a couple of function calls. But in the NAMED case,
10392 requires that languages coordinate a symbol name. It is therefore
10393 best put here in common code. */
10395 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10397 static void
10398 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10400 tree block;
10401 tree name, lock, unlock;
10402 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10403 gbind *bind;
10404 location_t loc = gimple_location (stmt);
10405 gimple_seq tbody;
10407 name = gimple_omp_critical_name (stmt);
10408 if (name)
10410 tree decl;
10412 if (!critical_name_mutexes)
10413 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10415 tree *n = critical_name_mutexes->get (name);
10416 if (n == NULL)
10418 char *new_str;
10420 decl = create_tmp_var_raw (ptr_type_node);
10422 new_str = ACONCAT ((".gomp_critical_user_",
10423 IDENTIFIER_POINTER (name), NULL));
10424 DECL_NAME (decl) = get_identifier (new_str);
10425 TREE_PUBLIC (decl) = 1;
10426 TREE_STATIC (decl) = 1;
10427 DECL_COMMON (decl) = 1;
10428 DECL_ARTIFICIAL (decl) = 1;
10429 DECL_IGNORED_P (decl) = 1;
10431 varpool_node::finalize_decl (decl);
10433 critical_name_mutexes->put (name, decl);
10435 else
10436 decl = *n;
10438 /* If '#pragma omp critical' is inside offloaded region or
10439 inside function marked as offloadable, the symbol must be
10440 marked as offloadable too. */
10441 omp_context *octx;
10442 if (cgraph_node::get (current_function_decl)->offloadable)
10443 varpool_node::get_create (decl)->offloadable = 1;
10444 else
10445 for (octx = ctx->outer; octx; octx = octx->outer)
10446 if (is_gimple_omp_offloaded (octx->stmt))
10448 varpool_node::get_create (decl)->offloadable = 1;
10449 break;
10452 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10453 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10455 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10456 unlock = build_call_expr_loc (loc, unlock, 1,
10457 build_fold_addr_expr_loc (loc, decl));
10459 else
10461 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10462 lock = build_call_expr_loc (loc, lock, 0);
10464 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10465 unlock = build_call_expr_loc (loc, unlock, 0);
10468 push_gimplify_context ();
10470 block = make_node (BLOCK);
10471 bind = gimple_build_bind (NULL, NULL, block);
10472 gsi_replace (gsi_p, bind, true);
10473 gimple_bind_add_stmt (bind, stmt);
10475 tbody = gimple_bind_body (bind);
10476 gimplify_and_add (lock, &tbody);
10477 gimple_bind_set_body (bind, tbody);
10479 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10480 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10481 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10482 gimple_omp_set_body (stmt, NULL);
10484 tbody = gimple_bind_body (bind);
10485 gimplify_and_add (unlock, &tbody);
10486 gimple_bind_set_body (bind, tbody);
10488 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10490 pop_gimplify_context (bind);
10491 gimple_bind_append_vars (bind, ctx->block_vars);
10492 BLOCK_VARS (block) = gimple_bind_vars (bind);
10496 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10497 for a lastprivate clause. Given a loop control predicate of (V
10498 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10499 is appended to *DLIST, iterator initialization is appended to
10500 *BODY_P. */
10502 static void
10503 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10504 gimple_seq *dlist, struct omp_context *ctx)
10506 tree clauses, cond, vinit;
10507 enum tree_code cond_code;
10508 gimple_seq stmts;
10510 cond_code = fd->loop.cond_code;
10511 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10513 /* When possible, use a strict equality expression. This can let VRP
10514 type optimizations deduce the value and remove a copy. */
10515 if (tree_fits_shwi_p (fd->loop.step))
10517 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10518 if (step == 1 || step == -1)
10519 cond_code = EQ_EXPR;
10522 tree n2 = fd->loop.n2;
10523 if (fd->collapse > 1
10524 && TREE_CODE (n2) != INTEGER_CST
10525 && gimple_omp_for_combined_into_p (fd->for_stmt)
10526 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10528 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10529 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
10531 struct omp_for_data outer_fd;
10532 extract_omp_for_data (gfor, &outer_fd, NULL);
10533 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10536 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
10538 clauses = gimple_omp_for_clauses (fd->for_stmt);
10539 stmts = NULL;
10540 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10541 if (!gimple_seq_empty_p (stmts))
10543 gimple_seq_add_seq (&stmts, *dlist);
10544 *dlist = stmts;
10546 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10547 vinit = fd->loop.n1;
10548 if (cond_code == EQ_EXPR
10549 && tree_fits_shwi_p (fd->loop.n2)
10550 && ! integer_zerop (fd->loop.n2))
10551 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10552 else
10553 vinit = unshare_expr (vinit);
10555 /* Initialize the iterator variable, so that threads that don't execute
10556 any iterations don't execute the lastprivate clauses by accident. */
10557 gimplify_assign (fd->loop.v, vinit, body_p);
10562 /* Lower code for an OMP loop directive. */
10564 static void
10565 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10567 tree *rhs_p, block;
10568 struct omp_for_data fd, *fdp = NULL;
10569 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10570 gbind *new_stmt;
10571 gimple_seq omp_for_body, body, dlist;
10572 size_t i;
10574 push_gimplify_context ();
10576 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10578 block = make_node (BLOCK);
10579 new_stmt = gimple_build_bind (NULL, NULL, block);
10580 /* Replace at gsi right away, so that 'stmt' is no member
10581 of a sequence anymore as we're going to add to to a different
10582 one below. */
10583 gsi_replace (gsi_p, new_stmt, true);
10585 /* Move declaration of temporaries in the loop body before we make
10586 it go away. */
10587 omp_for_body = gimple_omp_body (stmt);
10588 if (!gimple_seq_empty_p (omp_for_body)
10589 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10591 gbind *inner_bind
10592 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10593 tree vars = gimple_bind_vars (inner_bind);
10594 gimple_bind_append_vars (new_stmt, vars);
10595 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10596 keep them on the inner_bind and it's block. */
10597 gimple_bind_set_vars (inner_bind, NULL_TREE);
10598 if (gimple_bind_block (inner_bind))
10599 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10602 if (gimple_omp_for_combined_into_p (stmt))
10604 extract_omp_for_data (stmt, &fd, NULL);
10605 fdp = &fd;
10607 /* We need two temporaries with fd.loop.v type (istart/iend)
10608 and then (fd.collapse - 1) temporaries with the same
10609 type for count2 ... countN-1 vars if not constant. */
10610 size_t count = 2;
10611 tree type = fd.iter_type;
10612 if (fd.collapse > 1
10613 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10614 count += fd.collapse - 1;
10615 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10616 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10617 tree clauses = *pc;
10618 if (parallel_for)
10619 outerc
10620 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10621 OMP_CLAUSE__LOOPTEMP_);
10622 for (i = 0; i < count; i++)
10624 tree temp;
10625 if (parallel_for)
10627 gcc_assert (outerc);
10628 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10629 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10630 OMP_CLAUSE__LOOPTEMP_);
10632 else
10634 temp = create_tmp_var (type);
10635 insert_decl_map (&ctx->outer->cb, temp, temp);
10637 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10638 OMP_CLAUSE_DECL (*pc) = temp;
10639 pc = &OMP_CLAUSE_CHAIN (*pc);
10641 *pc = clauses;
10644 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10645 dlist = NULL;
10646 body = NULL;
10647 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10648 fdp);
10649 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10651 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10653 /* Lower the header expressions. At this point, we can assume that
10654 the header is of the form:
10656 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10658 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10659 using the .omp_data_s mapping, if needed. */
10660 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10662 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10663 if (!is_gimple_min_invariant (*rhs_p))
10664 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10666 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10667 if (!is_gimple_min_invariant (*rhs_p))
10668 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10670 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10671 if (!is_gimple_min_invariant (*rhs_p))
10672 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10675 /* Once lowered, extract the bounds and clauses. */
10676 extract_omp_for_data (stmt, &fd, NULL);
10678 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10680 gimple_seq_add_stmt (&body, stmt);
10681 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10683 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10684 fd.loop.v));
10686 /* After the loop, add exit clauses. */
10687 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10689 if (ctx->cancellable)
10690 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10692 gimple_seq_add_seq (&body, dlist);
10694 body = maybe_catch_exception (body);
10696 /* Region exit marker goes at the end of the loop body. */
10697 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10698 maybe_add_implicit_barrier_cancel (ctx, &body);
10699 pop_gimplify_context (new_stmt);
10701 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10702 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10703 if (BLOCK_VARS (block))
10704 TREE_USED (block) = 1;
10706 gimple_bind_set_body (new_stmt, body);
10707 gimple_omp_set_body (stmt, NULL);
10708 gimple_omp_for_set_pre_body (stmt, NULL);
10711 /* Callback for walk_stmts. Check if the current statement only contains
10712 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10714 static tree
10715 check_combined_parallel (gimple_stmt_iterator *gsi_p,
10716 bool *handled_ops_p,
10717 struct walk_stmt_info *wi)
10719 int *info = (int *) wi->info;
10720 gimple stmt = gsi_stmt (*gsi_p);
10722 *handled_ops_p = true;
10723 switch (gimple_code (stmt))
10725 WALK_SUBSTMTS;
10727 case GIMPLE_OMP_FOR:
10728 case GIMPLE_OMP_SECTIONS:
10729 *info = *info == 0 ? 1 : -1;
10730 break;
10731 default:
10732 *info = -1;
10733 break;
10735 return NULL;
10738 struct omp_taskcopy_context
10740 /* This field must be at the beginning, as we do "inheritance": Some
10741 callback functions for tree-inline.c (e.g., omp_copy_decl)
10742 receive a copy_body_data pointer that is up-casted to an
10743 omp_context pointer. */
10744 copy_body_data cb;
10745 omp_context *ctx;
10748 static tree
10749 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10751 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10753 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10754 return create_tmp_var (TREE_TYPE (var));
10756 return var;
10759 static tree
10760 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10762 tree name, new_fields = NULL, type, f;
10764 type = lang_hooks.types.make_type (RECORD_TYPE);
10765 name = DECL_NAME (TYPE_NAME (orig_type));
10766 name = build_decl (gimple_location (tcctx->ctx->stmt),
10767 TYPE_DECL, name, type);
10768 TYPE_NAME (type) = name;
10770 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10772 tree new_f = copy_node (f);
10773 DECL_CONTEXT (new_f) = type;
10774 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10775 TREE_CHAIN (new_f) = new_fields;
10776 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10777 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10778 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10779 &tcctx->cb, NULL);
10780 new_fields = new_f;
10781 tcctx->cb.decl_map->put (f, new_f);
10783 TYPE_FIELDS (type) = nreverse (new_fields);
10784 layout_type (type);
10785 return type;
10788 /* Create task copyfn. */
10790 static void
10791 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
10793 struct function *child_cfun;
10794 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10795 tree record_type, srecord_type, bind, list;
10796 bool record_needs_remap = false, srecord_needs_remap = false;
10797 splay_tree_node n;
10798 struct omp_taskcopy_context tcctx;
10799 location_t loc = gimple_location (task_stmt);
10801 child_fn = gimple_omp_task_copy_fn (task_stmt);
10802 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10803 gcc_assert (child_cfun->cfg == NULL);
10804 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10806 /* Reset DECL_CONTEXT on function arguments. */
10807 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10808 DECL_CONTEXT (t) = child_fn;
10810 /* Populate the function. */
10811 push_gimplify_context ();
10812 push_cfun (child_cfun);
10814 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10815 TREE_SIDE_EFFECTS (bind) = 1;
10816 list = NULL;
10817 DECL_SAVED_TREE (child_fn) = bind;
10818 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10820 /* Remap src and dst argument types if needed. */
10821 record_type = ctx->record_type;
10822 srecord_type = ctx->srecord_type;
10823 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10824 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10826 record_needs_remap = true;
10827 break;
10829 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10830 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10832 srecord_needs_remap = true;
10833 break;
10836 if (record_needs_remap || srecord_needs_remap)
10838 memset (&tcctx, '\0', sizeof (tcctx));
10839 tcctx.cb.src_fn = ctx->cb.src_fn;
10840 tcctx.cb.dst_fn = child_fn;
10841 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
10842 gcc_checking_assert (tcctx.cb.src_node);
10843 tcctx.cb.dst_node = tcctx.cb.src_node;
10844 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10845 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10846 tcctx.cb.eh_lp_nr = 0;
10847 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10848 tcctx.cb.decl_map = new hash_map<tree, tree>;
10849 tcctx.ctx = ctx;
10851 if (record_needs_remap)
10852 record_type = task_copyfn_remap_type (&tcctx, record_type);
10853 if (srecord_needs_remap)
10854 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10856 else
10857 tcctx.cb.decl_map = NULL;
10859 arg = DECL_ARGUMENTS (child_fn);
10860 TREE_TYPE (arg) = build_pointer_type (record_type);
10861 sarg = DECL_CHAIN (arg);
10862 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10864 /* First pass: initialize temporaries used in record_type and srecord_type
10865 sizes and field offsets. */
10866 if (tcctx.cb.decl_map)
10867 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10868 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10870 tree *p;
10872 decl = OMP_CLAUSE_DECL (c);
10873 p = tcctx.cb.decl_map->get (decl);
10874 if (p == NULL)
10875 continue;
10876 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10877 sf = (tree) n->value;
10878 sf = *tcctx.cb.decl_map->get (sf);
10879 src = build_simple_mem_ref_loc (loc, sarg);
10880 src = omp_build_component_ref (src, sf);
10881 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10882 append_to_statement_list (t, &list);
10885 /* Second pass: copy shared var pointers and copy construct non-VLA
10886 firstprivate vars. */
10887 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10888 switch (OMP_CLAUSE_CODE (c))
10890 case OMP_CLAUSE_SHARED:
10891 decl = OMP_CLAUSE_DECL (c);
10892 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10893 if (n == NULL)
10894 break;
10895 f = (tree) n->value;
10896 if (tcctx.cb.decl_map)
10897 f = *tcctx.cb.decl_map->get (f);
10898 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10899 sf = (tree) n->value;
10900 if (tcctx.cb.decl_map)
10901 sf = *tcctx.cb.decl_map->get (sf);
10902 src = build_simple_mem_ref_loc (loc, sarg);
10903 src = omp_build_component_ref (src, sf);
10904 dst = build_simple_mem_ref_loc (loc, arg);
10905 dst = omp_build_component_ref (dst, f);
10906 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10907 append_to_statement_list (t, &list);
10908 break;
10909 case OMP_CLAUSE_FIRSTPRIVATE:
10910 decl = OMP_CLAUSE_DECL (c);
10911 if (is_variable_sized (decl))
10912 break;
10913 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10914 if (n == NULL)
10915 break;
10916 f = (tree) n->value;
10917 if (tcctx.cb.decl_map)
10918 f = *tcctx.cb.decl_map->get (f);
10919 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10920 if (n != NULL)
10922 sf = (tree) n->value;
10923 if (tcctx.cb.decl_map)
10924 sf = *tcctx.cb.decl_map->get (sf);
10925 src = build_simple_mem_ref_loc (loc, sarg);
10926 src = omp_build_component_ref (src, sf);
10927 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
10928 src = build_simple_mem_ref_loc (loc, src);
10930 else
10931 src = decl;
10932 dst = build_simple_mem_ref_loc (loc, arg);
10933 dst = omp_build_component_ref (dst, f);
10934 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10935 append_to_statement_list (t, &list);
10936 break;
10937 case OMP_CLAUSE_PRIVATE:
10938 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10939 break;
10940 decl = OMP_CLAUSE_DECL (c);
10941 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10942 f = (tree) n->value;
10943 if (tcctx.cb.decl_map)
10944 f = *tcctx.cb.decl_map->get (f);
10945 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10946 if (n != NULL)
10948 sf = (tree) n->value;
10949 if (tcctx.cb.decl_map)
10950 sf = *tcctx.cb.decl_map->get (sf);
10951 src = build_simple_mem_ref_loc (loc, sarg);
10952 src = omp_build_component_ref (src, sf);
10953 if (use_pointer_for_field (decl, NULL))
10954 src = build_simple_mem_ref_loc (loc, src);
10956 else
10957 src = decl;
10958 dst = build_simple_mem_ref_loc (loc, arg);
10959 dst = omp_build_component_ref (dst, f);
10960 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10961 append_to_statement_list (t, &list);
10962 break;
10963 default:
10964 break;
10967 /* Last pass: handle VLA firstprivates. */
10968 if (tcctx.cb.decl_map)
10969 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10970 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10972 tree ind, ptr, df;
10974 decl = OMP_CLAUSE_DECL (c);
10975 if (!is_variable_sized (decl))
10976 continue;
10977 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10978 if (n == NULL)
10979 continue;
10980 f = (tree) n->value;
10981 f = *tcctx.cb.decl_map->get (f);
10982 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10983 ind = DECL_VALUE_EXPR (decl);
10984 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10985 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10986 n = splay_tree_lookup (ctx->sfield_map,
10987 (splay_tree_key) TREE_OPERAND (ind, 0));
10988 sf = (tree) n->value;
10989 sf = *tcctx.cb.decl_map->get (sf);
10990 src = build_simple_mem_ref_loc (loc, sarg);
10991 src = omp_build_component_ref (src, sf);
10992 src = build_simple_mem_ref_loc (loc, src);
10993 dst = build_simple_mem_ref_loc (loc, arg);
10994 dst = omp_build_component_ref (dst, f);
10995 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10996 append_to_statement_list (t, &list);
10997 n = splay_tree_lookup (ctx->field_map,
10998 (splay_tree_key) TREE_OPERAND (ind, 0));
10999 df = (tree) n->value;
11000 df = *tcctx.cb.decl_map->get (df);
11001 ptr = build_simple_mem_ref_loc (loc, arg);
11002 ptr = omp_build_component_ref (ptr, df);
11003 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
11004 build_fold_addr_expr_loc (loc, dst));
11005 append_to_statement_list (t, &list);
11008 t = build1 (RETURN_EXPR, void_type_node, NULL);
11009 append_to_statement_list (t, &list);
11011 if (tcctx.cb.decl_map)
11012 delete tcctx.cb.decl_map;
11013 pop_gimplify_context (NULL);
11014 BIND_EXPR_BODY (bind) = list;
11015 pop_cfun ();
11018 static void
11019 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
11021 tree c, clauses;
11022 gimple g;
11023 size_t n_in = 0, n_out = 0, idx = 2, i;
11025 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11026 OMP_CLAUSE_DEPEND);
11027 gcc_assert (clauses);
11028 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11029 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11030 switch (OMP_CLAUSE_DEPEND_KIND (c))
11032 case OMP_CLAUSE_DEPEND_IN:
11033 n_in++;
11034 break;
11035 case OMP_CLAUSE_DEPEND_OUT:
11036 case OMP_CLAUSE_DEPEND_INOUT:
11037 n_out++;
11038 break;
11039 default:
11040 gcc_unreachable ();
11042 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11043 tree array = create_tmp_var (type);
11044 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11045 NULL_TREE);
11046 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11047 gimple_seq_add_stmt (iseq, g);
11048 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11049 NULL_TREE);
11050 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11051 gimple_seq_add_stmt (iseq, g);
11052 for (i = 0; i < 2; i++)
11054 if ((i ? n_in : n_out) == 0)
11055 continue;
11056 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11057 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11058 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11060 tree t = OMP_CLAUSE_DECL (c);
11061 t = fold_convert (ptr_type_node, t);
11062 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11063 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11064 NULL_TREE, NULL_TREE);
11065 g = gimple_build_assign (r, t);
11066 gimple_seq_add_stmt (iseq, g);
11069 tree *p = gimple_omp_task_clauses_ptr (stmt);
11070 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11071 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11072 OMP_CLAUSE_CHAIN (c) = *p;
11073 *p = c;
11074 tree clobber = build_constructor (type, NULL);
11075 TREE_THIS_VOLATILE (clobber) = 1;
11076 g = gimple_build_assign (array, clobber);
11077 gimple_seq_add_stmt (oseq, g);
11080 /* Lower the OpenMP parallel or task directive in the current statement
11081 in GSI_P. CTX holds context information for the directive. */
11083 static void
11084 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11086 tree clauses;
11087 tree child_fn, t;
11088 gimple stmt = gsi_stmt (*gsi_p);
11089 gbind *par_bind, *bind, *dep_bind = NULL;
11090 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11091 location_t loc = gimple_location (stmt);
11093 clauses = gimple_omp_taskreg_clauses (stmt);
11094 par_bind
11095 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11096 par_body = gimple_bind_body (par_bind);
11097 child_fn = ctx->cb.dst_fn;
11098 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11099 && !gimple_omp_parallel_combined_p (stmt))
11101 struct walk_stmt_info wi;
11102 int ws_num = 0;
11104 memset (&wi, 0, sizeof (wi));
11105 wi.info = &ws_num;
11106 wi.val_only = true;
11107 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11108 if (ws_num == 1)
11109 gimple_omp_parallel_set_combined_p (stmt, true);
11111 gimple_seq dep_ilist = NULL;
11112 gimple_seq dep_olist = NULL;
11113 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11114 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11116 push_gimplify_context ();
11117 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11118 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11121 if (ctx->srecord_type)
11122 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11124 push_gimplify_context ();
11126 par_olist = NULL;
11127 par_ilist = NULL;
11128 par_rlist = NULL;
11129 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11130 lower_omp (&par_body, ctx);
11131 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11132 lower_reduction_clauses (clauses, &par_rlist, ctx);
11134 /* Declare all the variables created by mapping and the variables
11135 declared in the scope of the parallel body. */
11136 record_vars_into (ctx->block_vars, child_fn);
11137 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11139 if (ctx->record_type)
11141 ctx->sender_decl
11142 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11143 : ctx->record_type, ".omp_data_o");
11144 DECL_NAMELESS (ctx->sender_decl) = 1;
11145 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11146 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11149 olist = NULL;
11150 ilist = NULL;
11151 lower_send_clauses (clauses, &ilist, &olist, ctx);
11152 lower_send_shared_vars (&ilist, &olist, ctx);
11154 if (ctx->record_type)
11156 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11157 TREE_THIS_VOLATILE (clobber) = 1;
11158 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11159 clobber));
11162 /* Once all the expansions are done, sequence all the different
11163 fragments inside gimple_omp_body. */
11165 new_body = NULL;
11167 if (ctx->record_type)
11169 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11170 /* fixup_child_record_type might have changed receiver_decl's type. */
11171 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11172 gimple_seq_add_stmt (&new_body,
11173 gimple_build_assign (ctx->receiver_decl, t));
11176 gimple_seq_add_seq (&new_body, par_ilist);
11177 gimple_seq_add_seq (&new_body, par_body);
11178 gimple_seq_add_seq (&new_body, par_rlist);
11179 if (ctx->cancellable)
11180 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11181 gimple_seq_add_seq (&new_body, par_olist);
11182 new_body = maybe_catch_exception (new_body);
11183 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
11184 gimple_seq_add_stmt (&new_body,
11185 gimple_build_omp_continue (integer_zero_node,
11186 integer_zero_node));
11187 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11188 gimple_omp_set_body (stmt, new_body);
11190 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11191 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11192 gimple_bind_add_seq (bind, ilist);
11193 gimple_bind_add_stmt (bind, stmt);
11194 gimple_bind_add_seq (bind, olist);
11196 pop_gimplify_context (NULL);
11198 if (dep_bind)
11200 gimple_bind_add_seq (dep_bind, dep_ilist);
11201 gimple_bind_add_stmt (dep_bind, bind);
11202 gimple_bind_add_seq (dep_bind, dep_olist);
11203 pop_gimplify_context (dep_bind);
11207 /* Lower the GIMPLE_OMP_TARGET in the current statement
11208 in GSI_P. CTX holds context information for the directive. */
11210 static void
11211 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11213 tree clauses;
11214 tree child_fn, t, c;
11215 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11216 gbind *tgt_bind, *bind;
11217 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11218 location_t loc = gimple_location (stmt);
11219 bool offloaded, data_region;
11220 unsigned int map_cnt = 0;
11222 offloaded = is_gimple_omp_offloaded (stmt);
11223 switch (gimple_omp_target_kind (stmt))
11225 case GF_OMP_TARGET_KIND_REGION:
11226 case GF_OMP_TARGET_KIND_UPDATE:
11227 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11228 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11229 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11230 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11231 data_region = false;
11232 break;
11233 case GF_OMP_TARGET_KIND_DATA:
11234 case GF_OMP_TARGET_KIND_OACC_DATA:
11235 data_region = true;
11236 break;
11237 default:
11238 gcc_unreachable ();
11241 clauses = gimple_omp_target_clauses (stmt);
11243 tgt_bind = NULL;
11244 tgt_body = NULL;
11245 if (offloaded)
11247 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11248 tgt_body = gimple_bind_body (tgt_bind);
11250 else if (data_region)
11251 tgt_body = gimple_omp_body (stmt);
11252 child_fn = ctx->cb.dst_fn;
11254 push_gimplify_context ();
11256 irlist = NULL;
11257 orlist = NULL;
11258 if (offloaded
11259 && is_gimple_omp_oacc (stmt))
11260 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11262 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11263 switch (OMP_CLAUSE_CODE (c))
11265 tree var, x;
11267 default:
11268 break;
11269 case OMP_CLAUSE_MAP:
11270 #ifdef ENABLE_CHECKING
11271 /* First check what we're prepared to handle in the following. */
11272 switch (OMP_CLAUSE_MAP_KIND (c))
11274 case GOMP_MAP_ALLOC:
11275 case GOMP_MAP_TO:
11276 case GOMP_MAP_FROM:
11277 case GOMP_MAP_TOFROM:
11278 case GOMP_MAP_POINTER:
11279 case GOMP_MAP_TO_PSET:
11280 break;
11281 case GOMP_MAP_FORCE_ALLOC:
11282 case GOMP_MAP_FORCE_TO:
11283 case GOMP_MAP_FORCE_FROM:
11284 case GOMP_MAP_FORCE_TOFROM:
11285 case GOMP_MAP_FORCE_PRESENT:
11286 case GOMP_MAP_FORCE_DEALLOC:
11287 case GOMP_MAP_FORCE_DEVICEPTR:
11288 gcc_assert (is_gimple_omp_oacc (stmt));
11289 break;
11290 default:
11291 gcc_unreachable ();
11293 #endif
11294 /* FALLTHRU */
11295 case OMP_CLAUSE_TO:
11296 case OMP_CLAUSE_FROM:
11297 var = OMP_CLAUSE_DECL (c);
11298 if (!DECL_P (var))
11300 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11301 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11302 map_cnt++;
11303 continue;
11306 if (DECL_SIZE (var)
11307 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11309 tree var2 = DECL_VALUE_EXPR (var);
11310 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11311 var2 = TREE_OPERAND (var2, 0);
11312 gcc_assert (DECL_P (var2));
11313 var = var2;
11316 if (!maybe_lookup_field (var, ctx))
11317 continue;
11319 if (offloaded)
11321 x = build_receiver_ref (var, true, ctx);
11322 tree new_var = lookup_decl (var, ctx);
11323 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11324 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11325 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11326 x = build_simple_mem_ref (x);
11327 SET_DECL_VALUE_EXPR (new_var, x);
11328 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11330 map_cnt++;
11333 if (offloaded)
11335 target_nesting_level++;
11336 lower_omp (&tgt_body, ctx);
11337 target_nesting_level--;
11339 else if (data_region)
11340 lower_omp (&tgt_body, ctx);
11342 if (offloaded)
11344 /* Declare all the variables created by mapping and the variables
11345 declared in the scope of the target body. */
11346 record_vars_into (ctx->block_vars, child_fn);
11347 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11350 olist = NULL;
11351 ilist = NULL;
11352 if (ctx->record_type)
11354 ctx->sender_decl
11355 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11356 DECL_NAMELESS (ctx->sender_decl) = 1;
11357 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11358 t = make_tree_vec (3);
11359 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11360 TREE_VEC_ELT (t, 1)
11361 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11362 ".omp_data_sizes");
11363 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11364 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11365 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11366 tree tkind_type;
11367 int talign_shift;
11368 if (is_gimple_omp_oacc (stmt))
11370 tkind_type = short_unsigned_type_node;
11371 talign_shift = 8;
11373 else
11375 tkind_type = unsigned_char_type_node;
11376 talign_shift = 3;
11378 TREE_VEC_ELT (t, 2)
11379 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11380 ".omp_data_kinds");
11381 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11382 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11383 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11384 gimple_omp_target_set_data_arg (stmt, t);
11386 vec<constructor_elt, va_gc> *vsize;
11387 vec<constructor_elt, va_gc> *vkind;
11388 vec_alloc (vsize, map_cnt);
11389 vec_alloc (vkind, map_cnt);
11390 unsigned int map_idx = 0;
11392 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11393 switch (OMP_CLAUSE_CODE (c))
11395 tree ovar, nc;
11397 default:
11398 break;
11399 case OMP_CLAUSE_MAP:
11400 case OMP_CLAUSE_TO:
11401 case OMP_CLAUSE_FROM:
11402 nc = c;
11403 ovar = OMP_CLAUSE_DECL (c);
11404 if (!DECL_P (ovar))
11406 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11407 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11409 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11410 == get_base_address (ovar));
11411 nc = OMP_CLAUSE_CHAIN (c);
11412 ovar = OMP_CLAUSE_DECL (nc);
11414 else
11416 tree x = build_sender_ref (ovar, ctx);
11417 tree v
11418 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11419 gimplify_assign (x, v, &ilist);
11420 nc = NULL_TREE;
11423 else
11425 if (DECL_SIZE (ovar)
11426 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11428 tree ovar2 = DECL_VALUE_EXPR (ovar);
11429 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11430 ovar2 = TREE_OPERAND (ovar2, 0);
11431 gcc_assert (DECL_P (ovar2));
11432 ovar = ovar2;
11434 if (!maybe_lookup_field (ovar, ctx))
11435 continue;
11438 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11439 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11440 talign = DECL_ALIGN_UNIT (ovar);
11441 if (nc)
11443 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11444 tree x = build_sender_ref (ovar, ctx);
11445 if (maybe_lookup_oacc_reduction (var, ctx))
11447 gcc_checking_assert (offloaded
11448 && is_gimple_omp_oacc (stmt));
11449 gimplify_assign (x, var, &ilist);
11451 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11452 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11453 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11454 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11456 gcc_assert (offloaded);
11457 tree avar
11458 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11459 mark_addressable (avar);
11460 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11461 talign = DECL_ALIGN_UNIT (avar);
11462 avar = build_fold_addr_expr (avar);
11463 gimplify_assign (x, avar, &ilist);
11465 else if (is_gimple_reg (var))
11467 gcc_assert (offloaded);
11468 tree avar = create_tmp_var (TREE_TYPE (var));
11469 mark_addressable (avar);
11470 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11471 if (GOMP_MAP_COPY_TO_P (map_kind)
11472 || map_kind == GOMP_MAP_POINTER
11473 || map_kind == GOMP_MAP_TO_PSET
11474 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11475 gimplify_assign (avar, var, &ilist);
11476 avar = build_fold_addr_expr (avar);
11477 gimplify_assign (x, avar, &ilist);
11478 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11479 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11480 && !TYPE_READONLY (TREE_TYPE (var)))
11482 x = build_sender_ref (ovar, ctx);
11483 x = build_simple_mem_ref (x);
11484 gimplify_assign (var, x, &olist);
11487 else
11489 var = build_fold_addr_expr (var);
11490 gimplify_assign (x, var, &ilist);
11493 tree s = OMP_CLAUSE_SIZE (c);
11494 if (s == NULL_TREE)
11495 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11496 s = fold_convert (size_type_node, s);
11497 tree purpose = size_int (map_idx++);
11498 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11499 if (TREE_CODE (s) != INTEGER_CST)
11500 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11502 unsigned HOST_WIDE_INT tkind;
11503 switch (OMP_CLAUSE_CODE (c))
11505 case OMP_CLAUSE_MAP:
11506 tkind = OMP_CLAUSE_MAP_KIND (c);
11507 break;
11508 case OMP_CLAUSE_TO:
11509 tkind = GOMP_MAP_TO;
11510 break;
11511 case OMP_CLAUSE_FROM:
11512 tkind = GOMP_MAP_FROM;
11513 break;
11514 default:
11515 gcc_unreachable ();
11517 gcc_checking_assert (tkind
11518 < (HOST_WIDE_INT_C (1U) << talign_shift));
11519 talign = ceil_log2 (talign);
11520 tkind |= talign << talign_shift;
11521 gcc_checking_assert (tkind
11522 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11523 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11524 build_int_cstu (tkind_type, tkind));
11525 if (nc && nc != c)
11526 c = nc;
11529 gcc_assert (map_idx == map_cnt);
11531 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11532 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11533 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11534 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11535 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11537 gimple_seq initlist = NULL;
11538 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11539 TREE_VEC_ELT (t, 1)),
11540 &initlist, true, NULL_TREE);
11541 gimple_seq_add_seq (&ilist, initlist);
11543 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11544 NULL);
11545 TREE_THIS_VOLATILE (clobber) = 1;
11546 gimple_seq_add_stmt (&olist,
11547 gimple_build_assign (TREE_VEC_ELT (t, 1),
11548 clobber));
11551 tree clobber = build_constructor (ctx->record_type, NULL);
11552 TREE_THIS_VOLATILE (clobber) = 1;
11553 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11554 clobber));
11557 /* Once all the expansions are done, sequence all the different
11558 fragments inside gimple_omp_body. */
11560 new_body = NULL;
11562 if (offloaded
11563 && ctx->record_type)
11565 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11566 /* fixup_child_record_type might have changed receiver_decl's type. */
11567 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11568 gimple_seq_add_stmt (&new_body,
11569 gimple_build_assign (ctx->receiver_decl, t));
11572 if (offloaded)
11574 gimple_seq_add_seq (&new_body, tgt_body);
11575 new_body = maybe_catch_exception (new_body);
11577 else if (data_region)
11578 new_body = tgt_body;
11579 if (offloaded || data_region)
11581 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11582 gimple_omp_set_body (stmt, new_body);
11585 bind = gimple_build_bind (NULL, NULL,
11586 tgt_bind ? gimple_bind_block (tgt_bind)
11587 : NULL_TREE);
11588 gsi_replace (gsi_p, bind, true);
11589 gimple_bind_add_seq (bind, irlist);
11590 gimple_bind_add_seq (bind, ilist);
11591 gimple_bind_add_stmt (bind, stmt);
11592 gimple_bind_add_seq (bind, olist);
11593 gimple_bind_add_seq (bind, orlist);
11595 pop_gimplify_context (NULL);
11598 /* Expand code for an OpenMP teams directive. */
11600 static void
11601 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11603 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11604 push_gimplify_context ();
11606 tree block = make_node (BLOCK);
11607 gbind *bind = gimple_build_bind (NULL, NULL, block);
11608 gsi_replace (gsi_p, bind, true);
11609 gimple_seq bind_body = NULL;
11610 gimple_seq dlist = NULL;
11611 gimple_seq olist = NULL;
11613 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11614 OMP_CLAUSE_NUM_TEAMS);
11615 if (num_teams == NULL_TREE)
11616 num_teams = build_int_cst (unsigned_type_node, 0);
11617 else
11619 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11620 num_teams = fold_convert (unsigned_type_node, num_teams);
11621 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11623 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11624 OMP_CLAUSE_THREAD_LIMIT);
11625 if (thread_limit == NULL_TREE)
11626 thread_limit = build_int_cst (unsigned_type_node, 0);
11627 else
11629 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11630 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11631 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11632 fb_rvalue);
11635 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11636 &bind_body, &dlist, ctx, NULL);
11637 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11638 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11639 gimple_seq_add_stmt (&bind_body, teams_stmt);
11641 location_t loc = gimple_location (teams_stmt);
11642 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11643 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11644 gimple_set_location (call, loc);
11645 gimple_seq_add_stmt (&bind_body, call);
11647 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11648 gimple_omp_set_body (teams_stmt, NULL);
11649 gimple_seq_add_seq (&bind_body, olist);
11650 gimple_seq_add_seq (&bind_body, dlist);
11651 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11652 gimple_bind_set_body (bind, bind_body);
11654 pop_gimplify_context (bind);
11656 gimple_bind_append_vars (bind, ctx->block_vars);
11657 BLOCK_VARS (block) = ctx->block_vars;
11658 if (BLOCK_VARS (block))
11659 TREE_USED (block) = 1;
11663 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11664 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11665 of OMP context, but with task_shared_vars set. */
11667 static tree
11668 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11669 void *data)
11671 tree t = *tp;
11673 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11674 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11675 return t;
11677 if (task_shared_vars
11678 && DECL_P (t)
11679 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11680 return t;
11682 /* If a global variable has been privatized, TREE_CONSTANT on
11683 ADDR_EXPR might be wrong. */
11684 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11685 recompute_tree_invariant_for_addr_expr (t);
11687 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11688 return NULL_TREE;
11691 static void
11692 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11694 gimple stmt = gsi_stmt (*gsi_p);
11695 struct walk_stmt_info wi;
11696 gcall *call_stmt;
11698 if (gimple_has_location (stmt))
11699 input_location = gimple_location (stmt);
11701 if (task_shared_vars)
11702 memset (&wi, '\0', sizeof (wi));
11704 /* If we have issued syntax errors, avoid doing any heavy lifting.
11705 Just replace the OMP directives with a NOP to avoid
11706 confusing RTL expansion. */
11707 if (seen_error () && is_gimple_omp (stmt))
11709 gsi_replace (gsi_p, gimple_build_nop (), true);
11710 return;
11713 switch (gimple_code (stmt))
11715 case GIMPLE_COND:
11717 gcond *cond_stmt = as_a <gcond *> (stmt);
11718 if ((ctx || task_shared_vars)
11719 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11720 lower_omp_regimplify_p,
11721 ctx ? NULL : &wi, NULL)
11722 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11723 lower_omp_regimplify_p,
11724 ctx ? NULL : &wi, NULL)))
11725 gimple_regimplify_operands (cond_stmt, gsi_p);
11727 break;
11728 case GIMPLE_CATCH:
11729 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
11730 break;
11731 case GIMPLE_EH_FILTER:
11732 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
11733 break;
11734 case GIMPLE_TRY:
11735 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11736 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
11737 break;
11738 case GIMPLE_TRANSACTION:
11739 lower_omp (gimple_transaction_body_ptr (
11740 as_a <gtransaction *> (stmt)),
11741 ctx);
11742 break;
11743 case GIMPLE_BIND:
11744 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
11745 break;
11746 case GIMPLE_OMP_PARALLEL:
11747 case GIMPLE_OMP_TASK:
11748 ctx = maybe_lookup_ctx (stmt);
11749 gcc_assert (ctx);
11750 if (ctx->cancellable)
11751 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11752 lower_omp_taskreg (gsi_p, ctx);
11753 break;
11754 case GIMPLE_OMP_FOR:
11755 ctx = maybe_lookup_ctx (stmt);
11756 gcc_assert (ctx);
11757 if (ctx->cancellable)
11758 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11759 lower_omp_for (gsi_p, ctx);
11760 break;
11761 case GIMPLE_OMP_SECTIONS:
11762 ctx = maybe_lookup_ctx (stmt);
11763 gcc_assert (ctx);
11764 if (ctx->cancellable)
11765 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11766 lower_omp_sections (gsi_p, ctx);
11767 break;
11768 case GIMPLE_OMP_SINGLE:
11769 ctx = maybe_lookup_ctx (stmt);
11770 gcc_assert (ctx);
11771 lower_omp_single (gsi_p, ctx);
11772 break;
11773 case GIMPLE_OMP_MASTER:
11774 ctx = maybe_lookup_ctx (stmt);
11775 gcc_assert (ctx);
11776 lower_omp_master (gsi_p, ctx);
11777 break;
11778 case GIMPLE_OMP_TASKGROUP:
11779 ctx = maybe_lookup_ctx (stmt);
11780 gcc_assert (ctx);
11781 lower_omp_taskgroup (gsi_p, ctx);
11782 break;
11783 case GIMPLE_OMP_ORDERED:
11784 ctx = maybe_lookup_ctx (stmt);
11785 gcc_assert (ctx);
11786 lower_omp_ordered (gsi_p, ctx);
11787 break;
11788 case GIMPLE_OMP_CRITICAL:
11789 ctx = maybe_lookup_ctx (stmt);
11790 gcc_assert (ctx);
11791 lower_omp_critical (gsi_p, ctx);
11792 break;
11793 case GIMPLE_OMP_ATOMIC_LOAD:
11794 if ((ctx || task_shared_vars)
11795 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11796 as_a <gomp_atomic_load *> (stmt)),
11797 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11798 gimple_regimplify_operands (stmt, gsi_p);
11799 break;
11800 case GIMPLE_OMP_TARGET:
11801 ctx = maybe_lookup_ctx (stmt);
11802 gcc_assert (ctx);
11803 lower_omp_target (gsi_p, ctx);
11804 break;
11805 case GIMPLE_OMP_TEAMS:
11806 ctx = maybe_lookup_ctx (stmt);
11807 gcc_assert (ctx);
11808 lower_omp_teams (gsi_p, ctx);
11809 break;
11810 case GIMPLE_CALL:
11811 tree fndecl;
11812 call_stmt = as_a <gcall *> (stmt);
11813 fndecl = gimple_call_fndecl (call_stmt);
11814 if (fndecl
11815 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11816 switch (DECL_FUNCTION_CODE (fndecl))
11818 case BUILT_IN_GOMP_BARRIER:
11819 if (ctx == NULL)
11820 break;
11821 /* FALLTHRU */
11822 case BUILT_IN_GOMP_CANCEL:
11823 case BUILT_IN_GOMP_CANCELLATION_POINT:
11824 omp_context *cctx;
11825 cctx = ctx;
11826 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11827 cctx = cctx->outer;
11828 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
11829 if (!cctx->cancellable)
11831 if (DECL_FUNCTION_CODE (fndecl)
11832 == BUILT_IN_GOMP_CANCELLATION_POINT)
11834 stmt = gimple_build_nop ();
11835 gsi_replace (gsi_p, stmt, false);
11837 break;
11839 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11841 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
11842 gimple_call_set_fndecl (call_stmt, fndecl);
11843 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
11845 tree lhs;
11846 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
11847 gimple_call_set_lhs (call_stmt, lhs);
11848 tree fallthru_label;
11849 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11850 gimple g;
11851 g = gimple_build_label (fallthru_label);
11852 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11853 g = gimple_build_cond (NE_EXPR, lhs,
11854 fold_convert (TREE_TYPE (lhs),
11855 boolean_false_node),
11856 cctx->cancel_label, fallthru_label);
11857 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11858 break;
11859 default:
11860 break;
11862 /* FALLTHRU */
11863 default:
11864 if ((ctx || task_shared_vars)
11865 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11866 ctx ? NULL : &wi))
11868 /* Just remove clobbers, this should happen only if we have
11869 "privatized" local addressable variables in SIMD regions,
11870 the clobber isn't needed in that case and gimplifying address
11871 of the ARRAY_REF into a pointer and creating MEM_REF based
11872 clobber would create worse code than we get with the clobber
11873 dropped. */
11874 if (gimple_clobber_p (stmt))
11876 gsi_replace (gsi_p, gimple_build_nop (), true);
11877 break;
11879 gimple_regimplify_operands (stmt, gsi_p);
11881 break;
11885 static void
11886 lower_omp (gimple_seq *body, omp_context *ctx)
11888 location_t saved_location = input_location;
11889 gimple_stmt_iterator gsi;
11890 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11891 lower_omp_1 (&gsi, ctx);
11892 /* During gimplification, we haven't folded statments inside offloading
11893 regions (gimplify.c:maybe_fold_stmt); do that now. */
11894 if (target_nesting_level)
11895 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11896 fold_stmt (&gsi);
11897 input_location = saved_location;
11900 /* Main entry point. */
11902 static unsigned int
11903 execute_lower_omp (void)
11905 gimple_seq body;
11906 int i;
11907 omp_context *ctx;
11909 /* This pass always runs, to provide PROP_gimple_lomp.
11910 But often, there is nothing to do. */
11911 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11912 && flag_openmp_simd == 0)
11913 return 0;
11915 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11916 delete_omp_context);
11918 body = gimple_body (current_function_decl);
11919 scan_omp (&body, NULL);
11920 gcc_assert (taskreg_nesting_level == 0);
11921 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11922 finish_taskreg_scan (ctx);
11923 taskreg_contexts.release ();
11925 if (all_contexts->root)
11927 if (task_shared_vars)
11928 push_gimplify_context ();
11929 lower_omp (&body, NULL);
11930 if (task_shared_vars)
11931 pop_gimplify_context (NULL);
11934 if (all_contexts)
11936 splay_tree_delete (all_contexts);
11937 all_contexts = NULL;
11939 BITMAP_FREE (task_shared_vars);
11940 return 0;
11943 namespace {
11945 const pass_data pass_data_lower_omp =
11947 GIMPLE_PASS, /* type */
11948 "omplower", /* name */
11949 OPTGROUP_NONE, /* optinfo_flags */
11950 TV_NONE, /* tv_id */
11951 PROP_gimple_any, /* properties_required */
11952 PROP_gimple_lomp, /* properties_provided */
11953 0, /* properties_destroyed */
11954 0, /* todo_flags_start */
11955 0, /* todo_flags_finish */
11958 class pass_lower_omp : public gimple_opt_pass
11960 public:
11961 pass_lower_omp (gcc::context *ctxt)
11962 : gimple_opt_pass (pass_data_lower_omp, ctxt)
11965 /* opt_pass methods: */
11966 virtual unsigned int execute (function *) { return execute_lower_omp (); }
11968 }; // class pass_lower_omp
11970 } // anon namespace
11972 gimple_opt_pass *
11973 make_pass_lower_omp (gcc::context *ctxt)
11975 return new pass_lower_omp (ctxt);
11978 /* The following is a utility to diagnose structured block violations.
11979 It is not part of the "omplower" pass, as that's invoked too late. It
11980 should be invoked by the respective front ends after gimplification. */
11982 static splay_tree all_labels;
11984 /* Check for mismatched contexts and generate an error if needed. Return
11985 true if an error is detected. */
11987 static bool
11988 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
11989 gimple branch_ctx, gimple label_ctx)
11991 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
11992 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
11994 if (label_ctx == branch_ctx)
11995 return false;
11997 const char* kind = NULL;
11999 if (flag_cilkplus)
12001 if ((branch_ctx
12002 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12003 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12004 || (label_ctx
12005 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12006 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12007 kind = "Cilk Plus";
12009 if (flag_openacc)
12011 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
12012 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
12014 gcc_checking_assert (kind == NULL);
12015 kind = "OpenACC";
12018 if (kind == NULL)
12020 gcc_checking_assert (flag_openmp);
12021 kind = "OpenMP";
12025 Previously we kept track of the label's entire context in diagnose_sb_[12]
12026 so we could traverse it and issue a correct "exit" or "enter" error
12027 message upon a structured block violation.
12029 We built the context by building a list with tree_cons'ing, but there is
12030 no easy counterpart in gimple tuples. It seems like far too much work
12031 for issuing exit/enter error messages. If someone really misses the
12032 distinct error message... patches welcome.
12035 #if 0
12036 /* Try to avoid confusing the user by producing and error message
12037 with correct "exit" or "enter" verbiage. We prefer "exit"
12038 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12039 if (branch_ctx == NULL)
12040 exit_p = false;
12041 else
12043 while (label_ctx)
12045 if (TREE_VALUE (label_ctx) == branch_ctx)
12047 exit_p = false;
12048 break;
12050 label_ctx = TREE_CHAIN (label_ctx);
12054 if (exit_p)
12055 error ("invalid exit from %s structured block", kind);
12056 else
12057 error ("invalid entry to %s structured block", kind);
12058 #endif
12060 /* If it's obvious we have an invalid entry, be specific about the error. */
12061 if (branch_ctx == NULL)
12062 error ("invalid entry to %s structured block", kind);
12063 else
12065 /* Otherwise, be vague and lazy, but efficient. */
12066 error ("invalid branch to/from %s structured block", kind);
12069 gsi_replace (gsi_p, gimple_build_nop (), false);
12070 return true;
12073 /* Pass 1: Create a minimal tree of structured blocks, and record
12074 where each label is found. */
12076 static tree
12077 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12078 struct walk_stmt_info *wi)
12080 gimple context = (gimple) wi->info;
12081 gimple inner_context;
12082 gimple stmt = gsi_stmt (*gsi_p);
12084 *handled_ops_p = true;
12086 switch (gimple_code (stmt))
12088 WALK_SUBSTMTS;
12090 case GIMPLE_OMP_PARALLEL:
12091 case GIMPLE_OMP_TASK:
12092 case GIMPLE_OMP_SECTIONS:
12093 case GIMPLE_OMP_SINGLE:
12094 case GIMPLE_OMP_SECTION:
12095 case GIMPLE_OMP_MASTER:
12096 case GIMPLE_OMP_ORDERED:
12097 case GIMPLE_OMP_CRITICAL:
12098 case GIMPLE_OMP_TARGET:
12099 case GIMPLE_OMP_TEAMS:
12100 case GIMPLE_OMP_TASKGROUP:
12101 /* The minimal context here is just the current OMP construct. */
12102 inner_context = stmt;
12103 wi->info = inner_context;
12104 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12105 wi->info = context;
12106 break;
12108 case GIMPLE_OMP_FOR:
12109 inner_context = stmt;
12110 wi->info = inner_context;
12111 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12112 walk them. */
12113 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12114 diagnose_sb_1, NULL, wi);
12115 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12116 wi->info = context;
12117 break;
12119 case GIMPLE_LABEL:
12120 splay_tree_insert (all_labels,
12121 (splay_tree_key) gimple_label_label (
12122 as_a <glabel *> (stmt)),
12123 (splay_tree_value) context);
12124 break;
12126 default:
12127 break;
12130 return NULL_TREE;
12133 /* Pass 2: Check each branch and see if its context differs from that of
12134 the destination label's context. */
12136 static tree
12137 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12138 struct walk_stmt_info *wi)
12140 gimple context = (gimple) wi->info;
12141 splay_tree_node n;
12142 gimple stmt = gsi_stmt (*gsi_p);
12144 *handled_ops_p = true;
12146 switch (gimple_code (stmt))
12148 WALK_SUBSTMTS;
12150 case GIMPLE_OMP_PARALLEL:
12151 case GIMPLE_OMP_TASK:
12152 case GIMPLE_OMP_SECTIONS:
12153 case GIMPLE_OMP_SINGLE:
12154 case GIMPLE_OMP_SECTION:
12155 case GIMPLE_OMP_MASTER:
12156 case GIMPLE_OMP_ORDERED:
12157 case GIMPLE_OMP_CRITICAL:
12158 case GIMPLE_OMP_TARGET:
12159 case GIMPLE_OMP_TEAMS:
12160 case GIMPLE_OMP_TASKGROUP:
12161 wi->info = stmt;
12162 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12163 wi->info = context;
12164 break;
12166 case GIMPLE_OMP_FOR:
12167 wi->info = stmt;
12168 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12169 walk them. */
12170 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12171 diagnose_sb_2, NULL, wi);
12172 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12173 wi->info = context;
12174 break;
12176 case GIMPLE_COND:
12178 gcond *cond_stmt = as_a <gcond *> (stmt);
12179 tree lab = gimple_cond_true_label (cond_stmt);
12180 if (lab)
12182 n = splay_tree_lookup (all_labels,
12183 (splay_tree_key) lab);
12184 diagnose_sb_0 (gsi_p, context,
12185 n ? (gimple) n->value : NULL);
12187 lab = gimple_cond_false_label (cond_stmt);
12188 if (lab)
12190 n = splay_tree_lookup (all_labels,
12191 (splay_tree_key) lab);
12192 diagnose_sb_0 (gsi_p, context,
12193 n ? (gimple) n->value : NULL);
12196 break;
12198 case GIMPLE_GOTO:
12200 tree lab = gimple_goto_dest (stmt);
12201 if (TREE_CODE (lab) != LABEL_DECL)
12202 break;
12204 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12205 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
12207 break;
12209 case GIMPLE_SWITCH:
12211 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12212 unsigned int i;
12213 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12215 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12216 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12217 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
12218 break;
12221 break;
12223 case GIMPLE_RETURN:
12224 diagnose_sb_0 (gsi_p, context, NULL);
12225 break;
12227 default:
12228 break;
12231 return NULL_TREE;
12234 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12235 GIMPLE_* codes. */
12236 bool
12237 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12238 int *region_idx)
12240 gimple last = last_stmt (bb);
12241 enum gimple_code code = gimple_code (last);
12242 struct omp_region *cur_region = *region;
12243 bool fallthru = false;
12245 switch (code)
12247 case GIMPLE_OMP_PARALLEL:
12248 case GIMPLE_OMP_TASK:
12249 case GIMPLE_OMP_FOR:
12250 case GIMPLE_OMP_SINGLE:
12251 case GIMPLE_OMP_TEAMS:
12252 case GIMPLE_OMP_MASTER:
12253 case GIMPLE_OMP_TASKGROUP:
12254 case GIMPLE_OMP_ORDERED:
12255 case GIMPLE_OMP_CRITICAL:
12256 case GIMPLE_OMP_SECTION:
12257 cur_region = new_omp_region (bb, code, cur_region);
12258 fallthru = true;
12259 break;
12261 case GIMPLE_OMP_TARGET:
12262 cur_region = new_omp_region (bb, code, cur_region);
12263 fallthru = true;
12264 switch (gimple_omp_target_kind (last))
12266 case GF_OMP_TARGET_KIND_REGION:
12267 case GF_OMP_TARGET_KIND_DATA:
12268 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12269 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12270 case GF_OMP_TARGET_KIND_OACC_DATA:
12271 break;
12272 case GF_OMP_TARGET_KIND_UPDATE:
12273 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12274 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12275 cur_region = cur_region->outer;
12276 break;
12277 default:
12278 gcc_unreachable ();
12280 break;
12282 case GIMPLE_OMP_SECTIONS:
12283 cur_region = new_omp_region (bb, code, cur_region);
12284 fallthru = true;
12285 break;
12287 case GIMPLE_OMP_SECTIONS_SWITCH:
12288 fallthru = false;
12289 break;
12291 case GIMPLE_OMP_ATOMIC_LOAD:
12292 case GIMPLE_OMP_ATOMIC_STORE:
12293 fallthru = true;
12294 break;
12296 case GIMPLE_OMP_RETURN:
12297 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12298 somewhere other than the next block. This will be
12299 created later. */
12300 cur_region->exit = bb;
12301 if (cur_region->type == GIMPLE_OMP_TASK)
12302 /* Add an edge corresponding to not scheduling the task
12303 immediately. */
12304 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
12305 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12306 cur_region = cur_region->outer;
12307 break;
12309 case GIMPLE_OMP_CONTINUE:
12310 cur_region->cont = bb;
12311 switch (cur_region->type)
12313 case GIMPLE_OMP_FOR:
12314 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12315 succs edges as abnormal to prevent splitting
12316 them. */
12317 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12318 /* Make the loopback edge. */
12319 make_edge (bb, single_succ (cur_region->entry),
12320 EDGE_ABNORMAL);
12322 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12323 corresponds to the case that the body of the loop
12324 is not executed at all. */
12325 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12326 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12327 fallthru = false;
12328 break;
12330 case GIMPLE_OMP_SECTIONS:
12331 /* Wire up the edges into and out of the nested sections. */
12333 basic_block switch_bb = single_succ (cur_region->entry);
12335 struct omp_region *i;
12336 for (i = cur_region->inner; i ; i = i->next)
12338 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12339 make_edge (switch_bb, i->entry, 0);
12340 make_edge (i->exit, bb, EDGE_FALLTHRU);
12343 /* Make the loopback edge to the block with
12344 GIMPLE_OMP_SECTIONS_SWITCH. */
12345 make_edge (bb, switch_bb, 0);
12347 /* Make the edge from the switch to exit. */
12348 make_edge (switch_bb, bb->next_bb, 0);
12349 fallthru = false;
12351 break;
12353 case GIMPLE_OMP_TASK:
12354 fallthru = true;
12355 break;
12357 default:
12358 gcc_unreachable ();
12360 break;
12362 default:
12363 gcc_unreachable ();
12366 if (*region != cur_region)
12368 *region = cur_region;
12369 if (cur_region)
12370 *region_idx = cur_region->entry->index;
12371 else
12372 *region_idx = 0;
12375 return fallthru;
12378 static unsigned int
12379 diagnose_omp_structured_block_errors (void)
12381 struct walk_stmt_info wi;
12382 gimple_seq body = gimple_body (current_function_decl);
12384 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12386 memset (&wi, 0, sizeof (wi));
12387 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12389 memset (&wi, 0, sizeof (wi));
12390 wi.want_locations = true;
12391 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12393 gimple_set_body (current_function_decl, body);
12395 splay_tree_delete (all_labels);
12396 all_labels = NULL;
12398 return 0;
12401 namespace {
12403 const pass_data pass_data_diagnose_omp_blocks =
12405 GIMPLE_PASS, /* type */
12406 "*diagnose_omp_blocks", /* name */
12407 OPTGROUP_NONE, /* optinfo_flags */
12408 TV_NONE, /* tv_id */
12409 PROP_gimple_any, /* properties_required */
12410 0, /* properties_provided */
12411 0, /* properties_destroyed */
12412 0, /* todo_flags_start */
12413 0, /* todo_flags_finish */
12416 class pass_diagnose_omp_blocks : public gimple_opt_pass
12418 public:
12419 pass_diagnose_omp_blocks (gcc::context *ctxt)
12420 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12423 /* opt_pass methods: */
12424 virtual bool gate (function *)
12426 return flag_cilkplus || flag_openacc || flag_openmp;
12428 virtual unsigned int execute (function *)
12430 return diagnose_omp_structured_block_errors ();
12433 }; // class pass_diagnose_omp_blocks
12435 } // anon namespace
12437 gimple_opt_pass *
12438 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12440 return new pass_diagnose_omp_blocks (ctxt);
12443 /* SIMD clone supporting code. */
12445 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12446 of arguments to reserve space for. */
12448 static struct cgraph_simd_clone *
12449 simd_clone_struct_alloc (int nargs)
12451 struct cgraph_simd_clone *clone_info;
12452 size_t len = (sizeof (struct cgraph_simd_clone)
12453 + nargs * sizeof (struct cgraph_simd_clone_arg));
12454 clone_info = (struct cgraph_simd_clone *)
12455 ggc_internal_cleared_alloc (len);
12456 return clone_info;
12459 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12461 static inline void
12462 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12463 struct cgraph_simd_clone *from)
12465 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12466 + ((from->nargs - from->inbranch)
12467 * sizeof (struct cgraph_simd_clone_arg))));
12470 /* Return vector of parameter types of function FNDECL. This uses
12471 TYPE_ARG_TYPES if available, otherwise falls back to types of
12472 DECL_ARGUMENTS types. */
12474 vec<tree>
12475 simd_clone_vector_of_formal_parm_types (tree fndecl)
12477 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12478 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12479 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12480 unsigned int i;
12481 tree arg;
12482 FOR_EACH_VEC_ELT (args, i, arg)
12483 args[i] = TREE_TYPE (args[i]);
12484 return args;
12487 /* Given a simd function in NODE, extract the simd specific
12488 information from the OMP clauses passed in CLAUSES, and return
12489 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12490 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12491 otherwise set to FALSE. */
12493 static struct cgraph_simd_clone *
12494 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12495 bool *inbranch_specified)
12497 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12498 tree t;
12499 int n;
12500 *inbranch_specified = false;
12502 n = args.length ();
12503 if (n > 0 && args.last () == void_type_node)
12504 n--;
12506 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12507 be cloned have a distinctive artificial label in addition to "omp
12508 declare simd". */
12509 bool cilk_clone
12510 = (flag_cilkplus
12511 && lookup_attribute ("cilk simd function",
12512 DECL_ATTRIBUTES (node->decl)));
12514 /* Allocate one more than needed just in case this is an in-branch
12515 clone which will require a mask argument. */
12516 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12517 clone_info->nargs = n;
12518 clone_info->cilk_elemental = cilk_clone;
12520 if (!clauses)
12522 args.release ();
12523 return clone_info;
12525 clauses = TREE_VALUE (clauses);
12526 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12527 return clone_info;
12529 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12531 switch (OMP_CLAUSE_CODE (t))
12533 case OMP_CLAUSE_INBRANCH:
12534 clone_info->inbranch = 1;
12535 *inbranch_specified = true;
12536 break;
12537 case OMP_CLAUSE_NOTINBRANCH:
12538 clone_info->inbranch = 0;
12539 *inbranch_specified = true;
12540 break;
12541 case OMP_CLAUSE_SIMDLEN:
12542 clone_info->simdlen
12543 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12544 break;
12545 case OMP_CLAUSE_LINEAR:
12547 tree decl = OMP_CLAUSE_DECL (t);
12548 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12549 int argno = TREE_INT_CST_LOW (decl);
12550 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12552 clone_info->args[argno].arg_type
12553 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12554 clone_info->args[argno].linear_step = tree_to_shwi (step);
12555 gcc_assert (clone_info->args[argno].linear_step >= 0
12556 && clone_info->args[argno].linear_step < n);
12558 else
12560 if (POINTER_TYPE_P (args[argno]))
12561 step = fold_convert (ssizetype, step);
12562 if (!tree_fits_shwi_p (step))
12564 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12565 "ignoring large linear step");
12566 args.release ();
12567 return NULL;
12569 else if (integer_zerop (step))
12571 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12572 "ignoring zero linear step");
12573 args.release ();
12574 return NULL;
12576 else
12578 clone_info->args[argno].arg_type
12579 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12580 clone_info->args[argno].linear_step = tree_to_shwi (step);
12583 break;
12585 case OMP_CLAUSE_UNIFORM:
12587 tree decl = OMP_CLAUSE_DECL (t);
12588 int argno = tree_to_uhwi (decl);
12589 clone_info->args[argno].arg_type
12590 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12591 break;
12593 case OMP_CLAUSE_ALIGNED:
12595 tree decl = OMP_CLAUSE_DECL (t);
12596 int argno = tree_to_uhwi (decl);
12597 clone_info->args[argno].alignment
12598 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12599 break;
12601 default:
12602 break;
12605 args.release ();
12606 return clone_info;
12609 /* Given a SIMD clone in NODE, calculate the characteristic data
12610 type and return the coresponding type. The characteristic data
12611 type is computed as described in the Intel Vector ABI. */
12613 static tree
12614 simd_clone_compute_base_data_type (struct cgraph_node *node,
12615 struct cgraph_simd_clone *clone_info)
12617 tree type = integer_type_node;
12618 tree fndecl = node->decl;
12620 /* a) For non-void function, the characteristic data type is the
12621 return type. */
12622 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12623 type = TREE_TYPE (TREE_TYPE (fndecl));
12625 /* b) If the function has any non-uniform, non-linear parameters,
12626 then the characteristic data type is the type of the first
12627 such parameter. */
12628 else
12630 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12631 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12632 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12634 type = map[i];
12635 break;
12637 map.release ();
12640 /* c) If the characteristic data type determined by a) or b) above
12641 is struct, union, or class type which is pass-by-value (except
12642 for the type that maps to the built-in complex data type), the
12643 characteristic data type is int. */
12644 if (RECORD_OR_UNION_TYPE_P (type)
12645 && !aggregate_value_p (type, NULL)
12646 && TREE_CODE (type) != COMPLEX_TYPE)
12647 return integer_type_node;
12649 /* d) If none of the above three classes is applicable, the
12650 characteristic data type is int. */
12652 return type;
12654 /* e) For Intel Xeon Phi native and offload compilation, if the
12655 resulting characteristic data type is 8-bit or 16-bit integer
12656 data type, the characteristic data type is int. */
12657 /* Well, we don't handle Xeon Phi yet. */
12660 static tree
12661 simd_clone_mangle (struct cgraph_node *node,
12662 struct cgraph_simd_clone *clone_info)
12664 char vecsize_mangle = clone_info->vecsize_mangle;
12665 char mask = clone_info->inbranch ? 'M' : 'N';
12666 unsigned int simdlen = clone_info->simdlen;
12667 unsigned int n;
12668 pretty_printer pp;
12670 gcc_assert (vecsize_mangle && simdlen);
12672 pp_string (&pp, "_ZGV");
12673 pp_character (&pp, vecsize_mangle);
12674 pp_character (&pp, mask);
12675 pp_decimal_int (&pp, simdlen);
12677 for (n = 0; n < clone_info->nargs; ++n)
12679 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12681 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12682 pp_character (&pp, 'u');
12683 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12685 gcc_assert (arg.linear_step != 0);
12686 pp_character (&pp, 'l');
12687 if (arg.linear_step > 1)
12688 pp_unsigned_wide_integer (&pp, arg.linear_step);
12689 else if (arg.linear_step < 0)
12691 pp_character (&pp, 'n');
12692 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12693 arg.linear_step));
12696 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12698 pp_character (&pp, 's');
12699 pp_unsigned_wide_integer (&pp, arg.linear_step);
12701 else
12702 pp_character (&pp, 'v');
12703 if (arg.alignment)
12705 pp_character (&pp, 'a');
12706 pp_decimal_int (&pp, arg.alignment);
12710 pp_underscore (&pp);
12711 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12712 if (*str == '*')
12713 ++str;
12714 pp_string (&pp, str);
12715 str = pp_formatted_text (&pp);
12717 /* If there already is a SIMD clone with the same mangled name, don't
12718 add another one. This can happen e.g. for
12719 #pragma omp declare simd
12720 #pragma omp declare simd simdlen(8)
12721 int foo (int, int);
12722 if the simdlen is assumed to be 8 for the first one, etc. */
12723 for (struct cgraph_node *clone = node->simd_clones; clone;
12724 clone = clone->simdclone->next_clone)
12725 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12726 str) == 0)
12727 return NULL_TREE;
12729 return get_identifier (str);
12732 /* Create a simd clone of OLD_NODE and return it. */
12734 static struct cgraph_node *
12735 simd_clone_create (struct cgraph_node *old_node)
12737 struct cgraph_node *new_node;
12738 if (old_node->definition)
12740 if (!old_node->has_gimple_body_p ())
12741 return NULL;
12742 old_node->get_body ();
12743 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12744 false, NULL, NULL,
12745 "simdclone");
12747 else
12749 tree old_decl = old_node->decl;
12750 tree new_decl = copy_node (old_node->decl);
12751 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12752 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12753 SET_DECL_RTL (new_decl, NULL);
12754 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12755 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
12756 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
12757 symtab->call_cgraph_insertion_hooks (new_node);
12759 if (new_node == NULL)
12760 return new_node;
12762 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12764 /* The function cgraph_function_versioning () will force the new
12765 symbol local. Undo this, and inherit external visability from
12766 the old node. */
12767 new_node->local.local = old_node->local.local;
12768 new_node->externally_visible = old_node->externally_visible;
12770 return new_node;
12773 /* Adjust the return type of the given function to its appropriate
12774 vector counterpart. Returns a simd array to be used throughout the
12775 function as a return value. */
12777 static tree
12778 simd_clone_adjust_return_type (struct cgraph_node *node)
12780 tree fndecl = node->decl;
12781 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12782 unsigned int veclen;
12783 tree t;
12785 /* Adjust the function return type. */
12786 if (orig_rettype == void_type_node)
12787 return NULL_TREE;
12788 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
12789 t = TREE_TYPE (TREE_TYPE (fndecl));
12790 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
12791 veclen = node->simdclone->vecsize_int;
12792 else
12793 veclen = node->simdclone->vecsize_float;
12794 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
12795 if (veclen > node->simdclone->simdlen)
12796 veclen = node->simdclone->simdlen;
12797 if (POINTER_TYPE_P (t))
12798 t = pointer_sized_int_node;
12799 if (veclen == node->simdclone->simdlen)
12800 t = build_vector_type (t, node->simdclone->simdlen);
12801 else
12803 t = build_vector_type (t, veclen);
12804 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
12806 TREE_TYPE (TREE_TYPE (fndecl)) = t;
12807 if (!node->definition)
12808 return NULL_TREE;
12810 t = DECL_RESULT (fndecl);
12811 /* Adjust the DECL_RESULT. */
12812 gcc_assert (TREE_TYPE (t) != void_type_node);
12813 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12814 relayout_decl (t);
12816 tree atype = build_array_type_nelts (orig_rettype,
12817 node->simdclone->simdlen);
12818 if (veclen != node->simdclone->simdlen)
12819 return build1 (VIEW_CONVERT_EXPR, atype, t);
12821 /* Set up a SIMD array to use as the return value. */
12822 tree retval = create_tmp_var_raw (atype, "retval");
12823 gimple_add_tmp_var (retval);
12824 return retval;
12827 /* Each vector argument has a corresponding array to be used locally
12828 as part of the eventual loop. Create such temporary array and
12829 return it.
12831 PREFIX is the prefix to be used for the temporary.
12833 TYPE is the inner element type.
12835 SIMDLEN is the number of elements. */
12837 static tree
12838 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12840 tree atype = build_array_type_nelts (type, simdlen);
12841 tree avar = create_tmp_var_raw (atype, prefix);
12842 gimple_add_tmp_var (avar);
12843 return avar;
12846 /* Modify the function argument types to their corresponding vector
12847 counterparts if appropriate. Also, create one array for each simd
12848 argument to be used locally when using the function arguments as
12849 part of the loop.
12851 NODE is the function whose arguments are to be adjusted.
12853 Returns an adjustment vector that will be filled describing how the
12854 argument types will be adjusted. */
12856 static ipa_parm_adjustment_vec
12857 simd_clone_adjust_argument_types (struct cgraph_node *node)
12859 vec<tree> args;
12860 ipa_parm_adjustment_vec adjustments;
12862 if (node->definition)
12863 args = ipa_get_vector_of_formal_parms (node->decl);
12864 else
12865 args = simd_clone_vector_of_formal_parm_types (node->decl);
12866 adjustments.create (args.length ());
12867 unsigned i, j, veclen;
12868 struct ipa_parm_adjustment adj;
12869 for (i = 0; i < node->simdclone->nargs; ++i)
12871 memset (&adj, 0, sizeof (adj));
12872 tree parm = args[i];
12873 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12874 adj.base_index = i;
12875 adj.base = parm;
12877 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12878 node->simdclone->args[i].orig_type = parm_type;
12880 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12882 /* No adjustment necessary for scalar arguments. */
12883 adj.op = IPA_PARM_OP_COPY;
12885 else
12887 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12888 veclen = node->simdclone->vecsize_int;
12889 else
12890 veclen = node->simdclone->vecsize_float;
12891 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12892 if (veclen > node->simdclone->simdlen)
12893 veclen = node->simdclone->simdlen;
12894 adj.arg_prefix = "simd";
12895 if (POINTER_TYPE_P (parm_type))
12896 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12897 else
12898 adj.type = build_vector_type (parm_type, veclen);
12899 node->simdclone->args[i].vector_type = adj.type;
12900 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12902 adjustments.safe_push (adj);
12903 if (j == veclen)
12905 memset (&adj, 0, sizeof (adj));
12906 adj.op = IPA_PARM_OP_NEW;
12907 adj.arg_prefix = "simd";
12908 adj.base_index = i;
12909 adj.type = node->simdclone->args[i].vector_type;
12913 if (node->definition)
12914 node->simdclone->args[i].simd_array
12915 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12916 parm_type, node->simdclone->simdlen);
12918 adjustments.safe_push (adj);
12921 if (node->simdclone->inbranch)
12923 tree base_type
12924 = simd_clone_compute_base_data_type (node->simdclone->origin,
12925 node->simdclone);
12927 memset (&adj, 0, sizeof (adj));
12928 adj.op = IPA_PARM_OP_NEW;
12929 adj.arg_prefix = "mask";
12931 adj.base_index = i;
12932 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12933 veclen = node->simdclone->vecsize_int;
12934 else
12935 veclen = node->simdclone->vecsize_float;
12936 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12937 if (veclen > node->simdclone->simdlen)
12938 veclen = node->simdclone->simdlen;
12939 if (POINTER_TYPE_P (base_type))
12940 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12941 else
12942 adj.type = build_vector_type (base_type, veclen);
12943 adjustments.safe_push (adj);
12945 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12946 adjustments.safe_push (adj);
12948 /* We have previously allocated one extra entry for the mask. Use
12949 it and fill it. */
12950 struct cgraph_simd_clone *sc = node->simdclone;
12951 sc->nargs++;
12952 if (node->definition)
12954 sc->args[i].orig_arg
12955 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12956 sc->args[i].simd_array
12957 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12959 sc->args[i].orig_type = base_type;
12960 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12963 if (node->definition)
12964 ipa_modify_formal_parameters (node->decl, adjustments);
12965 else
12967 tree new_arg_types = NULL_TREE, new_reversed;
12968 bool last_parm_void = false;
12969 if (args.length () > 0 && args.last () == void_type_node)
12970 last_parm_void = true;
12972 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12973 j = adjustments.length ();
12974 for (i = 0; i < j; i++)
12976 struct ipa_parm_adjustment *adj = &adjustments[i];
12977 tree ptype;
12978 if (adj->op == IPA_PARM_OP_COPY)
12979 ptype = args[adj->base_index];
12980 else
12981 ptype = adj->type;
12982 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12984 new_reversed = nreverse (new_arg_types);
12985 if (last_parm_void)
12987 if (new_reversed)
12988 TREE_CHAIN (new_arg_types) = void_list_node;
12989 else
12990 new_reversed = void_list_node;
12993 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
12994 TYPE_ARG_TYPES (new_type) = new_reversed;
12995 TREE_TYPE (node->decl) = new_type;
12997 adjustments.release ();
12999 args.release ();
13000 return adjustments;
13003 /* Initialize and copy the function arguments in NODE to their
13004 corresponding local simd arrays. Returns a fresh gimple_seq with
13005 the instruction sequence generated. */
13007 static gimple_seq
13008 simd_clone_init_simd_arrays (struct cgraph_node *node,
13009 ipa_parm_adjustment_vec adjustments)
13011 gimple_seq seq = NULL;
13012 unsigned i = 0, j = 0, k;
13014 for (tree arg = DECL_ARGUMENTS (node->decl);
13015 arg;
13016 arg = DECL_CHAIN (arg), i++, j++)
13018 if (adjustments[j].op == IPA_PARM_OP_COPY)
13019 continue;
13021 node->simdclone->args[i].vector_arg = arg;
13023 tree array = node->simdclone->args[i].simd_array;
13024 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13026 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13027 tree ptr = build_fold_addr_expr (array);
13028 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13029 build_int_cst (ptype, 0));
13030 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13031 gimplify_and_add (t, &seq);
13033 else
13035 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13036 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13037 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13039 tree ptr = build_fold_addr_expr (array);
13040 int elemsize;
13041 if (k)
13043 arg = DECL_CHAIN (arg);
13044 j++;
13046 elemsize
13047 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13048 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13049 build_int_cst (ptype, k * elemsize));
13050 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13051 gimplify_and_add (t, &seq);
13055 return seq;
13058 /* Callback info for ipa_simd_modify_stmt_ops below. */
13060 struct modify_stmt_info {
13061 ipa_parm_adjustment_vec adjustments;
13062 gimple stmt;
13063 /* True if the parent statement was modified by
13064 ipa_simd_modify_stmt_ops. */
13065 bool modified;
13068 /* Callback for walk_gimple_op.
13070 Adjust operands from a given statement as specified in the
13071 adjustments vector in the callback data. */
13073 static tree
13074 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13076 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13077 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13078 tree *orig_tp = tp;
13079 if (TREE_CODE (*tp) == ADDR_EXPR)
13080 tp = &TREE_OPERAND (*tp, 0);
13081 struct ipa_parm_adjustment *cand = NULL;
13082 if (TREE_CODE (*tp) == PARM_DECL)
13083 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13084 else
13086 if (TYPE_P (*tp))
13087 *walk_subtrees = 0;
13090 tree repl = NULL_TREE;
13091 if (cand)
13092 repl = unshare_expr (cand->new_decl);
13093 else
13095 if (tp != orig_tp)
13097 *walk_subtrees = 0;
13098 bool modified = info->modified;
13099 info->modified = false;
13100 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13101 if (!info->modified)
13103 info->modified = modified;
13104 return NULL_TREE;
13106 info->modified = modified;
13107 repl = *tp;
13109 else
13110 return NULL_TREE;
13113 if (tp != orig_tp)
13115 repl = build_fold_addr_expr (repl);
13116 gimple stmt;
13117 if (is_gimple_debug (info->stmt))
13119 tree vexpr = make_node (DEBUG_EXPR_DECL);
13120 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13121 DECL_ARTIFICIAL (vexpr) = 1;
13122 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13123 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13124 repl = vexpr;
13126 else
13128 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13129 repl = gimple_assign_lhs (stmt);
13131 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13132 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13133 *orig_tp = repl;
13135 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13137 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13138 *tp = vce;
13140 else
13141 *tp = repl;
13143 info->modified = true;
13144 return NULL_TREE;
13147 /* Traverse the function body and perform all modifications as
13148 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13149 modified such that the replacement/reduction value will now be an
13150 offset into the corresponding simd_array.
13152 This function will replace all function argument uses with their
13153 corresponding simd array elements, and ajust the return values
13154 accordingly. */
13156 static void
13157 ipa_simd_modify_function_body (struct cgraph_node *node,
13158 ipa_parm_adjustment_vec adjustments,
13159 tree retval_array, tree iter)
13161 basic_block bb;
13162 unsigned int i, j, l;
13164 /* Re-use the adjustments array, but this time use it to replace
13165 every function argument use to an offset into the corresponding
13166 simd_array. */
13167 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13169 if (!node->simdclone->args[i].vector_arg)
13170 continue;
13172 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13173 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13174 adjustments[j].new_decl
13175 = build4 (ARRAY_REF,
13176 basetype,
13177 node->simdclone->args[i].simd_array,
13178 iter,
13179 NULL_TREE, NULL_TREE);
13180 if (adjustments[j].op == IPA_PARM_OP_NONE
13181 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13182 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13185 l = adjustments.length ();
13186 for (i = 1; i < num_ssa_names; i++)
13188 tree name = ssa_name (i);
13189 if (name
13190 && SSA_NAME_VAR (name)
13191 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13193 for (j = 0; j < l; j++)
13194 if (SSA_NAME_VAR (name) == adjustments[j].base
13195 && adjustments[j].new_decl)
13197 tree base_var;
13198 if (adjustments[j].new_ssa_base == NULL_TREE)
13200 base_var
13201 = copy_var_decl (adjustments[j].base,
13202 DECL_NAME (adjustments[j].base),
13203 TREE_TYPE (adjustments[j].base));
13204 adjustments[j].new_ssa_base = base_var;
13206 else
13207 base_var = adjustments[j].new_ssa_base;
13208 if (SSA_NAME_IS_DEFAULT_DEF (name))
13210 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13211 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13212 tree new_decl = unshare_expr (adjustments[j].new_decl);
13213 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13214 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13215 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13216 gimple stmt = gimple_build_assign (name, new_decl);
13217 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13219 else
13220 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13225 struct modify_stmt_info info;
13226 info.adjustments = adjustments;
13228 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13230 gimple_stmt_iterator gsi;
13232 gsi = gsi_start_bb (bb);
13233 while (!gsi_end_p (gsi))
13235 gimple stmt = gsi_stmt (gsi);
13236 info.stmt = stmt;
13237 struct walk_stmt_info wi;
13239 memset (&wi, 0, sizeof (wi));
13240 info.modified = false;
13241 wi.info = &info;
13242 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13244 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13246 tree retval = gimple_return_retval (return_stmt);
13247 if (!retval)
13249 gsi_remove (&gsi, true);
13250 continue;
13253 /* Replace `return foo' with `retval_array[iter] = foo'. */
13254 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13255 retval_array, iter, NULL, NULL);
13256 stmt = gimple_build_assign (ref, retval);
13257 gsi_replace (&gsi, stmt, true);
13258 info.modified = true;
13261 if (info.modified)
13263 update_stmt (stmt);
13264 if (maybe_clean_eh_stmt (stmt))
13265 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13267 gsi_next (&gsi);
13272 /* Adjust the argument types in NODE to their appropriate vector
13273 counterparts. */
13275 static void
13276 simd_clone_adjust (struct cgraph_node *node)
13278 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13280 targetm.simd_clone.adjust (node);
13282 tree retval = simd_clone_adjust_return_type (node);
13283 ipa_parm_adjustment_vec adjustments
13284 = simd_clone_adjust_argument_types (node);
13286 push_gimplify_context ();
13288 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13290 /* Adjust all uses of vector arguments accordingly. Adjust all
13291 return values accordingly. */
13292 tree iter = create_tmp_var (unsigned_type_node, "iter");
13293 tree iter1 = make_ssa_name (iter);
13294 tree iter2 = make_ssa_name (iter);
13295 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13297 /* Initialize the iteration variable. */
13298 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13299 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13300 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13301 /* Insert the SIMD array and iv initialization at function
13302 entry. */
13303 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13305 pop_gimplify_context (NULL);
13307 /* Create a new BB right before the original exit BB, to hold the
13308 iteration increment and the condition/branch. */
13309 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13310 basic_block incr_bb = create_empty_bb (orig_exit);
13311 add_bb_to_loop (incr_bb, body_bb->loop_father);
13312 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13313 flag. Set it now to be a FALLTHRU_EDGE. */
13314 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13315 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13316 for (unsigned i = 0;
13317 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13319 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13320 redirect_edge_succ (e, incr_bb);
13322 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13323 e->probability = REG_BR_PROB_BASE;
13324 gsi = gsi_last_bb (incr_bb);
13325 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13326 build_int_cst (unsigned_type_node, 1));
13327 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13329 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13330 struct loop *loop = alloc_loop ();
13331 cfun->has_force_vectorize_loops = true;
13332 loop->safelen = node->simdclone->simdlen;
13333 loop->force_vectorize = true;
13334 loop->header = body_bb;
13336 /* Branch around the body if the mask applies. */
13337 if (node->simdclone->inbranch)
13339 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13340 tree mask_array
13341 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13342 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13343 tree aref = build4 (ARRAY_REF,
13344 TREE_TYPE (TREE_TYPE (mask_array)),
13345 mask_array, iter1,
13346 NULL, NULL);
13347 g = gimple_build_assign (mask, aref);
13348 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13349 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13350 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13352 aref = build1 (VIEW_CONVERT_EXPR,
13353 build_nonstandard_integer_type (bitsize, 0), mask);
13354 mask = make_ssa_name (TREE_TYPE (aref));
13355 g = gimple_build_assign (mask, aref);
13356 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13359 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13360 NULL, NULL);
13361 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13362 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13363 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13366 /* Generate the condition. */
13367 g = gimple_build_cond (LT_EXPR,
13368 iter2,
13369 build_int_cst (unsigned_type_node,
13370 node->simdclone->simdlen),
13371 NULL, NULL);
13372 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13373 e = split_block (incr_bb, gsi_stmt (gsi));
13374 basic_block latch_bb = e->dest;
13375 basic_block new_exit_bb;
13376 new_exit_bb = split_block_after_labels (latch_bb)->dest;
13377 loop->latch = latch_bb;
13379 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13381 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13382 /* The successor of incr_bb is already pointing to latch_bb; just
13383 change the flags.
13384 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13385 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13387 gphi *phi = create_phi_node (iter1, body_bb);
13388 edge preheader_edge = find_edge (entry_bb, body_bb);
13389 edge latch_edge = single_succ_edge (latch_bb);
13390 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13391 UNKNOWN_LOCATION);
13392 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13394 /* Generate the new return. */
13395 gsi = gsi_last_bb (new_exit_bb);
13396 if (retval
13397 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13398 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13399 retval = TREE_OPERAND (retval, 0);
13400 else if (retval)
13402 retval = build1 (VIEW_CONVERT_EXPR,
13403 TREE_TYPE (TREE_TYPE (node->decl)),
13404 retval);
13405 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13406 false, GSI_CONTINUE_LINKING);
13408 g = gimple_build_return (retval);
13409 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13411 /* Handle aligned clauses by replacing default defs of the aligned
13412 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13413 lhs. Handle linear by adding PHIs. */
13414 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13415 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13416 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
13417 || !is_gimple_reg_type
13418 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
13420 tree orig_arg = node->simdclone->args[i].orig_arg;
13421 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
13422 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
13423 else
13425 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
13426 gimple_add_tmp_var (iter1);
13428 gsi = gsi_after_labels (entry_bb);
13429 g = gimple_build_assign (iter1, orig_arg);
13430 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13431 gsi = gsi_after_labels (body_bb);
13432 g = gimple_build_assign (orig_arg, iter1);
13433 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13435 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13436 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
13437 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13438 == REFERENCE_TYPE
13439 && TREE_ADDRESSABLE
13440 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
13442 tree orig_arg = node->simdclone->args[i].orig_arg;
13443 tree def = ssa_default_def (cfun, orig_arg);
13444 if (def && !has_zero_uses (def))
13446 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
13447 gimple_add_tmp_var (iter1);
13448 gsi = gsi_after_labels (entry_bb);
13449 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
13450 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13451 gsi = gsi_after_labels (body_bb);
13452 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
13453 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13456 else if (node->simdclone->args[i].alignment
13457 && node->simdclone->args[i].arg_type
13458 == SIMD_CLONE_ARG_TYPE_UNIFORM
13459 && (node->simdclone->args[i].alignment
13460 & (node->simdclone->args[i].alignment - 1)) == 0
13461 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13462 == POINTER_TYPE)
13464 unsigned int alignment = node->simdclone->args[i].alignment;
13465 tree orig_arg = node->simdclone->args[i].orig_arg;
13466 tree def = ssa_default_def (cfun, orig_arg);
13467 if (def && !has_zero_uses (def))
13469 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13470 gimple_seq seq = NULL;
13471 bool need_cvt = false;
13472 gcall *call
13473 = gimple_build_call (fn, 2, def, size_int (alignment));
13474 g = call;
13475 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13476 ptr_type_node))
13477 need_cvt = true;
13478 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13479 gimple_call_set_lhs (g, t);
13480 gimple_seq_add_stmt_without_update (&seq, g);
13481 if (need_cvt)
13483 t = make_ssa_name (orig_arg);
13484 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13485 gimple_seq_add_stmt_without_update (&seq, g);
13487 gsi_insert_seq_on_edge_immediate
13488 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13490 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13491 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13492 entry_bb);
13493 node->create_edge (cgraph_node::get_create (fn),
13494 call, entry_bb->count, freq);
13496 imm_use_iterator iter;
13497 use_operand_p use_p;
13498 gimple use_stmt;
13499 tree repl = gimple_get_lhs (g);
13500 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13501 if (is_gimple_debug (use_stmt) || use_stmt == call)
13502 continue;
13503 else
13504 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13505 SET_USE (use_p, repl);
13508 else if (node->simdclone->args[i].arg_type
13509 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13511 tree orig_arg = node->simdclone->args[i].orig_arg;
13512 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13513 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13514 tree def = NULL_TREE;
13515 if (TREE_ADDRESSABLE (orig_arg))
13517 def = make_ssa_name (TREE_TYPE (orig_arg));
13518 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
13519 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
13520 gsi = gsi_after_labels (entry_bb);
13521 g = gimple_build_assign (def, orig_arg);
13522 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13524 else
13526 def = ssa_default_def (cfun, orig_arg);
13527 if (!def || has_zero_uses (def))
13528 def = NULL_TREE;
13529 else
13531 iter1 = make_ssa_name (orig_arg);
13532 iter2 = make_ssa_name (orig_arg);
13535 if (def)
13537 phi = create_phi_node (iter1, body_bb);
13538 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13539 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13540 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13541 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13542 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13543 ? TREE_TYPE (orig_arg) : sizetype;
13544 tree addcst
13545 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13546 g = gimple_build_assign (iter2, code, iter1, addcst);
13547 gsi = gsi_last_bb (incr_bb);
13548 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13550 imm_use_iterator iter;
13551 use_operand_p use_p;
13552 gimple use_stmt;
13553 if (TREE_ADDRESSABLE (orig_arg))
13555 gsi = gsi_after_labels (body_bb);
13556 g = gimple_build_assign (orig_arg, iter1);
13557 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13559 else
13560 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13561 if (use_stmt == phi)
13562 continue;
13563 else
13564 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13565 SET_USE (use_p, iter1);
13569 calculate_dominance_info (CDI_DOMINATORS);
13570 add_loop (loop, loop->header->loop_father);
13571 update_ssa (TODO_update_ssa);
13573 pop_cfun ();
13576 /* If the function in NODE is tagged as an elemental SIMD function,
13577 create the appropriate SIMD clones. */
13579 static void
13580 expand_simd_clones (struct cgraph_node *node)
13582 tree attr = lookup_attribute ("omp declare simd",
13583 DECL_ATTRIBUTES (node->decl));
13584 if (attr == NULL_TREE
13585 || node->global.inlined_to
13586 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13587 return;
13589 /* Ignore
13590 #pragma omp declare simd
13591 extern int foo ();
13592 in C, there we don't know the argument types at all. */
13593 if (!node->definition
13594 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13595 return;
13599 /* Start with parsing the "omp declare simd" attribute(s). */
13600 bool inbranch_clause_specified;
13601 struct cgraph_simd_clone *clone_info
13602 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13603 &inbranch_clause_specified);
13604 if (clone_info == NULL)
13605 continue;
13607 int orig_simdlen = clone_info->simdlen;
13608 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13609 /* The target can return 0 (no simd clones should be created),
13610 1 (just one ISA of simd clones should be created) or higher
13611 count of ISA variants. In that case, clone_info is initialized
13612 for the first ISA variant. */
13613 int count
13614 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13615 base_type, 0);
13616 if (count == 0)
13617 continue;
13619 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13620 also create one inbranch and one !inbranch clone of it. */
13621 for (int i = 0; i < count * 2; i++)
13623 struct cgraph_simd_clone *clone = clone_info;
13624 if (inbranch_clause_specified && (i & 1) != 0)
13625 continue;
13627 if (i != 0)
13629 clone = simd_clone_struct_alloc (clone_info->nargs
13630 + ((i & 1) != 0));
13631 simd_clone_struct_copy (clone, clone_info);
13632 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13633 and simd_clone_adjust_argument_types did to the first
13634 clone's info. */
13635 clone->nargs -= clone_info->inbranch;
13636 clone->simdlen = orig_simdlen;
13637 /* And call the target hook again to get the right ISA. */
13638 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13639 base_type,
13640 i / 2);
13641 if ((i & 1) != 0)
13642 clone->inbranch = 1;
13645 /* simd_clone_mangle might fail if such a clone has been created
13646 already. */
13647 tree id = simd_clone_mangle (node, clone);
13648 if (id == NULL_TREE)
13649 continue;
13651 /* Only when we are sure we want to create the clone actually
13652 clone the function (or definitions) or create another
13653 extern FUNCTION_DECL (for prototypes without definitions). */
13654 struct cgraph_node *n = simd_clone_create (node);
13655 if (n == NULL)
13656 continue;
13658 n->simdclone = clone;
13659 clone->origin = node;
13660 clone->next_clone = NULL;
13661 if (node->simd_clones == NULL)
13663 clone->prev_clone = n;
13664 node->simd_clones = n;
13666 else
13668 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13669 clone->prev_clone->simdclone->next_clone = n;
13670 node->simd_clones->simdclone->prev_clone = n;
13672 symtab->change_decl_assembler_name (n->decl, id);
13673 /* And finally adjust the return type, parameters and for
13674 definitions also function body. */
13675 if (node->definition)
13676 simd_clone_adjust (n);
13677 else
13679 simd_clone_adjust_return_type (n);
13680 simd_clone_adjust_argument_types (n);
13684 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13687 /* Entry point for IPA simd clone creation pass. */
13689 static unsigned int
13690 ipa_omp_simd_clone (void)
13692 struct cgraph_node *node;
13693 FOR_EACH_FUNCTION (node)
13694 expand_simd_clones (node);
13695 return 0;
13698 namespace {
13700 const pass_data pass_data_omp_simd_clone =
13702 SIMPLE_IPA_PASS, /* type */
13703 "simdclone", /* name */
13704 OPTGROUP_NONE, /* optinfo_flags */
13705 TV_NONE, /* tv_id */
13706 ( PROP_ssa | PROP_cfg ), /* properties_required */
13707 0, /* properties_provided */
13708 0, /* properties_destroyed */
13709 0, /* todo_flags_start */
13710 0, /* todo_flags_finish */
13713 class pass_omp_simd_clone : public simple_ipa_opt_pass
13715 public:
13716 pass_omp_simd_clone(gcc::context *ctxt)
13717 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13720 /* opt_pass methods: */
13721 virtual bool gate (function *);
13722 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
13725 bool
13726 pass_omp_simd_clone::gate (function *)
13728 return ((flag_openmp || flag_openmp_simd
13729 || flag_cilkplus
13730 || (in_lto_p && !flag_wpa))
13731 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13734 } // anon namespace
13736 simple_ipa_opt_pass *
13737 make_pass_omp_simd_clone (gcc::context *ctxt)
13739 return new pass_omp_simd_clone (ctxt);
13742 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13743 adds their addresses and sizes to constructor-vector V_CTOR. */
13744 static void
13745 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13746 vec<constructor_elt, va_gc> *v_ctor)
13748 unsigned len = vec_safe_length (v_decls);
13749 for (unsigned i = 0; i < len; i++)
13751 tree it = (*v_decls)[i];
13752 bool is_function = TREE_CODE (it) != VAR_DECL;
13754 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13755 if (!is_function)
13756 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13757 fold_convert (const_ptr_type_node,
13758 DECL_SIZE_UNIT (it)));
13762 /* Create new symbols containing (address, size) pairs for global variables,
13763 marked with "omp declare target" attribute, as well as addresses for the
13764 functions, which are outlined offloading regions. */
13765 void
13766 omp_finish_file (void)
13768 unsigned num_funcs = vec_safe_length (offload_funcs);
13769 unsigned num_vars = vec_safe_length (offload_vars);
13771 if (num_funcs == 0 && num_vars == 0)
13772 return;
13774 if (targetm_common.have_named_sections)
13776 vec<constructor_elt, va_gc> *v_f, *v_v;
13777 vec_alloc (v_f, num_funcs);
13778 vec_alloc (v_v, num_vars * 2);
13780 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13781 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13783 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13784 num_vars * 2);
13785 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13786 num_funcs);
13787 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13788 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13789 tree ctor_v = build_constructor (vars_decl_type, v_v);
13790 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13791 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13792 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13793 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13794 get_identifier (".offload_func_table"),
13795 funcs_decl_type);
13796 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13797 get_identifier (".offload_var_table"),
13798 vars_decl_type);
13799 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13800 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13801 otherwise a joint table in a binary will contain padding between
13802 tables from multiple object files. */
13803 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13804 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13805 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13806 DECL_INITIAL (funcs_decl) = ctor_f;
13807 DECL_INITIAL (vars_decl) = ctor_v;
13808 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13809 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13811 varpool_node::finalize_decl (vars_decl);
13812 varpool_node::finalize_decl (funcs_decl);
13814 else
13816 for (unsigned i = 0; i < num_funcs; i++)
13818 tree it = (*offload_funcs)[i];
13819 targetm.record_offload_symbol (it);
13821 for (unsigned i = 0; i < num_vars; i++)
13823 tree it = (*offload_vars)[i];
13824 targetm.record_offload_symbol (it);
13829 #include "gt-omp-low.h"