[PR libgomp/64625] Remove __OFFLOAD_TABLE__ variable/formal parameter.
[official-gcc.git] / gcc / omp-low.c
blob15893109889b6ae6acffd241e13a9531f08944cf
1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "hash-set.h"
30 #include "machmode.h"
31 #include "vec.h"
32 #include "double-int.h"
33 #include "input.h"
34 #include "alias.h"
35 #include "symtab.h"
36 #include "wide-int.h"
37 #include "inchash.h"
38 #include "tree.h"
39 #include "fold-const.h"
40 #include "stringpool.h"
41 #include "stor-layout.h"
42 #include "rtl.h"
43 #include "predict.h"
44 #include "hard-reg-set.h"
45 #include "function.h"
46 #include "dominance.h"
47 #include "cfg.h"
48 #include "cfganal.h"
49 #include "basic-block.h"
50 #include "tree-ssa-alias.h"
51 #include "internal-fn.h"
52 #include "gimple-fold.h"
53 #include "gimple-expr.h"
54 #include "is-a.h"
55 #include "gimple.h"
56 #include "gimplify.h"
57 #include "gimple-iterator.h"
58 #include "gimplify-me.h"
59 #include "gimple-walk.h"
60 #include "tree-iterator.h"
61 #include "tree-inline.h"
62 #include "langhooks.h"
63 #include "diagnostic-core.h"
64 #include "gimple-ssa.h"
65 #include "hash-map.h"
66 #include "plugin-api.h"
67 #include "ipa-ref.h"
68 #include "cgraph.h"
69 #include "tree-cfg.h"
70 #include "tree-phinodes.h"
71 #include "ssa-iterators.h"
72 #include "tree-ssanames.h"
73 #include "tree-into-ssa.h"
74 #include "hashtab.h"
75 #include "flags.h"
76 #include "statistics.h"
77 #include "real.h"
78 #include "fixed-value.h"
79 #include "insn-config.h"
80 #include "expmed.h"
81 #include "dojump.h"
82 #include "explow.h"
83 #include "calls.h"
84 #include "emit-rtl.h"
85 #include "varasm.h"
86 #include "stmt.h"
87 #include "expr.h"
88 #include "tree-dfa.h"
89 #include "tree-ssa.h"
90 #include "tree-pass.h"
91 #include "except.h"
92 #include "splay-tree.h"
93 #include "insn-codes.h"
94 #include "optabs.h"
95 #include "cfgloop.h"
96 #include "target.h"
97 #include "common/common-target.h"
98 #include "omp-low.h"
99 #include "gimple-low.h"
100 #include "tree-cfgcleanup.h"
101 #include "pretty-print.h"
102 #include "alloc-pool.h"
103 #include "symbol-summary.h"
104 #include "ipa-prop.h"
105 #include "tree-nested.h"
106 #include "tree-eh.h"
107 #include "cilk.h"
108 #include "context.h"
109 #include "lto-section-names.h"
110 #include "gomp-constants.h"
113 /* Lowering of OMP parallel and workshare constructs proceeds in two
114 phases. The first phase scans the function looking for OMP statements
115 and then for variables that must be replaced to satisfy data sharing
116 clauses. The second phase expands code for the constructs, as well as
117 re-gimplifying things when variables have been replaced with complex
118 expressions.
120 Final code generation is done by pass_expand_omp. The flowgraph is
121 scanned for regions which are then moved to a new
122 function, to be invoked by the thread library, or offloaded. */
124 /* OMP region information. Every parallel and workshare
125 directive is enclosed between two markers, the OMP_* directive
126 and a corresponding OMP_RETURN statement. */
128 struct omp_region
130 /* The enclosing region. */
131 struct omp_region *outer;
133 /* First child region. */
134 struct omp_region *inner;
136 /* Next peer region. */
137 struct omp_region *next;
139 /* Block containing the omp directive as its last stmt. */
140 basic_block entry;
142 /* Block containing the OMP_RETURN as its last stmt. */
143 basic_block exit;
145 /* Block containing the OMP_CONTINUE as its last stmt. */
146 basic_block cont;
148 /* If this is a combined parallel+workshare region, this is a list
149 of additional arguments needed by the combined parallel+workshare
150 library call. */
151 vec<tree, va_gc> *ws_args;
153 /* The code for the omp directive of this region. */
154 enum gimple_code type;
156 /* Schedule kind, only used for OMP_FOR type regions. */
157 enum omp_clause_schedule_kind sched_kind;
159 /* True if this is a combined parallel+workshare region. */
160 bool is_combined_parallel;
163 /* Levels of parallelism as defined by OpenACC. Increasing numbers
164 correspond to deeper loop nesting levels. */
165 #define MASK_GANG 1
166 #define MASK_WORKER 2
167 #define MASK_VECTOR 4
169 /* Context structure. Used to store information about each parallel
170 directive in the code. */
172 typedef struct omp_context
174 /* This field must be at the beginning, as we do "inheritance": Some
175 callback functions for tree-inline.c (e.g., omp_copy_decl)
176 receive a copy_body_data pointer that is up-casted to an
177 omp_context pointer. */
178 copy_body_data cb;
180 /* The tree of contexts corresponding to the encountered constructs. */
181 struct omp_context *outer;
182 gimple stmt;
184 /* Map variables to fields in a structure that allows communication
185 between sending and receiving threads. */
186 splay_tree field_map;
187 tree record_type;
188 tree sender_decl;
189 tree receiver_decl;
191 /* These are used just by task contexts, if task firstprivate fn is
192 needed. srecord_type is used to communicate from the thread
193 that encountered the task construct to task firstprivate fn,
194 record_type is allocated by GOMP_task, initialized by task firstprivate
195 fn and passed to the task body fn. */
196 splay_tree sfield_map;
197 tree srecord_type;
199 /* A chain of variables to add to the top-level block surrounding the
200 construct. In the case of a parallel, this is in the child function. */
201 tree block_vars;
203 /* A map of reduction pointer variables. For accelerators, each
204 reduction variable is replaced with an array. Each thread, in turn,
205 is assigned to a slot on that array. */
206 splay_tree reduction_map;
208 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
209 barriers should jump to during omplower pass. */
210 tree cancel_label;
212 /* What to do with variables with implicitly determined sharing
213 attributes. */
214 enum omp_clause_default_kind default_kind;
216 /* Nesting depth of this context. Used to beautify error messages re
217 invalid gotos. The outermost ctx is depth 1, with depth 0 being
218 reserved for the main body of the function. */
219 int depth;
221 /* True if this parallel directive is nested within another. */
222 bool is_nested;
224 /* True if this construct can be cancelled. */
225 bool cancellable;
227 /* For OpenACC loops, a mask of gang, worker and vector used at
228 levels below this one. */
229 int gwv_below;
230 /* For OpenACC loops, a mask of gang, worker and vector used at
231 this level and above. For parallel and kernels clauses, a mask
232 indicating which of num_gangs/num_workers/num_vectors was used. */
233 int gwv_this;
234 } omp_context;
236 /* A structure holding the elements of:
237 for (V = N1; V cond N2; V += STEP) [...] */
239 struct omp_for_data_loop
241 tree v, n1, n2, step;
242 enum tree_code cond_code;
245 /* A structure describing the main elements of a parallel loop. */
247 struct omp_for_data
249 struct omp_for_data_loop loop;
250 tree chunk_size;
251 gomp_for *for_stmt;
252 tree pre, iter_type;
253 int collapse;
254 bool have_nowait, have_ordered;
255 enum omp_clause_schedule_kind sched_kind;
256 struct omp_for_data_loop *loops;
260 static splay_tree all_contexts;
261 static int taskreg_nesting_level;
262 static int target_nesting_level;
263 static struct omp_region *root_omp_region;
264 static bitmap task_shared_vars;
265 static vec<omp_context *> taskreg_contexts;
267 static void scan_omp (gimple_seq *, omp_context *);
268 static tree scan_omp_1_op (tree *, int *, void *);
270 #define WALK_SUBSTMTS \
271 case GIMPLE_BIND: \
272 case GIMPLE_TRY: \
273 case GIMPLE_CATCH: \
274 case GIMPLE_EH_FILTER: \
275 case GIMPLE_TRANSACTION: \
276 /* The sub-statements for these should be walked. */ \
277 *handled_ops_p = false; \
278 break;
280 /* Helper function to get the name of the array containing the partial
281 reductions for OpenACC reductions. */
282 static const char *
283 oacc_get_reduction_array_id (tree node)
285 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
286 int len = strlen ("OACC") + strlen (id);
287 char *temp_name = XALLOCAVEC (char, len + 1);
288 snprintf (temp_name, len + 1, "OACC%s", id);
289 return IDENTIFIER_POINTER (get_identifier (temp_name));
292 /* Determine the number of threads OpenACC threads used to determine the
293 size of the array of partial reductions. Currently, this is num_gangs
294 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
295 because it is independed of the device used. */
297 static tree
298 oacc_max_threads (omp_context *ctx)
300 tree nthreads, vector_length, gangs, clauses;
302 gangs = fold_convert (sizetype, integer_one_node);
303 vector_length = gangs;
305 /* The reduction clause may be nested inside a loop directive.
306 Scan for the innermost vector_length clause. */
307 for (omp_context *oc = ctx; oc; oc = oc->outer)
309 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
310 || (gimple_omp_target_kind (oc->stmt)
311 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
312 continue;
314 clauses = gimple_omp_target_clauses (oc->stmt);
316 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
317 if (vector_length)
318 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
319 sizetype,
320 OMP_CLAUSE_VECTOR_LENGTH_EXPR
321 (vector_length));
322 else
323 vector_length = fold_convert (sizetype, integer_one_node);
325 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
326 if (gangs)
327 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
328 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
329 else
330 gangs = fold_convert (sizetype, integer_one_node);
332 break;
335 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
337 return nthreads;
340 /* Holds offload tables with decls. */
341 vec<tree, va_gc> *offload_funcs, *offload_vars;
343 /* Convenience function for calling scan_omp_1_op on tree operands. */
345 static inline tree
346 scan_omp_op (tree *tp, omp_context *ctx)
348 struct walk_stmt_info wi;
350 memset (&wi, 0, sizeof (wi));
351 wi.info = ctx;
352 wi.want_locations = true;
354 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
357 static void lower_omp (gimple_seq *, omp_context *);
358 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
359 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
361 /* Find an OMP clause of type KIND within CLAUSES. */
363 tree
364 find_omp_clause (tree clauses, enum omp_clause_code kind)
366 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
367 if (OMP_CLAUSE_CODE (clauses) == kind)
368 return clauses;
370 return NULL_TREE;
373 /* Return true if CTX is for an omp parallel. */
375 static inline bool
376 is_parallel_ctx (omp_context *ctx)
378 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
382 /* Return true if CTX is for an omp task. */
384 static inline bool
385 is_task_ctx (omp_context *ctx)
387 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
391 /* Return true if CTX is for an omp parallel or omp task. */
393 static inline bool
394 is_taskreg_ctx (omp_context *ctx)
396 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
397 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
401 /* Return true if REGION is a combined parallel+workshare region. */
403 static inline bool
404 is_combined_parallel (struct omp_region *region)
406 return region->is_combined_parallel;
410 /* Extract the header elements of parallel loop FOR_STMT and store
411 them into *FD. */
413 static void
414 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
415 struct omp_for_data_loop *loops)
417 tree t, var, *collapse_iter, *collapse_count;
418 tree count = NULL_TREE, iter_type = long_integer_type_node;
419 struct omp_for_data_loop *loop;
420 int i;
421 struct omp_for_data_loop dummy_loop;
422 location_t loc = gimple_location (for_stmt);
423 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
424 bool distribute = gimple_omp_for_kind (for_stmt)
425 == GF_OMP_FOR_KIND_DISTRIBUTE;
427 fd->for_stmt = for_stmt;
428 fd->pre = NULL;
429 fd->collapse = gimple_omp_for_collapse (for_stmt);
430 if (fd->collapse > 1)
431 fd->loops = loops;
432 else
433 fd->loops = &fd->loop;
435 fd->have_nowait = distribute || simd;
436 fd->have_ordered = false;
437 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
438 fd->chunk_size = NULL_TREE;
439 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
440 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
441 collapse_iter = NULL;
442 collapse_count = NULL;
444 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
445 switch (OMP_CLAUSE_CODE (t))
447 case OMP_CLAUSE_NOWAIT:
448 fd->have_nowait = true;
449 break;
450 case OMP_CLAUSE_ORDERED:
451 fd->have_ordered = true;
452 break;
453 case OMP_CLAUSE_SCHEDULE:
454 gcc_assert (!distribute);
455 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
456 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
457 break;
458 case OMP_CLAUSE_DIST_SCHEDULE:
459 gcc_assert (distribute);
460 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
461 break;
462 case OMP_CLAUSE_COLLAPSE:
463 if (fd->collapse > 1)
465 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
466 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
468 break;
469 default:
470 break;
473 /* FIXME: for now map schedule(auto) to schedule(static).
474 There should be analysis to determine whether all iterations
475 are approximately the same amount of work (then schedule(static)
476 is best) or if it varies (then schedule(dynamic,N) is better). */
477 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
479 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
480 gcc_assert (fd->chunk_size == NULL);
482 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
483 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
484 gcc_assert (fd->chunk_size == NULL);
485 else if (fd->chunk_size == NULL)
487 /* We only need to compute a default chunk size for ordered
488 static loops and dynamic loops. */
489 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
490 || fd->have_ordered)
491 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
492 ? integer_zero_node : integer_one_node;
495 for (i = 0; i < fd->collapse; i++)
497 if (fd->collapse == 1)
498 loop = &fd->loop;
499 else if (loops != NULL)
500 loop = loops + i;
501 else
502 loop = &dummy_loop;
504 loop->v = gimple_omp_for_index (for_stmt, i);
505 gcc_assert (SSA_VAR_P (loop->v));
506 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
507 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
508 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
509 loop->n1 = gimple_omp_for_initial (for_stmt, i);
511 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
512 loop->n2 = gimple_omp_for_final (for_stmt, i);
513 switch (loop->cond_code)
515 case LT_EXPR:
516 case GT_EXPR:
517 break;
518 case NE_EXPR:
519 gcc_assert (gimple_omp_for_kind (for_stmt)
520 == GF_OMP_FOR_KIND_CILKSIMD
521 || (gimple_omp_for_kind (for_stmt)
522 == GF_OMP_FOR_KIND_CILKFOR));
523 break;
524 case LE_EXPR:
525 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
526 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
527 else
528 loop->n2 = fold_build2_loc (loc,
529 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
530 build_int_cst (TREE_TYPE (loop->n2), 1));
531 loop->cond_code = LT_EXPR;
532 break;
533 case GE_EXPR:
534 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
535 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
536 else
537 loop->n2 = fold_build2_loc (loc,
538 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
539 build_int_cst (TREE_TYPE (loop->n2), 1));
540 loop->cond_code = GT_EXPR;
541 break;
542 default:
543 gcc_unreachable ();
546 t = gimple_omp_for_incr (for_stmt, i);
547 gcc_assert (TREE_OPERAND (t, 0) == var);
548 switch (TREE_CODE (t))
550 case PLUS_EXPR:
551 loop->step = TREE_OPERAND (t, 1);
552 break;
553 case POINTER_PLUS_EXPR:
554 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
555 break;
556 case MINUS_EXPR:
557 loop->step = TREE_OPERAND (t, 1);
558 loop->step = fold_build1_loc (loc,
559 NEGATE_EXPR, TREE_TYPE (loop->step),
560 loop->step);
561 break;
562 default:
563 gcc_unreachable ();
566 if (simd
567 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
568 && !fd->have_ordered))
570 if (fd->collapse == 1)
571 iter_type = TREE_TYPE (loop->v);
572 else if (i == 0
573 || TYPE_PRECISION (iter_type)
574 < TYPE_PRECISION (TREE_TYPE (loop->v)))
575 iter_type
576 = build_nonstandard_integer_type
577 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
579 else if (iter_type != long_long_unsigned_type_node)
581 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
582 iter_type = long_long_unsigned_type_node;
583 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
584 && TYPE_PRECISION (TREE_TYPE (loop->v))
585 >= TYPE_PRECISION (iter_type))
587 tree n;
589 if (loop->cond_code == LT_EXPR)
590 n = fold_build2_loc (loc,
591 PLUS_EXPR, TREE_TYPE (loop->v),
592 loop->n2, loop->step);
593 else
594 n = loop->n1;
595 if (TREE_CODE (n) != INTEGER_CST
596 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
597 iter_type = long_long_unsigned_type_node;
599 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
600 > TYPE_PRECISION (iter_type))
602 tree n1, n2;
604 if (loop->cond_code == LT_EXPR)
606 n1 = loop->n1;
607 n2 = fold_build2_loc (loc,
608 PLUS_EXPR, TREE_TYPE (loop->v),
609 loop->n2, loop->step);
611 else
613 n1 = fold_build2_loc (loc,
614 MINUS_EXPR, TREE_TYPE (loop->v),
615 loop->n2, loop->step);
616 n2 = loop->n1;
618 if (TREE_CODE (n1) != INTEGER_CST
619 || TREE_CODE (n2) != INTEGER_CST
620 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
621 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
622 iter_type = long_long_unsigned_type_node;
626 if (collapse_count && *collapse_count == NULL)
628 t = fold_binary (loop->cond_code, boolean_type_node,
629 fold_convert (TREE_TYPE (loop->v), loop->n1),
630 fold_convert (TREE_TYPE (loop->v), loop->n2));
631 if (t && integer_zerop (t))
632 count = build_zero_cst (long_long_unsigned_type_node);
633 else if ((i == 0 || count != NULL_TREE)
634 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
635 && TREE_CONSTANT (loop->n1)
636 && TREE_CONSTANT (loop->n2)
637 && TREE_CODE (loop->step) == INTEGER_CST)
639 tree itype = TREE_TYPE (loop->v);
641 if (POINTER_TYPE_P (itype))
642 itype = signed_type_for (itype);
643 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
644 t = fold_build2_loc (loc,
645 PLUS_EXPR, itype,
646 fold_convert_loc (loc, itype, loop->step), t);
647 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
648 fold_convert_loc (loc, itype, loop->n2));
649 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
650 fold_convert_loc (loc, itype, loop->n1));
651 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
652 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
653 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
654 fold_build1_loc (loc, NEGATE_EXPR, itype,
655 fold_convert_loc (loc, itype,
656 loop->step)));
657 else
658 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
659 fold_convert_loc (loc, itype, loop->step));
660 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
661 if (count != NULL_TREE)
662 count = fold_build2_loc (loc,
663 MULT_EXPR, long_long_unsigned_type_node,
664 count, t);
665 else
666 count = t;
667 if (TREE_CODE (count) != INTEGER_CST)
668 count = NULL_TREE;
670 else if (count && !integer_zerop (count))
671 count = NULL_TREE;
675 if (count
676 && !simd
677 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
678 || fd->have_ordered))
680 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
681 iter_type = long_long_unsigned_type_node;
682 else
683 iter_type = long_integer_type_node;
685 else if (collapse_iter && *collapse_iter != NULL)
686 iter_type = TREE_TYPE (*collapse_iter);
687 fd->iter_type = iter_type;
688 if (collapse_iter && *collapse_iter == NULL)
689 *collapse_iter = create_tmp_var (iter_type, ".iter");
690 if (collapse_count && *collapse_count == NULL)
692 if (count)
693 *collapse_count = fold_convert_loc (loc, iter_type, count);
694 else
695 *collapse_count = create_tmp_var (iter_type, ".count");
698 if (fd->collapse > 1)
700 fd->loop.v = *collapse_iter;
701 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
702 fd->loop.n2 = *collapse_count;
703 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
704 fd->loop.cond_code = LT_EXPR;
707 /* For OpenACC loops, force a chunk size of one, as this avoids the default
708 scheduling where several subsequent iterations are being executed by the
709 same thread. */
710 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
712 gcc_assert (fd->chunk_size == NULL_TREE);
713 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
718 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
719 is the immediate dominator of PAR_ENTRY_BB, return true if there
720 are no data dependencies that would prevent expanding the parallel
721 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
723 When expanding a combined parallel+workshare region, the call to
724 the child function may need additional arguments in the case of
725 GIMPLE_OMP_FOR regions. In some cases, these arguments are
726 computed out of variables passed in from the parent to the child
727 via 'struct .omp_data_s'. For instance:
729 #pragma omp parallel for schedule (guided, i * 4)
730 for (j ...)
732 Is lowered into:
734 # BLOCK 2 (PAR_ENTRY_BB)
735 .omp_data_o.i = i;
736 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
738 # BLOCK 3 (WS_ENTRY_BB)
739 .omp_data_i = &.omp_data_o;
740 D.1667 = .omp_data_i->i;
741 D.1598 = D.1667 * 4;
742 #pragma omp for schedule (guided, D.1598)
744 When we outline the parallel region, the call to the child function
745 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
746 that value is computed *after* the call site. So, in principle we
747 cannot do the transformation.
749 To see whether the code in WS_ENTRY_BB blocks the combined
750 parallel+workshare call, we collect all the variables used in the
751 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
752 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
753 call.
755 FIXME. If we had the SSA form built at this point, we could merely
756 hoist the code in block 3 into block 2 and be done with it. But at
757 this point we don't have dataflow information and though we could
758 hack something up here, it is really not worth the aggravation. */
760 static bool
761 workshare_safe_to_combine_p (basic_block ws_entry_bb)
763 struct omp_for_data fd;
764 gimple ws_stmt = last_stmt (ws_entry_bb);
766 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
767 return true;
769 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
771 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
773 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
774 return false;
775 if (fd.iter_type != long_integer_type_node)
776 return false;
778 /* FIXME. We give up too easily here. If any of these arguments
779 are not constants, they will likely involve variables that have
780 been mapped into fields of .omp_data_s for sharing with the child
781 function. With appropriate data flow, it would be possible to
782 see through this. */
783 if (!is_gimple_min_invariant (fd.loop.n1)
784 || !is_gimple_min_invariant (fd.loop.n2)
785 || !is_gimple_min_invariant (fd.loop.step)
786 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
787 return false;
789 return true;
793 /* Collect additional arguments needed to emit a combined
794 parallel+workshare call. WS_STMT is the workshare directive being
795 expanded. */
797 static vec<tree, va_gc> *
798 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
800 tree t;
801 location_t loc = gimple_location (ws_stmt);
802 vec<tree, va_gc> *ws_args;
804 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
806 struct omp_for_data fd;
807 tree n1, n2;
809 extract_omp_for_data (for_stmt, &fd, NULL);
810 n1 = fd.loop.n1;
811 n2 = fd.loop.n2;
813 if (gimple_omp_for_combined_into_p (for_stmt))
815 tree innerc
816 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
817 OMP_CLAUSE__LOOPTEMP_);
818 gcc_assert (innerc);
819 n1 = OMP_CLAUSE_DECL (innerc);
820 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
821 OMP_CLAUSE__LOOPTEMP_);
822 gcc_assert (innerc);
823 n2 = OMP_CLAUSE_DECL (innerc);
826 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
828 t = fold_convert_loc (loc, long_integer_type_node, n1);
829 ws_args->quick_push (t);
831 t = fold_convert_loc (loc, long_integer_type_node, n2);
832 ws_args->quick_push (t);
834 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
835 ws_args->quick_push (t);
837 if (fd.chunk_size)
839 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
840 ws_args->quick_push (t);
843 return ws_args;
845 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
847 /* Number of sections is equal to the number of edges from the
848 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
849 the exit of the sections region. */
850 basic_block bb = single_succ (gimple_bb (ws_stmt));
851 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
852 vec_alloc (ws_args, 1);
853 ws_args->quick_push (t);
854 return ws_args;
857 gcc_unreachable ();
861 /* Discover whether REGION is a combined parallel+workshare region. */
863 static void
864 determine_parallel_type (struct omp_region *region)
866 basic_block par_entry_bb, par_exit_bb;
867 basic_block ws_entry_bb, ws_exit_bb;
869 if (region == NULL || region->inner == NULL
870 || region->exit == NULL || region->inner->exit == NULL
871 || region->inner->cont == NULL)
872 return;
874 /* We only support parallel+for and parallel+sections. */
875 if (region->type != GIMPLE_OMP_PARALLEL
876 || (region->inner->type != GIMPLE_OMP_FOR
877 && region->inner->type != GIMPLE_OMP_SECTIONS))
878 return;
880 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
881 WS_EXIT_BB -> PAR_EXIT_BB. */
882 par_entry_bb = region->entry;
883 par_exit_bb = region->exit;
884 ws_entry_bb = region->inner->entry;
885 ws_exit_bb = region->inner->exit;
887 if (single_succ (par_entry_bb) == ws_entry_bb
888 && single_succ (ws_exit_bb) == par_exit_bb
889 && workshare_safe_to_combine_p (ws_entry_bb)
890 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
891 || (last_and_only_stmt (ws_entry_bb)
892 && last_and_only_stmt (par_exit_bb))))
894 gimple par_stmt = last_stmt (par_entry_bb);
895 gimple ws_stmt = last_stmt (ws_entry_bb);
897 if (region->inner->type == GIMPLE_OMP_FOR)
899 /* If this is a combined parallel loop, we need to determine
900 whether or not to use the combined library calls. There
901 are two cases where we do not apply the transformation:
902 static loops and any kind of ordered loop. In the first
903 case, we already open code the loop so there is no need
904 to do anything else. In the latter case, the combined
905 parallel loop call would still need extra synchronization
906 to implement ordered semantics, so there would not be any
907 gain in using the combined call. */
908 tree clauses = gimple_omp_for_clauses (ws_stmt);
909 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
910 if (c == NULL
911 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
912 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
914 region->is_combined_parallel = false;
915 region->inner->is_combined_parallel = false;
916 return;
920 region->is_combined_parallel = true;
921 region->inner->is_combined_parallel = true;
922 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
927 /* Return true if EXPR is variable sized. */
929 static inline bool
930 is_variable_sized (const_tree expr)
932 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
935 /* Return true if DECL is a reference type. */
937 static inline bool
938 is_reference (tree decl)
940 return lang_hooks.decls.omp_privatize_by_reference (decl);
943 /* Return the type of a decl. If the decl is reference type,
944 return its base type. */
945 static inline tree
946 get_base_type (tree decl)
948 tree type = TREE_TYPE (decl);
949 if (is_reference (decl))
950 type = TREE_TYPE (type);
951 return type;
954 /* Lookup variables. The "maybe" form
955 allows for the variable form to not have been entered, otherwise we
956 assert that the variable must have been entered. */
958 static inline tree
959 lookup_decl (tree var, omp_context *ctx)
961 tree *n = ctx->cb.decl_map->get (var);
962 return *n;
965 static inline tree
966 maybe_lookup_decl (const_tree var, omp_context *ctx)
968 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
969 return n ? *n : NULL_TREE;
972 static inline tree
973 lookup_field (tree var, omp_context *ctx)
975 splay_tree_node n;
976 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
977 return (tree) n->value;
980 static inline tree
981 lookup_sfield (tree var, omp_context *ctx)
983 splay_tree_node n;
984 n = splay_tree_lookup (ctx->sfield_map
985 ? ctx->sfield_map : ctx->field_map,
986 (splay_tree_key) var);
987 return (tree) n->value;
990 static inline tree
991 maybe_lookup_field (tree var, omp_context *ctx)
993 splay_tree_node n;
994 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
995 return n ? (tree) n->value : NULL_TREE;
998 static inline tree
999 lookup_oacc_reduction (const char *id, omp_context *ctx)
1001 splay_tree_node n;
1002 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
1003 return (tree) n->value;
1006 static inline tree
1007 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
1009 splay_tree_node n = NULL;
1010 if (ctx->reduction_map)
1011 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
1012 return n ? (tree) n->value : NULL_TREE;
1015 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1016 the parallel context if DECL is to be shared. */
1018 static bool
1019 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1021 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1022 return true;
1024 /* We can only use copy-in/copy-out semantics for shared variables
1025 when we know the value is not accessible from an outer scope. */
1026 if (shared_ctx)
1028 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1030 /* ??? Trivially accessible from anywhere. But why would we even
1031 be passing an address in this case? Should we simply assert
1032 this to be false, or should we have a cleanup pass that removes
1033 these from the list of mappings? */
1034 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1035 return true;
1037 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1038 without analyzing the expression whether or not its location
1039 is accessible to anyone else. In the case of nested parallel
1040 regions it certainly may be. */
1041 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1042 return true;
1044 /* Do not use copy-in/copy-out for variables that have their
1045 address taken. */
1046 if (TREE_ADDRESSABLE (decl))
1047 return true;
1049 /* lower_send_shared_vars only uses copy-in, but not copy-out
1050 for these. */
1051 if (TREE_READONLY (decl)
1052 || ((TREE_CODE (decl) == RESULT_DECL
1053 || TREE_CODE (decl) == PARM_DECL)
1054 && DECL_BY_REFERENCE (decl)))
1055 return false;
1057 /* Disallow copy-in/out in nested parallel if
1058 decl is shared in outer parallel, otherwise
1059 each thread could store the shared variable
1060 in its own copy-in location, making the
1061 variable no longer really shared. */
1062 if (shared_ctx->is_nested)
1064 omp_context *up;
1066 for (up = shared_ctx->outer; up; up = up->outer)
1067 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1068 break;
1070 if (up)
1072 tree c;
1074 for (c = gimple_omp_taskreg_clauses (up->stmt);
1075 c; c = OMP_CLAUSE_CHAIN (c))
1076 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1077 && OMP_CLAUSE_DECL (c) == decl)
1078 break;
1080 if (c)
1081 goto maybe_mark_addressable_and_ret;
1085 /* For tasks avoid using copy-in/out. As tasks can be
1086 deferred or executed in different thread, when GOMP_task
1087 returns, the task hasn't necessarily terminated. */
1088 if (is_task_ctx (shared_ctx))
1090 tree outer;
1091 maybe_mark_addressable_and_ret:
1092 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1093 if (is_gimple_reg (outer))
1095 /* Taking address of OUTER in lower_send_shared_vars
1096 might need regimplification of everything that uses the
1097 variable. */
1098 if (!task_shared_vars)
1099 task_shared_vars = BITMAP_ALLOC (NULL);
1100 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1101 TREE_ADDRESSABLE (outer) = 1;
1103 return true;
1107 return false;
1110 /* Construct a new automatic decl similar to VAR. */
1112 static tree
1113 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1115 tree copy = copy_var_decl (var, name, type);
1117 DECL_CONTEXT (copy) = current_function_decl;
1118 DECL_CHAIN (copy) = ctx->block_vars;
1119 ctx->block_vars = copy;
1121 return copy;
1124 static tree
1125 omp_copy_decl_1 (tree var, omp_context *ctx)
1127 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1130 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1131 as appropriate. */
1132 static tree
1133 omp_build_component_ref (tree obj, tree field)
1135 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1136 if (TREE_THIS_VOLATILE (field))
1137 TREE_THIS_VOLATILE (ret) |= 1;
1138 if (TREE_READONLY (field))
1139 TREE_READONLY (ret) |= 1;
1140 return ret;
1143 /* Build tree nodes to access the field for VAR on the receiver side. */
1145 static tree
1146 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1148 tree x, field = lookup_field (var, ctx);
1150 /* If the receiver record type was remapped in the child function,
1151 remap the field into the new record type. */
1152 x = maybe_lookup_field (field, ctx);
1153 if (x != NULL)
1154 field = x;
1156 x = build_simple_mem_ref (ctx->receiver_decl);
1157 x = omp_build_component_ref (x, field);
1158 if (by_ref)
1159 x = build_simple_mem_ref (x);
1161 return x;
1164 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1165 of a parallel, this is a component reference; for workshare constructs
1166 this is some variable. */
1168 static tree
1169 build_outer_var_ref (tree var, omp_context *ctx)
1171 tree x;
1173 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1174 x = var;
1175 else if (is_variable_sized (var))
1177 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1178 x = build_outer_var_ref (x, ctx);
1179 x = build_simple_mem_ref (x);
1181 else if (is_taskreg_ctx (ctx))
1183 bool by_ref = use_pointer_for_field (var, NULL);
1184 x = build_receiver_ref (var, by_ref, ctx);
1186 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1187 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1189 /* #pragma omp simd isn't a worksharing construct, and can reference even
1190 private vars in its linear etc. clauses. */
1191 x = NULL_TREE;
1192 if (ctx->outer && is_taskreg_ctx (ctx))
1193 x = lookup_decl (var, ctx->outer);
1194 else if (ctx->outer)
1195 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1196 if (x == NULL_TREE)
1197 x = var;
1199 else if (ctx->outer)
1200 x = lookup_decl (var, ctx->outer);
1201 else if (is_reference (var))
1202 /* This can happen with orphaned constructs. If var is reference, it is
1203 possible it is shared and as such valid. */
1204 x = var;
1205 else
1206 gcc_unreachable ();
1208 if (is_reference (var))
1209 x = build_simple_mem_ref (x);
1211 return x;
1214 /* Build tree nodes to access the field for VAR on the sender side. */
1216 static tree
1217 build_sender_ref (tree var, omp_context *ctx)
1219 tree field = lookup_sfield (var, ctx);
1220 return omp_build_component_ref (ctx->sender_decl, field);
1223 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1225 static void
1226 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1228 tree field, type, sfield = NULL_TREE;
1230 gcc_assert ((mask & 1) == 0
1231 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1232 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1233 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1234 gcc_assert ((mask & 3) == 3
1235 || !is_gimple_omp_oacc (ctx->stmt));
1237 type = TREE_TYPE (var);
1238 if (mask & 4)
1240 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1241 type = build_pointer_type (build_pointer_type (type));
1243 else if (by_ref)
1244 type = build_pointer_type (type);
1245 else if ((mask & 3) == 1 && is_reference (var))
1246 type = TREE_TYPE (type);
1248 field = build_decl (DECL_SOURCE_LOCATION (var),
1249 FIELD_DECL, DECL_NAME (var), type);
1251 /* Remember what variable this field was created for. This does have a
1252 side effect of making dwarf2out ignore this member, so for helpful
1253 debugging we clear it later in delete_omp_context. */
1254 DECL_ABSTRACT_ORIGIN (field) = var;
1255 if (type == TREE_TYPE (var))
1257 DECL_ALIGN (field) = DECL_ALIGN (var);
1258 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1259 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1261 else
1262 DECL_ALIGN (field) = TYPE_ALIGN (type);
1264 if ((mask & 3) == 3)
1266 insert_field_into_struct (ctx->record_type, field);
1267 if (ctx->srecord_type)
1269 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1270 FIELD_DECL, DECL_NAME (var), type);
1271 DECL_ABSTRACT_ORIGIN (sfield) = var;
1272 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1273 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1274 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1275 insert_field_into_struct (ctx->srecord_type, sfield);
1278 else
1280 if (ctx->srecord_type == NULL_TREE)
1282 tree t;
1284 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1285 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1286 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1288 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1289 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1290 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1291 insert_field_into_struct (ctx->srecord_type, sfield);
1292 splay_tree_insert (ctx->sfield_map,
1293 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1294 (splay_tree_value) sfield);
1297 sfield = field;
1298 insert_field_into_struct ((mask & 1) ? ctx->record_type
1299 : ctx->srecord_type, field);
1302 if (mask & 1)
1303 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1304 (splay_tree_value) field);
1305 if ((mask & 2) && ctx->sfield_map)
1306 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1307 (splay_tree_value) sfield);
1310 static tree
1311 install_var_local (tree var, omp_context *ctx)
1313 tree new_var = omp_copy_decl_1 (var, ctx);
1314 insert_decl_map (&ctx->cb, var, new_var);
1315 return new_var;
1318 /* Adjust the replacement for DECL in CTX for the new context. This means
1319 copying the DECL_VALUE_EXPR, and fixing up the type. */
1321 static void
1322 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1324 tree new_decl, size;
1326 new_decl = lookup_decl (decl, ctx);
1328 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1330 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1331 && DECL_HAS_VALUE_EXPR_P (decl))
1333 tree ve = DECL_VALUE_EXPR (decl);
1334 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1335 SET_DECL_VALUE_EXPR (new_decl, ve);
1336 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1339 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1341 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1342 if (size == error_mark_node)
1343 size = TYPE_SIZE (TREE_TYPE (new_decl));
1344 DECL_SIZE (new_decl) = size;
1346 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1347 if (size == error_mark_node)
1348 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1349 DECL_SIZE_UNIT (new_decl) = size;
1353 /* The callback for remap_decl. Search all containing contexts for a
1354 mapping of the variable; this avoids having to duplicate the splay
1355 tree ahead of time. We know a mapping doesn't already exist in the
1356 given context. Create new mappings to implement default semantics. */
1358 static tree
1359 omp_copy_decl (tree var, copy_body_data *cb)
1361 omp_context *ctx = (omp_context *) cb;
1362 tree new_var;
1364 if (TREE_CODE (var) == LABEL_DECL)
1366 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1367 DECL_CONTEXT (new_var) = current_function_decl;
1368 insert_decl_map (&ctx->cb, var, new_var);
1369 return new_var;
1372 while (!is_taskreg_ctx (ctx))
1374 ctx = ctx->outer;
1375 if (ctx == NULL)
1376 return var;
1377 new_var = maybe_lookup_decl (var, ctx);
1378 if (new_var)
1379 return new_var;
1382 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1383 return var;
1385 return error_mark_node;
1389 /* Debugging dumps for parallel regions. */
1390 void dump_omp_region (FILE *, struct omp_region *, int);
1391 void debug_omp_region (struct omp_region *);
1392 void debug_all_omp_regions (void);
1394 /* Dump the parallel region tree rooted at REGION. */
1396 void
1397 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1399 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1400 gimple_code_name[region->type]);
1402 if (region->inner)
1403 dump_omp_region (file, region->inner, indent + 4);
1405 if (region->cont)
1407 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1408 region->cont->index);
1411 if (region->exit)
1412 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1413 region->exit->index);
1414 else
1415 fprintf (file, "%*s[no exit marker]\n", indent, "");
1417 if (region->next)
1418 dump_omp_region (file, region->next, indent);
1421 DEBUG_FUNCTION void
1422 debug_omp_region (struct omp_region *region)
1424 dump_omp_region (stderr, region, 0);
1427 DEBUG_FUNCTION void
1428 debug_all_omp_regions (void)
1430 dump_omp_region (stderr, root_omp_region, 0);
1434 /* Create a new parallel region starting at STMT inside region PARENT. */
1436 static struct omp_region *
1437 new_omp_region (basic_block bb, enum gimple_code type,
1438 struct omp_region *parent)
1440 struct omp_region *region = XCNEW (struct omp_region);
1442 region->outer = parent;
1443 region->entry = bb;
1444 region->type = type;
1446 if (parent)
1448 /* This is a nested region. Add it to the list of inner
1449 regions in PARENT. */
1450 region->next = parent->inner;
1451 parent->inner = region;
1453 else
1455 /* This is a toplevel region. Add it to the list of toplevel
1456 regions in ROOT_OMP_REGION. */
1457 region->next = root_omp_region;
1458 root_omp_region = region;
1461 return region;
1464 /* Release the memory associated with the region tree rooted at REGION. */
1466 static void
1467 free_omp_region_1 (struct omp_region *region)
1469 struct omp_region *i, *n;
1471 for (i = region->inner; i ; i = n)
1473 n = i->next;
1474 free_omp_region_1 (i);
1477 free (region);
1480 /* Release the memory for the entire omp region tree. */
1482 void
1483 free_omp_regions (void)
1485 struct omp_region *r, *n;
1486 for (r = root_omp_region; r ; r = n)
1488 n = r->next;
1489 free_omp_region_1 (r);
1491 root_omp_region = NULL;
1495 /* Create a new context, with OUTER_CTX being the surrounding context. */
1497 static omp_context *
1498 new_omp_context (gimple stmt, omp_context *outer_ctx)
1500 omp_context *ctx = XCNEW (omp_context);
1502 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1503 (splay_tree_value) ctx);
1504 ctx->stmt = stmt;
1506 if (outer_ctx)
1508 ctx->outer = outer_ctx;
1509 ctx->cb = outer_ctx->cb;
1510 ctx->cb.block = NULL;
1511 ctx->depth = outer_ctx->depth + 1;
1512 ctx->reduction_map = outer_ctx->reduction_map;
1514 else
1516 ctx->cb.src_fn = current_function_decl;
1517 ctx->cb.dst_fn = current_function_decl;
1518 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1519 gcc_checking_assert (ctx->cb.src_node);
1520 ctx->cb.dst_node = ctx->cb.src_node;
1521 ctx->cb.src_cfun = cfun;
1522 ctx->cb.copy_decl = omp_copy_decl;
1523 ctx->cb.eh_lp_nr = 0;
1524 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1525 ctx->depth = 1;
1528 ctx->cb.decl_map = new hash_map<tree, tree>;
1530 return ctx;
1533 static gimple_seq maybe_catch_exception (gimple_seq);
1535 /* Finalize task copyfn. */
1537 static void
1538 finalize_task_copyfn (gomp_task *task_stmt)
1540 struct function *child_cfun;
1541 tree child_fn;
1542 gimple_seq seq = NULL, new_seq;
1543 gbind *bind;
1545 child_fn = gimple_omp_task_copy_fn (task_stmt);
1546 if (child_fn == NULL_TREE)
1547 return;
1549 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1550 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1552 push_cfun (child_cfun);
1553 bind = gimplify_body (child_fn, false);
1554 gimple_seq_add_stmt (&seq, bind);
1555 new_seq = maybe_catch_exception (seq);
1556 if (new_seq != seq)
1558 bind = gimple_build_bind (NULL, new_seq, NULL);
1559 seq = NULL;
1560 gimple_seq_add_stmt (&seq, bind);
1562 gimple_set_body (child_fn, seq);
1563 pop_cfun ();
1565 /* Inform the callgraph about the new function. */
1566 cgraph_node::add_new_function (child_fn, false);
1569 /* Destroy a omp_context data structures. Called through the splay tree
1570 value delete callback. */
1572 static void
1573 delete_omp_context (splay_tree_value value)
1575 omp_context *ctx = (omp_context *) value;
1577 delete ctx->cb.decl_map;
1579 if (ctx->field_map)
1580 splay_tree_delete (ctx->field_map);
1581 if (ctx->sfield_map)
1582 splay_tree_delete (ctx->sfield_map);
1583 if (ctx->reduction_map
1584 /* Shared over several omp_contexts. */
1585 && (ctx->outer == NULL
1586 || ctx->reduction_map != ctx->outer->reduction_map))
1587 splay_tree_delete (ctx->reduction_map);
1589 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1590 it produces corrupt debug information. */
1591 if (ctx->record_type)
1593 tree t;
1594 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1595 DECL_ABSTRACT_ORIGIN (t) = NULL;
1597 if (ctx->srecord_type)
1599 tree t;
1600 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1601 DECL_ABSTRACT_ORIGIN (t) = NULL;
1604 if (is_task_ctx (ctx))
1605 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1607 XDELETE (ctx);
1610 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1611 context. */
1613 static void
1614 fixup_child_record_type (omp_context *ctx)
1616 tree f, type = ctx->record_type;
1618 /* ??? It isn't sufficient to just call remap_type here, because
1619 variably_modified_type_p doesn't work the way we expect for
1620 record types. Testing each field for whether it needs remapping
1621 and creating a new record by hand works, however. */
1622 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1623 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1624 break;
1625 if (f)
1627 tree name, new_fields = NULL;
1629 type = lang_hooks.types.make_type (RECORD_TYPE);
1630 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1631 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1632 TYPE_DECL, name, type);
1633 TYPE_NAME (type) = name;
1635 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1637 tree new_f = copy_node (f);
1638 DECL_CONTEXT (new_f) = type;
1639 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1640 DECL_CHAIN (new_f) = new_fields;
1641 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1642 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1643 &ctx->cb, NULL);
1644 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1645 &ctx->cb, NULL);
1646 new_fields = new_f;
1648 /* Arrange to be able to look up the receiver field
1649 given the sender field. */
1650 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1651 (splay_tree_value) new_f);
1653 TYPE_FIELDS (type) = nreverse (new_fields);
1654 layout_type (type);
1657 TREE_TYPE (ctx->receiver_decl)
1658 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1661 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1662 specified by CLAUSES. */
1664 static void
1665 scan_sharing_clauses (tree clauses, omp_context *ctx)
1667 tree c, decl;
1668 bool scan_array_reductions = false;
1670 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1672 bool by_ref;
1674 switch (OMP_CLAUSE_CODE (c))
1676 case OMP_CLAUSE_PRIVATE:
1677 decl = OMP_CLAUSE_DECL (c);
1678 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1679 goto do_private;
1680 else if (!is_variable_sized (decl))
1681 install_var_local (decl, ctx);
1682 break;
1684 case OMP_CLAUSE_SHARED:
1685 decl = OMP_CLAUSE_DECL (c);
1686 /* Ignore shared directives in teams construct. */
1687 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1689 /* Global variables don't need to be copied,
1690 the receiver side will use them directly. */
1691 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1692 if (is_global_var (odecl))
1693 break;
1694 insert_decl_map (&ctx->cb, decl, odecl);
1695 break;
1697 gcc_assert (is_taskreg_ctx (ctx));
1698 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1699 || !is_variable_sized (decl));
1700 /* Global variables don't need to be copied,
1701 the receiver side will use them directly. */
1702 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1703 break;
1704 by_ref = use_pointer_for_field (decl, ctx);
1705 if (! TREE_READONLY (decl)
1706 || TREE_ADDRESSABLE (decl)
1707 || by_ref
1708 || is_reference (decl))
1710 install_var_field (decl, by_ref, 3, ctx);
1711 install_var_local (decl, ctx);
1712 break;
1714 /* We don't need to copy const scalar vars back. */
1715 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1716 goto do_private;
1718 case OMP_CLAUSE_LASTPRIVATE:
1719 /* Let the corresponding firstprivate clause create
1720 the variable. */
1721 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1722 break;
1723 /* FALLTHRU */
1725 case OMP_CLAUSE_FIRSTPRIVATE:
1726 if (is_gimple_omp_oacc (ctx->stmt))
1728 sorry ("clause not supported yet");
1729 break;
1731 /* FALLTHRU */
1732 case OMP_CLAUSE_REDUCTION:
1733 case OMP_CLAUSE_LINEAR:
1734 decl = OMP_CLAUSE_DECL (c);
1735 do_private:
1736 if (is_variable_sized (decl))
1738 if (is_task_ctx (ctx))
1739 install_var_field (decl, false, 1, ctx);
1740 break;
1742 else if (is_taskreg_ctx (ctx))
1744 bool global
1745 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1746 by_ref = use_pointer_for_field (decl, NULL);
1748 if (is_task_ctx (ctx)
1749 && (global || by_ref || is_reference (decl)))
1751 install_var_field (decl, false, 1, ctx);
1752 if (!global)
1753 install_var_field (decl, by_ref, 2, ctx);
1755 else if (!global)
1756 install_var_field (decl, by_ref, 3, ctx);
1758 install_var_local (decl, ctx);
1759 if (is_gimple_omp_oacc (ctx->stmt)
1760 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1762 /* Create a decl for the reduction array. */
1763 tree var = OMP_CLAUSE_DECL (c);
1764 tree type = get_base_type (var);
1765 tree ptype = build_pointer_type (type);
1766 tree array = create_tmp_var (ptype,
1767 oacc_get_reduction_array_id (var));
1768 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1769 install_var_field (array, true, 3, c);
1770 install_var_local (array, c);
1772 /* Insert it into the current context. */
1773 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1774 oacc_get_reduction_array_id (var),
1775 (splay_tree_value) array);
1776 splay_tree_insert (ctx->reduction_map,
1777 (splay_tree_key) array,
1778 (splay_tree_value) array);
1780 break;
1782 case OMP_CLAUSE__LOOPTEMP_:
1783 gcc_assert (is_parallel_ctx (ctx));
1784 decl = OMP_CLAUSE_DECL (c);
1785 install_var_field (decl, false, 3, ctx);
1786 install_var_local (decl, ctx);
1787 break;
1789 case OMP_CLAUSE_COPYPRIVATE:
1790 case OMP_CLAUSE_COPYIN:
1791 decl = OMP_CLAUSE_DECL (c);
1792 by_ref = use_pointer_for_field (decl, NULL);
1793 install_var_field (decl, by_ref, 3, ctx);
1794 break;
1796 case OMP_CLAUSE_DEFAULT:
1797 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1798 break;
1800 case OMP_CLAUSE_FINAL:
1801 case OMP_CLAUSE_IF:
1802 case OMP_CLAUSE_NUM_THREADS:
1803 case OMP_CLAUSE_NUM_TEAMS:
1804 case OMP_CLAUSE_THREAD_LIMIT:
1805 case OMP_CLAUSE_DEVICE:
1806 case OMP_CLAUSE_SCHEDULE:
1807 case OMP_CLAUSE_DIST_SCHEDULE:
1808 case OMP_CLAUSE_DEPEND:
1809 case OMP_CLAUSE__CILK_FOR_COUNT_:
1810 case OMP_CLAUSE_NUM_GANGS:
1811 case OMP_CLAUSE_NUM_WORKERS:
1812 case OMP_CLAUSE_VECTOR_LENGTH:
1813 if (ctx->outer)
1814 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1815 break;
1817 case OMP_CLAUSE_TO:
1818 case OMP_CLAUSE_FROM:
1819 case OMP_CLAUSE_MAP:
1820 if (ctx->outer)
1821 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1822 decl = OMP_CLAUSE_DECL (c);
1823 /* Global variables with "omp declare target" attribute
1824 don't need to be copied, the receiver side will use them
1825 directly. */
1826 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1827 && DECL_P (decl)
1828 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1829 && varpool_node::get_create (decl)->offloadable)
1830 break;
1831 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1832 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
1834 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1835 not offloaded; there is nothing to map for those. */
1836 if (!is_gimple_omp_offloaded (ctx->stmt)
1837 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1838 break;
1840 if (DECL_P (decl))
1842 if (DECL_SIZE (decl)
1843 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1845 tree decl2 = DECL_VALUE_EXPR (decl);
1846 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1847 decl2 = TREE_OPERAND (decl2, 0);
1848 gcc_assert (DECL_P (decl2));
1849 install_var_field (decl2, true, 3, ctx);
1850 install_var_local (decl2, ctx);
1851 install_var_local (decl, ctx);
1853 else
1855 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1856 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1857 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1858 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1859 install_var_field (decl, true, 7, ctx);
1860 else
1861 install_var_field (decl, true, 3, ctx);
1862 if (is_gimple_omp_offloaded (ctx->stmt))
1863 install_var_local (decl, ctx);
1866 else
1868 tree base = get_base_address (decl);
1869 tree nc = OMP_CLAUSE_CHAIN (c);
1870 if (DECL_P (base)
1871 && nc != NULL_TREE
1872 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1873 && OMP_CLAUSE_DECL (nc) == base
1874 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1875 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1877 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1878 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1880 else
1882 if (ctx->outer)
1884 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1885 decl = OMP_CLAUSE_DECL (c);
1887 gcc_assert (!splay_tree_lookup (ctx->field_map,
1888 (splay_tree_key) decl));
1889 tree field
1890 = build_decl (OMP_CLAUSE_LOCATION (c),
1891 FIELD_DECL, NULL_TREE, ptr_type_node);
1892 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1893 insert_field_into_struct (ctx->record_type, field);
1894 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1895 (splay_tree_value) field);
1898 break;
1900 case OMP_CLAUSE_NOWAIT:
1901 case OMP_CLAUSE_ORDERED:
1902 case OMP_CLAUSE_COLLAPSE:
1903 case OMP_CLAUSE_UNTIED:
1904 case OMP_CLAUSE_MERGEABLE:
1905 case OMP_CLAUSE_PROC_BIND:
1906 case OMP_CLAUSE_SAFELEN:
1907 case OMP_CLAUSE_ASYNC:
1908 case OMP_CLAUSE_WAIT:
1909 case OMP_CLAUSE_GANG:
1910 case OMP_CLAUSE_WORKER:
1911 case OMP_CLAUSE_VECTOR:
1912 break;
1914 case OMP_CLAUSE_ALIGNED:
1915 decl = OMP_CLAUSE_DECL (c);
1916 if (is_global_var (decl)
1917 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1918 install_var_local (decl, ctx);
1919 break;
1921 case OMP_CLAUSE_DEVICE_RESIDENT:
1922 case OMP_CLAUSE_USE_DEVICE:
1923 case OMP_CLAUSE__CACHE_:
1924 case OMP_CLAUSE_INDEPENDENT:
1925 case OMP_CLAUSE_AUTO:
1926 case OMP_CLAUSE_SEQ:
1927 sorry ("Clause not supported yet");
1928 break;
1930 default:
1931 gcc_unreachable ();
1935 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1937 switch (OMP_CLAUSE_CODE (c))
1939 case OMP_CLAUSE_LASTPRIVATE:
1940 /* Let the corresponding firstprivate clause create
1941 the variable. */
1942 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1943 scan_array_reductions = true;
1944 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1945 break;
1946 /* FALLTHRU */
1948 case OMP_CLAUSE_FIRSTPRIVATE:
1949 if (is_gimple_omp_oacc (ctx->stmt))
1951 sorry ("clause not supported yet");
1952 break;
1954 /* FALLTHRU */
1955 case OMP_CLAUSE_PRIVATE:
1956 case OMP_CLAUSE_REDUCTION:
1957 case OMP_CLAUSE_LINEAR:
1958 decl = OMP_CLAUSE_DECL (c);
1959 if (is_variable_sized (decl))
1960 install_var_local (decl, ctx);
1961 fixup_remapped_decl (decl, ctx,
1962 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1963 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1964 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1965 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1966 scan_array_reductions = true;
1967 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1968 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1969 scan_array_reductions = true;
1970 break;
1972 case OMP_CLAUSE_SHARED:
1973 /* Ignore shared directives in teams construct. */
1974 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1975 break;
1976 decl = OMP_CLAUSE_DECL (c);
1977 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1978 fixup_remapped_decl (decl, ctx, false);
1979 break;
1981 case OMP_CLAUSE_MAP:
1982 if (!is_gimple_omp_offloaded (ctx->stmt))
1983 break;
1984 decl = OMP_CLAUSE_DECL (c);
1985 if (DECL_P (decl)
1986 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1987 && varpool_node::get_create (decl)->offloadable)
1988 break;
1989 if (DECL_P (decl))
1991 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1992 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1993 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1995 tree new_decl = lookup_decl (decl, ctx);
1996 TREE_TYPE (new_decl)
1997 = remap_type (TREE_TYPE (decl), &ctx->cb);
1999 else if (DECL_SIZE (decl)
2000 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2002 tree decl2 = DECL_VALUE_EXPR (decl);
2003 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2004 decl2 = TREE_OPERAND (decl2, 0);
2005 gcc_assert (DECL_P (decl2));
2006 fixup_remapped_decl (decl2, ctx, false);
2007 fixup_remapped_decl (decl, ctx, true);
2009 else
2010 fixup_remapped_decl (decl, ctx, false);
2012 break;
2014 case OMP_CLAUSE_COPYPRIVATE:
2015 case OMP_CLAUSE_COPYIN:
2016 case OMP_CLAUSE_DEFAULT:
2017 case OMP_CLAUSE_IF:
2018 case OMP_CLAUSE_NUM_THREADS:
2019 case OMP_CLAUSE_NUM_TEAMS:
2020 case OMP_CLAUSE_THREAD_LIMIT:
2021 case OMP_CLAUSE_DEVICE:
2022 case OMP_CLAUSE_SCHEDULE:
2023 case OMP_CLAUSE_DIST_SCHEDULE:
2024 case OMP_CLAUSE_NOWAIT:
2025 case OMP_CLAUSE_ORDERED:
2026 case OMP_CLAUSE_COLLAPSE:
2027 case OMP_CLAUSE_UNTIED:
2028 case OMP_CLAUSE_FINAL:
2029 case OMP_CLAUSE_MERGEABLE:
2030 case OMP_CLAUSE_PROC_BIND:
2031 case OMP_CLAUSE_SAFELEN:
2032 case OMP_CLAUSE_ALIGNED:
2033 case OMP_CLAUSE_DEPEND:
2034 case OMP_CLAUSE__LOOPTEMP_:
2035 case OMP_CLAUSE_TO:
2036 case OMP_CLAUSE_FROM:
2037 case OMP_CLAUSE__CILK_FOR_COUNT_:
2038 case OMP_CLAUSE_ASYNC:
2039 case OMP_CLAUSE_WAIT:
2040 case OMP_CLAUSE_NUM_GANGS:
2041 case OMP_CLAUSE_NUM_WORKERS:
2042 case OMP_CLAUSE_VECTOR_LENGTH:
2043 case OMP_CLAUSE_GANG:
2044 case OMP_CLAUSE_WORKER:
2045 case OMP_CLAUSE_VECTOR:
2046 break;
2048 case OMP_CLAUSE_DEVICE_RESIDENT:
2049 case OMP_CLAUSE_USE_DEVICE:
2050 case OMP_CLAUSE__CACHE_:
2051 case OMP_CLAUSE_INDEPENDENT:
2052 case OMP_CLAUSE_AUTO:
2053 case OMP_CLAUSE_SEQ:
2054 sorry ("Clause not supported yet");
2055 break;
2057 default:
2058 gcc_unreachable ();
2062 gcc_checking_assert (!scan_array_reductions
2063 || !is_gimple_omp_oacc (ctx->stmt));
2064 if (scan_array_reductions)
2065 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2066 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2067 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2069 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2070 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2072 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2073 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2074 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2075 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2076 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2077 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2080 /* Create a new name for omp child function. Returns an identifier. If
2081 IS_CILK_FOR is true then the suffix for the child function is
2082 "_cilk_for_fn." */
2084 static tree
2085 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2087 if (is_cilk_for)
2088 return clone_function_name (current_function_decl, "_cilk_for_fn");
2089 return clone_function_name (current_function_decl,
2090 task_copy ? "_omp_cpyfn" : "_omp_fn");
2093 /* Returns the type of the induction variable for the child function for
2094 _Cilk_for and the types for _high and _low variables based on TYPE. */
2096 static tree
2097 cilk_for_check_loop_diff_type (tree type)
2099 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2101 if (TYPE_UNSIGNED (type))
2102 return uint32_type_node;
2103 else
2104 return integer_type_node;
2106 else
2108 if (TYPE_UNSIGNED (type))
2109 return uint64_type_node;
2110 else
2111 return long_long_integer_type_node;
2115 /* Build a decl for the omp child function. It'll not contain a body
2116 yet, just the bare decl. */
2118 static void
2119 create_omp_child_function (omp_context *ctx, bool task_copy)
2121 tree decl, type, name, t;
2123 tree cilk_for_count
2124 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2125 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2126 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2127 tree cilk_var_type = NULL_TREE;
2129 name = create_omp_child_function_name (task_copy,
2130 cilk_for_count != NULL_TREE);
2131 if (task_copy)
2132 type = build_function_type_list (void_type_node, ptr_type_node,
2133 ptr_type_node, NULL_TREE);
2134 else if (cilk_for_count)
2136 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2137 cilk_var_type = cilk_for_check_loop_diff_type (type);
2138 type = build_function_type_list (void_type_node, ptr_type_node,
2139 cilk_var_type, cilk_var_type, NULL_TREE);
2141 else
2142 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2144 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2146 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2147 || !task_copy);
2148 if (!task_copy)
2149 ctx->cb.dst_fn = decl;
2150 else
2151 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2153 TREE_STATIC (decl) = 1;
2154 TREE_USED (decl) = 1;
2155 DECL_ARTIFICIAL (decl) = 1;
2156 DECL_IGNORED_P (decl) = 0;
2157 TREE_PUBLIC (decl) = 0;
2158 DECL_UNINLINABLE (decl) = 1;
2159 DECL_EXTERNAL (decl) = 0;
2160 DECL_CONTEXT (decl) = NULL_TREE;
2161 DECL_INITIAL (decl) = make_node (BLOCK);
2162 if (cgraph_node::get (current_function_decl)->offloadable)
2163 cgraph_node::get_create (decl)->offloadable = 1;
2164 else
2166 omp_context *octx;
2167 for (octx = ctx; octx; octx = octx->outer)
2168 if (is_gimple_omp_offloaded (octx->stmt))
2170 cgraph_node::get_create (decl)->offloadable = 1;
2171 #ifdef ENABLE_OFFLOADING
2172 g->have_offload = true;
2173 #endif
2174 break;
2178 t = build_decl (DECL_SOURCE_LOCATION (decl),
2179 RESULT_DECL, NULL_TREE, void_type_node);
2180 DECL_ARTIFICIAL (t) = 1;
2181 DECL_IGNORED_P (t) = 1;
2182 DECL_CONTEXT (t) = decl;
2183 DECL_RESULT (decl) = t;
2185 /* _Cilk_for's child function requires two extra parameters called
2186 __low and __high that are set the by Cilk runtime when it calls this
2187 function. */
2188 if (cilk_for_count)
2190 t = build_decl (DECL_SOURCE_LOCATION (decl),
2191 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2192 DECL_ARTIFICIAL (t) = 1;
2193 DECL_NAMELESS (t) = 1;
2194 DECL_ARG_TYPE (t) = ptr_type_node;
2195 DECL_CONTEXT (t) = current_function_decl;
2196 TREE_USED (t) = 1;
2197 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2198 DECL_ARGUMENTS (decl) = t;
2200 t = build_decl (DECL_SOURCE_LOCATION (decl),
2201 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2202 DECL_ARTIFICIAL (t) = 1;
2203 DECL_NAMELESS (t) = 1;
2204 DECL_ARG_TYPE (t) = ptr_type_node;
2205 DECL_CONTEXT (t) = current_function_decl;
2206 TREE_USED (t) = 1;
2207 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2208 DECL_ARGUMENTS (decl) = t;
2211 tree data_name = get_identifier (".omp_data_i");
2212 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2213 ptr_type_node);
2214 DECL_ARTIFICIAL (t) = 1;
2215 DECL_NAMELESS (t) = 1;
2216 DECL_ARG_TYPE (t) = ptr_type_node;
2217 DECL_CONTEXT (t) = current_function_decl;
2218 TREE_USED (t) = 1;
2219 if (cilk_for_count)
2220 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2221 DECL_ARGUMENTS (decl) = t;
2222 if (!task_copy)
2223 ctx->receiver_decl = t;
2224 else
2226 t = build_decl (DECL_SOURCE_LOCATION (decl),
2227 PARM_DECL, get_identifier (".omp_data_o"),
2228 ptr_type_node);
2229 DECL_ARTIFICIAL (t) = 1;
2230 DECL_NAMELESS (t) = 1;
2231 DECL_ARG_TYPE (t) = ptr_type_node;
2232 DECL_CONTEXT (t) = current_function_decl;
2233 TREE_USED (t) = 1;
2234 TREE_ADDRESSABLE (t) = 1;
2235 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2236 DECL_ARGUMENTS (decl) = t;
2239 /* Allocate memory for the function structure. The call to
2240 allocate_struct_function clobbers CFUN, so we need to restore
2241 it afterward. */
2242 push_struct_function (decl);
2243 cfun->function_end_locus = gimple_location (ctx->stmt);
2244 pop_cfun ();
2247 /* Callback for walk_gimple_seq. Check if combined parallel
2248 contains gimple_omp_for_combined_into_p OMP_FOR. */
2250 static tree
2251 find_combined_for (gimple_stmt_iterator *gsi_p,
2252 bool *handled_ops_p,
2253 struct walk_stmt_info *wi)
2255 gimple stmt = gsi_stmt (*gsi_p);
2257 *handled_ops_p = true;
2258 switch (gimple_code (stmt))
2260 WALK_SUBSTMTS;
2262 case GIMPLE_OMP_FOR:
2263 if (gimple_omp_for_combined_into_p (stmt)
2264 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2266 wi->info = stmt;
2267 return integer_zero_node;
2269 break;
2270 default:
2271 break;
2273 return NULL;
2276 /* Scan an OpenMP parallel directive. */
2278 static void
2279 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2281 omp_context *ctx;
2282 tree name;
2283 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2285 /* Ignore parallel directives with empty bodies, unless there
2286 are copyin clauses. */
2287 if (optimize > 0
2288 && empty_body_p (gimple_omp_body (stmt))
2289 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2290 OMP_CLAUSE_COPYIN) == NULL)
2292 gsi_replace (gsi, gimple_build_nop (), false);
2293 return;
2296 if (gimple_omp_parallel_combined_p (stmt))
2298 struct walk_stmt_info wi;
2300 memset (&wi, 0, sizeof (wi));
2301 wi.val_only = true;
2302 walk_gimple_seq (gimple_omp_body (stmt),
2303 find_combined_for, NULL, &wi);
2304 if (wi.info)
2306 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2307 struct omp_for_data fd;
2308 extract_omp_for_data (for_stmt, &fd, NULL);
2309 /* We need two temporaries with fd.loop.v type (istart/iend)
2310 and then (fd.collapse - 1) temporaries with the same
2311 type for count2 ... countN-1 vars if not constant. */
2312 size_t count = 2, i;
2313 tree type = fd.iter_type;
2314 if (fd.collapse > 1
2315 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2316 count += fd.collapse - 1;
2317 for (i = 0; i < count; i++)
2319 tree temp = create_tmp_var (type);
2320 tree c = build_omp_clause (UNKNOWN_LOCATION,
2321 OMP_CLAUSE__LOOPTEMP_);
2322 insert_decl_map (&outer_ctx->cb, temp, temp);
2323 OMP_CLAUSE_DECL (c) = temp;
2324 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2325 gimple_omp_parallel_set_clauses (stmt, c);
2330 ctx = new_omp_context (stmt, outer_ctx);
2331 taskreg_contexts.safe_push (ctx);
2332 if (taskreg_nesting_level > 1)
2333 ctx->is_nested = true;
2334 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2335 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2336 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2337 name = create_tmp_var_name (".omp_data_s");
2338 name = build_decl (gimple_location (stmt),
2339 TYPE_DECL, name, ctx->record_type);
2340 DECL_ARTIFICIAL (name) = 1;
2341 DECL_NAMELESS (name) = 1;
2342 TYPE_NAME (ctx->record_type) = name;
2343 create_omp_child_function (ctx, false);
2344 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2346 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2347 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2349 if (TYPE_FIELDS (ctx->record_type) == NULL)
2350 ctx->record_type = ctx->receiver_decl = NULL;
2353 /* Scan an OpenMP task directive. */
2355 static void
2356 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2358 omp_context *ctx;
2359 tree name, t;
2360 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2362 /* Ignore task directives with empty bodies. */
2363 if (optimize > 0
2364 && empty_body_p (gimple_omp_body (stmt)))
2366 gsi_replace (gsi, gimple_build_nop (), false);
2367 return;
2370 ctx = new_omp_context (stmt, outer_ctx);
2371 taskreg_contexts.safe_push (ctx);
2372 if (taskreg_nesting_level > 1)
2373 ctx->is_nested = true;
2374 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2375 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2376 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2377 name = create_tmp_var_name (".omp_data_s");
2378 name = build_decl (gimple_location (stmt),
2379 TYPE_DECL, name, ctx->record_type);
2380 DECL_ARTIFICIAL (name) = 1;
2381 DECL_NAMELESS (name) = 1;
2382 TYPE_NAME (ctx->record_type) = name;
2383 create_omp_child_function (ctx, false);
2384 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2386 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2388 if (ctx->srecord_type)
2390 name = create_tmp_var_name (".omp_data_a");
2391 name = build_decl (gimple_location (stmt),
2392 TYPE_DECL, name, ctx->srecord_type);
2393 DECL_ARTIFICIAL (name) = 1;
2394 DECL_NAMELESS (name) = 1;
2395 TYPE_NAME (ctx->srecord_type) = name;
2396 create_omp_child_function (ctx, true);
2399 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2401 if (TYPE_FIELDS (ctx->record_type) == NULL)
2403 ctx->record_type = ctx->receiver_decl = NULL;
2404 t = build_int_cst (long_integer_type_node, 0);
2405 gimple_omp_task_set_arg_size (stmt, t);
2406 t = build_int_cst (long_integer_type_node, 1);
2407 gimple_omp_task_set_arg_align (stmt, t);
2412 /* If any decls have been made addressable during scan_omp,
2413 adjust their fields if needed, and layout record types
2414 of parallel/task constructs. */
2416 static void
2417 finish_taskreg_scan (omp_context *ctx)
2419 if (ctx->record_type == NULL_TREE)
2420 return;
2422 /* If any task_shared_vars were needed, verify all
2423 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2424 statements if use_pointer_for_field hasn't changed
2425 because of that. If it did, update field types now. */
2426 if (task_shared_vars)
2428 tree c;
2430 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2431 c; c = OMP_CLAUSE_CHAIN (c))
2432 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2434 tree decl = OMP_CLAUSE_DECL (c);
2436 /* Global variables don't need to be copied,
2437 the receiver side will use them directly. */
2438 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2439 continue;
2440 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2441 || !use_pointer_for_field (decl, ctx))
2442 continue;
2443 tree field = lookup_field (decl, ctx);
2444 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2445 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2446 continue;
2447 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2448 TREE_THIS_VOLATILE (field) = 0;
2449 DECL_USER_ALIGN (field) = 0;
2450 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2451 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2452 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2453 if (ctx->srecord_type)
2455 tree sfield = lookup_sfield (decl, ctx);
2456 TREE_TYPE (sfield) = TREE_TYPE (field);
2457 TREE_THIS_VOLATILE (sfield) = 0;
2458 DECL_USER_ALIGN (sfield) = 0;
2459 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2460 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2461 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2466 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2468 layout_type (ctx->record_type);
2469 fixup_child_record_type (ctx);
2471 else
2473 location_t loc = gimple_location (ctx->stmt);
2474 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2475 /* Move VLA fields to the end. */
2476 p = &TYPE_FIELDS (ctx->record_type);
2477 while (*p)
2478 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2479 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2481 *q = *p;
2482 *p = TREE_CHAIN (*p);
2483 TREE_CHAIN (*q) = NULL_TREE;
2484 q = &TREE_CHAIN (*q);
2486 else
2487 p = &DECL_CHAIN (*p);
2488 *p = vla_fields;
2489 layout_type (ctx->record_type);
2490 fixup_child_record_type (ctx);
2491 if (ctx->srecord_type)
2492 layout_type (ctx->srecord_type);
2493 tree t = fold_convert_loc (loc, long_integer_type_node,
2494 TYPE_SIZE_UNIT (ctx->record_type));
2495 gimple_omp_task_set_arg_size (ctx->stmt, t);
2496 t = build_int_cst (long_integer_type_node,
2497 TYPE_ALIGN_UNIT (ctx->record_type));
2498 gimple_omp_task_set_arg_align (ctx->stmt, t);
2503 static omp_context *
2504 enclosing_target_ctx (omp_context *ctx)
2506 while (ctx != NULL
2507 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2508 ctx = ctx->outer;
2509 gcc_assert (ctx != NULL);
2510 return ctx;
2513 static bool
2514 oacc_loop_or_target_p (gimple stmt)
2516 enum gimple_code outer_type = gimple_code (stmt);
2517 return ((outer_type == GIMPLE_OMP_TARGET
2518 && ((gimple_omp_target_kind (stmt)
2519 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2520 || (gimple_omp_target_kind (stmt)
2521 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2522 || (outer_type == GIMPLE_OMP_FOR
2523 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2526 /* Scan a GIMPLE_OMP_FOR. */
2528 static void
2529 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2531 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
2532 omp_context *ctx;
2533 size_t i;
2534 tree clauses = gimple_omp_for_clauses (stmt);
2536 if (outer_ctx)
2537 outer_type = gimple_code (outer_ctx->stmt);
2539 ctx = new_omp_context (stmt, outer_ctx);
2541 if (is_gimple_omp_oacc (stmt))
2543 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2544 ctx->gwv_this = outer_ctx->gwv_this;
2545 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2547 int val;
2548 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2549 val = MASK_GANG;
2550 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2551 val = MASK_WORKER;
2552 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2553 val = MASK_VECTOR;
2554 else
2555 continue;
2556 ctx->gwv_this |= val;
2557 if (!outer_ctx)
2559 /* Skip; not nested inside a region. */
2560 continue;
2562 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2564 /* Skip; not nested inside an OpenACC region. */
2565 continue;
2567 if (outer_type == GIMPLE_OMP_FOR)
2568 outer_ctx->gwv_below |= val;
2569 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2571 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2572 if (gimple_omp_target_kind (enclosing->stmt)
2573 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2574 error_at (gimple_location (stmt),
2575 "no arguments allowed to gang, worker and vector clauses inside parallel");
2580 scan_sharing_clauses (clauses, ctx);
2582 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2583 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2585 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2586 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2587 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2588 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2590 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2592 if (is_gimple_omp_oacc (stmt))
2594 if (ctx->gwv_this & ctx->gwv_below)
2595 error_at (gimple_location (stmt),
2596 "gang, worker and vector may occur only once in a loop nest");
2597 else if (ctx->gwv_below != 0
2598 && ctx->gwv_this > ctx->gwv_below)
2599 error_at (gimple_location (stmt),
2600 "gang, worker and vector must occur in this order in a loop nest");
2601 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2602 outer_ctx->gwv_below |= ctx->gwv_below;
2606 /* Scan an OpenMP sections directive. */
2608 static void
2609 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2611 omp_context *ctx;
2613 ctx = new_omp_context (stmt, outer_ctx);
2614 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2615 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2618 /* Scan an OpenMP single directive. */
2620 static void
2621 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2623 omp_context *ctx;
2624 tree name;
2626 ctx = new_omp_context (stmt, outer_ctx);
2627 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2628 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2629 name = create_tmp_var_name (".omp_copy_s");
2630 name = build_decl (gimple_location (stmt),
2631 TYPE_DECL, name, ctx->record_type);
2632 TYPE_NAME (ctx->record_type) = name;
2634 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2635 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2637 if (TYPE_FIELDS (ctx->record_type) == NULL)
2638 ctx->record_type = NULL;
2639 else
2640 layout_type (ctx->record_type);
2643 /* Scan a GIMPLE_OMP_TARGET. */
2645 static void
2646 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2648 omp_context *ctx;
2649 tree name;
2650 bool offloaded = is_gimple_omp_offloaded (stmt);
2651 tree clauses = gimple_omp_target_clauses (stmt);
2653 ctx = new_omp_context (stmt, outer_ctx);
2654 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2655 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2656 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2657 name = create_tmp_var_name (".omp_data_t");
2658 name = build_decl (gimple_location (stmt),
2659 TYPE_DECL, name, ctx->record_type);
2660 DECL_ARTIFICIAL (name) = 1;
2661 DECL_NAMELESS (name) = 1;
2662 TYPE_NAME (ctx->record_type) = name;
2663 if (offloaded)
2665 if (is_gimple_omp_oacc (stmt))
2666 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2667 0, 0);
2669 create_omp_child_function (ctx, false);
2670 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2673 if (is_gimple_omp_oacc (stmt))
2675 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2677 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2678 ctx->gwv_this |= MASK_GANG;
2679 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2680 ctx->gwv_this |= MASK_WORKER;
2681 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2682 ctx->gwv_this |= MASK_VECTOR;
2686 scan_sharing_clauses (clauses, ctx);
2687 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2689 if (TYPE_FIELDS (ctx->record_type) == NULL)
2690 ctx->record_type = ctx->receiver_decl = NULL;
2691 else
2693 TYPE_FIELDS (ctx->record_type)
2694 = nreverse (TYPE_FIELDS (ctx->record_type));
2695 #ifdef ENABLE_CHECKING
2696 tree field;
2697 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2698 for (field = TYPE_FIELDS (ctx->record_type);
2699 field;
2700 field = DECL_CHAIN (field))
2701 gcc_assert (DECL_ALIGN (field) == align);
2702 #endif
2703 layout_type (ctx->record_type);
2704 if (offloaded)
2705 fixup_child_record_type (ctx);
2709 /* Scan an OpenMP teams directive. */
2711 static void
2712 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2714 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2715 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2716 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2719 /* Check nesting restrictions. */
2720 static bool
2721 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2723 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2724 inside an OpenACC CTX. */
2725 if (!(is_gimple_omp (stmt)
2726 && is_gimple_omp_oacc (stmt)))
2728 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2729 if (is_gimple_omp (ctx_->stmt)
2730 && is_gimple_omp_oacc (ctx_->stmt))
2732 error_at (gimple_location (stmt),
2733 "non-OpenACC construct inside of OpenACC region");
2734 return false;
2738 if (ctx != NULL)
2740 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2741 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2743 error_at (gimple_location (stmt),
2744 "OpenMP constructs may not be nested inside simd region");
2745 return false;
2747 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2749 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2750 || (gimple_omp_for_kind (stmt)
2751 != GF_OMP_FOR_KIND_DISTRIBUTE))
2752 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2754 error_at (gimple_location (stmt),
2755 "only distribute or parallel constructs are allowed to "
2756 "be closely nested inside teams construct");
2757 return false;
2761 switch (gimple_code (stmt))
2763 case GIMPLE_OMP_FOR:
2764 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2765 return true;
2766 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2768 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2770 error_at (gimple_location (stmt),
2771 "distribute construct must be closely nested inside "
2772 "teams construct");
2773 return false;
2775 return true;
2777 /* FALLTHRU */
2778 case GIMPLE_CALL:
2779 if (is_gimple_call (stmt)
2780 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2781 == BUILT_IN_GOMP_CANCEL
2782 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2783 == BUILT_IN_GOMP_CANCELLATION_POINT))
2785 const char *bad = NULL;
2786 const char *kind = NULL;
2787 if (ctx == NULL)
2789 error_at (gimple_location (stmt), "orphaned %qs construct",
2790 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2791 == BUILT_IN_GOMP_CANCEL
2792 ? "#pragma omp cancel"
2793 : "#pragma omp cancellation point");
2794 return false;
2796 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2797 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2798 : 0)
2800 case 1:
2801 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2802 bad = "#pragma omp parallel";
2803 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2804 == BUILT_IN_GOMP_CANCEL
2805 && !integer_zerop (gimple_call_arg (stmt, 1)))
2806 ctx->cancellable = true;
2807 kind = "parallel";
2808 break;
2809 case 2:
2810 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2811 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2812 bad = "#pragma omp for";
2813 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2814 == BUILT_IN_GOMP_CANCEL
2815 && !integer_zerop (gimple_call_arg (stmt, 1)))
2817 ctx->cancellable = true;
2818 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2819 OMP_CLAUSE_NOWAIT))
2820 warning_at (gimple_location (stmt), 0,
2821 "%<#pragma omp cancel for%> inside "
2822 "%<nowait%> for construct");
2823 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2824 OMP_CLAUSE_ORDERED))
2825 warning_at (gimple_location (stmt), 0,
2826 "%<#pragma omp cancel for%> inside "
2827 "%<ordered%> for construct");
2829 kind = "for";
2830 break;
2831 case 4:
2832 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2833 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2834 bad = "#pragma omp sections";
2835 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2836 == BUILT_IN_GOMP_CANCEL
2837 && !integer_zerop (gimple_call_arg (stmt, 1)))
2839 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2841 ctx->cancellable = true;
2842 if (find_omp_clause (gimple_omp_sections_clauses
2843 (ctx->stmt),
2844 OMP_CLAUSE_NOWAIT))
2845 warning_at (gimple_location (stmt), 0,
2846 "%<#pragma omp cancel sections%> inside "
2847 "%<nowait%> sections construct");
2849 else
2851 gcc_assert (ctx->outer
2852 && gimple_code (ctx->outer->stmt)
2853 == GIMPLE_OMP_SECTIONS);
2854 ctx->outer->cancellable = true;
2855 if (find_omp_clause (gimple_omp_sections_clauses
2856 (ctx->outer->stmt),
2857 OMP_CLAUSE_NOWAIT))
2858 warning_at (gimple_location (stmt), 0,
2859 "%<#pragma omp cancel sections%> inside "
2860 "%<nowait%> sections construct");
2863 kind = "sections";
2864 break;
2865 case 8:
2866 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2867 bad = "#pragma omp task";
2868 else
2869 ctx->cancellable = true;
2870 kind = "taskgroup";
2871 break;
2872 default:
2873 error_at (gimple_location (stmt), "invalid arguments");
2874 return false;
2876 if (bad)
2878 error_at (gimple_location (stmt),
2879 "%<%s %s%> construct not closely nested inside of %qs",
2880 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2881 == BUILT_IN_GOMP_CANCEL
2882 ? "#pragma omp cancel"
2883 : "#pragma omp cancellation point", kind, bad);
2884 return false;
2887 /* FALLTHRU */
2888 case GIMPLE_OMP_SECTIONS:
2889 case GIMPLE_OMP_SINGLE:
2890 for (; ctx != NULL; ctx = ctx->outer)
2891 switch (gimple_code (ctx->stmt))
2893 case GIMPLE_OMP_FOR:
2894 case GIMPLE_OMP_SECTIONS:
2895 case GIMPLE_OMP_SINGLE:
2896 case GIMPLE_OMP_ORDERED:
2897 case GIMPLE_OMP_MASTER:
2898 case GIMPLE_OMP_TASK:
2899 case GIMPLE_OMP_CRITICAL:
2900 if (is_gimple_call (stmt))
2902 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2903 != BUILT_IN_GOMP_BARRIER)
2904 return true;
2905 error_at (gimple_location (stmt),
2906 "barrier region may not be closely nested inside "
2907 "of work-sharing, critical, ordered, master or "
2908 "explicit task region");
2909 return false;
2911 error_at (gimple_location (stmt),
2912 "work-sharing region may not be closely nested inside "
2913 "of work-sharing, critical, ordered, master or explicit "
2914 "task region");
2915 return false;
2916 case GIMPLE_OMP_PARALLEL:
2917 return true;
2918 default:
2919 break;
2921 break;
2922 case GIMPLE_OMP_MASTER:
2923 for (; ctx != NULL; ctx = ctx->outer)
2924 switch (gimple_code (ctx->stmt))
2926 case GIMPLE_OMP_FOR:
2927 case GIMPLE_OMP_SECTIONS:
2928 case GIMPLE_OMP_SINGLE:
2929 case GIMPLE_OMP_TASK:
2930 error_at (gimple_location (stmt),
2931 "master region may not be closely nested inside "
2932 "of work-sharing or explicit task region");
2933 return false;
2934 case GIMPLE_OMP_PARALLEL:
2935 return true;
2936 default:
2937 break;
2939 break;
2940 case GIMPLE_OMP_ORDERED:
2941 for (; ctx != NULL; ctx = ctx->outer)
2942 switch (gimple_code (ctx->stmt))
2944 case GIMPLE_OMP_CRITICAL:
2945 case GIMPLE_OMP_TASK:
2946 error_at (gimple_location (stmt),
2947 "ordered region may not be closely nested inside "
2948 "of critical or explicit task region");
2949 return false;
2950 case GIMPLE_OMP_FOR:
2951 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2952 OMP_CLAUSE_ORDERED) == NULL)
2954 error_at (gimple_location (stmt),
2955 "ordered region must be closely nested inside "
2956 "a loop region with an ordered clause");
2957 return false;
2959 return true;
2960 case GIMPLE_OMP_PARALLEL:
2961 error_at (gimple_location (stmt),
2962 "ordered region must be closely nested inside "
2963 "a loop region with an ordered clause");
2964 return false;
2965 default:
2966 break;
2968 break;
2969 case GIMPLE_OMP_CRITICAL:
2971 tree this_stmt_name
2972 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2973 for (; ctx != NULL; ctx = ctx->outer)
2974 if (gomp_critical *other_crit
2975 = dyn_cast <gomp_critical *> (ctx->stmt))
2976 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2978 error_at (gimple_location (stmt),
2979 "critical region may not be nested inside a critical "
2980 "region with the same name");
2981 return false;
2984 break;
2985 case GIMPLE_OMP_TEAMS:
2986 if (ctx == NULL
2987 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
2988 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
2990 error_at (gimple_location (stmt),
2991 "teams construct not closely nested inside of target "
2992 "region");
2993 return false;
2995 break;
2996 case GIMPLE_OMP_TARGET:
2997 for (; ctx != NULL; ctx = ctx->outer)
2999 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3001 if (is_gimple_omp (stmt)
3002 && is_gimple_omp_oacc (stmt)
3003 && is_gimple_omp (ctx->stmt))
3005 error_at (gimple_location (stmt),
3006 "OpenACC construct inside of non-OpenACC region");
3007 return false;
3009 continue;
3012 const char *stmt_name, *ctx_stmt_name;
3013 switch (gimple_omp_target_kind (stmt))
3015 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3016 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3017 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3018 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3019 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3020 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3021 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3022 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3023 default: gcc_unreachable ();
3025 switch (gimple_omp_target_kind (ctx->stmt))
3027 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3028 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3029 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3030 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3031 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3032 default: gcc_unreachable ();
3035 /* OpenACC/OpenMP mismatch? */
3036 if (is_gimple_omp_oacc (stmt)
3037 != is_gimple_omp_oacc (ctx->stmt))
3039 error_at (gimple_location (stmt),
3040 "%s %s construct inside of %s %s region",
3041 (is_gimple_omp_oacc (stmt)
3042 ? "OpenACC" : "OpenMP"), stmt_name,
3043 (is_gimple_omp_oacc (ctx->stmt)
3044 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3045 return false;
3047 if (is_gimple_omp_offloaded (ctx->stmt))
3049 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3050 if (is_gimple_omp_oacc (ctx->stmt))
3052 error_at (gimple_location (stmt),
3053 "%s construct inside of %s region",
3054 stmt_name, ctx_stmt_name);
3055 return false;
3057 else
3059 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3060 warning_at (gimple_location (stmt), 0,
3061 "%s construct inside of %s region",
3062 stmt_name, ctx_stmt_name);
3066 break;
3067 default:
3068 break;
3070 return true;
3074 /* Helper function scan_omp.
3076 Callback for walk_tree or operators in walk_gimple_stmt used to
3077 scan for OMP directives in TP. */
3079 static tree
3080 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3082 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3083 omp_context *ctx = (omp_context *) wi->info;
3084 tree t = *tp;
3086 switch (TREE_CODE (t))
3088 case VAR_DECL:
3089 case PARM_DECL:
3090 case LABEL_DECL:
3091 case RESULT_DECL:
3092 if (ctx)
3093 *tp = remap_decl (t, &ctx->cb);
3094 break;
3096 default:
3097 if (ctx && TYPE_P (t))
3098 *tp = remap_type (t, &ctx->cb);
3099 else if (!DECL_P (t))
3101 *walk_subtrees = 1;
3102 if (ctx)
3104 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3105 if (tem != TREE_TYPE (t))
3107 if (TREE_CODE (t) == INTEGER_CST)
3108 *tp = wide_int_to_tree (tem, t);
3109 else
3110 TREE_TYPE (t) = tem;
3114 break;
3117 return NULL_TREE;
3120 /* Return true if FNDECL is a setjmp or a longjmp. */
3122 static bool
3123 setjmp_or_longjmp_p (const_tree fndecl)
3125 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3126 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3127 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3128 return true;
3130 tree declname = DECL_NAME (fndecl);
3131 if (!declname)
3132 return false;
3133 const char *name = IDENTIFIER_POINTER (declname);
3134 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3138 /* Helper function for scan_omp.
3140 Callback for walk_gimple_stmt used to scan for OMP directives in
3141 the current statement in GSI. */
3143 static tree
3144 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3145 struct walk_stmt_info *wi)
3147 gimple stmt = gsi_stmt (*gsi);
3148 omp_context *ctx = (omp_context *) wi->info;
3150 if (gimple_has_location (stmt))
3151 input_location = gimple_location (stmt);
3153 /* Check the nesting restrictions. */
3154 bool remove = false;
3155 if (is_gimple_omp (stmt))
3156 remove = !check_omp_nesting_restrictions (stmt, ctx);
3157 else if (is_gimple_call (stmt))
3159 tree fndecl = gimple_call_fndecl (stmt);
3160 if (fndecl)
3162 if (setjmp_or_longjmp_p (fndecl)
3163 && ctx
3164 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3165 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3167 remove = true;
3168 error_at (gimple_location (stmt),
3169 "setjmp/longjmp inside simd construct");
3171 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3172 switch (DECL_FUNCTION_CODE (fndecl))
3174 case BUILT_IN_GOMP_BARRIER:
3175 case BUILT_IN_GOMP_CANCEL:
3176 case BUILT_IN_GOMP_CANCELLATION_POINT:
3177 case BUILT_IN_GOMP_TASKYIELD:
3178 case BUILT_IN_GOMP_TASKWAIT:
3179 case BUILT_IN_GOMP_TASKGROUP_START:
3180 case BUILT_IN_GOMP_TASKGROUP_END:
3181 remove = !check_omp_nesting_restrictions (stmt, ctx);
3182 break;
3183 default:
3184 break;
3188 if (remove)
3190 stmt = gimple_build_nop ();
3191 gsi_replace (gsi, stmt, false);
3194 *handled_ops_p = true;
3196 switch (gimple_code (stmt))
3198 case GIMPLE_OMP_PARALLEL:
3199 taskreg_nesting_level++;
3200 scan_omp_parallel (gsi, ctx);
3201 taskreg_nesting_level--;
3202 break;
3204 case GIMPLE_OMP_TASK:
3205 taskreg_nesting_level++;
3206 scan_omp_task (gsi, ctx);
3207 taskreg_nesting_level--;
3208 break;
3210 case GIMPLE_OMP_FOR:
3211 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3212 break;
3214 case GIMPLE_OMP_SECTIONS:
3215 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3216 break;
3218 case GIMPLE_OMP_SINGLE:
3219 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3220 break;
3222 case GIMPLE_OMP_SECTION:
3223 case GIMPLE_OMP_MASTER:
3224 case GIMPLE_OMP_TASKGROUP:
3225 case GIMPLE_OMP_ORDERED:
3226 case GIMPLE_OMP_CRITICAL:
3227 ctx = new_omp_context (stmt, ctx);
3228 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3229 break;
3231 case GIMPLE_OMP_TARGET:
3232 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3233 break;
3235 case GIMPLE_OMP_TEAMS:
3236 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3237 break;
3239 case GIMPLE_BIND:
3241 tree var;
3243 *handled_ops_p = false;
3244 if (ctx)
3245 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3246 var ;
3247 var = DECL_CHAIN (var))
3248 insert_decl_map (&ctx->cb, var, var);
3250 break;
3251 default:
3252 *handled_ops_p = false;
3253 break;
3256 return NULL_TREE;
3260 /* Scan all the statements starting at the current statement. CTX
3261 contains context information about the OMP directives and
3262 clauses found during the scan. */
3264 static void
3265 scan_omp (gimple_seq *body_p, omp_context *ctx)
3267 location_t saved_location;
3268 struct walk_stmt_info wi;
3270 memset (&wi, 0, sizeof (wi));
3271 wi.info = ctx;
3272 wi.want_locations = true;
3274 saved_location = input_location;
3275 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3276 input_location = saved_location;
3279 /* Re-gimplification and code generation routines. */
3281 /* Build a call to GOMP_barrier. */
3283 static gimple
3284 build_omp_barrier (tree lhs)
3286 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3287 : BUILT_IN_GOMP_BARRIER);
3288 gcall *g = gimple_build_call (fndecl, 0);
3289 if (lhs)
3290 gimple_call_set_lhs (g, lhs);
3291 return g;
3294 /* If a context was created for STMT when it was scanned, return it. */
3296 static omp_context *
3297 maybe_lookup_ctx (gimple stmt)
3299 splay_tree_node n;
3300 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3301 return n ? (omp_context *) n->value : NULL;
3305 /* Find the mapping for DECL in CTX or the immediately enclosing
3306 context that has a mapping for DECL.
3308 If CTX is a nested parallel directive, we may have to use the decl
3309 mappings created in CTX's parent context. Suppose that we have the
3310 following parallel nesting (variable UIDs showed for clarity):
3312 iD.1562 = 0;
3313 #omp parallel shared(iD.1562) -> outer parallel
3314 iD.1562 = iD.1562 + 1;
3316 #omp parallel shared (iD.1562) -> inner parallel
3317 iD.1562 = iD.1562 - 1;
3319 Each parallel structure will create a distinct .omp_data_s structure
3320 for copying iD.1562 in/out of the directive:
3322 outer parallel .omp_data_s.1.i -> iD.1562
3323 inner parallel .omp_data_s.2.i -> iD.1562
3325 A shared variable mapping will produce a copy-out operation before
3326 the parallel directive and a copy-in operation after it. So, in
3327 this case we would have:
3329 iD.1562 = 0;
3330 .omp_data_o.1.i = iD.1562;
3331 #omp parallel shared(iD.1562) -> outer parallel
3332 .omp_data_i.1 = &.omp_data_o.1
3333 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3335 .omp_data_o.2.i = iD.1562; -> **
3336 #omp parallel shared(iD.1562) -> inner parallel
3337 .omp_data_i.2 = &.omp_data_o.2
3338 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3341 ** This is a problem. The symbol iD.1562 cannot be referenced
3342 inside the body of the outer parallel region. But since we are
3343 emitting this copy operation while expanding the inner parallel
3344 directive, we need to access the CTX structure of the outer
3345 parallel directive to get the correct mapping:
3347 .omp_data_o.2.i = .omp_data_i.1->i
3349 Since there may be other workshare or parallel directives enclosing
3350 the parallel directive, it may be necessary to walk up the context
3351 parent chain. This is not a problem in general because nested
3352 parallelism happens only rarely. */
3354 static tree
3355 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3357 tree t;
3358 omp_context *up;
3360 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3361 t = maybe_lookup_decl (decl, up);
3363 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3365 return t ? t : decl;
3369 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3370 in outer contexts. */
3372 static tree
3373 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3375 tree t = NULL;
3376 omp_context *up;
3378 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3379 t = maybe_lookup_decl (decl, up);
3381 return t ? t : decl;
3385 /* Construct the initialization value for reduction CLAUSE. */
3387 tree
3388 omp_reduction_init (tree clause, tree type)
3390 location_t loc = OMP_CLAUSE_LOCATION (clause);
3391 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3393 case PLUS_EXPR:
3394 case MINUS_EXPR:
3395 case BIT_IOR_EXPR:
3396 case BIT_XOR_EXPR:
3397 case TRUTH_OR_EXPR:
3398 case TRUTH_ORIF_EXPR:
3399 case TRUTH_XOR_EXPR:
3400 case NE_EXPR:
3401 return build_zero_cst (type);
3403 case MULT_EXPR:
3404 case TRUTH_AND_EXPR:
3405 case TRUTH_ANDIF_EXPR:
3406 case EQ_EXPR:
3407 return fold_convert_loc (loc, type, integer_one_node);
3409 case BIT_AND_EXPR:
3410 return fold_convert_loc (loc, type, integer_minus_one_node);
3412 case MAX_EXPR:
3413 if (SCALAR_FLOAT_TYPE_P (type))
3415 REAL_VALUE_TYPE max, min;
3416 if (HONOR_INFINITIES (type))
3418 real_inf (&max);
3419 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3421 else
3422 real_maxval (&min, 1, TYPE_MODE (type));
3423 return build_real (type, min);
3425 else
3427 gcc_assert (INTEGRAL_TYPE_P (type));
3428 return TYPE_MIN_VALUE (type);
3431 case MIN_EXPR:
3432 if (SCALAR_FLOAT_TYPE_P (type))
3434 REAL_VALUE_TYPE max;
3435 if (HONOR_INFINITIES (type))
3436 real_inf (&max);
3437 else
3438 real_maxval (&max, 0, TYPE_MODE (type));
3439 return build_real (type, max);
3441 else
3443 gcc_assert (INTEGRAL_TYPE_P (type));
3444 return TYPE_MAX_VALUE (type);
3447 default:
3448 gcc_unreachable ();
3452 /* Return alignment to be assumed for var in CLAUSE, which should be
3453 OMP_CLAUSE_ALIGNED. */
3455 static tree
3456 omp_clause_aligned_alignment (tree clause)
3458 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3459 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3461 /* Otherwise return implementation defined alignment. */
3462 unsigned int al = 1;
3463 machine_mode mode, vmode;
3464 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3465 if (vs)
3466 vs = 1 << floor_log2 (vs);
3467 static enum mode_class classes[]
3468 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3469 for (int i = 0; i < 4; i += 2)
3470 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3471 mode != VOIDmode;
3472 mode = GET_MODE_WIDER_MODE (mode))
3474 vmode = targetm.vectorize.preferred_simd_mode (mode);
3475 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3476 continue;
3477 while (vs
3478 && GET_MODE_SIZE (vmode) < vs
3479 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3480 vmode = GET_MODE_2XWIDER_MODE (vmode);
3482 tree type = lang_hooks.types.type_for_mode (mode, 1);
3483 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3484 continue;
3485 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3486 / GET_MODE_SIZE (mode));
3487 if (TYPE_MODE (type) != vmode)
3488 continue;
3489 if (TYPE_ALIGN_UNIT (type) > al)
3490 al = TYPE_ALIGN_UNIT (type);
3492 return build_int_cst (integer_type_node, al);
3495 /* Return maximum possible vectorization factor for the target. */
3497 static int
3498 omp_max_vf (void)
3500 if (!optimize
3501 || optimize_debug
3502 || !flag_tree_loop_optimize
3503 || (!flag_tree_loop_vectorize
3504 && (global_options_set.x_flag_tree_loop_vectorize
3505 || global_options_set.x_flag_tree_vectorize)))
3506 return 1;
3508 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3509 if (vs)
3511 vs = 1 << floor_log2 (vs);
3512 return vs;
3514 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3515 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3516 return GET_MODE_NUNITS (vqimode);
3517 return 1;
3520 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3521 privatization. */
3523 static bool
3524 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3525 tree &idx, tree &lane, tree &ivar, tree &lvar)
3527 if (max_vf == 0)
3529 max_vf = omp_max_vf ();
3530 if (max_vf > 1)
3532 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3533 OMP_CLAUSE_SAFELEN);
3534 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3535 max_vf = 1;
3536 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3537 max_vf) == -1)
3538 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3540 if (max_vf > 1)
3542 idx = create_tmp_var (unsigned_type_node);
3543 lane = create_tmp_var (unsigned_type_node);
3546 if (max_vf == 1)
3547 return false;
3549 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3550 tree avar = create_tmp_var_raw (atype);
3551 if (TREE_ADDRESSABLE (new_var))
3552 TREE_ADDRESSABLE (avar) = 1;
3553 DECL_ATTRIBUTES (avar)
3554 = tree_cons (get_identifier ("omp simd array"), NULL,
3555 DECL_ATTRIBUTES (avar));
3556 gimple_add_tmp_var (avar);
3557 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3558 NULL_TREE, NULL_TREE);
3559 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3560 NULL_TREE, NULL_TREE);
3561 if (DECL_P (new_var))
3563 SET_DECL_VALUE_EXPR (new_var, lvar);
3564 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3566 return true;
3569 /* Helper function of lower_rec_input_clauses. For a reference
3570 in simd reduction, add an underlying variable it will reference. */
3572 static void
3573 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3575 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3576 if (TREE_CONSTANT (z))
3578 const char *name = NULL;
3579 if (DECL_NAME (new_vard))
3580 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3582 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3583 gimple_add_tmp_var (z);
3584 TREE_ADDRESSABLE (z) = 1;
3585 z = build_fold_addr_expr_loc (loc, z);
3586 gimplify_assign (new_vard, z, ilist);
3590 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3591 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3592 private variables. Initialization statements go in ILIST, while calls
3593 to destructors go in DLIST. */
3595 static void
3596 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3597 omp_context *ctx, struct omp_for_data *fd)
3599 tree c, dtor, copyin_seq, x, ptr;
3600 bool copyin_by_ref = false;
3601 bool lastprivate_firstprivate = false;
3602 bool reduction_omp_orig_ref = false;
3603 int pass;
3604 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3605 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3606 int max_vf = 0;
3607 tree lane = NULL_TREE, idx = NULL_TREE;
3608 tree ivar = NULL_TREE, lvar = NULL_TREE;
3609 gimple_seq llist[2] = { NULL, NULL };
3611 copyin_seq = NULL;
3613 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3614 with data sharing clauses referencing variable sized vars. That
3615 is unnecessarily hard to support and very unlikely to result in
3616 vectorized code anyway. */
3617 if (is_simd)
3618 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3619 switch (OMP_CLAUSE_CODE (c))
3621 case OMP_CLAUSE_LINEAR:
3622 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3623 max_vf = 1;
3624 /* FALLTHRU */
3625 case OMP_CLAUSE_REDUCTION:
3626 case OMP_CLAUSE_PRIVATE:
3627 case OMP_CLAUSE_FIRSTPRIVATE:
3628 case OMP_CLAUSE_LASTPRIVATE:
3629 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3630 max_vf = 1;
3631 break;
3632 default:
3633 continue;
3636 /* Do all the fixed sized types in the first pass, and the variable sized
3637 types in the second pass. This makes sure that the scalar arguments to
3638 the variable sized types are processed before we use them in the
3639 variable sized operations. */
3640 for (pass = 0; pass < 2; ++pass)
3642 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3644 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3645 tree var, new_var;
3646 bool by_ref;
3647 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3649 switch (c_kind)
3651 case OMP_CLAUSE_PRIVATE:
3652 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3653 continue;
3654 break;
3655 case OMP_CLAUSE_SHARED:
3656 /* Ignore shared directives in teams construct. */
3657 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3658 continue;
3659 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3661 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3662 continue;
3664 case OMP_CLAUSE_FIRSTPRIVATE:
3665 case OMP_CLAUSE_COPYIN:
3666 case OMP_CLAUSE_LINEAR:
3667 break;
3668 case OMP_CLAUSE_REDUCTION:
3669 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3670 reduction_omp_orig_ref = true;
3671 break;
3672 case OMP_CLAUSE__LOOPTEMP_:
3673 /* Handle _looptemp_ clauses only on parallel. */
3674 if (fd)
3675 continue;
3676 break;
3677 case OMP_CLAUSE_LASTPRIVATE:
3678 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3680 lastprivate_firstprivate = true;
3681 if (pass != 0)
3682 continue;
3684 /* Even without corresponding firstprivate, if
3685 decl is Fortran allocatable, it needs outer var
3686 reference. */
3687 else if (pass == 0
3688 && lang_hooks.decls.omp_private_outer_ref
3689 (OMP_CLAUSE_DECL (c)))
3690 lastprivate_firstprivate = true;
3691 break;
3692 case OMP_CLAUSE_ALIGNED:
3693 if (pass == 0)
3694 continue;
3695 var = OMP_CLAUSE_DECL (c);
3696 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3697 && !is_global_var (var))
3699 new_var = maybe_lookup_decl (var, ctx);
3700 if (new_var == NULL_TREE)
3701 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3702 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3703 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3704 omp_clause_aligned_alignment (c));
3705 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3706 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3707 gimplify_and_add (x, ilist);
3709 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3710 && is_global_var (var))
3712 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3713 new_var = lookup_decl (var, ctx);
3714 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3715 t = build_fold_addr_expr_loc (clause_loc, t);
3716 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3717 t = build_call_expr_loc (clause_loc, t2, 2, t,
3718 omp_clause_aligned_alignment (c));
3719 t = fold_convert_loc (clause_loc, ptype, t);
3720 x = create_tmp_var (ptype);
3721 t = build2 (MODIFY_EXPR, ptype, x, t);
3722 gimplify_and_add (t, ilist);
3723 t = build_simple_mem_ref_loc (clause_loc, x);
3724 SET_DECL_VALUE_EXPR (new_var, t);
3725 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3727 continue;
3728 default:
3729 continue;
3732 new_var = var = OMP_CLAUSE_DECL (c);
3733 if (c_kind != OMP_CLAUSE_COPYIN)
3734 new_var = lookup_decl (var, ctx);
3736 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3738 if (pass != 0)
3739 continue;
3741 else if (is_variable_sized (var))
3743 /* For variable sized types, we need to allocate the
3744 actual storage here. Call alloca and store the
3745 result in the pointer decl that we created elsewhere. */
3746 if (pass == 0)
3747 continue;
3749 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3751 gcall *stmt;
3752 tree tmp, atmp;
3754 ptr = DECL_VALUE_EXPR (new_var);
3755 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3756 ptr = TREE_OPERAND (ptr, 0);
3757 gcc_assert (DECL_P (ptr));
3758 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3760 /* void *tmp = __builtin_alloca */
3761 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3762 stmt = gimple_build_call (atmp, 1, x);
3763 tmp = create_tmp_var_raw (ptr_type_node);
3764 gimple_add_tmp_var (tmp);
3765 gimple_call_set_lhs (stmt, tmp);
3767 gimple_seq_add_stmt (ilist, stmt);
3769 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3770 gimplify_assign (ptr, x, ilist);
3773 else if (is_reference (var))
3775 /* For references that are being privatized for Fortran,
3776 allocate new backing storage for the new pointer
3777 variable. This allows us to avoid changing all the
3778 code that expects a pointer to something that expects
3779 a direct variable. */
3780 if (pass == 0)
3781 continue;
3783 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3784 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3786 x = build_receiver_ref (var, false, ctx);
3787 x = build_fold_addr_expr_loc (clause_loc, x);
3789 else if (TREE_CONSTANT (x))
3791 /* For reduction in SIMD loop, defer adding the
3792 initialization of the reference, because if we decide
3793 to use SIMD array for it, the initilization could cause
3794 expansion ICE. */
3795 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3796 x = NULL_TREE;
3797 else
3799 const char *name = NULL;
3800 if (DECL_NAME (var))
3801 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3803 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3804 name);
3805 gimple_add_tmp_var (x);
3806 TREE_ADDRESSABLE (x) = 1;
3807 x = build_fold_addr_expr_loc (clause_loc, x);
3810 else
3812 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3813 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3816 if (x)
3818 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3819 gimplify_assign (new_var, x, ilist);
3822 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3824 else if (c_kind == OMP_CLAUSE_REDUCTION
3825 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3827 if (pass == 0)
3828 continue;
3830 else if (pass != 0)
3831 continue;
3833 switch (OMP_CLAUSE_CODE (c))
3835 case OMP_CLAUSE_SHARED:
3836 /* Ignore shared directives in teams construct. */
3837 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3838 continue;
3839 /* Shared global vars are just accessed directly. */
3840 if (is_global_var (new_var))
3841 break;
3842 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3843 needs to be delayed until after fixup_child_record_type so
3844 that we get the correct type during the dereference. */
3845 by_ref = use_pointer_for_field (var, ctx);
3846 x = build_receiver_ref (var, by_ref, ctx);
3847 SET_DECL_VALUE_EXPR (new_var, x);
3848 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3850 /* ??? If VAR is not passed by reference, and the variable
3851 hasn't been initialized yet, then we'll get a warning for
3852 the store into the omp_data_s structure. Ideally, we'd be
3853 able to notice this and not store anything at all, but
3854 we're generating code too early. Suppress the warning. */
3855 if (!by_ref)
3856 TREE_NO_WARNING (var) = 1;
3857 break;
3859 case OMP_CLAUSE_LASTPRIVATE:
3860 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3861 break;
3862 /* FALLTHRU */
3864 case OMP_CLAUSE_PRIVATE:
3865 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3866 x = build_outer_var_ref (var, ctx);
3867 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3869 if (is_task_ctx (ctx))
3870 x = build_receiver_ref (var, false, ctx);
3871 else
3872 x = build_outer_var_ref (var, ctx);
3874 else
3875 x = NULL;
3876 do_private:
3877 tree nx;
3878 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3879 if (is_simd)
3881 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3882 if ((TREE_ADDRESSABLE (new_var) || nx || y
3883 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3884 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3885 idx, lane, ivar, lvar))
3887 if (nx)
3888 x = lang_hooks.decls.omp_clause_default_ctor
3889 (c, unshare_expr (ivar), x);
3890 if (nx && x)
3891 gimplify_and_add (x, &llist[0]);
3892 if (y)
3894 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3895 if (y)
3897 gimple_seq tseq = NULL;
3899 dtor = y;
3900 gimplify_stmt (&dtor, &tseq);
3901 gimple_seq_add_seq (&llist[1], tseq);
3904 break;
3907 if (nx)
3908 gimplify_and_add (nx, ilist);
3909 /* FALLTHRU */
3911 do_dtor:
3912 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3913 if (x)
3915 gimple_seq tseq = NULL;
3917 dtor = x;
3918 gimplify_stmt (&dtor, &tseq);
3919 gimple_seq_add_seq (dlist, tseq);
3921 break;
3923 case OMP_CLAUSE_LINEAR:
3924 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3925 goto do_firstprivate;
3926 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3927 x = NULL;
3928 else
3929 x = build_outer_var_ref (var, ctx);
3930 goto do_private;
3932 case OMP_CLAUSE_FIRSTPRIVATE:
3933 if (is_task_ctx (ctx))
3935 if (is_reference (var) || is_variable_sized (var))
3936 goto do_dtor;
3937 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3938 ctx))
3939 || use_pointer_for_field (var, NULL))
3941 x = build_receiver_ref (var, false, ctx);
3942 SET_DECL_VALUE_EXPR (new_var, x);
3943 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3944 goto do_dtor;
3947 do_firstprivate:
3948 x = build_outer_var_ref (var, ctx);
3949 if (is_simd)
3951 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3952 && gimple_omp_for_combined_into_p (ctx->stmt))
3954 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3955 tree stept = TREE_TYPE (t);
3956 tree ct = find_omp_clause (clauses,
3957 OMP_CLAUSE__LOOPTEMP_);
3958 gcc_assert (ct);
3959 tree l = OMP_CLAUSE_DECL (ct);
3960 tree n1 = fd->loop.n1;
3961 tree step = fd->loop.step;
3962 tree itype = TREE_TYPE (l);
3963 if (POINTER_TYPE_P (itype))
3964 itype = signed_type_for (itype);
3965 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3966 if (TYPE_UNSIGNED (itype)
3967 && fd->loop.cond_code == GT_EXPR)
3968 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3969 fold_build1 (NEGATE_EXPR, itype, l),
3970 fold_build1 (NEGATE_EXPR,
3971 itype, step));
3972 else
3973 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3974 t = fold_build2 (MULT_EXPR, stept,
3975 fold_convert (stept, l), t);
3977 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3979 x = lang_hooks.decls.omp_clause_linear_ctor
3980 (c, new_var, x, t);
3981 gimplify_and_add (x, ilist);
3982 goto do_dtor;
3985 if (POINTER_TYPE_P (TREE_TYPE (x)))
3986 x = fold_build2 (POINTER_PLUS_EXPR,
3987 TREE_TYPE (x), x, t);
3988 else
3989 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
3992 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
3993 || TREE_ADDRESSABLE (new_var))
3994 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3995 idx, lane, ivar, lvar))
3997 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
3999 tree iv = create_tmp_var (TREE_TYPE (new_var));
4000 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4001 gimplify_and_add (x, ilist);
4002 gimple_stmt_iterator gsi
4003 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4004 gassign *g
4005 = gimple_build_assign (unshare_expr (lvar), iv);
4006 gsi_insert_before_without_update (&gsi, g,
4007 GSI_SAME_STMT);
4008 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4009 enum tree_code code = PLUS_EXPR;
4010 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4011 code = POINTER_PLUS_EXPR;
4012 g = gimple_build_assign (iv, code, iv, t);
4013 gsi_insert_before_without_update (&gsi, g,
4014 GSI_SAME_STMT);
4015 break;
4017 x = lang_hooks.decls.omp_clause_copy_ctor
4018 (c, unshare_expr (ivar), x);
4019 gimplify_and_add (x, &llist[0]);
4020 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4021 if (x)
4023 gimple_seq tseq = NULL;
4025 dtor = x;
4026 gimplify_stmt (&dtor, &tseq);
4027 gimple_seq_add_seq (&llist[1], tseq);
4029 break;
4032 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4033 gimplify_and_add (x, ilist);
4034 goto do_dtor;
4036 case OMP_CLAUSE__LOOPTEMP_:
4037 gcc_assert (is_parallel_ctx (ctx));
4038 x = build_outer_var_ref (var, ctx);
4039 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4040 gimplify_and_add (x, ilist);
4041 break;
4043 case OMP_CLAUSE_COPYIN:
4044 by_ref = use_pointer_for_field (var, NULL);
4045 x = build_receiver_ref (var, by_ref, ctx);
4046 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4047 append_to_statement_list (x, &copyin_seq);
4048 copyin_by_ref |= by_ref;
4049 break;
4051 case OMP_CLAUSE_REDUCTION:
4052 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4054 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4055 gimple tseq;
4056 x = build_outer_var_ref (var, ctx);
4058 if (is_reference (var)
4059 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4060 TREE_TYPE (x)))
4061 x = build_fold_addr_expr_loc (clause_loc, x);
4062 SET_DECL_VALUE_EXPR (placeholder, x);
4063 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4064 tree new_vard = new_var;
4065 if (is_reference (var))
4067 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4068 new_vard = TREE_OPERAND (new_var, 0);
4069 gcc_assert (DECL_P (new_vard));
4071 if (is_simd
4072 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4073 idx, lane, ivar, lvar))
4075 if (new_vard == new_var)
4077 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4078 SET_DECL_VALUE_EXPR (new_var, ivar);
4080 else
4082 SET_DECL_VALUE_EXPR (new_vard,
4083 build_fold_addr_expr (ivar));
4084 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4086 x = lang_hooks.decls.omp_clause_default_ctor
4087 (c, unshare_expr (ivar),
4088 build_outer_var_ref (var, ctx));
4089 if (x)
4090 gimplify_and_add (x, &llist[0]);
4091 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4093 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4094 lower_omp (&tseq, ctx);
4095 gimple_seq_add_seq (&llist[0], tseq);
4097 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4098 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4099 lower_omp (&tseq, ctx);
4100 gimple_seq_add_seq (&llist[1], tseq);
4101 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4102 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4103 if (new_vard == new_var)
4104 SET_DECL_VALUE_EXPR (new_var, lvar);
4105 else
4106 SET_DECL_VALUE_EXPR (new_vard,
4107 build_fold_addr_expr (lvar));
4108 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4109 if (x)
4111 tseq = NULL;
4112 dtor = x;
4113 gimplify_stmt (&dtor, &tseq);
4114 gimple_seq_add_seq (&llist[1], tseq);
4116 break;
4118 /* If this is a reference to constant size reduction var
4119 with placeholder, we haven't emitted the initializer
4120 for it because it is undesirable if SIMD arrays are used.
4121 But if they aren't used, we need to emit the deferred
4122 initialization now. */
4123 else if (is_reference (var) && is_simd)
4124 handle_simd_reference (clause_loc, new_vard, ilist);
4125 x = lang_hooks.decls.omp_clause_default_ctor
4126 (c, unshare_expr (new_var),
4127 build_outer_var_ref (var, ctx));
4128 if (x)
4129 gimplify_and_add (x, ilist);
4130 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4132 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4133 lower_omp (&tseq, ctx);
4134 gimple_seq_add_seq (ilist, tseq);
4136 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4137 if (is_simd)
4139 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4140 lower_omp (&tseq, ctx);
4141 gimple_seq_add_seq (dlist, tseq);
4142 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4144 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4145 goto do_dtor;
4147 else
4149 x = omp_reduction_init (c, TREE_TYPE (new_var));
4150 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4151 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4153 /* reduction(-:var) sums up the partial results, so it
4154 acts identically to reduction(+:var). */
4155 if (code == MINUS_EXPR)
4156 code = PLUS_EXPR;
4158 tree new_vard = new_var;
4159 if (is_simd && is_reference (var))
4161 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4162 new_vard = TREE_OPERAND (new_var, 0);
4163 gcc_assert (DECL_P (new_vard));
4165 if (is_simd
4166 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4167 idx, lane, ivar, lvar))
4169 tree ref = build_outer_var_ref (var, ctx);
4171 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4173 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4174 ref = build_outer_var_ref (var, ctx);
4175 gimplify_assign (ref, x, &llist[1]);
4177 if (new_vard != new_var)
4179 SET_DECL_VALUE_EXPR (new_vard,
4180 build_fold_addr_expr (lvar));
4181 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4184 else
4186 if (is_reference (var) && is_simd)
4187 handle_simd_reference (clause_loc, new_vard, ilist);
4188 gimplify_assign (new_var, x, ilist);
4189 if (is_simd)
4191 tree ref = build_outer_var_ref (var, ctx);
4193 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4194 ref = build_outer_var_ref (var, ctx);
4195 gimplify_assign (ref, x, dlist);
4199 break;
4201 default:
4202 gcc_unreachable ();
4207 if (lane)
4209 tree uid = create_tmp_var (ptr_type_node, "simduid");
4210 /* Don't want uninit warnings on simduid, it is always uninitialized,
4211 but we use it not for the value, but for the DECL_UID only. */
4212 TREE_NO_WARNING (uid) = 1;
4213 gimple g
4214 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4215 gimple_call_set_lhs (g, lane);
4216 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4217 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4218 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4219 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4220 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4221 gimple_omp_for_set_clauses (ctx->stmt, c);
4222 g = gimple_build_assign (lane, INTEGER_CST,
4223 build_int_cst (unsigned_type_node, 0));
4224 gimple_seq_add_stmt (ilist, g);
4225 for (int i = 0; i < 2; i++)
4226 if (llist[i])
4228 tree vf = create_tmp_var (unsigned_type_node);
4229 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4230 gimple_call_set_lhs (g, vf);
4231 gimple_seq *seq = i == 0 ? ilist : dlist;
4232 gimple_seq_add_stmt (seq, g);
4233 tree t = build_int_cst (unsigned_type_node, 0);
4234 g = gimple_build_assign (idx, INTEGER_CST, t);
4235 gimple_seq_add_stmt (seq, g);
4236 tree body = create_artificial_label (UNKNOWN_LOCATION);
4237 tree header = create_artificial_label (UNKNOWN_LOCATION);
4238 tree end = create_artificial_label (UNKNOWN_LOCATION);
4239 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4240 gimple_seq_add_stmt (seq, gimple_build_label (body));
4241 gimple_seq_add_seq (seq, llist[i]);
4242 t = build_int_cst (unsigned_type_node, 1);
4243 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4244 gimple_seq_add_stmt (seq, g);
4245 gimple_seq_add_stmt (seq, gimple_build_label (header));
4246 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4247 gimple_seq_add_stmt (seq, g);
4248 gimple_seq_add_stmt (seq, gimple_build_label (end));
4252 /* The copyin sequence is not to be executed by the main thread, since
4253 that would result in self-copies. Perhaps not visible to scalars,
4254 but it certainly is to C++ operator=. */
4255 if (copyin_seq)
4257 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4259 x = build2 (NE_EXPR, boolean_type_node, x,
4260 build_int_cst (TREE_TYPE (x), 0));
4261 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4262 gimplify_and_add (x, ilist);
4265 /* If any copyin variable is passed by reference, we must ensure the
4266 master thread doesn't modify it before it is copied over in all
4267 threads. Similarly for variables in both firstprivate and
4268 lastprivate clauses we need to ensure the lastprivate copying
4269 happens after firstprivate copying in all threads. And similarly
4270 for UDRs if initializer expression refers to omp_orig. */
4271 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4273 /* Don't add any barrier for #pragma omp simd or
4274 #pragma omp distribute. */
4275 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4276 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4277 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4280 /* If max_vf is non-zero, then we can use only a vectorization factor
4281 up to the max_vf we chose. So stick it into the safelen clause. */
4282 if (max_vf)
4284 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4285 OMP_CLAUSE_SAFELEN);
4286 if (c == NULL_TREE
4287 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4288 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4289 max_vf) == 1))
4291 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4292 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4293 max_vf);
4294 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4295 gimple_omp_for_set_clauses (ctx->stmt, c);
4301 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4302 both parallel and workshare constructs. PREDICATE may be NULL if it's
4303 always true. */
4305 static void
4306 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4307 omp_context *ctx)
4309 tree x, c, label = NULL, orig_clauses = clauses;
4310 bool par_clauses = false;
4311 tree simduid = NULL, lastlane = NULL;
4313 /* Early exit if there are no lastprivate or linear clauses. */
4314 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4315 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4316 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4317 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4318 break;
4319 if (clauses == NULL)
4321 /* If this was a workshare clause, see if it had been combined
4322 with its parallel. In that case, look for the clauses on the
4323 parallel statement itself. */
4324 if (is_parallel_ctx (ctx))
4325 return;
4327 ctx = ctx->outer;
4328 if (ctx == NULL || !is_parallel_ctx (ctx))
4329 return;
4331 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4332 OMP_CLAUSE_LASTPRIVATE);
4333 if (clauses == NULL)
4334 return;
4335 par_clauses = true;
4338 if (predicate)
4340 gcond *stmt;
4341 tree label_true, arm1, arm2;
4343 label = create_artificial_label (UNKNOWN_LOCATION);
4344 label_true = create_artificial_label (UNKNOWN_LOCATION);
4345 arm1 = TREE_OPERAND (predicate, 0);
4346 arm2 = TREE_OPERAND (predicate, 1);
4347 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4348 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4349 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4350 label_true, label);
4351 gimple_seq_add_stmt (stmt_list, stmt);
4352 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4355 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4356 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4358 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4359 if (simduid)
4360 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4363 for (c = clauses; c ;)
4365 tree var, new_var;
4366 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4368 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4369 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4370 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4372 var = OMP_CLAUSE_DECL (c);
4373 new_var = lookup_decl (var, ctx);
4375 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4377 tree val = DECL_VALUE_EXPR (new_var);
4378 if (TREE_CODE (val) == ARRAY_REF
4379 && VAR_P (TREE_OPERAND (val, 0))
4380 && lookup_attribute ("omp simd array",
4381 DECL_ATTRIBUTES (TREE_OPERAND (val,
4382 0))))
4384 if (lastlane == NULL)
4386 lastlane = create_tmp_var (unsigned_type_node);
4387 gcall *g
4388 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4389 2, simduid,
4390 TREE_OPERAND (val, 1));
4391 gimple_call_set_lhs (g, lastlane);
4392 gimple_seq_add_stmt (stmt_list, g);
4394 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4395 TREE_OPERAND (val, 0), lastlane,
4396 NULL_TREE, NULL_TREE);
4400 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4401 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4403 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4404 gimple_seq_add_seq (stmt_list,
4405 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4406 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4408 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4409 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4411 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4412 gimple_seq_add_seq (stmt_list,
4413 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4414 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4417 x = build_outer_var_ref (var, ctx);
4418 if (is_reference (var))
4419 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4420 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4421 gimplify_and_add (x, stmt_list);
4423 c = OMP_CLAUSE_CHAIN (c);
4424 if (c == NULL && !par_clauses)
4426 /* If this was a workshare clause, see if it had been combined
4427 with its parallel. In that case, continue looking for the
4428 clauses also on the parallel statement itself. */
4429 if (is_parallel_ctx (ctx))
4430 break;
4432 ctx = ctx->outer;
4433 if (ctx == NULL || !is_parallel_ctx (ctx))
4434 break;
4436 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4437 OMP_CLAUSE_LASTPRIVATE);
4438 par_clauses = true;
4442 if (label)
4443 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4446 static void
4447 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4448 tree tid, tree var, tree new_var)
4450 /* The atomic add at the end of the sum creates unnecessary
4451 write contention on accelerators. To work around this,
4452 create an array to store the partial reductions. Later, in
4453 lower_omp_for (for openacc), the values of array will be
4454 combined. */
4456 tree t = NULL_TREE, array, x;
4457 tree type = get_base_type (var);
4458 gimple stmt;
4460 /* Now insert the partial reductions into the array. */
4462 /* Find the reduction array. */
4464 tree ptype = build_pointer_type (type);
4466 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4467 t = build_receiver_ref (t, false, ctx->outer);
4469 array = create_tmp_var (ptype);
4470 gimplify_assign (array, t, stmt_seqp);
4472 tree ptr = create_tmp_var (TREE_TYPE (array));
4474 /* Find the reduction array. */
4476 /* testing a unary conversion. */
4477 tree offset = create_tmp_var (sizetype);
4478 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4479 stmt_seqp);
4480 t = create_tmp_var (sizetype);
4481 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4482 stmt_seqp);
4483 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4484 gimple_seq_add_stmt (stmt_seqp, stmt);
4486 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4487 of adding sizeof(var) to the array? */
4488 ptr = create_tmp_var (ptype);
4489 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4490 offset);
4491 gimple_seq_add_stmt (stmt_seqp, stmt);
4493 /* Move the local sum to gfc$sum[i]. */
4494 x = unshare_expr (build_simple_mem_ref (ptr));
4495 stmt = gimplify_assign (x, new_var, stmt_seqp);
4498 /* Generate code to implement the REDUCTION clauses. */
4500 static void
4501 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4503 gimple_seq sub_seq = NULL;
4504 gimple stmt;
4505 tree x, c, tid = NULL_TREE;
4506 int count = 0;
4508 /* SIMD reductions are handled in lower_rec_input_clauses. */
4509 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4510 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4511 return;
4513 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4514 update in that case, otherwise use a lock. */
4515 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4516 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4518 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4520 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4521 count = -1;
4522 break;
4524 count++;
4527 if (count == 0)
4528 return;
4530 /* Initialize thread info for OpenACC. */
4531 if (is_gimple_omp_oacc (ctx->stmt))
4533 /* Get the current thread id. */
4534 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4535 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4536 gimple stmt = gimple_build_call (call, 0);
4537 gimple_call_set_lhs (stmt, tid);
4538 gimple_seq_add_stmt (stmt_seqp, stmt);
4541 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4543 tree var, ref, new_var;
4544 enum tree_code code;
4545 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4547 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4548 continue;
4550 var = OMP_CLAUSE_DECL (c);
4551 new_var = lookup_decl (var, ctx);
4552 if (is_reference (var))
4553 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4554 ref = build_outer_var_ref (var, ctx);
4555 code = OMP_CLAUSE_REDUCTION_CODE (c);
4557 /* reduction(-:var) sums up the partial results, so it acts
4558 identically to reduction(+:var). */
4559 if (code == MINUS_EXPR)
4560 code = PLUS_EXPR;
4562 if (is_gimple_omp_oacc (ctx->stmt))
4564 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4566 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4568 else if (count == 1)
4570 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4572 addr = save_expr (addr);
4573 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4574 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4575 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4576 gimplify_and_add (x, stmt_seqp);
4577 return;
4579 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4581 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4583 if (is_reference (var)
4584 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4585 TREE_TYPE (ref)))
4586 ref = build_fold_addr_expr_loc (clause_loc, ref);
4587 SET_DECL_VALUE_EXPR (placeholder, ref);
4588 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4589 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4590 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4591 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4592 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4594 else
4596 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4597 ref = build_outer_var_ref (var, ctx);
4598 gimplify_assign (ref, x, &sub_seq);
4602 if (is_gimple_omp_oacc (ctx->stmt))
4603 return;
4605 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4607 gimple_seq_add_stmt (stmt_seqp, stmt);
4609 gimple_seq_add_seq (stmt_seqp, sub_seq);
4611 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4613 gimple_seq_add_stmt (stmt_seqp, stmt);
4617 /* Generate code to implement the COPYPRIVATE clauses. */
4619 static void
4620 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4621 omp_context *ctx)
4623 tree c;
4625 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4627 tree var, new_var, ref, x;
4628 bool by_ref;
4629 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4631 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4632 continue;
4634 var = OMP_CLAUSE_DECL (c);
4635 by_ref = use_pointer_for_field (var, NULL);
4637 ref = build_sender_ref (var, ctx);
4638 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4639 if (by_ref)
4641 x = build_fold_addr_expr_loc (clause_loc, new_var);
4642 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4644 gimplify_assign (ref, x, slist);
4646 ref = build_receiver_ref (var, false, ctx);
4647 if (by_ref)
4649 ref = fold_convert_loc (clause_loc,
4650 build_pointer_type (TREE_TYPE (new_var)),
4651 ref);
4652 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4654 if (is_reference (var))
4656 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4657 ref = build_simple_mem_ref_loc (clause_loc, ref);
4658 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4660 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4661 gimplify_and_add (x, rlist);
4666 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4667 and REDUCTION from the sender (aka parent) side. */
4669 static void
4670 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4671 omp_context *ctx)
4673 tree c;
4675 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4677 tree val, ref, x, var;
4678 bool by_ref, do_in = false, do_out = false;
4679 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4681 switch (OMP_CLAUSE_CODE (c))
4683 case OMP_CLAUSE_PRIVATE:
4684 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4685 break;
4686 continue;
4687 case OMP_CLAUSE_FIRSTPRIVATE:
4688 case OMP_CLAUSE_COPYIN:
4689 case OMP_CLAUSE_LASTPRIVATE:
4690 case OMP_CLAUSE_REDUCTION:
4691 case OMP_CLAUSE__LOOPTEMP_:
4692 break;
4693 default:
4694 continue;
4697 val = OMP_CLAUSE_DECL (c);
4698 var = lookup_decl_in_outer_ctx (val, ctx);
4700 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4701 && is_global_var (var))
4702 continue;
4703 if (is_variable_sized (val))
4704 continue;
4705 by_ref = use_pointer_for_field (val, NULL);
4707 switch (OMP_CLAUSE_CODE (c))
4709 case OMP_CLAUSE_PRIVATE:
4710 case OMP_CLAUSE_FIRSTPRIVATE:
4711 case OMP_CLAUSE_COPYIN:
4712 case OMP_CLAUSE__LOOPTEMP_:
4713 do_in = true;
4714 break;
4716 case OMP_CLAUSE_LASTPRIVATE:
4717 if (by_ref || is_reference (val))
4719 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4720 continue;
4721 do_in = true;
4723 else
4725 do_out = true;
4726 if (lang_hooks.decls.omp_private_outer_ref (val))
4727 do_in = true;
4729 break;
4731 case OMP_CLAUSE_REDUCTION:
4732 do_in = true;
4733 do_out = !(by_ref || is_reference (val));
4734 break;
4736 default:
4737 gcc_unreachable ();
4740 if (do_in)
4742 ref = build_sender_ref (val, ctx);
4743 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4744 gimplify_assign (ref, x, ilist);
4745 if (is_task_ctx (ctx))
4746 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4749 if (do_out)
4751 ref = build_sender_ref (val, ctx);
4752 gimplify_assign (var, ref, olist);
4757 /* Generate code to implement SHARED from the sender (aka parent)
4758 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4759 list things that got automatically shared. */
4761 static void
4762 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4764 tree var, ovar, nvar, f, x, record_type;
4766 if (ctx->record_type == NULL)
4767 return;
4769 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4770 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4772 ovar = DECL_ABSTRACT_ORIGIN (f);
4773 nvar = maybe_lookup_decl (ovar, ctx);
4774 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4775 continue;
4777 /* If CTX is a nested parallel directive. Find the immediately
4778 enclosing parallel or workshare construct that contains a
4779 mapping for OVAR. */
4780 var = lookup_decl_in_outer_ctx (ovar, ctx);
4782 if (use_pointer_for_field (ovar, ctx))
4784 x = build_sender_ref (ovar, ctx);
4785 var = build_fold_addr_expr (var);
4786 gimplify_assign (x, var, ilist);
4788 else
4790 x = build_sender_ref (ovar, ctx);
4791 gimplify_assign (x, var, ilist);
4793 if (!TREE_READONLY (var)
4794 /* We don't need to receive a new reference to a result
4795 or parm decl. In fact we may not store to it as we will
4796 invalidate any pending RSO and generate wrong gimple
4797 during inlining. */
4798 && !((TREE_CODE (var) == RESULT_DECL
4799 || TREE_CODE (var) == PARM_DECL)
4800 && DECL_BY_REFERENCE (var)))
4802 x = build_sender_ref (ovar, ctx);
4803 gimplify_assign (var, x, olist);
4810 /* A convenience function to build an empty GIMPLE_COND with just the
4811 condition. */
4813 static gcond *
4814 gimple_build_cond_empty (tree cond)
4816 enum tree_code pred_code;
4817 tree lhs, rhs;
4819 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4820 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4824 /* Build the function calls to GOMP_parallel_start etc to actually
4825 generate the parallel operation. REGION is the parallel region
4826 being expanded. BB is the block where to insert the code. WS_ARGS
4827 will be set if this is a call to a combined parallel+workshare
4828 construct, it contains the list of additional arguments needed by
4829 the workshare construct. */
4831 static void
4832 expand_parallel_call (struct omp_region *region, basic_block bb,
4833 gomp_parallel *entry_stmt,
4834 vec<tree, va_gc> *ws_args)
4836 tree t, t1, t2, val, cond, c, clauses, flags;
4837 gimple_stmt_iterator gsi;
4838 gimple stmt;
4839 enum built_in_function start_ix;
4840 int start_ix2;
4841 location_t clause_loc;
4842 vec<tree, va_gc> *args;
4844 clauses = gimple_omp_parallel_clauses (entry_stmt);
4846 /* Determine what flavor of GOMP_parallel we will be
4847 emitting. */
4848 start_ix = BUILT_IN_GOMP_PARALLEL;
4849 if (is_combined_parallel (region))
4851 switch (region->inner->type)
4853 case GIMPLE_OMP_FOR:
4854 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4855 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4856 + (region->inner->sched_kind
4857 == OMP_CLAUSE_SCHEDULE_RUNTIME
4858 ? 3 : region->inner->sched_kind));
4859 start_ix = (enum built_in_function)start_ix2;
4860 break;
4861 case GIMPLE_OMP_SECTIONS:
4862 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4863 break;
4864 default:
4865 gcc_unreachable ();
4869 /* By default, the value of NUM_THREADS is zero (selected at run time)
4870 and there is no conditional. */
4871 cond = NULL_TREE;
4872 val = build_int_cst (unsigned_type_node, 0);
4873 flags = build_int_cst (unsigned_type_node, 0);
4875 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4876 if (c)
4877 cond = OMP_CLAUSE_IF_EXPR (c);
4879 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4880 if (c)
4882 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4883 clause_loc = OMP_CLAUSE_LOCATION (c);
4885 else
4886 clause_loc = gimple_location (entry_stmt);
4888 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4889 if (c)
4890 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4892 /* Ensure 'val' is of the correct type. */
4893 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4895 /* If we found the clause 'if (cond)', build either
4896 (cond != 0) or (cond ? val : 1u). */
4897 if (cond)
4899 cond = gimple_boolify (cond);
4901 if (integer_zerop (val))
4902 val = fold_build2_loc (clause_loc,
4903 EQ_EXPR, unsigned_type_node, cond,
4904 build_int_cst (TREE_TYPE (cond), 0));
4905 else
4907 basic_block cond_bb, then_bb, else_bb;
4908 edge e, e_then, e_else;
4909 tree tmp_then, tmp_else, tmp_join, tmp_var;
4911 tmp_var = create_tmp_var (TREE_TYPE (val));
4912 if (gimple_in_ssa_p (cfun))
4914 tmp_then = make_ssa_name (tmp_var);
4915 tmp_else = make_ssa_name (tmp_var);
4916 tmp_join = make_ssa_name (tmp_var);
4918 else
4920 tmp_then = tmp_var;
4921 tmp_else = tmp_var;
4922 tmp_join = tmp_var;
4925 e = split_block (bb, NULL);
4926 cond_bb = e->src;
4927 bb = e->dest;
4928 remove_edge (e);
4930 then_bb = create_empty_bb (cond_bb);
4931 else_bb = create_empty_bb (then_bb);
4932 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4933 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4935 stmt = gimple_build_cond_empty (cond);
4936 gsi = gsi_start_bb (cond_bb);
4937 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4939 gsi = gsi_start_bb (then_bb);
4940 stmt = gimple_build_assign (tmp_then, val);
4941 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4943 gsi = gsi_start_bb (else_bb);
4944 stmt = gimple_build_assign
4945 (tmp_else, build_int_cst (unsigned_type_node, 1));
4946 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4948 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4949 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4950 add_bb_to_loop (then_bb, cond_bb->loop_father);
4951 add_bb_to_loop (else_bb, cond_bb->loop_father);
4952 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4953 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4955 if (gimple_in_ssa_p (cfun))
4957 gphi *phi = create_phi_node (tmp_join, bb);
4958 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4959 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4962 val = tmp_join;
4965 gsi = gsi_start_bb (bb);
4966 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4967 false, GSI_CONTINUE_LINKING);
4970 gsi = gsi_last_bb (bb);
4971 t = gimple_omp_parallel_data_arg (entry_stmt);
4972 if (t == NULL)
4973 t1 = null_pointer_node;
4974 else
4975 t1 = build_fold_addr_expr (t);
4976 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4978 vec_alloc (args, 4 + vec_safe_length (ws_args));
4979 args->quick_push (t2);
4980 args->quick_push (t1);
4981 args->quick_push (val);
4982 if (ws_args)
4983 args->splice (*ws_args);
4984 args->quick_push (flags);
4986 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
4987 builtin_decl_explicit (start_ix), args);
4989 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
4990 false, GSI_CONTINUE_LINKING);
4993 /* Insert a function call whose name is FUNC_NAME with the information from
4994 ENTRY_STMT into the basic_block BB. */
4996 static void
4997 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
4998 vec <tree, va_gc> *ws_args)
5000 tree t, t1, t2;
5001 gimple_stmt_iterator gsi;
5002 vec <tree, va_gc> *args;
5004 gcc_assert (vec_safe_length (ws_args) == 2);
5005 tree func_name = (*ws_args)[0];
5006 tree grain = (*ws_args)[1];
5008 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5009 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5010 gcc_assert (count != NULL_TREE);
5011 count = OMP_CLAUSE_OPERAND (count, 0);
5013 gsi = gsi_last_bb (bb);
5014 t = gimple_omp_parallel_data_arg (entry_stmt);
5015 if (t == NULL)
5016 t1 = null_pointer_node;
5017 else
5018 t1 = build_fold_addr_expr (t);
5019 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5021 vec_alloc (args, 4);
5022 args->quick_push (t2);
5023 args->quick_push (t1);
5024 args->quick_push (count);
5025 args->quick_push (grain);
5026 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5028 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5029 GSI_CONTINUE_LINKING);
5032 /* Build the function call to GOMP_task to actually
5033 generate the task operation. BB is the block where to insert the code. */
5035 static void
5036 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5038 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5039 gimple_stmt_iterator gsi;
5040 location_t loc = gimple_location (entry_stmt);
5042 clauses = gimple_omp_task_clauses (entry_stmt);
5044 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5045 if (c)
5046 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5047 else
5048 cond = boolean_true_node;
5050 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5051 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5052 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5053 flags = build_int_cst (unsigned_type_node,
5054 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5056 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5057 if (c)
5059 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5060 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5061 build_int_cst (unsigned_type_node, 2),
5062 build_int_cst (unsigned_type_node, 0));
5063 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5065 if (depend)
5066 depend = OMP_CLAUSE_DECL (depend);
5067 else
5068 depend = build_int_cst (ptr_type_node, 0);
5070 gsi = gsi_last_bb (bb);
5071 t = gimple_omp_task_data_arg (entry_stmt);
5072 if (t == NULL)
5073 t2 = null_pointer_node;
5074 else
5075 t2 = build_fold_addr_expr_loc (loc, t);
5076 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5077 t = gimple_omp_task_copy_fn (entry_stmt);
5078 if (t == NULL)
5079 t3 = null_pointer_node;
5080 else
5081 t3 = build_fold_addr_expr_loc (loc, t);
5083 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5084 8, t1, t2, t3,
5085 gimple_omp_task_arg_size (entry_stmt),
5086 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5087 depend);
5089 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5090 false, GSI_CONTINUE_LINKING);
5094 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5095 catch handler and return it. This prevents programs from violating the
5096 structured block semantics with throws. */
5098 static gimple_seq
5099 maybe_catch_exception (gimple_seq body)
5101 gimple g;
5102 tree decl;
5104 if (!flag_exceptions)
5105 return body;
5107 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5108 decl = lang_hooks.eh_protect_cleanup_actions ();
5109 else
5110 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5112 g = gimple_build_eh_must_not_throw (decl);
5113 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5114 GIMPLE_TRY_CATCH);
5116 return gimple_seq_alloc_with_stmt (g);
5119 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5121 static tree
5122 vec2chain (vec<tree, va_gc> *v)
5124 tree chain = NULL_TREE, t;
5125 unsigned ix;
5127 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5129 DECL_CHAIN (t) = chain;
5130 chain = t;
5133 return chain;
5137 /* Remove barriers in REGION->EXIT's block. Note that this is only
5138 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5139 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5140 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5141 removed. */
5143 static void
5144 remove_exit_barrier (struct omp_region *region)
5146 gimple_stmt_iterator gsi;
5147 basic_block exit_bb;
5148 edge_iterator ei;
5149 edge e;
5150 gimple stmt;
5151 int any_addressable_vars = -1;
5153 exit_bb = region->exit;
5155 /* If the parallel region doesn't return, we don't have REGION->EXIT
5156 block at all. */
5157 if (! exit_bb)
5158 return;
5160 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5161 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5162 statements that can appear in between are extremely limited -- no
5163 memory operations at all. Here, we allow nothing at all, so the
5164 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5165 gsi = gsi_last_bb (exit_bb);
5166 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5167 gsi_prev (&gsi);
5168 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5169 return;
5171 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5173 gsi = gsi_last_bb (e->src);
5174 if (gsi_end_p (gsi))
5175 continue;
5176 stmt = gsi_stmt (gsi);
5177 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5178 && !gimple_omp_return_nowait_p (stmt))
5180 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5181 in many cases. If there could be tasks queued, the barrier
5182 might be needed to let the tasks run before some local
5183 variable of the parallel that the task uses as shared
5184 runs out of scope. The task can be spawned either
5185 from within current function (this would be easy to check)
5186 or from some function it calls and gets passed an address
5187 of such a variable. */
5188 if (any_addressable_vars < 0)
5190 gomp_parallel *parallel_stmt
5191 = as_a <gomp_parallel *> (last_stmt (region->entry));
5192 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5193 tree local_decls, block, decl;
5194 unsigned ix;
5196 any_addressable_vars = 0;
5197 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5198 if (TREE_ADDRESSABLE (decl))
5200 any_addressable_vars = 1;
5201 break;
5203 for (block = gimple_block (stmt);
5204 !any_addressable_vars
5205 && block
5206 && TREE_CODE (block) == BLOCK;
5207 block = BLOCK_SUPERCONTEXT (block))
5209 for (local_decls = BLOCK_VARS (block);
5210 local_decls;
5211 local_decls = DECL_CHAIN (local_decls))
5212 if (TREE_ADDRESSABLE (local_decls))
5214 any_addressable_vars = 1;
5215 break;
5217 if (block == gimple_block (parallel_stmt))
5218 break;
5221 if (!any_addressable_vars)
5222 gimple_omp_return_set_nowait (stmt);
5227 static void
5228 remove_exit_barriers (struct omp_region *region)
5230 if (region->type == GIMPLE_OMP_PARALLEL)
5231 remove_exit_barrier (region);
5233 if (region->inner)
5235 region = region->inner;
5236 remove_exit_barriers (region);
5237 while (region->next)
5239 region = region->next;
5240 remove_exit_barriers (region);
5245 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5246 calls. These can't be declared as const functions, but
5247 within one parallel body they are constant, so they can be
5248 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5249 which are declared const. Similarly for task body, except
5250 that in untied task omp_get_thread_num () can change at any task
5251 scheduling point. */
5253 static void
5254 optimize_omp_library_calls (gimple entry_stmt)
5256 basic_block bb;
5257 gimple_stmt_iterator gsi;
5258 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5259 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5260 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5261 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5262 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5263 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5264 OMP_CLAUSE_UNTIED) != NULL);
5266 FOR_EACH_BB_FN (bb, cfun)
5267 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5269 gimple call = gsi_stmt (gsi);
5270 tree decl;
5272 if (is_gimple_call (call)
5273 && (decl = gimple_call_fndecl (call))
5274 && DECL_EXTERNAL (decl)
5275 && TREE_PUBLIC (decl)
5276 && DECL_INITIAL (decl) == NULL)
5278 tree built_in;
5280 if (DECL_NAME (decl) == thr_num_id)
5282 /* In #pragma omp task untied omp_get_thread_num () can change
5283 during the execution of the task region. */
5284 if (untied_task)
5285 continue;
5286 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5288 else if (DECL_NAME (decl) == num_thr_id)
5289 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5290 else
5291 continue;
5293 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5294 || gimple_call_num_args (call) != 0)
5295 continue;
5297 if (flag_exceptions && !TREE_NOTHROW (decl))
5298 continue;
5300 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5301 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5302 TREE_TYPE (TREE_TYPE (built_in))))
5303 continue;
5305 gimple_call_set_fndecl (call, built_in);
5310 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5311 regimplified. */
5313 static tree
5314 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5316 tree t = *tp;
5318 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5319 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5320 return t;
5322 if (TREE_CODE (t) == ADDR_EXPR)
5323 recompute_tree_invariant_for_addr_expr (t);
5325 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5326 return NULL_TREE;
5329 /* Prepend TO = FROM assignment before *GSI_P. */
5331 static void
5332 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5334 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5335 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5336 true, GSI_SAME_STMT);
5337 gimple stmt = gimple_build_assign (to, from);
5338 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5339 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5340 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5342 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5343 gimple_regimplify_operands (stmt, &gsi);
5347 /* Expand the OpenMP parallel or task directive starting at REGION. */
5349 static void
5350 expand_omp_taskreg (struct omp_region *region)
5352 basic_block entry_bb, exit_bb, new_bb;
5353 struct function *child_cfun;
5354 tree child_fn, block, t;
5355 gimple_stmt_iterator gsi;
5356 gimple entry_stmt, stmt;
5357 edge e;
5358 vec<tree, va_gc> *ws_args;
5360 entry_stmt = last_stmt (region->entry);
5361 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5362 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5364 entry_bb = region->entry;
5365 exit_bb = region->exit;
5367 bool is_cilk_for
5368 = (flag_cilkplus
5369 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5370 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5371 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5373 if (is_cilk_for)
5374 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5375 and the inner statement contains the name of the built-in function
5376 and grain. */
5377 ws_args = region->inner->ws_args;
5378 else if (is_combined_parallel (region))
5379 ws_args = region->ws_args;
5380 else
5381 ws_args = NULL;
5383 if (child_cfun->cfg)
5385 /* Due to inlining, it may happen that we have already outlined
5386 the region, in which case all we need to do is make the
5387 sub-graph unreachable and emit the parallel call. */
5388 edge entry_succ_e, exit_succ_e;
5390 entry_succ_e = single_succ_edge (entry_bb);
5392 gsi = gsi_last_bb (entry_bb);
5393 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5394 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5395 gsi_remove (&gsi, true);
5397 new_bb = entry_bb;
5398 if (exit_bb)
5400 exit_succ_e = single_succ_edge (exit_bb);
5401 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5403 remove_edge_and_dominated_blocks (entry_succ_e);
5405 else
5407 unsigned srcidx, dstidx, num;
5409 /* If the parallel region needs data sent from the parent
5410 function, then the very first statement (except possible
5411 tree profile counter updates) of the parallel body
5412 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5413 &.OMP_DATA_O is passed as an argument to the child function,
5414 we need to replace it with the argument as seen by the child
5415 function.
5417 In most cases, this will end up being the identity assignment
5418 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5419 a function call that has been inlined, the original PARM_DECL
5420 .OMP_DATA_I may have been converted into a different local
5421 variable. In which case, we need to keep the assignment. */
5422 if (gimple_omp_taskreg_data_arg (entry_stmt))
5424 basic_block entry_succ_bb = single_succ (entry_bb);
5425 tree arg, narg;
5426 gimple parcopy_stmt = NULL;
5428 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5430 gimple stmt;
5432 gcc_assert (!gsi_end_p (gsi));
5433 stmt = gsi_stmt (gsi);
5434 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5435 continue;
5437 if (gimple_num_ops (stmt) == 2)
5439 tree arg = gimple_assign_rhs1 (stmt);
5441 /* We're ignore the subcode because we're
5442 effectively doing a STRIP_NOPS. */
5444 if (TREE_CODE (arg) == ADDR_EXPR
5445 && TREE_OPERAND (arg, 0)
5446 == gimple_omp_taskreg_data_arg (entry_stmt))
5448 parcopy_stmt = stmt;
5449 break;
5454 gcc_assert (parcopy_stmt != NULL);
5455 arg = DECL_ARGUMENTS (child_fn);
5457 if (!gimple_in_ssa_p (cfun))
5459 if (gimple_assign_lhs (parcopy_stmt) == arg)
5460 gsi_remove (&gsi, true);
5461 else
5463 /* ?? Is setting the subcode really necessary ?? */
5464 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5465 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5468 else
5470 /* If we are in ssa form, we must load the value from the default
5471 definition of the argument. That should not be defined now,
5472 since the argument is not used uninitialized. */
5473 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5474 narg = make_ssa_name (arg, gimple_build_nop ());
5475 set_ssa_default_def (cfun, arg, narg);
5476 /* ?? Is setting the subcode really necessary ?? */
5477 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5478 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5479 update_stmt (parcopy_stmt);
5483 /* Declare local variables needed in CHILD_CFUN. */
5484 block = DECL_INITIAL (child_fn);
5485 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5486 /* The gimplifier could record temporaries in parallel/task block
5487 rather than in containing function's local_decls chain,
5488 which would mean cgraph missed finalizing them. Do it now. */
5489 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5490 if (TREE_CODE (t) == VAR_DECL
5491 && TREE_STATIC (t)
5492 && !DECL_EXTERNAL (t))
5493 varpool_node::finalize_decl (t);
5494 DECL_SAVED_TREE (child_fn) = NULL;
5495 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5496 gimple_set_body (child_fn, NULL);
5497 TREE_USED (block) = 1;
5499 /* Reset DECL_CONTEXT on function arguments. */
5500 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5501 DECL_CONTEXT (t) = child_fn;
5503 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5504 so that it can be moved to the child function. */
5505 gsi = gsi_last_bb (entry_bb);
5506 stmt = gsi_stmt (gsi);
5507 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5508 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5509 gsi_remove (&gsi, true);
5510 e = split_block (entry_bb, stmt);
5511 entry_bb = e->dest;
5512 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5514 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5515 if (exit_bb)
5517 gsi = gsi_last_bb (exit_bb);
5518 gcc_assert (!gsi_end_p (gsi)
5519 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5520 stmt = gimple_build_return (NULL);
5521 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5522 gsi_remove (&gsi, true);
5525 /* Move the parallel region into CHILD_CFUN. */
5527 if (gimple_in_ssa_p (cfun))
5529 init_tree_ssa (child_cfun);
5530 init_ssa_operands (child_cfun);
5531 child_cfun->gimple_df->in_ssa_p = true;
5532 block = NULL_TREE;
5534 else
5535 block = gimple_block (entry_stmt);
5537 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5538 if (exit_bb)
5539 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5540 /* When the OMP expansion process cannot guarantee an up-to-date
5541 loop tree arrange for the child function to fixup loops. */
5542 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5543 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5545 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5546 num = vec_safe_length (child_cfun->local_decls);
5547 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5549 t = (*child_cfun->local_decls)[srcidx];
5550 if (DECL_CONTEXT (t) == cfun->decl)
5551 continue;
5552 if (srcidx != dstidx)
5553 (*child_cfun->local_decls)[dstidx] = t;
5554 dstidx++;
5556 if (dstidx != num)
5557 vec_safe_truncate (child_cfun->local_decls, dstidx);
5559 /* Inform the callgraph about the new function. */
5560 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5561 cgraph_node::add_new_function (child_fn, true);
5563 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5564 fixed in a following pass. */
5565 push_cfun (child_cfun);
5566 if (optimize)
5567 optimize_omp_library_calls (entry_stmt);
5568 cgraph_edge::rebuild_edges ();
5570 /* Some EH regions might become dead, see PR34608. If
5571 pass_cleanup_cfg isn't the first pass to happen with the
5572 new child, these dead EH edges might cause problems.
5573 Clean them up now. */
5574 if (flag_exceptions)
5576 basic_block bb;
5577 bool changed = false;
5579 FOR_EACH_BB_FN (bb, cfun)
5580 changed |= gimple_purge_dead_eh_edges (bb);
5581 if (changed)
5582 cleanup_tree_cfg ();
5584 if (gimple_in_ssa_p (cfun))
5585 update_ssa (TODO_update_ssa);
5586 pop_cfun ();
5589 /* Emit a library call to launch the children threads. */
5590 if (is_cilk_for)
5591 expand_cilk_for_call (new_bb,
5592 as_a <gomp_parallel *> (entry_stmt), ws_args);
5593 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5594 expand_parallel_call (region, new_bb,
5595 as_a <gomp_parallel *> (entry_stmt), ws_args);
5596 else
5597 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5598 if (gimple_in_ssa_p (cfun))
5599 update_ssa (TODO_update_ssa_only_virtuals);
5603 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5604 of the combined collapse > 1 loop constructs, generate code like:
5605 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5606 if (cond3 is <)
5607 adj = STEP3 - 1;
5608 else
5609 adj = STEP3 + 1;
5610 count3 = (adj + N32 - N31) / STEP3;
5611 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5612 if (cond2 is <)
5613 adj = STEP2 - 1;
5614 else
5615 adj = STEP2 + 1;
5616 count2 = (adj + N22 - N21) / STEP2;
5617 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5618 if (cond1 is <)
5619 adj = STEP1 - 1;
5620 else
5621 adj = STEP1 + 1;
5622 count1 = (adj + N12 - N11) / STEP1;
5623 count = count1 * count2 * count3;
5624 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5625 count = 0;
5626 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5627 of the combined loop constructs, just initialize COUNTS array
5628 from the _looptemp_ clauses. */
5630 /* NOTE: It *could* be better to moosh all of the BBs together,
5631 creating one larger BB with all the computation and the unexpected
5632 jump at the end. I.e.
5634 bool zero3, zero2, zero1, zero;
5636 zero3 = N32 c3 N31;
5637 count3 = (N32 - N31) /[cl] STEP3;
5638 zero2 = N22 c2 N21;
5639 count2 = (N22 - N21) /[cl] STEP2;
5640 zero1 = N12 c1 N11;
5641 count1 = (N12 - N11) /[cl] STEP1;
5642 zero = zero3 || zero2 || zero1;
5643 count = count1 * count2 * count3;
5644 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5646 After all, we expect the zero=false, and thus we expect to have to
5647 evaluate all of the comparison expressions, so short-circuiting
5648 oughtn't be a win. Since the condition isn't protecting a
5649 denominator, we're not concerned about divide-by-zero, so we can
5650 fully evaluate count even if a numerator turned out to be wrong.
5652 It seems like putting this all together would create much better
5653 scheduling opportunities, and less pressure on the chip's branch
5654 predictor. */
5656 static void
5657 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5658 basic_block &entry_bb, tree *counts,
5659 basic_block &zero_iter_bb, int &first_zero_iter,
5660 basic_block &l2_dom_bb)
5662 tree t, type = TREE_TYPE (fd->loop.v);
5663 edge e, ne;
5664 int i;
5666 /* Collapsed loops need work for expansion into SSA form. */
5667 gcc_assert (!gimple_in_ssa_p (cfun));
5669 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5670 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5672 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5673 isn't supposed to be handled, as the inner loop doesn't
5674 use it. */
5675 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5676 OMP_CLAUSE__LOOPTEMP_);
5677 gcc_assert (innerc);
5678 for (i = 0; i < fd->collapse; i++)
5680 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5681 OMP_CLAUSE__LOOPTEMP_);
5682 gcc_assert (innerc);
5683 if (i)
5684 counts[i] = OMP_CLAUSE_DECL (innerc);
5685 else
5686 counts[0] = NULL_TREE;
5688 return;
5691 for (i = 0; i < fd->collapse; i++)
5693 tree itype = TREE_TYPE (fd->loops[i].v);
5695 if (SSA_VAR_P (fd->loop.n2)
5696 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5697 fold_convert (itype, fd->loops[i].n1),
5698 fold_convert (itype, fd->loops[i].n2)))
5699 == NULL_TREE || !integer_onep (t)))
5701 gcond *cond_stmt;
5702 tree n1, n2;
5703 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5704 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5705 true, GSI_SAME_STMT);
5706 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5707 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5708 true, GSI_SAME_STMT);
5709 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5710 NULL_TREE, NULL_TREE);
5711 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5712 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5713 expand_omp_regimplify_p, NULL, NULL)
5714 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5715 expand_omp_regimplify_p, NULL, NULL))
5717 *gsi = gsi_for_stmt (cond_stmt);
5718 gimple_regimplify_operands (cond_stmt, gsi);
5720 e = split_block (entry_bb, cond_stmt);
5721 if (zero_iter_bb == NULL)
5723 gassign *assign_stmt;
5724 first_zero_iter = i;
5725 zero_iter_bb = create_empty_bb (entry_bb);
5726 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5727 *gsi = gsi_after_labels (zero_iter_bb);
5728 assign_stmt = gimple_build_assign (fd->loop.n2,
5729 build_zero_cst (type));
5730 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5731 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5732 entry_bb);
5734 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5735 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5736 e->flags = EDGE_TRUE_VALUE;
5737 e->probability = REG_BR_PROB_BASE - ne->probability;
5738 if (l2_dom_bb == NULL)
5739 l2_dom_bb = entry_bb;
5740 entry_bb = e->dest;
5741 *gsi = gsi_last_bb (entry_bb);
5744 if (POINTER_TYPE_P (itype))
5745 itype = signed_type_for (itype);
5746 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5747 ? -1 : 1));
5748 t = fold_build2 (PLUS_EXPR, itype,
5749 fold_convert (itype, fd->loops[i].step), t);
5750 t = fold_build2 (PLUS_EXPR, itype, t,
5751 fold_convert (itype, fd->loops[i].n2));
5752 t = fold_build2 (MINUS_EXPR, itype, t,
5753 fold_convert (itype, fd->loops[i].n1));
5754 /* ?? We could probably use CEIL_DIV_EXPR instead of
5755 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5756 generate the same code in the end because generically we
5757 don't know that the values involved must be negative for
5758 GT?? */
5759 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5760 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5761 fold_build1 (NEGATE_EXPR, itype, t),
5762 fold_build1 (NEGATE_EXPR, itype,
5763 fold_convert (itype,
5764 fd->loops[i].step)));
5765 else
5766 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5767 fold_convert (itype, fd->loops[i].step));
5768 t = fold_convert (type, t);
5769 if (TREE_CODE (t) == INTEGER_CST)
5770 counts[i] = t;
5771 else
5773 counts[i] = create_tmp_reg (type, ".count");
5774 expand_omp_build_assign (gsi, counts[i], t);
5776 if (SSA_VAR_P (fd->loop.n2))
5778 if (i == 0)
5779 t = counts[0];
5780 else
5781 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5782 expand_omp_build_assign (gsi, fd->loop.n2, t);
5788 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5789 T = V;
5790 V3 = N31 + (T % count3) * STEP3;
5791 T = T / count3;
5792 V2 = N21 + (T % count2) * STEP2;
5793 T = T / count2;
5794 V1 = N11 + T * STEP1;
5795 if this loop doesn't have an inner loop construct combined with it.
5796 If it does have an inner loop construct combined with it and the
5797 iteration count isn't known constant, store values from counts array
5798 into its _looptemp_ temporaries instead. */
5800 static void
5801 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5802 tree *counts, gimple inner_stmt, tree startvar)
5804 int i;
5805 if (gimple_omp_for_combined_p (fd->for_stmt))
5807 /* If fd->loop.n2 is constant, then no propagation of the counts
5808 is needed, they are constant. */
5809 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5810 return;
5812 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5813 ? gimple_omp_parallel_clauses (inner_stmt)
5814 : gimple_omp_for_clauses (inner_stmt);
5815 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5816 isn't supposed to be handled, as the inner loop doesn't
5817 use it. */
5818 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5819 gcc_assert (innerc);
5820 for (i = 0; i < fd->collapse; i++)
5822 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5823 OMP_CLAUSE__LOOPTEMP_);
5824 gcc_assert (innerc);
5825 if (i)
5827 tree tem = OMP_CLAUSE_DECL (innerc);
5828 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5829 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5830 false, GSI_CONTINUE_LINKING);
5831 gassign *stmt = gimple_build_assign (tem, t);
5832 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5835 return;
5838 tree type = TREE_TYPE (fd->loop.v);
5839 tree tem = create_tmp_reg (type, ".tem");
5840 gassign *stmt = gimple_build_assign (tem, startvar);
5841 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5843 for (i = fd->collapse - 1; i >= 0; i--)
5845 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5846 itype = vtype;
5847 if (POINTER_TYPE_P (vtype))
5848 itype = signed_type_for (vtype);
5849 if (i != 0)
5850 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5851 else
5852 t = tem;
5853 t = fold_convert (itype, t);
5854 t = fold_build2 (MULT_EXPR, itype, t,
5855 fold_convert (itype, fd->loops[i].step));
5856 if (POINTER_TYPE_P (vtype))
5857 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5858 else
5859 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5860 t = force_gimple_operand_gsi (gsi, t,
5861 DECL_P (fd->loops[i].v)
5862 && TREE_ADDRESSABLE (fd->loops[i].v),
5863 NULL_TREE, false,
5864 GSI_CONTINUE_LINKING);
5865 stmt = gimple_build_assign (fd->loops[i].v, t);
5866 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5867 if (i != 0)
5869 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5870 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5871 false, GSI_CONTINUE_LINKING);
5872 stmt = gimple_build_assign (tem, t);
5873 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5879 /* Helper function for expand_omp_for_*. Generate code like:
5880 L10:
5881 V3 += STEP3;
5882 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5883 L11:
5884 V3 = N31;
5885 V2 += STEP2;
5886 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5887 L12:
5888 V2 = N21;
5889 V1 += STEP1;
5890 goto BODY_BB; */
5892 static basic_block
5893 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5894 basic_block body_bb)
5896 basic_block last_bb, bb, collapse_bb = NULL;
5897 int i;
5898 gimple_stmt_iterator gsi;
5899 edge e;
5900 tree t;
5901 gimple stmt;
5903 last_bb = cont_bb;
5904 for (i = fd->collapse - 1; i >= 0; i--)
5906 tree vtype = TREE_TYPE (fd->loops[i].v);
5908 bb = create_empty_bb (last_bb);
5909 add_bb_to_loop (bb, last_bb->loop_father);
5910 gsi = gsi_start_bb (bb);
5912 if (i < fd->collapse - 1)
5914 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5915 e->probability = REG_BR_PROB_BASE / 8;
5917 t = fd->loops[i + 1].n1;
5918 t = force_gimple_operand_gsi (&gsi, t,
5919 DECL_P (fd->loops[i + 1].v)
5920 && TREE_ADDRESSABLE (fd->loops[i
5921 + 1].v),
5922 NULL_TREE, false,
5923 GSI_CONTINUE_LINKING);
5924 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5925 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5927 else
5928 collapse_bb = bb;
5930 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5932 if (POINTER_TYPE_P (vtype))
5933 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5934 else
5935 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5936 t = force_gimple_operand_gsi (&gsi, t,
5937 DECL_P (fd->loops[i].v)
5938 && TREE_ADDRESSABLE (fd->loops[i].v),
5939 NULL_TREE, false, GSI_CONTINUE_LINKING);
5940 stmt = gimple_build_assign (fd->loops[i].v, t);
5941 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5943 if (i > 0)
5945 t = fd->loops[i].n2;
5946 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5947 false, GSI_CONTINUE_LINKING);
5948 tree v = fd->loops[i].v;
5949 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5950 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5951 false, GSI_CONTINUE_LINKING);
5952 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5953 stmt = gimple_build_cond_empty (t);
5954 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5955 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5956 e->probability = REG_BR_PROB_BASE * 7 / 8;
5958 else
5959 make_edge (bb, body_bb, EDGE_FALLTHRU);
5960 last_bb = bb;
5963 return collapse_bb;
5967 /* A subroutine of expand_omp_for. Generate code for a parallel
5968 loop with any schedule. Given parameters:
5970 for (V = N1; V cond N2; V += STEP) BODY;
5972 where COND is "<" or ">", we generate pseudocode
5974 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5975 if (more) goto L0; else goto L3;
5977 V = istart0;
5978 iend = iend0;
5980 BODY;
5981 V += STEP;
5982 if (V cond iend) goto L1; else goto L2;
5984 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
5987 If this is a combined omp parallel loop, instead of the call to
5988 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
5989 If this is gimple_omp_for_combined_p loop, then instead of assigning
5990 V and iend in L0 we assign the first two _looptemp_ clause decls of the
5991 inner GIMPLE_OMP_FOR and V += STEP; and
5992 if (V cond iend) goto L1; else goto L2; are removed.
5994 For collapsed loops, given parameters:
5995 collapse(3)
5996 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
5997 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
5998 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
5999 BODY;
6001 we generate pseudocode
6003 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6004 if (cond3 is <)
6005 adj = STEP3 - 1;
6006 else
6007 adj = STEP3 + 1;
6008 count3 = (adj + N32 - N31) / STEP3;
6009 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6010 if (cond2 is <)
6011 adj = STEP2 - 1;
6012 else
6013 adj = STEP2 + 1;
6014 count2 = (adj + N22 - N21) / STEP2;
6015 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6016 if (cond1 is <)
6017 adj = STEP1 - 1;
6018 else
6019 adj = STEP1 + 1;
6020 count1 = (adj + N12 - N11) / STEP1;
6021 count = count1 * count2 * count3;
6022 goto Z1;
6024 count = 0;
6026 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6027 if (more) goto L0; else goto L3;
6029 V = istart0;
6030 T = V;
6031 V3 = N31 + (T % count3) * STEP3;
6032 T = T / count3;
6033 V2 = N21 + (T % count2) * STEP2;
6034 T = T / count2;
6035 V1 = N11 + T * STEP1;
6036 iend = iend0;
6038 BODY;
6039 V += 1;
6040 if (V < iend) goto L10; else goto L2;
6041 L10:
6042 V3 += STEP3;
6043 if (V3 cond3 N32) goto L1; else goto L11;
6044 L11:
6045 V3 = N31;
6046 V2 += STEP2;
6047 if (V2 cond2 N22) goto L1; else goto L12;
6048 L12:
6049 V2 = N21;
6050 V1 += STEP1;
6051 goto L1;
6053 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6058 static void
6059 expand_omp_for_generic (struct omp_region *region,
6060 struct omp_for_data *fd,
6061 enum built_in_function start_fn,
6062 enum built_in_function next_fn,
6063 gimple inner_stmt)
6065 tree type, istart0, iend0, iend;
6066 tree t, vmain, vback, bias = NULL_TREE;
6067 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6068 basic_block l2_bb = NULL, l3_bb = NULL;
6069 gimple_stmt_iterator gsi;
6070 gassign *assign_stmt;
6071 bool in_combined_parallel = is_combined_parallel (region);
6072 bool broken_loop = region->cont == NULL;
6073 edge e, ne;
6074 tree *counts = NULL;
6075 int i;
6077 gcc_assert (!broken_loop || !in_combined_parallel);
6078 gcc_assert (fd->iter_type == long_integer_type_node
6079 || !in_combined_parallel);
6081 type = TREE_TYPE (fd->loop.v);
6082 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6083 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6084 TREE_ADDRESSABLE (istart0) = 1;
6085 TREE_ADDRESSABLE (iend0) = 1;
6087 /* See if we need to bias by LLONG_MIN. */
6088 if (fd->iter_type == long_long_unsigned_type_node
6089 && TREE_CODE (type) == INTEGER_TYPE
6090 && !TYPE_UNSIGNED (type))
6092 tree n1, n2;
6094 if (fd->loop.cond_code == LT_EXPR)
6096 n1 = fd->loop.n1;
6097 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6099 else
6101 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6102 n2 = fd->loop.n1;
6104 if (TREE_CODE (n1) != INTEGER_CST
6105 || TREE_CODE (n2) != INTEGER_CST
6106 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6107 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6110 entry_bb = region->entry;
6111 cont_bb = region->cont;
6112 collapse_bb = NULL;
6113 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6114 gcc_assert (broken_loop
6115 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6116 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6117 l1_bb = single_succ (l0_bb);
6118 if (!broken_loop)
6120 l2_bb = create_empty_bb (cont_bb);
6121 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6122 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6124 else
6125 l2_bb = NULL;
6126 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6127 exit_bb = region->exit;
6129 gsi = gsi_last_bb (entry_bb);
6131 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6132 if (fd->collapse > 1)
6134 int first_zero_iter = -1;
6135 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6137 counts = XALLOCAVEC (tree, fd->collapse);
6138 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6139 zero_iter_bb, first_zero_iter,
6140 l2_dom_bb);
6142 if (zero_iter_bb)
6144 /* Some counts[i] vars might be uninitialized if
6145 some loop has zero iterations. But the body shouldn't
6146 be executed in that case, so just avoid uninit warnings. */
6147 for (i = first_zero_iter; i < fd->collapse; i++)
6148 if (SSA_VAR_P (counts[i]))
6149 TREE_NO_WARNING (counts[i]) = 1;
6150 gsi_prev (&gsi);
6151 e = split_block (entry_bb, gsi_stmt (gsi));
6152 entry_bb = e->dest;
6153 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6154 gsi = gsi_last_bb (entry_bb);
6155 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6156 get_immediate_dominator (CDI_DOMINATORS,
6157 zero_iter_bb));
6160 if (in_combined_parallel)
6162 /* In a combined parallel loop, emit a call to
6163 GOMP_loop_foo_next. */
6164 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6165 build_fold_addr_expr (istart0),
6166 build_fold_addr_expr (iend0));
6168 else
6170 tree t0, t1, t2, t3, t4;
6171 /* If this is not a combined parallel loop, emit a call to
6172 GOMP_loop_foo_start in ENTRY_BB. */
6173 t4 = build_fold_addr_expr (iend0);
6174 t3 = build_fold_addr_expr (istart0);
6175 t2 = fold_convert (fd->iter_type, fd->loop.step);
6176 t1 = fd->loop.n2;
6177 t0 = fd->loop.n1;
6178 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6180 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6181 OMP_CLAUSE__LOOPTEMP_);
6182 gcc_assert (innerc);
6183 t0 = OMP_CLAUSE_DECL (innerc);
6184 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6185 OMP_CLAUSE__LOOPTEMP_);
6186 gcc_assert (innerc);
6187 t1 = OMP_CLAUSE_DECL (innerc);
6189 if (POINTER_TYPE_P (TREE_TYPE (t0))
6190 && TYPE_PRECISION (TREE_TYPE (t0))
6191 != TYPE_PRECISION (fd->iter_type))
6193 /* Avoid casting pointers to integer of a different size. */
6194 tree itype = signed_type_for (type);
6195 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6196 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6198 else
6200 t1 = fold_convert (fd->iter_type, t1);
6201 t0 = fold_convert (fd->iter_type, t0);
6203 if (bias)
6205 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6206 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6208 if (fd->iter_type == long_integer_type_node)
6210 if (fd->chunk_size)
6212 t = fold_convert (fd->iter_type, fd->chunk_size);
6213 t = build_call_expr (builtin_decl_explicit (start_fn),
6214 6, t0, t1, t2, t, t3, t4);
6216 else
6217 t = build_call_expr (builtin_decl_explicit (start_fn),
6218 5, t0, t1, t2, t3, t4);
6220 else
6222 tree t5;
6223 tree c_bool_type;
6224 tree bfn_decl;
6226 /* The GOMP_loop_ull_*start functions have additional boolean
6227 argument, true for < loops and false for > loops.
6228 In Fortran, the C bool type can be different from
6229 boolean_type_node. */
6230 bfn_decl = builtin_decl_explicit (start_fn);
6231 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6232 t5 = build_int_cst (c_bool_type,
6233 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6234 if (fd->chunk_size)
6236 tree bfn_decl = builtin_decl_explicit (start_fn);
6237 t = fold_convert (fd->iter_type, fd->chunk_size);
6238 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6240 else
6241 t = build_call_expr (builtin_decl_explicit (start_fn),
6242 6, t5, t0, t1, t2, t3, t4);
6245 if (TREE_TYPE (t) != boolean_type_node)
6246 t = fold_build2 (NE_EXPR, boolean_type_node,
6247 t, build_int_cst (TREE_TYPE (t), 0));
6248 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6249 true, GSI_SAME_STMT);
6250 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6252 /* Remove the GIMPLE_OMP_FOR statement. */
6253 gsi_remove (&gsi, true);
6255 /* Iteration setup for sequential loop goes in L0_BB. */
6256 tree startvar = fd->loop.v;
6257 tree endvar = NULL_TREE;
6259 if (gimple_omp_for_combined_p (fd->for_stmt))
6261 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6262 && gimple_omp_for_kind (inner_stmt)
6263 == GF_OMP_FOR_KIND_SIMD);
6264 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6265 OMP_CLAUSE__LOOPTEMP_);
6266 gcc_assert (innerc);
6267 startvar = OMP_CLAUSE_DECL (innerc);
6268 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6269 OMP_CLAUSE__LOOPTEMP_);
6270 gcc_assert (innerc);
6271 endvar = OMP_CLAUSE_DECL (innerc);
6274 gsi = gsi_start_bb (l0_bb);
6275 t = istart0;
6276 if (bias)
6277 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6278 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6279 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6280 t = fold_convert (TREE_TYPE (startvar), t);
6281 t = force_gimple_operand_gsi (&gsi, t,
6282 DECL_P (startvar)
6283 && TREE_ADDRESSABLE (startvar),
6284 NULL_TREE, false, GSI_CONTINUE_LINKING);
6285 assign_stmt = gimple_build_assign (startvar, t);
6286 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6288 t = iend0;
6289 if (bias)
6290 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6291 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6292 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6293 t = fold_convert (TREE_TYPE (startvar), t);
6294 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6295 false, GSI_CONTINUE_LINKING);
6296 if (endvar)
6298 assign_stmt = gimple_build_assign (endvar, iend);
6299 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6300 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6301 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6302 else
6303 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6304 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6306 if (fd->collapse > 1)
6307 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6309 if (!broken_loop)
6311 /* Code to control the increment and predicate for the sequential
6312 loop goes in the CONT_BB. */
6313 gsi = gsi_last_bb (cont_bb);
6314 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6315 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6316 vmain = gimple_omp_continue_control_use (cont_stmt);
6317 vback = gimple_omp_continue_control_def (cont_stmt);
6319 if (!gimple_omp_for_combined_p (fd->for_stmt))
6321 if (POINTER_TYPE_P (type))
6322 t = fold_build_pointer_plus (vmain, fd->loop.step);
6323 else
6324 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6325 t = force_gimple_operand_gsi (&gsi, t,
6326 DECL_P (vback)
6327 && TREE_ADDRESSABLE (vback),
6328 NULL_TREE, true, GSI_SAME_STMT);
6329 assign_stmt = gimple_build_assign (vback, t);
6330 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6332 t = build2 (fd->loop.cond_code, boolean_type_node,
6333 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6334 iend);
6335 gcond *cond_stmt = gimple_build_cond_empty (t);
6336 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6339 /* Remove GIMPLE_OMP_CONTINUE. */
6340 gsi_remove (&gsi, true);
6342 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6343 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6345 /* Emit code to get the next parallel iteration in L2_BB. */
6346 gsi = gsi_start_bb (l2_bb);
6348 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6349 build_fold_addr_expr (istart0),
6350 build_fold_addr_expr (iend0));
6351 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6352 false, GSI_CONTINUE_LINKING);
6353 if (TREE_TYPE (t) != boolean_type_node)
6354 t = fold_build2 (NE_EXPR, boolean_type_node,
6355 t, build_int_cst (TREE_TYPE (t), 0));
6356 gcond *cond_stmt = gimple_build_cond_empty (t);
6357 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6360 /* Add the loop cleanup function. */
6361 gsi = gsi_last_bb (exit_bb);
6362 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6363 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6364 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6365 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6366 else
6367 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6368 gcall *call_stmt = gimple_build_call (t, 0);
6369 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6370 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6371 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6372 gsi_remove (&gsi, true);
6374 /* Connect the new blocks. */
6375 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6376 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6378 if (!broken_loop)
6380 gimple_seq phis;
6382 e = find_edge (cont_bb, l3_bb);
6383 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6385 phis = phi_nodes (l3_bb);
6386 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6388 gimple phi = gsi_stmt (gsi);
6389 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6390 PHI_ARG_DEF_FROM_EDGE (phi, e));
6392 remove_edge (e);
6394 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6395 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6396 e = find_edge (cont_bb, l1_bb);
6397 if (gimple_omp_for_combined_p (fd->for_stmt))
6399 remove_edge (e);
6400 e = NULL;
6402 else if (fd->collapse > 1)
6404 remove_edge (e);
6405 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6407 else
6408 e->flags = EDGE_TRUE_VALUE;
6409 if (e)
6411 e->probability = REG_BR_PROB_BASE * 7 / 8;
6412 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6414 else
6416 e = find_edge (cont_bb, l2_bb);
6417 e->flags = EDGE_FALLTHRU;
6419 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6421 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6422 recompute_dominator (CDI_DOMINATORS, l2_bb));
6423 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6424 recompute_dominator (CDI_DOMINATORS, l3_bb));
6425 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6426 recompute_dominator (CDI_DOMINATORS, l0_bb));
6427 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6428 recompute_dominator (CDI_DOMINATORS, l1_bb));
6430 struct loop *outer_loop = alloc_loop ();
6431 outer_loop->header = l0_bb;
6432 outer_loop->latch = l2_bb;
6433 add_loop (outer_loop, l0_bb->loop_father);
6435 if (!gimple_omp_for_combined_p (fd->for_stmt))
6437 struct loop *loop = alloc_loop ();
6438 loop->header = l1_bb;
6439 /* The loop may have multiple latches. */
6440 add_loop (loop, outer_loop);
6446 /* A subroutine of expand_omp_for. Generate code for a parallel
6447 loop with static schedule and no specified chunk size. Given
6448 parameters:
6450 for (V = N1; V cond N2; V += STEP) BODY;
6452 where COND is "<" or ">", we generate pseudocode
6454 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6455 if (cond is <)
6456 adj = STEP - 1;
6457 else
6458 adj = STEP + 1;
6459 if ((__typeof (V)) -1 > 0 && cond is >)
6460 n = -(adj + N2 - N1) / -STEP;
6461 else
6462 n = (adj + N2 - N1) / STEP;
6463 q = n / nthreads;
6464 tt = n % nthreads;
6465 if (threadid < tt) goto L3; else goto L4;
6467 tt = 0;
6468 q = q + 1;
6470 s0 = q * threadid + tt;
6471 e0 = s0 + q;
6472 V = s0 * STEP + N1;
6473 if (s0 >= e0) goto L2; else goto L0;
6475 e = e0 * STEP + N1;
6477 BODY;
6478 V += STEP;
6479 if (V cond e) goto L1;
6483 static void
6484 expand_omp_for_static_nochunk (struct omp_region *region,
6485 struct omp_for_data *fd,
6486 gimple inner_stmt)
6488 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6489 tree type, itype, vmain, vback;
6490 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6491 basic_block body_bb, cont_bb, collapse_bb = NULL;
6492 basic_block fin_bb;
6493 gimple_stmt_iterator gsi;
6494 edge ep;
6495 bool broken_loop = region->cont == NULL;
6496 tree *counts = NULL;
6497 tree n1, n2, step;
6499 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6500 != GF_OMP_FOR_KIND_OACC_LOOP)
6501 || !inner_stmt);
6503 itype = type = TREE_TYPE (fd->loop.v);
6504 if (POINTER_TYPE_P (type))
6505 itype = signed_type_for (type);
6507 entry_bb = region->entry;
6508 cont_bb = region->cont;
6509 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6510 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6511 gcc_assert (broken_loop
6512 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6513 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6514 body_bb = single_succ (seq_start_bb);
6515 if (!broken_loop)
6517 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6518 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6520 exit_bb = region->exit;
6522 /* Iteration space partitioning goes in ENTRY_BB. */
6523 gsi = gsi_last_bb (entry_bb);
6524 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6526 if (fd->collapse > 1)
6528 int first_zero_iter = -1;
6529 basic_block l2_dom_bb = NULL;
6531 counts = XALLOCAVEC (tree, fd->collapse);
6532 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6533 fin_bb, first_zero_iter,
6534 l2_dom_bb);
6535 t = NULL_TREE;
6537 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6538 t = integer_one_node;
6539 else
6540 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6541 fold_convert (type, fd->loop.n1),
6542 fold_convert (type, fd->loop.n2));
6543 if (fd->collapse == 1
6544 && TYPE_UNSIGNED (type)
6545 && (t == NULL_TREE || !integer_onep (t)))
6547 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6548 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6549 true, GSI_SAME_STMT);
6550 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6551 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6552 true, GSI_SAME_STMT);
6553 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6554 NULL_TREE, NULL_TREE);
6555 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6556 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6557 expand_omp_regimplify_p, NULL, NULL)
6558 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6559 expand_omp_regimplify_p, NULL, NULL))
6561 gsi = gsi_for_stmt (cond_stmt);
6562 gimple_regimplify_operands (cond_stmt, &gsi);
6564 ep = split_block (entry_bb, cond_stmt);
6565 ep->flags = EDGE_TRUE_VALUE;
6566 entry_bb = ep->dest;
6567 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6568 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6569 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6570 if (gimple_in_ssa_p (cfun))
6572 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6573 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6574 !gsi_end_p (gpi); gsi_next (&gpi))
6576 gphi *phi = gpi.phi ();
6577 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6578 ep, UNKNOWN_LOCATION);
6581 gsi = gsi_last_bb (entry_bb);
6584 switch (gimple_omp_for_kind (fd->for_stmt))
6586 case GF_OMP_FOR_KIND_FOR:
6587 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6588 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6589 break;
6590 case GF_OMP_FOR_KIND_DISTRIBUTE:
6591 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6592 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6593 break;
6594 case GF_OMP_FOR_KIND_OACC_LOOP:
6595 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6596 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6597 break;
6598 default:
6599 gcc_unreachable ();
6601 nthreads = build_call_expr (nthreads, 0);
6602 nthreads = fold_convert (itype, nthreads);
6603 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6604 true, GSI_SAME_STMT);
6605 threadid = build_call_expr (threadid, 0);
6606 threadid = fold_convert (itype, threadid);
6607 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6608 true, GSI_SAME_STMT);
6610 n1 = fd->loop.n1;
6611 n2 = fd->loop.n2;
6612 step = fd->loop.step;
6613 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6615 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6616 OMP_CLAUSE__LOOPTEMP_);
6617 gcc_assert (innerc);
6618 n1 = OMP_CLAUSE_DECL (innerc);
6619 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6620 OMP_CLAUSE__LOOPTEMP_);
6621 gcc_assert (innerc);
6622 n2 = OMP_CLAUSE_DECL (innerc);
6624 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6625 true, NULL_TREE, true, GSI_SAME_STMT);
6626 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6627 true, NULL_TREE, true, GSI_SAME_STMT);
6628 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6629 true, NULL_TREE, true, GSI_SAME_STMT);
6631 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6632 t = fold_build2 (PLUS_EXPR, itype, step, t);
6633 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6634 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6635 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6636 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6637 fold_build1 (NEGATE_EXPR, itype, t),
6638 fold_build1 (NEGATE_EXPR, itype, step));
6639 else
6640 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6641 t = fold_convert (itype, t);
6642 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6644 q = create_tmp_reg (itype, "q");
6645 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6646 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6647 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6649 tt = create_tmp_reg (itype, "tt");
6650 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6651 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6652 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6654 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6655 gcond *cond_stmt = gimple_build_cond_empty (t);
6656 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6658 second_bb = split_block (entry_bb, cond_stmt)->dest;
6659 gsi = gsi_last_bb (second_bb);
6660 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6662 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6663 GSI_SAME_STMT);
6664 gassign *assign_stmt
6665 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6666 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6668 third_bb = split_block (second_bb, assign_stmt)->dest;
6669 gsi = gsi_last_bb (third_bb);
6670 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6672 t = build2 (MULT_EXPR, itype, q, threadid);
6673 t = build2 (PLUS_EXPR, itype, t, tt);
6674 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6676 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6677 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6679 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6680 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6682 /* Remove the GIMPLE_OMP_FOR statement. */
6683 gsi_remove (&gsi, true);
6685 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6686 gsi = gsi_start_bb (seq_start_bb);
6688 tree startvar = fd->loop.v;
6689 tree endvar = NULL_TREE;
6691 if (gimple_omp_for_combined_p (fd->for_stmt))
6693 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6694 ? gimple_omp_parallel_clauses (inner_stmt)
6695 : gimple_omp_for_clauses (inner_stmt);
6696 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6697 gcc_assert (innerc);
6698 startvar = OMP_CLAUSE_DECL (innerc);
6699 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6700 OMP_CLAUSE__LOOPTEMP_);
6701 gcc_assert (innerc);
6702 endvar = OMP_CLAUSE_DECL (innerc);
6704 t = fold_convert (itype, s0);
6705 t = fold_build2 (MULT_EXPR, itype, t, step);
6706 if (POINTER_TYPE_P (type))
6707 t = fold_build_pointer_plus (n1, t);
6708 else
6709 t = fold_build2 (PLUS_EXPR, type, t, n1);
6710 t = fold_convert (TREE_TYPE (startvar), t);
6711 t = force_gimple_operand_gsi (&gsi, t,
6712 DECL_P (startvar)
6713 && TREE_ADDRESSABLE (startvar),
6714 NULL_TREE, false, GSI_CONTINUE_LINKING);
6715 assign_stmt = gimple_build_assign (startvar, t);
6716 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6718 t = fold_convert (itype, e0);
6719 t = fold_build2 (MULT_EXPR, itype, t, step);
6720 if (POINTER_TYPE_P (type))
6721 t = fold_build_pointer_plus (n1, t);
6722 else
6723 t = fold_build2 (PLUS_EXPR, type, t, n1);
6724 t = fold_convert (TREE_TYPE (startvar), t);
6725 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6726 false, GSI_CONTINUE_LINKING);
6727 if (endvar)
6729 assign_stmt = gimple_build_assign (endvar, e);
6730 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6731 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6732 assign_stmt = gimple_build_assign (fd->loop.v, e);
6733 else
6734 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6735 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6737 if (fd->collapse > 1)
6738 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6740 if (!broken_loop)
6742 /* The code controlling the sequential loop replaces the
6743 GIMPLE_OMP_CONTINUE. */
6744 gsi = gsi_last_bb (cont_bb);
6745 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6746 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6747 vmain = gimple_omp_continue_control_use (cont_stmt);
6748 vback = gimple_omp_continue_control_def (cont_stmt);
6750 if (!gimple_omp_for_combined_p (fd->for_stmt))
6752 if (POINTER_TYPE_P (type))
6753 t = fold_build_pointer_plus (vmain, step);
6754 else
6755 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6756 t = force_gimple_operand_gsi (&gsi, t,
6757 DECL_P (vback)
6758 && TREE_ADDRESSABLE (vback),
6759 NULL_TREE, true, GSI_SAME_STMT);
6760 assign_stmt = gimple_build_assign (vback, t);
6761 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6763 t = build2 (fd->loop.cond_code, boolean_type_node,
6764 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6765 ? t : vback, e);
6766 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6769 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6770 gsi_remove (&gsi, true);
6772 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6773 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6776 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6777 gsi = gsi_last_bb (exit_bb);
6778 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6780 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6781 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6782 gcc_checking_assert (t == NULL_TREE);
6783 else
6784 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6786 gsi_remove (&gsi, true);
6788 /* Connect all the blocks. */
6789 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6790 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6791 ep = find_edge (entry_bb, second_bb);
6792 ep->flags = EDGE_TRUE_VALUE;
6793 ep->probability = REG_BR_PROB_BASE / 4;
6794 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6795 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6797 if (!broken_loop)
6799 ep = find_edge (cont_bb, body_bb);
6800 if (gimple_omp_for_combined_p (fd->for_stmt))
6802 remove_edge (ep);
6803 ep = NULL;
6805 else if (fd->collapse > 1)
6807 remove_edge (ep);
6808 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6810 else
6811 ep->flags = EDGE_TRUE_VALUE;
6812 find_edge (cont_bb, fin_bb)->flags
6813 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6816 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6817 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6818 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6820 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6821 recompute_dominator (CDI_DOMINATORS, body_bb));
6822 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6823 recompute_dominator (CDI_DOMINATORS, fin_bb));
6825 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6827 struct loop *loop = alloc_loop ();
6828 loop->header = body_bb;
6829 if (collapse_bb == NULL)
6830 loop->latch = cont_bb;
6831 add_loop (loop, body_bb->loop_father);
6836 /* A subroutine of expand_omp_for. Generate code for a parallel
6837 loop with static schedule and a specified chunk size. Given
6838 parameters:
6840 for (V = N1; V cond N2; V += STEP) BODY;
6842 where COND is "<" or ">", we generate pseudocode
6844 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6845 if (cond is <)
6846 adj = STEP - 1;
6847 else
6848 adj = STEP + 1;
6849 if ((__typeof (V)) -1 > 0 && cond is >)
6850 n = -(adj + N2 - N1) / -STEP;
6851 else
6852 n = (adj + N2 - N1) / STEP;
6853 trip = 0;
6854 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6855 here so that V is defined
6856 if the loop is not entered
6858 s0 = (trip * nthreads + threadid) * CHUNK;
6859 e0 = min(s0 + CHUNK, n);
6860 if (s0 < n) goto L1; else goto L4;
6862 V = s0 * STEP + N1;
6863 e = e0 * STEP + N1;
6865 BODY;
6866 V += STEP;
6867 if (V cond e) goto L2; else goto L3;
6869 trip += 1;
6870 goto L0;
6874 static void
6875 expand_omp_for_static_chunk (struct omp_region *region,
6876 struct omp_for_data *fd, gimple inner_stmt)
6878 tree n, s0, e0, e, t;
6879 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6880 tree type, itype, vmain, vback, vextra;
6881 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6882 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6883 gimple_stmt_iterator gsi;
6884 edge se;
6885 bool broken_loop = region->cont == NULL;
6886 tree *counts = NULL;
6887 tree n1, n2, step;
6889 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6890 != GF_OMP_FOR_KIND_OACC_LOOP)
6891 || !inner_stmt);
6893 itype = type = TREE_TYPE (fd->loop.v);
6894 if (POINTER_TYPE_P (type))
6895 itype = signed_type_for (type);
6897 entry_bb = region->entry;
6898 se = split_block (entry_bb, last_stmt (entry_bb));
6899 entry_bb = se->src;
6900 iter_part_bb = se->dest;
6901 cont_bb = region->cont;
6902 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6903 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6904 gcc_assert (broken_loop
6905 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6906 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6907 body_bb = single_succ (seq_start_bb);
6908 if (!broken_loop)
6910 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6911 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6912 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6914 exit_bb = region->exit;
6916 /* Trip and adjustment setup goes in ENTRY_BB. */
6917 gsi = gsi_last_bb (entry_bb);
6918 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6920 if (fd->collapse > 1)
6922 int first_zero_iter = -1;
6923 basic_block l2_dom_bb = NULL;
6925 counts = XALLOCAVEC (tree, fd->collapse);
6926 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6927 fin_bb, first_zero_iter,
6928 l2_dom_bb);
6929 t = NULL_TREE;
6931 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6932 t = integer_one_node;
6933 else
6934 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6935 fold_convert (type, fd->loop.n1),
6936 fold_convert (type, fd->loop.n2));
6937 if (fd->collapse == 1
6938 && TYPE_UNSIGNED (type)
6939 && (t == NULL_TREE || !integer_onep (t)))
6941 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6942 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6943 true, GSI_SAME_STMT);
6944 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6945 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6946 true, GSI_SAME_STMT);
6947 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6948 NULL_TREE, NULL_TREE);
6949 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6950 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6951 expand_omp_regimplify_p, NULL, NULL)
6952 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6953 expand_omp_regimplify_p, NULL, NULL))
6955 gsi = gsi_for_stmt (cond_stmt);
6956 gimple_regimplify_operands (cond_stmt, &gsi);
6958 se = split_block (entry_bb, cond_stmt);
6959 se->flags = EDGE_TRUE_VALUE;
6960 entry_bb = se->dest;
6961 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6962 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6963 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6964 if (gimple_in_ssa_p (cfun))
6966 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6967 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6968 !gsi_end_p (gpi); gsi_next (&gpi))
6970 gphi *phi = gpi.phi ();
6971 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6972 se, UNKNOWN_LOCATION);
6975 gsi = gsi_last_bb (entry_bb);
6978 switch (gimple_omp_for_kind (fd->for_stmt))
6980 case GF_OMP_FOR_KIND_FOR:
6981 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6982 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6983 break;
6984 case GF_OMP_FOR_KIND_DISTRIBUTE:
6985 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6986 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6987 break;
6988 case GF_OMP_FOR_KIND_OACC_LOOP:
6989 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6990 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6991 break;
6992 default:
6993 gcc_unreachable ();
6995 nthreads = build_call_expr (nthreads, 0);
6996 nthreads = fold_convert (itype, nthreads);
6997 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6998 true, GSI_SAME_STMT);
6999 threadid = build_call_expr (threadid, 0);
7000 threadid = fold_convert (itype, threadid);
7001 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7002 true, GSI_SAME_STMT);
7004 n1 = fd->loop.n1;
7005 n2 = fd->loop.n2;
7006 step = fd->loop.step;
7007 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7009 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7010 OMP_CLAUSE__LOOPTEMP_);
7011 gcc_assert (innerc);
7012 n1 = OMP_CLAUSE_DECL (innerc);
7013 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7014 OMP_CLAUSE__LOOPTEMP_);
7015 gcc_assert (innerc);
7016 n2 = OMP_CLAUSE_DECL (innerc);
7018 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7019 true, NULL_TREE, true, GSI_SAME_STMT);
7020 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7021 true, NULL_TREE, true, GSI_SAME_STMT);
7022 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7023 true, NULL_TREE, true, GSI_SAME_STMT);
7024 fd->chunk_size
7025 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7026 true, NULL_TREE, true, GSI_SAME_STMT);
7028 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7029 t = fold_build2 (PLUS_EXPR, itype, step, t);
7030 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7031 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7032 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7033 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7034 fold_build1 (NEGATE_EXPR, itype, t),
7035 fold_build1 (NEGATE_EXPR, itype, step));
7036 else
7037 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7038 t = fold_convert (itype, t);
7039 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7040 true, GSI_SAME_STMT);
7042 trip_var = create_tmp_reg (itype, ".trip");
7043 if (gimple_in_ssa_p (cfun))
7045 trip_init = make_ssa_name (trip_var);
7046 trip_main = make_ssa_name (trip_var);
7047 trip_back = make_ssa_name (trip_var);
7049 else
7051 trip_init = trip_var;
7052 trip_main = trip_var;
7053 trip_back = trip_var;
7056 gassign *assign_stmt
7057 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7058 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7060 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7061 t = fold_build2 (MULT_EXPR, itype, t, step);
7062 if (POINTER_TYPE_P (type))
7063 t = fold_build_pointer_plus (n1, t);
7064 else
7065 t = fold_build2 (PLUS_EXPR, type, t, n1);
7066 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7067 true, GSI_SAME_STMT);
7069 /* Remove the GIMPLE_OMP_FOR. */
7070 gsi_remove (&gsi, true);
7072 /* Iteration space partitioning goes in ITER_PART_BB. */
7073 gsi = gsi_last_bb (iter_part_bb);
7075 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7076 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7077 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7078 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7079 false, GSI_CONTINUE_LINKING);
7081 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7082 t = fold_build2 (MIN_EXPR, itype, t, n);
7083 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7084 false, GSI_CONTINUE_LINKING);
7086 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7087 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7089 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7090 gsi = gsi_start_bb (seq_start_bb);
7092 tree startvar = fd->loop.v;
7093 tree endvar = NULL_TREE;
7095 if (gimple_omp_for_combined_p (fd->for_stmt))
7097 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7098 ? gimple_omp_parallel_clauses (inner_stmt)
7099 : gimple_omp_for_clauses (inner_stmt);
7100 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7101 gcc_assert (innerc);
7102 startvar = OMP_CLAUSE_DECL (innerc);
7103 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7104 OMP_CLAUSE__LOOPTEMP_);
7105 gcc_assert (innerc);
7106 endvar = OMP_CLAUSE_DECL (innerc);
7109 t = fold_convert (itype, s0);
7110 t = fold_build2 (MULT_EXPR, itype, t, step);
7111 if (POINTER_TYPE_P (type))
7112 t = fold_build_pointer_plus (n1, t);
7113 else
7114 t = fold_build2 (PLUS_EXPR, type, t, n1);
7115 t = fold_convert (TREE_TYPE (startvar), t);
7116 t = force_gimple_operand_gsi (&gsi, t,
7117 DECL_P (startvar)
7118 && TREE_ADDRESSABLE (startvar),
7119 NULL_TREE, false, GSI_CONTINUE_LINKING);
7120 assign_stmt = gimple_build_assign (startvar, t);
7121 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7123 t = fold_convert (itype, e0);
7124 t = fold_build2 (MULT_EXPR, itype, t, step);
7125 if (POINTER_TYPE_P (type))
7126 t = fold_build_pointer_plus (n1, t);
7127 else
7128 t = fold_build2 (PLUS_EXPR, type, t, n1);
7129 t = fold_convert (TREE_TYPE (startvar), t);
7130 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7131 false, GSI_CONTINUE_LINKING);
7132 if (endvar)
7134 assign_stmt = gimple_build_assign (endvar, e);
7135 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7136 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7137 assign_stmt = gimple_build_assign (fd->loop.v, e);
7138 else
7139 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7140 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7142 if (fd->collapse > 1)
7143 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7145 if (!broken_loop)
7147 /* The code controlling the sequential loop goes in CONT_BB,
7148 replacing the GIMPLE_OMP_CONTINUE. */
7149 gsi = gsi_last_bb (cont_bb);
7150 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7151 vmain = gimple_omp_continue_control_use (cont_stmt);
7152 vback = gimple_omp_continue_control_def (cont_stmt);
7154 if (!gimple_omp_for_combined_p (fd->for_stmt))
7156 if (POINTER_TYPE_P (type))
7157 t = fold_build_pointer_plus (vmain, step);
7158 else
7159 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7160 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7161 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7162 true, GSI_SAME_STMT);
7163 assign_stmt = gimple_build_assign (vback, t);
7164 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7166 t = build2 (fd->loop.cond_code, boolean_type_node,
7167 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7168 ? t : vback, e);
7169 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7172 /* Remove GIMPLE_OMP_CONTINUE. */
7173 gsi_remove (&gsi, true);
7175 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7176 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7178 /* Trip update code goes into TRIP_UPDATE_BB. */
7179 gsi = gsi_start_bb (trip_update_bb);
7181 t = build_int_cst (itype, 1);
7182 t = build2 (PLUS_EXPR, itype, trip_main, t);
7183 assign_stmt = gimple_build_assign (trip_back, t);
7184 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7187 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7188 gsi = gsi_last_bb (exit_bb);
7189 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7191 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7192 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7193 gcc_checking_assert (t == NULL_TREE);
7194 else
7195 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7197 gsi_remove (&gsi, true);
7199 /* Connect the new blocks. */
7200 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7201 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7203 if (!broken_loop)
7205 se = find_edge (cont_bb, body_bb);
7206 if (gimple_omp_for_combined_p (fd->for_stmt))
7208 remove_edge (se);
7209 se = NULL;
7211 else if (fd->collapse > 1)
7213 remove_edge (se);
7214 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7216 else
7217 se->flags = EDGE_TRUE_VALUE;
7218 find_edge (cont_bb, trip_update_bb)->flags
7219 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7221 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7224 if (gimple_in_ssa_p (cfun))
7226 gphi_iterator psi;
7227 gphi *phi;
7228 edge re, ene;
7229 edge_var_map *vm;
7230 size_t i;
7232 gcc_assert (fd->collapse == 1 && !broken_loop);
7234 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7235 remove arguments of the phi nodes in fin_bb. We need to create
7236 appropriate phi nodes in iter_part_bb instead. */
7237 se = single_pred_edge (fin_bb);
7238 re = single_succ_edge (trip_update_bb);
7239 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7240 ene = single_succ_edge (entry_bb);
7242 psi = gsi_start_phis (fin_bb);
7243 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7244 gsi_next (&psi), ++i)
7246 gphi *nphi;
7247 source_location locus;
7249 phi = psi.phi ();
7250 t = gimple_phi_result (phi);
7251 gcc_assert (t == redirect_edge_var_map_result (vm));
7252 nphi = create_phi_node (t, iter_part_bb);
7254 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7255 locus = gimple_phi_arg_location_from_edge (phi, se);
7257 /* A special case -- fd->loop.v is not yet computed in
7258 iter_part_bb, we need to use vextra instead. */
7259 if (t == fd->loop.v)
7260 t = vextra;
7261 add_phi_arg (nphi, t, ene, locus);
7262 locus = redirect_edge_var_map_location (vm);
7263 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7265 gcc_assert (gsi_end_p (psi) && i == head->length ());
7266 redirect_edge_var_map_clear (re);
7267 while (1)
7269 psi = gsi_start_phis (fin_bb);
7270 if (gsi_end_p (psi))
7271 break;
7272 remove_phi_node (&psi, false);
7275 /* Make phi node for trip. */
7276 phi = create_phi_node (trip_main, iter_part_bb);
7277 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7278 UNKNOWN_LOCATION);
7279 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7280 UNKNOWN_LOCATION);
7283 if (!broken_loop)
7284 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7285 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7286 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7287 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7288 recompute_dominator (CDI_DOMINATORS, fin_bb));
7289 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7290 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7291 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7292 recompute_dominator (CDI_DOMINATORS, body_bb));
7294 if (!broken_loop)
7296 struct loop *trip_loop = alloc_loop ();
7297 trip_loop->header = iter_part_bb;
7298 trip_loop->latch = trip_update_bb;
7299 add_loop (trip_loop, iter_part_bb->loop_father);
7301 if (!gimple_omp_for_combined_p (fd->for_stmt))
7303 struct loop *loop = alloc_loop ();
7304 loop->header = body_bb;
7305 if (collapse_bb == NULL)
7306 loop->latch = cont_bb;
7307 add_loop (loop, trip_loop);
7312 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7313 Given parameters:
7314 for (V = N1; V cond N2; V += STEP) BODY;
7316 where COND is "<" or ">" or "!=", we generate pseudocode
7318 for (ind_var = low; ind_var < high; ind_var++)
7320 V = n1 + (ind_var * STEP)
7322 <BODY>
7325 In the above pseudocode, low and high are function parameters of the
7326 child function. In the function below, we are inserting a temp.
7327 variable that will be making a call to two OMP functions that will not be
7328 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7329 with _Cilk_for). These functions are replaced with low and high
7330 by the function that handles taskreg. */
7333 static void
7334 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7336 bool broken_loop = region->cont == NULL;
7337 basic_block entry_bb = region->entry;
7338 basic_block cont_bb = region->cont;
7340 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7341 gcc_assert (broken_loop
7342 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7343 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7344 basic_block l1_bb, l2_bb;
7346 if (!broken_loop)
7348 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7349 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7350 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7351 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7353 else
7355 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7356 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7357 l2_bb = single_succ (l1_bb);
7359 basic_block exit_bb = region->exit;
7360 basic_block l2_dom_bb = NULL;
7362 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7364 /* Below statements until the "tree high_val = ..." are pseudo statements
7365 used to pass information to be used by expand_omp_taskreg.
7366 low_val and high_val will be replaced by the __low and __high
7367 parameter from the child function.
7369 The call_exprs part is a place-holder, it is mainly used
7370 to distinctly identify to the top-level part that this is
7371 where we should put low and high (reasoning given in header
7372 comment). */
7374 tree child_fndecl
7375 = gimple_omp_parallel_child_fn (
7376 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7377 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7378 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7380 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7381 high_val = t;
7382 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7383 low_val = t;
7385 gcc_assert (low_val && high_val);
7387 tree type = TREE_TYPE (low_val);
7388 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7389 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7391 /* Not needed in SSA form right now. */
7392 gcc_assert (!gimple_in_ssa_p (cfun));
7393 if (l2_dom_bb == NULL)
7394 l2_dom_bb = l1_bb;
7396 tree n1 = low_val;
7397 tree n2 = high_val;
7399 gimple stmt = gimple_build_assign (ind_var, n1);
7401 /* Replace the GIMPLE_OMP_FOR statement. */
7402 gsi_replace (&gsi, stmt, true);
7404 if (!broken_loop)
7406 /* Code to control the increment goes in the CONT_BB. */
7407 gsi = gsi_last_bb (cont_bb);
7408 stmt = gsi_stmt (gsi);
7409 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7410 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7411 build_one_cst (type));
7413 /* Replace GIMPLE_OMP_CONTINUE. */
7414 gsi_replace (&gsi, stmt, true);
7417 /* Emit the condition in L1_BB. */
7418 gsi = gsi_after_labels (l1_bb);
7419 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7420 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7421 fd->loop.step);
7422 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7423 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7424 fd->loop.n1, fold_convert (sizetype, t));
7425 else
7426 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7427 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7428 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7429 expand_omp_build_assign (&gsi, fd->loop.v, t);
7431 /* The condition is always '<' since the runtime will fill in the low
7432 and high values. */
7433 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7434 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7436 /* Remove GIMPLE_OMP_RETURN. */
7437 gsi = gsi_last_bb (exit_bb);
7438 gsi_remove (&gsi, true);
7440 /* Connect the new blocks. */
7441 remove_edge (FALLTHRU_EDGE (entry_bb));
7443 edge e, ne;
7444 if (!broken_loop)
7446 remove_edge (BRANCH_EDGE (entry_bb));
7447 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7449 e = BRANCH_EDGE (l1_bb);
7450 ne = FALLTHRU_EDGE (l1_bb);
7451 e->flags = EDGE_TRUE_VALUE;
7453 else
7455 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7457 ne = single_succ_edge (l1_bb);
7458 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7461 ne->flags = EDGE_FALSE_VALUE;
7462 e->probability = REG_BR_PROB_BASE * 7 / 8;
7463 ne->probability = REG_BR_PROB_BASE / 8;
7465 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7466 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7467 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7469 if (!broken_loop)
7471 struct loop *loop = alloc_loop ();
7472 loop->header = l1_bb;
7473 loop->latch = cont_bb;
7474 add_loop (loop, l1_bb->loop_father);
7475 loop->safelen = INT_MAX;
7478 /* Pick the correct library function based on the precision of the
7479 induction variable type. */
7480 tree lib_fun = NULL_TREE;
7481 if (TYPE_PRECISION (type) == 32)
7482 lib_fun = cilk_for_32_fndecl;
7483 else if (TYPE_PRECISION (type) == 64)
7484 lib_fun = cilk_for_64_fndecl;
7485 else
7486 gcc_unreachable ();
7488 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7490 /* WS_ARGS contains the library function flavor to call:
7491 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7492 user-defined grain value. If the user does not define one, then zero
7493 is passed in by the parser. */
7494 vec_alloc (region->ws_args, 2);
7495 region->ws_args->quick_push (lib_fun);
7496 region->ws_args->quick_push (fd->chunk_size);
7499 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7500 loop. Given parameters:
7502 for (V = N1; V cond N2; V += STEP) BODY;
7504 where COND is "<" or ">", we generate pseudocode
7506 V = N1;
7507 goto L1;
7509 BODY;
7510 V += STEP;
7512 if (V cond N2) goto L0; else goto L2;
7515 For collapsed loops, given parameters:
7516 collapse(3)
7517 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7518 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7519 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7520 BODY;
7522 we generate pseudocode
7524 if (cond3 is <)
7525 adj = STEP3 - 1;
7526 else
7527 adj = STEP3 + 1;
7528 count3 = (adj + N32 - N31) / STEP3;
7529 if (cond2 is <)
7530 adj = STEP2 - 1;
7531 else
7532 adj = STEP2 + 1;
7533 count2 = (adj + N22 - N21) / STEP2;
7534 if (cond1 is <)
7535 adj = STEP1 - 1;
7536 else
7537 adj = STEP1 + 1;
7538 count1 = (adj + N12 - N11) / STEP1;
7539 count = count1 * count2 * count3;
7540 V = 0;
7541 V1 = N11;
7542 V2 = N21;
7543 V3 = N31;
7544 goto L1;
7546 BODY;
7547 V += 1;
7548 V3 += STEP3;
7549 V2 += (V3 cond3 N32) ? 0 : STEP2;
7550 V3 = (V3 cond3 N32) ? V3 : N31;
7551 V1 += (V2 cond2 N22) ? 0 : STEP1;
7552 V2 = (V2 cond2 N22) ? V2 : N21;
7554 if (V < count) goto L0; else goto L2;
7559 static void
7560 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7562 tree type, t;
7563 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7564 gimple_stmt_iterator gsi;
7565 gimple stmt;
7566 gcond *cond_stmt;
7567 bool broken_loop = region->cont == NULL;
7568 edge e, ne;
7569 tree *counts = NULL;
7570 int i;
7571 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7572 OMP_CLAUSE_SAFELEN);
7573 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7574 OMP_CLAUSE__SIMDUID_);
7575 tree n1, n2;
7577 type = TREE_TYPE (fd->loop.v);
7578 entry_bb = region->entry;
7579 cont_bb = region->cont;
7580 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7581 gcc_assert (broken_loop
7582 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7583 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7584 if (!broken_loop)
7586 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7587 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7588 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7589 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7591 else
7593 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7594 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7595 l2_bb = single_succ (l1_bb);
7597 exit_bb = region->exit;
7598 l2_dom_bb = NULL;
7600 gsi = gsi_last_bb (entry_bb);
7602 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7603 /* Not needed in SSA form right now. */
7604 gcc_assert (!gimple_in_ssa_p (cfun));
7605 if (fd->collapse > 1)
7607 int first_zero_iter = -1;
7608 basic_block zero_iter_bb = l2_bb;
7610 counts = XALLOCAVEC (tree, fd->collapse);
7611 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7612 zero_iter_bb, first_zero_iter,
7613 l2_dom_bb);
7615 if (l2_dom_bb == NULL)
7616 l2_dom_bb = l1_bb;
7618 n1 = fd->loop.n1;
7619 n2 = fd->loop.n2;
7620 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7622 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7623 OMP_CLAUSE__LOOPTEMP_);
7624 gcc_assert (innerc);
7625 n1 = OMP_CLAUSE_DECL (innerc);
7626 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7627 OMP_CLAUSE__LOOPTEMP_);
7628 gcc_assert (innerc);
7629 n2 = OMP_CLAUSE_DECL (innerc);
7630 expand_omp_build_assign (&gsi, fd->loop.v,
7631 fold_convert (type, n1));
7632 if (fd->collapse > 1)
7634 gsi_prev (&gsi);
7635 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7636 gsi_next (&gsi);
7639 else
7641 expand_omp_build_assign (&gsi, fd->loop.v,
7642 fold_convert (type, fd->loop.n1));
7643 if (fd->collapse > 1)
7644 for (i = 0; i < fd->collapse; i++)
7646 tree itype = TREE_TYPE (fd->loops[i].v);
7647 if (POINTER_TYPE_P (itype))
7648 itype = signed_type_for (itype);
7649 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7650 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7654 /* Remove the GIMPLE_OMP_FOR statement. */
7655 gsi_remove (&gsi, true);
7657 if (!broken_loop)
7659 /* Code to control the increment goes in the CONT_BB. */
7660 gsi = gsi_last_bb (cont_bb);
7661 stmt = gsi_stmt (gsi);
7662 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7664 if (POINTER_TYPE_P (type))
7665 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7666 else
7667 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7668 expand_omp_build_assign (&gsi, fd->loop.v, t);
7670 if (fd->collapse > 1)
7672 i = fd->collapse - 1;
7673 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7675 t = fold_convert (sizetype, fd->loops[i].step);
7676 t = fold_build_pointer_plus (fd->loops[i].v, t);
7678 else
7680 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7681 fd->loops[i].step);
7682 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7683 fd->loops[i].v, t);
7685 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7687 for (i = fd->collapse - 1; i > 0; i--)
7689 tree itype = TREE_TYPE (fd->loops[i].v);
7690 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7691 if (POINTER_TYPE_P (itype2))
7692 itype2 = signed_type_for (itype2);
7693 t = build3 (COND_EXPR, itype2,
7694 build2 (fd->loops[i].cond_code, boolean_type_node,
7695 fd->loops[i].v,
7696 fold_convert (itype, fd->loops[i].n2)),
7697 build_int_cst (itype2, 0),
7698 fold_convert (itype2, fd->loops[i - 1].step));
7699 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7700 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7701 else
7702 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7703 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7705 t = build3 (COND_EXPR, itype,
7706 build2 (fd->loops[i].cond_code, boolean_type_node,
7707 fd->loops[i].v,
7708 fold_convert (itype, fd->loops[i].n2)),
7709 fd->loops[i].v,
7710 fold_convert (itype, fd->loops[i].n1));
7711 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7715 /* Remove GIMPLE_OMP_CONTINUE. */
7716 gsi_remove (&gsi, true);
7719 /* Emit the condition in L1_BB. */
7720 gsi = gsi_start_bb (l1_bb);
7722 t = fold_convert (type, n2);
7723 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7724 false, GSI_CONTINUE_LINKING);
7725 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7726 cond_stmt = gimple_build_cond_empty (t);
7727 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7728 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7729 NULL, NULL)
7730 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7731 NULL, NULL))
7733 gsi = gsi_for_stmt (cond_stmt);
7734 gimple_regimplify_operands (cond_stmt, &gsi);
7737 /* Remove GIMPLE_OMP_RETURN. */
7738 gsi = gsi_last_bb (exit_bb);
7739 gsi_remove (&gsi, true);
7741 /* Connect the new blocks. */
7742 remove_edge (FALLTHRU_EDGE (entry_bb));
7744 if (!broken_loop)
7746 remove_edge (BRANCH_EDGE (entry_bb));
7747 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7749 e = BRANCH_EDGE (l1_bb);
7750 ne = FALLTHRU_EDGE (l1_bb);
7751 e->flags = EDGE_TRUE_VALUE;
7753 else
7755 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7757 ne = single_succ_edge (l1_bb);
7758 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7761 ne->flags = EDGE_FALSE_VALUE;
7762 e->probability = REG_BR_PROB_BASE * 7 / 8;
7763 ne->probability = REG_BR_PROB_BASE / 8;
7765 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7766 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7767 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7769 if (!broken_loop)
7771 struct loop *loop = alloc_loop ();
7772 loop->header = l1_bb;
7773 loop->latch = cont_bb;
7774 add_loop (loop, l1_bb->loop_father);
7775 if (safelen == NULL_TREE)
7776 loop->safelen = INT_MAX;
7777 else
7779 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7780 if (TREE_CODE (safelen) != INTEGER_CST)
7781 loop->safelen = 0;
7782 else if (!tree_fits_uhwi_p (safelen)
7783 || tree_to_uhwi (safelen) > INT_MAX)
7784 loop->safelen = INT_MAX;
7785 else
7786 loop->safelen = tree_to_uhwi (safelen);
7787 if (loop->safelen == 1)
7788 loop->safelen = 0;
7790 if (simduid)
7792 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7793 cfun->has_simduid_loops = true;
7795 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7796 the loop. */
7797 if ((flag_tree_loop_vectorize
7798 || (!global_options_set.x_flag_tree_loop_vectorize
7799 && !global_options_set.x_flag_tree_vectorize))
7800 && flag_tree_loop_optimize
7801 && loop->safelen > 1)
7803 loop->force_vectorize = true;
7804 cfun->has_force_vectorize_loops = true;
7810 /* Expand the OMP loop defined by REGION. */
7812 static void
7813 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7815 struct omp_for_data fd;
7816 struct omp_for_data_loop *loops;
7818 loops
7819 = (struct omp_for_data_loop *)
7820 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7821 * sizeof (struct omp_for_data_loop));
7822 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7823 &fd, loops);
7824 region->sched_kind = fd.sched_kind;
7826 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7827 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7828 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7829 if (region->cont)
7831 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7832 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7833 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7835 else
7836 /* If there isn't a continue then this is a degerate case where
7837 the introduction of abnormal edges during lowering will prevent
7838 original loops from being detected. Fix that up. */
7839 loops_state_set (LOOPS_NEED_FIXUP);
7841 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7842 expand_omp_simd (region, &fd);
7843 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7844 expand_cilk_for (region, &fd);
7845 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7846 && !fd.have_ordered)
7848 if (fd.chunk_size == NULL)
7849 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7850 else
7851 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7853 else
7855 int fn_index, start_ix, next_ix;
7857 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7858 == GF_OMP_FOR_KIND_FOR);
7859 if (fd.chunk_size == NULL
7860 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7861 fd.chunk_size = integer_zero_node;
7862 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7863 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7864 ? 3 : fd.sched_kind;
7865 fn_index += fd.have_ordered * 4;
7866 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7867 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7868 if (fd.iter_type == long_long_unsigned_type_node)
7870 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7871 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7872 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7873 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7875 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7876 (enum built_in_function) next_ix, inner_stmt);
7879 if (gimple_in_ssa_p (cfun))
7880 update_ssa (TODO_update_ssa_only_virtuals);
7884 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7886 v = GOMP_sections_start (n);
7888 switch (v)
7890 case 0:
7891 goto L2;
7892 case 1:
7893 section 1;
7894 goto L1;
7895 case 2:
7897 case n:
7899 default:
7900 abort ();
7903 v = GOMP_sections_next ();
7904 goto L0;
7906 reduction;
7908 If this is a combined parallel sections, replace the call to
7909 GOMP_sections_start with call to GOMP_sections_next. */
7911 static void
7912 expand_omp_sections (struct omp_region *region)
7914 tree t, u, vin = NULL, vmain, vnext, l2;
7915 unsigned len;
7916 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7917 gimple_stmt_iterator si, switch_si;
7918 gomp_sections *sections_stmt;
7919 gimple stmt;
7920 gomp_continue *cont;
7921 edge_iterator ei;
7922 edge e;
7923 struct omp_region *inner;
7924 unsigned i, casei;
7925 bool exit_reachable = region->cont != NULL;
7927 gcc_assert (region->exit != NULL);
7928 entry_bb = region->entry;
7929 l0_bb = single_succ (entry_bb);
7930 l1_bb = region->cont;
7931 l2_bb = region->exit;
7932 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7933 l2 = gimple_block_label (l2_bb);
7934 else
7936 /* This can happen if there are reductions. */
7937 len = EDGE_COUNT (l0_bb->succs);
7938 gcc_assert (len > 0);
7939 e = EDGE_SUCC (l0_bb, len - 1);
7940 si = gsi_last_bb (e->dest);
7941 l2 = NULL_TREE;
7942 if (gsi_end_p (si)
7943 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7944 l2 = gimple_block_label (e->dest);
7945 else
7946 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7948 si = gsi_last_bb (e->dest);
7949 if (gsi_end_p (si)
7950 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7952 l2 = gimple_block_label (e->dest);
7953 break;
7957 if (exit_reachable)
7958 default_bb = create_empty_bb (l1_bb->prev_bb);
7959 else
7960 default_bb = create_empty_bb (l0_bb);
7962 /* We will build a switch() with enough cases for all the
7963 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7964 and a default case to abort if something goes wrong. */
7965 len = EDGE_COUNT (l0_bb->succs);
7967 /* Use vec::quick_push on label_vec throughout, since we know the size
7968 in advance. */
7969 auto_vec<tree> label_vec (len);
7971 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7972 GIMPLE_OMP_SECTIONS statement. */
7973 si = gsi_last_bb (entry_bb);
7974 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
7975 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7976 vin = gimple_omp_sections_control (sections_stmt);
7977 if (!is_combined_parallel (region))
7979 /* If we are not inside a combined parallel+sections region,
7980 call GOMP_sections_start. */
7981 t = build_int_cst (unsigned_type_node, len - 1);
7982 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
7983 stmt = gimple_build_call (u, 1, t);
7985 else
7987 /* Otherwise, call GOMP_sections_next. */
7988 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
7989 stmt = gimple_build_call (u, 0);
7991 gimple_call_set_lhs (stmt, vin);
7992 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
7993 gsi_remove (&si, true);
7995 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
7996 L0_BB. */
7997 switch_si = gsi_last_bb (l0_bb);
7998 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
7999 if (exit_reachable)
8001 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8002 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8003 vmain = gimple_omp_continue_control_use (cont);
8004 vnext = gimple_omp_continue_control_def (cont);
8006 else
8008 vmain = vin;
8009 vnext = NULL_TREE;
8012 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8013 label_vec.quick_push (t);
8014 i = 1;
8016 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8017 for (inner = region->inner, casei = 1;
8018 inner;
8019 inner = inner->next, i++, casei++)
8021 basic_block s_entry_bb, s_exit_bb;
8023 /* Skip optional reduction region. */
8024 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8026 --i;
8027 --casei;
8028 continue;
8031 s_entry_bb = inner->entry;
8032 s_exit_bb = inner->exit;
8034 t = gimple_block_label (s_entry_bb);
8035 u = build_int_cst (unsigned_type_node, casei);
8036 u = build_case_label (u, NULL, t);
8037 label_vec.quick_push (u);
8039 si = gsi_last_bb (s_entry_bb);
8040 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8041 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8042 gsi_remove (&si, true);
8043 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8045 if (s_exit_bb == NULL)
8046 continue;
8048 si = gsi_last_bb (s_exit_bb);
8049 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8050 gsi_remove (&si, true);
8052 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8055 /* Error handling code goes in DEFAULT_BB. */
8056 t = gimple_block_label (default_bb);
8057 u = build_case_label (NULL, NULL, t);
8058 make_edge (l0_bb, default_bb, 0);
8059 add_bb_to_loop (default_bb, current_loops->tree_root);
8061 stmt = gimple_build_switch (vmain, u, label_vec);
8062 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8063 gsi_remove (&switch_si, true);
8065 si = gsi_start_bb (default_bb);
8066 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8067 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8069 if (exit_reachable)
8071 tree bfn_decl;
8073 /* Code to get the next section goes in L1_BB. */
8074 si = gsi_last_bb (l1_bb);
8075 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8077 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8078 stmt = gimple_build_call (bfn_decl, 0);
8079 gimple_call_set_lhs (stmt, vnext);
8080 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8081 gsi_remove (&si, true);
8083 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8086 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8087 si = gsi_last_bb (l2_bb);
8088 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8089 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8090 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8091 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8092 else
8093 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8094 stmt = gimple_build_call (t, 0);
8095 if (gimple_omp_return_lhs (gsi_stmt (si)))
8096 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8097 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8098 gsi_remove (&si, true);
8100 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8104 /* Expand code for an OpenMP single directive. We've already expanded
8105 much of the code, here we simply place the GOMP_barrier call. */
8107 static void
8108 expand_omp_single (struct omp_region *region)
8110 basic_block entry_bb, exit_bb;
8111 gimple_stmt_iterator si;
8113 entry_bb = region->entry;
8114 exit_bb = region->exit;
8116 si = gsi_last_bb (entry_bb);
8117 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8118 gsi_remove (&si, true);
8119 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8121 si = gsi_last_bb (exit_bb);
8122 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8124 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8125 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8127 gsi_remove (&si, true);
8128 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8132 /* Generic expansion for OpenMP synchronization directives: master,
8133 ordered and critical. All we need to do here is remove the entry
8134 and exit markers for REGION. */
8136 static void
8137 expand_omp_synch (struct omp_region *region)
8139 basic_block entry_bb, exit_bb;
8140 gimple_stmt_iterator si;
8142 entry_bb = region->entry;
8143 exit_bb = region->exit;
8145 si = gsi_last_bb (entry_bb);
8146 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8147 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8148 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8149 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8150 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8151 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8152 gsi_remove (&si, true);
8153 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8155 if (exit_bb)
8157 si = gsi_last_bb (exit_bb);
8158 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8159 gsi_remove (&si, true);
8160 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8164 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8165 operation as a normal volatile load. */
8167 static bool
8168 expand_omp_atomic_load (basic_block load_bb, tree addr,
8169 tree loaded_val, int index)
8171 enum built_in_function tmpbase;
8172 gimple_stmt_iterator gsi;
8173 basic_block store_bb;
8174 location_t loc;
8175 gimple stmt;
8176 tree decl, call, type, itype;
8178 gsi = gsi_last_bb (load_bb);
8179 stmt = gsi_stmt (gsi);
8180 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8181 loc = gimple_location (stmt);
8183 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8184 is smaller than word size, then expand_atomic_load assumes that the load
8185 is atomic. We could avoid the builtin entirely in this case. */
8187 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8188 decl = builtin_decl_explicit (tmpbase);
8189 if (decl == NULL_TREE)
8190 return false;
8192 type = TREE_TYPE (loaded_val);
8193 itype = TREE_TYPE (TREE_TYPE (decl));
8195 call = build_call_expr_loc (loc, decl, 2, addr,
8196 build_int_cst (NULL,
8197 gimple_omp_atomic_seq_cst_p (stmt)
8198 ? MEMMODEL_SEQ_CST
8199 : MEMMODEL_RELAXED));
8200 if (!useless_type_conversion_p (type, itype))
8201 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8202 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8204 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8205 gsi_remove (&gsi, true);
8207 store_bb = single_succ (load_bb);
8208 gsi = gsi_last_bb (store_bb);
8209 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8210 gsi_remove (&gsi, true);
8212 if (gimple_in_ssa_p (cfun))
8213 update_ssa (TODO_update_ssa_no_phi);
8215 return true;
8218 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8219 operation as a normal volatile store. */
8221 static bool
8222 expand_omp_atomic_store (basic_block load_bb, tree addr,
8223 tree loaded_val, tree stored_val, int index)
8225 enum built_in_function tmpbase;
8226 gimple_stmt_iterator gsi;
8227 basic_block store_bb = single_succ (load_bb);
8228 location_t loc;
8229 gimple stmt;
8230 tree decl, call, type, itype;
8231 machine_mode imode;
8232 bool exchange;
8234 gsi = gsi_last_bb (load_bb);
8235 stmt = gsi_stmt (gsi);
8236 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8238 /* If the load value is needed, then this isn't a store but an exchange. */
8239 exchange = gimple_omp_atomic_need_value_p (stmt);
8241 gsi = gsi_last_bb (store_bb);
8242 stmt = gsi_stmt (gsi);
8243 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8244 loc = gimple_location (stmt);
8246 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8247 is smaller than word size, then expand_atomic_store assumes that the store
8248 is atomic. We could avoid the builtin entirely in this case. */
8250 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8251 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8252 decl = builtin_decl_explicit (tmpbase);
8253 if (decl == NULL_TREE)
8254 return false;
8256 type = TREE_TYPE (stored_val);
8258 /* Dig out the type of the function's second argument. */
8259 itype = TREE_TYPE (decl);
8260 itype = TYPE_ARG_TYPES (itype);
8261 itype = TREE_CHAIN (itype);
8262 itype = TREE_VALUE (itype);
8263 imode = TYPE_MODE (itype);
8265 if (exchange && !can_atomic_exchange_p (imode, true))
8266 return false;
8268 if (!useless_type_conversion_p (itype, type))
8269 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8270 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8271 build_int_cst (NULL,
8272 gimple_omp_atomic_seq_cst_p (stmt)
8273 ? MEMMODEL_SEQ_CST
8274 : MEMMODEL_RELAXED));
8275 if (exchange)
8277 if (!useless_type_conversion_p (type, itype))
8278 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8279 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8282 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8283 gsi_remove (&gsi, true);
8285 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8286 gsi = gsi_last_bb (load_bb);
8287 gsi_remove (&gsi, true);
8289 if (gimple_in_ssa_p (cfun))
8290 update_ssa (TODO_update_ssa_no_phi);
8292 return true;
8295 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8296 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8297 size of the data type, and thus usable to find the index of the builtin
8298 decl. Returns false if the expression is not of the proper form. */
8300 static bool
8301 expand_omp_atomic_fetch_op (basic_block load_bb,
8302 tree addr, tree loaded_val,
8303 tree stored_val, int index)
8305 enum built_in_function oldbase, newbase, tmpbase;
8306 tree decl, itype, call;
8307 tree lhs, rhs;
8308 basic_block store_bb = single_succ (load_bb);
8309 gimple_stmt_iterator gsi;
8310 gimple stmt;
8311 location_t loc;
8312 enum tree_code code;
8313 bool need_old, need_new;
8314 machine_mode imode;
8315 bool seq_cst;
8317 /* We expect to find the following sequences:
8319 load_bb:
8320 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8322 store_bb:
8323 val = tmp OP something; (or: something OP tmp)
8324 GIMPLE_OMP_STORE (val)
8326 ???FIXME: Allow a more flexible sequence.
8327 Perhaps use data flow to pick the statements.
8331 gsi = gsi_after_labels (store_bb);
8332 stmt = gsi_stmt (gsi);
8333 loc = gimple_location (stmt);
8334 if (!is_gimple_assign (stmt))
8335 return false;
8336 gsi_next (&gsi);
8337 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8338 return false;
8339 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8340 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8341 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8342 gcc_checking_assert (!need_old || !need_new);
8344 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8345 return false;
8347 /* Check for one of the supported fetch-op operations. */
8348 code = gimple_assign_rhs_code (stmt);
8349 switch (code)
8351 case PLUS_EXPR:
8352 case POINTER_PLUS_EXPR:
8353 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8354 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8355 break;
8356 case MINUS_EXPR:
8357 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8358 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8359 break;
8360 case BIT_AND_EXPR:
8361 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8362 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8363 break;
8364 case BIT_IOR_EXPR:
8365 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8366 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8367 break;
8368 case BIT_XOR_EXPR:
8369 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8370 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8371 break;
8372 default:
8373 return false;
8376 /* Make sure the expression is of the proper form. */
8377 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8378 rhs = gimple_assign_rhs2 (stmt);
8379 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8380 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8381 rhs = gimple_assign_rhs1 (stmt);
8382 else
8383 return false;
8385 tmpbase = ((enum built_in_function)
8386 ((need_new ? newbase : oldbase) + index + 1));
8387 decl = builtin_decl_explicit (tmpbase);
8388 if (decl == NULL_TREE)
8389 return false;
8390 itype = TREE_TYPE (TREE_TYPE (decl));
8391 imode = TYPE_MODE (itype);
8393 /* We could test all of the various optabs involved, but the fact of the
8394 matter is that (with the exception of i486 vs i586 and xadd) all targets
8395 that support any atomic operaton optab also implements compare-and-swap.
8396 Let optabs.c take care of expanding any compare-and-swap loop. */
8397 if (!can_compare_and_swap_p (imode, true))
8398 return false;
8400 gsi = gsi_last_bb (load_bb);
8401 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8403 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8404 It only requires that the operation happen atomically. Thus we can
8405 use the RELAXED memory model. */
8406 call = build_call_expr_loc (loc, decl, 3, addr,
8407 fold_convert_loc (loc, itype, rhs),
8408 build_int_cst (NULL,
8409 seq_cst ? MEMMODEL_SEQ_CST
8410 : MEMMODEL_RELAXED));
8412 if (need_old || need_new)
8414 lhs = need_old ? loaded_val : stored_val;
8415 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8416 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8418 else
8419 call = fold_convert_loc (loc, void_type_node, call);
8420 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8421 gsi_remove (&gsi, true);
8423 gsi = gsi_last_bb (store_bb);
8424 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8425 gsi_remove (&gsi, true);
8426 gsi = gsi_last_bb (store_bb);
8427 gsi_remove (&gsi, true);
8429 if (gimple_in_ssa_p (cfun))
8430 update_ssa (TODO_update_ssa_no_phi);
8432 return true;
8435 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8437 oldval = *addr;
8438 repeat:
8439 newval = rhs; // with oldval replacing *addr in rhs
8440 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8441 if (oldval != newval)
8442 goto repeat;
8444 INDEX is log2 of the size of the data type, and thus usable to find the
8445 index of the builtin decl. */
8447 static bool
8448 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8449 tree addr, tree loaded_val, tree stored_val,
8450 int index)
8452 tree loadedi, storedi, initial, new_storedi, old_vali;
8453 tree type, itype, cmpxchg, iaddr;
8454 gimple_stmt_iterator si;
8455 basic_block loop_header = single_succ (load_bb);
8456 gimple phi, stmt;
8457 edge e;
8458 enum built_in_function fncode;
8460 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8461 order to use the RELAXED memory model effectively. */
8462 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8463 + index + 1);
8464 cmpxchg = builtin_decl_explicit (fncode);
8465 if (cmpxchg == NULL_TREE)
8466 return false;
8467 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8468 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8470 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8471 return false;
8473 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8474 si = gsi_last_bb (load_bb);
8475 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8477 /* For floating-point values, we'll need to view-convert them to integers
8478 so that we can perform the atomic compare and swap. Simplify the
8479 following code by always setting up the "i"ntegral variables. */
8480 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8482 tree iaddr_val;
8484 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8485 true));
8486 iaddr_val
8487 = force_gimple_operand_gsi (&si,
8488 fold_convert (TREE_TYPE (iaddr), addr),
8489 false, NULL_TREE, true, GSI_SAME_STMT);
8490 stmt = gimple_build_assign (iaddr, iaddr_val);
8491 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8492 loadedi = create_tmp_var (itype);
8493 if (gimple_in_ssa_p (cfun))
8494 loadedi = make_ssa_name (loadedi);
8496 else
8498 iaddr = addr;
8499 loadedi = loaded_val;
8502 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8503 tree loaddecl = builtin_decl_explicit (fncode);
8504 if (loaddecl)
8505 initial
8506 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8507 build_call_expr (loaddecl, 2, iaddr,
8508 build_int_cst (NULL_TREE,
8509 MEMMODEL_RELAXED)));
8510 else
8511 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8512 build_int_cst (TREE_TYPE (iaddr), 0));
8514 initial
8515 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8516 GSI_SAME_STMT);
8518 /* Move the value to the LOADEDI temporary. */
8519 if (gimple_in_ssa_p (cfun))
8521 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8522 phi = create_phi_node (loadedi, loop_header);
8523 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8524 initial);
8526 else
8527 gsi_insert_before (&si,
8528 gimple_build_assign (loadedi, initial),
8529 GSI_SAME_STMT);
8530 if (loadedi != loaded_val)
8532 gimple_stmt_iterator gsi2;
8533 tree x;
8535 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8536 gsi2 = gsi_start_bb (loop_header);
8537 if (gimple_in_ssa_p (cfun))
8539 gassign *stmt;
8540 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8541 true, GSI_SAME_STMT);
8542 stmt = gimple_build_assign (loaded_val, x);
8543 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8545 else
8547 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8548 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8549 true, GSI_SAME_STMT);
8552 gsi_remove (&si, true);
8554 si = gsi_last_bb (store_bb);
8555 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8557 if (iaddr == addr)
8558 storedi = stored_val;
8559 else
8560 storedi =
8561 force_gimple_operand_gsi (&si,
8562 build1 (VIEW_CONVERT_EXPR, itype,
8563 stored_val), true, NULL_TREE, true,
8564 GSI_SAME_STMT);
8566 /* Build the compare&swap statement. */
8567 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8568 new_storedi = force_gimple_operand_gsi (&si,
8569 fold_convert (TREE_TYPE (loadedi),
8570 new_storedi),
8571 true, NULL_TREE,
8572 true, GSI_SAME_STMT);
8574 if (gimple_in_ssa_p (cfun))
8575 old_vali = loadedi;
8576 else
8578 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8579 stmt = gimple_build_assign (old_vali, loadedi);
8580 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8582 stmt = gimple_build_assign (loadedi, new_storedi);
8583 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8586 /* Note that we always perform the comparison as an integer, even for
8587 floating point. This allows the atomic operation to properly
8588 succeed even with NaNs and -0.0. */
8589 stmt = gimple_build_cond_empty
8590 (build2 (NE_EXPR, boolean_type_node,
8591 new_storedi, old_vali));
8592 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8594 /* Update cfg. */
8595 e = single_succ_edge (store_bb);
8596 e->flags &= ~EDGE_FALLTHRU;
8597 e->flags |= EDGE_FALSE_VALUE;
8599 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8601 /* Copy the new value to loadedi (we already did that before the condition
8602 if we are not in SSA). */
8603 if (gimple_in_ssa_p (cfun))
8605 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8606 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8609 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8610 gsi_remove (&si, true);
8612 struct loop *loop = alloc_loop ();
8613 loop->header = loop_header;
8614 loop->latch = store_bb;
8615 add_loop (loop, loop_header->loop_father);
8617 if (gimple_in_ssa_p (cfun))
8618 update_ssa (TODO_update_ssa_no_phi);
8620 return true;
8623 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8625 GOMP_atomic_start ();
8626 *addr = rhs;
8627 GOMP_atomic_end ();
8629 The result is not globally atomic, but works so long as all parallel
8630 references are within #pragma omp atomic directives. According to
8631 responses received from omp@openmp.org, appears to be within spec.
8632 Which makes sense, since that's how several other compilers handle
8633 this situation as well.
8634 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8635 expanding. STORED_VAL is the operand of the matching
8636 GIMPLE_OMP_ATOMIC_STORE.
8638 We replace
8639 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8640 loaded_val = *addr;
8642 and replace
8643 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8644 *addr = stored_val;
8647 static bool
8648 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8649 tree addr, tree loaded_val, tree stored_val)
8651 gimple_stmt_iterator si;
8652 gassign *stmt;
8653 tree t;
8655 si = gsi_last_bb (load_bb);
8656 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8658 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8659 t = build_call_expr (t, 0);
8660 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8662 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8663 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8664 gsi_remove (&si, true);
8666 si = gsi_last_bb (store_bb);
8667 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8669 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8670 stored_val);
8671 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8673 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8674 t = build_call_expr (t, 0);
8675 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8676 gsi_remove (&si, true);
8678 if (gimple_in_ssa_p (cfun))
8679 update_ssa (TODO_update_ssa_no_phi);
8680 return true;
8683 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8684 using expand_omp_atomic_fetch_op. If it failed, we try to
8685 call expand_omp_atomic_pipeline, and if it fails too, the
8686 ultimate fallback is wrapping the operation in a mutex
8687 (expand_omp_atomic_mutex). REGION is the atomic region built
8688 by build_omp_regions_1(). */
8690 static void
8691 expand_omp_atomic (struct omp_region *region)
8693 basic_block load_bb = region->entry, store_bb = region->exit;
8694 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8695 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8696 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8697 tree addr = gimple_omp_atomic_load_rhs (load);
8698 tree stored_val = gimple_omp_atomic_store_val (store);
8699 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8700 HOST_WIDE_INT index;
8702 /* Make sure the type is one of the supported sizes. */
8703 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8704 index = exact_log2 (index);
8705 if (index >= 0 && index <= 4)
8707 unsigned int align = TYPE_ALIGN_UNIT (type);
8709 /* __sync builtins require strict data alignment. */
8710 if (exact_log2 (align) >= index)
8712 /* Atomic load. */
8713 if (loaded_val == stored_val
8714 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8715 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8716 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8717 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8718 return;
8720 /* Atomic store. */
8721 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8722 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8723 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8724 && store_bb == single_succ (load_bb)
8725 && first_stmt (store_bb) == store
8726 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8727 stored_val, index))
8728 return;
8730 /* When possible, use specialized atomic update functions. */
8731 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8732 && store_bb == single_succ (load_bb)
8733 && expand_omp_atomic_fetch_op (load_bb, addr,
8734 loaded_val, stored_val, index))
8735 return;
8737 /* If we don't have specialized __sync builtins, try and implement
8738 as a compare and swap loop. */
8739 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8740 loaded_val, stored_val, index))
8741 return;
8745 /* The ultimate fallback is wrapping the operation in a mutex. */
8746 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8750 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8752 static void
8753 expand_omp_target (struct omp_region *region)
8755 basic_block entry_bb, exit_bb, new_bb;
8756 struct function *child_cfun;
8757 tree child_fn, block, t;
8758 gimple_stmt_iterator gsi;
8759 gomp_target *entry_stmt;
8760 gimple stmt;
8761 edge e;
8762 bool offloaded, data_region;
8764 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8765 new_bb = region->entry;
8767 offloaded = is_gimple_omp_offloaded (entry_stmt);
8768 switch (gimple_omp_target_kind (entry_stmt))
8770 case GF_OMP_TARGET_KIND_REGION:
8771 case GF_OMP_TARGET_KIND_UPDATE:
8772 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8773 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8774 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8775 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8776 data_region = false;
8777 break;
8778 case GF_OMP_TARGET_KIND_DATA:
8779 case GF_OMP_TARGET_KIND_OACC_DATA:
8780 data_region = true;
8781 break;
8782 default:
8783 gcc_unreachable ();
8786 child_fn = NULL_TREE;
8787 child_cfun = NULL;
8788 if (offloaded)
8790 child_fn = gimple_omp_target_child_fn (entry_stmt);
8791 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8794 /* Supported by expand_omp_taskreg, but not here. */
8795 if (child_cfun != NULL)
8796 gcc_checking_assert (!child_cfun->cfg);
8797 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8799 entry_bb = region->entry;
8800 exit_bb = region->exit;
8802 if (offloaded)
8804 unsigned srcidx, dstidx, num;
8806 /* If the offloading region needs data sent from the parent
8807 function, then the very first statement (except possible
8808 tree profile counter updates) of the offloading body
8809 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8810 &.OMP_DATA_O is passed as an argument to the child function,
8811 we need to replace it with the argument as seen by the child
8812 function.
8814 In most cases, this will end up being the identity assignment
8815 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8816 a function call that has been inlined, the original PARM_DECL
8817 .OMP_DATA_I may have been converted into a different local
8818 variable. In which case, we need to keep the assignment. */
8819 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8820 if (data_arg)
8822 basic_block entry_succ_bb = single_succ (entry_bb);
8823 gimple_stmt_iterator gsi;
8824 tree arg;
8825 gimple tgtcopy_stmt = NULL;
8826 tree sender = TREE_VEC_ELT (data_arg, 0);
8828 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8830 gcc_assert (!gsi_end_p (gsi));
8831 stmt = gsi_stmt (gsi);
8832 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8833 continue;
8835 if (gimple_num_ops (stmt) == 2)
8837 tree arg = gimple_assign_rhs1 (stmt);
8839 /* We're ignoring the subcode because we're
8840 effectively doing a STRIP_NOPS. */
8842 if (TREE_CODE (arg) == ADDR_EXPR
8843 && TREE_OPERAND (arg, 0) == sender)
8845 tgtcopy_stmt = stmt;
8846 break;
8851 gcc_assert (tgtcopy_stmt != NULL);
8852 arg = DECL_ARGUMENTS (child_fn);
8854 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8855 gsi_remove (&gsi, true);
8858 /* Declare local variables needed in CHILD_CFUN. */
8859 block = DECL_INITIAL (child_fn);
8860 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8861 /* The gimplifier could record temporaries in the offloading block
8862 rather than in containing function's local_decls chain,
8863 which would mean cgraph missed finalizing them. Do it now. */
8864 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8865 if (TREE_CODE (t) == VAR_DECL
8866 && TREE_STATIC (t)
8867 && !DECL_EXTERNAL (t))
8868 varpool_node::finalize_decl (t);
8869 DECL_SAVED_TREE (child_fn) = NULL;
8870 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8871 gimple_set_body (child_fn, NULL);
8872 TREE_USED (block) = 1;
8874 /* Reset DECL_CONTEXT on function arguments. */
8875 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8876 DECL_CONTEXT (t) = child_fn;
8878 /* Split ENTRY_BB at GIMPLE_*,
8879 so that it can be moved to the child function. */
8880 gsi = gsi_last_bb (entry_bb);
8881 stmt = gsi_stmt (gsi);
8882 gcc_assert (stmt
8883 && gimple_code (stmt) == gimple_code (entry_stmt));
8884 gsi_remove (&gsi, true);
8885 e = split_block (entry_bb, stmt);
8886 entry_bb = e->dest;
8887 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8889 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8890 if (exit_bb)
8892 gsi = gsi_last_bb (exit_bb);
8893 gcc_assert (!gsi_end_p (gsi)
8894 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8895 stmt = gimple_build_return (NULL);
8896 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8897 gsi_remove (&gsi, true);
8900 /* Move the offloading region into CHILD_CFUN. */
8902 block = gimple_block (entry_stmt);
8904 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8905 if (exit_bb)
8906 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8907 /* When the OMP expansion process cannot guarantee an up-to-date
8908 loop tree arrange for the child function to fixup loops. */
8909 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8910 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8912 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8913 num = vec_safe_length (child_cfun->local_decls);
8914 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8916 t = (*child_cfun->local_decls)[srcidx];
8917 if (DECL_CONTEXT (t) == cfun->decl)
8918 continue;
8919 if (srcidx != dstidx)
8920 (*child_cfun->local_decls)[dstidx] = t;
8921 dstidx++;
8923 if (dstidx != num)
8924 vec_safe_truncate (child_cfun->local_decls, dstidx);
8926 /* Inform the callgraph about the new function. */
8927 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8928 cgraph_node::add_new_function (child_fn, true);
8930 #ifdef ENABLE_OFFLOADING
8931 /* Add the new function to the offload table. */
8932 vec_safe_push (offload_funcs, child_fn);
8933 #endif
8935 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8936 fixed in a following pass. */
8937 push_cfun (child_cfun);
8938 cgraph_edge::rebuild_edges ();
8940 #ifdef ENABLE_OFFLOADING
8941 /* Prevent IPA from removing child_fn as unreachable, since there are no
8942 refs from the parent function to child_fn in offload LTO mode. */
8943 struct cgraph_node *node = cgraph_node::get (child_fn);
8944 node->mark_force_output ();
8945 #endif
8947 /* Some EH regions might become dead, see PR34608. If
8948 pass_cleanup_cfg isn't the first pass to happen with the
8949 new child, these dead EH edges might cause problems.
8950 Clean them up now. */
8951 if (flag_exceptions)
8953 basic_block bb;
8954 bool changed = false;
8956 FOR_EACH_BB_FN (bb, cfun)
8957 changed |= gimple_purge_dead_eh_edges (bb);
8958 if (changed)
8959 cleanup_tree_cfg ();
8961 pop_cfun ();
8964 /* Emit a library call to launch the offloading region, or do data
8965 transfers. */
8966 tree t1, t2, t3, t4, device, cond, c, clauses;
8967 enum built_in_function start_ix;
8968 location_t clause_loc;
8970 switch (gimple_omp_target_kind (entry_stmt))
8972 case GF_OMP_TARGET_KIND_REGION:
8973 start_ix = BUILT_IN_GOMP_TARGET;
8974 break;
8975 case GF_OMP_TARGET_KIND_DATA:
8976 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8977 break;
8978 case GF_OMP_TARGET_KIND_UPDATE:
8979 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8980 break;
8981 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8982 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8983 start_ix = BUILT_IN_GOACC_PARALLEL;
8984 break;
8985 case GF_OMP_TARGET_KIND_OACC_DATA:
8986 start_ix = BUILT_IN_GOACC_DATA_START;
8987 break;
8988 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8989 start_ix = BUILT_IN_GOACC_UPDATE;
8990 break;
8991 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8992 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
8993 break;
8994 default:
8995 gcc_unreachable ();
8998 clauses = gimple_omp_target_clauses (entry_stmt);
9000 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9001 library choose) and there is no conditional. */
9002 cond = NULL_TREE;
9003 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
9005 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9006 if (c)
9007 cond = OMP_CLAUSE_IF_EXPR (c);
9009 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9010 if (c)
9012 /* Even if we pass it to all library function calls, it is currently only
9013 defined/used for the OpenMP target ones. */
9014 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9015 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9016 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9018 device = OMP_CLAUSE_DEVICE_ID (c);
9019 clause_loc = OMP_CLAUSE_LOCATION (c);
9021 else
9022 clause_loc = gimple_location (entry_stmt);
9024 /* Ensure 'device' is of the correct type. */
9025 device = fold_convert_loc (clause_loc, integer_type_node, device);
9027 /* If we found the clause 'if (cond)', build
9028 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9029 if (cond)
9031 cond = gimple_boolify (cond);
9033 basic_block cond_bb, then_bb, else_bb;
9034 edge e;
9035 tree tmp_var;
9037 tmp_var = create_tmp_var (TREE_TYPE (device));
9038 if (offloaded)
9039 e = split_block (new_bb, NULL);
9040 else
9042 gsi = gsi_last_bb (new_bb);
9043 gsi_prev (&gsi);
9044 e = split_block (new_bb, gsi_stmt (gsi));
9046 cond_bb = e->src;
9047 new_bb = e->dest;
9048 remove_edge (e);
9050 then_bb = create_empty_bb (cond_bb);
9051 else_bb = create_empty_bb (then_bb);
9052 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9053 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9055 stmt = gimple_build_cond_empty (cond);
9056 gsi = gsi_last_bb (cond_bb);
9057 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9059 gsi = gsi_start_bb (then_bb);
9060 stmt = gimple_build_assign (tmp_var, device);
9061 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9063 gsi = gsi_start_bb (else_bb);
9064 stmt = gimple_build_assign (tmp_var,
9065 build_int_cst (integer_type_node,
9066 GOMP_DEVICE_HOST_FALLBACK));
9067 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9069 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9070 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9071 add_bb_to_loop (then_bb, cond_bb->loop_father);
9072 add_bb_to_loop (else_bb, cond_bb->loop_father);
9073 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9074 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9076 device = tmp_var;
9079 gsi = gsi_last_bb (new_bb);
9080 t = gimple_omp_target_data_arg (entry_stmt);
9081 if (t == NULL)
9083 t1 = size_zero_node;
9084 t2 = build_zero_cst (ptr_type_node);
9085 t3 = t2;
9086 t4 = t2;
9088 else
9090 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9091 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9092 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9093 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9094 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9097 gimple g;
9098 vec<tree> *args;
9099 /* The maximum number used by any start_ix, without varargs. */
9100 unsigned int argcnt = 11;
9102 vec_alloc (args, argcnt);
9103 args->quick_push (device);
9104 if (offloaded)
9105 args->quick_push (build_fold_addr_expr (child_fn));
9106 switch (start_ix)
9108 case BUILT_IN_GOMP_TARGET:
9109 case BUILT_IN_GOMP_TARGET_DATA:
9110 case BUILT_IN_GOMP_TARGET_UPDATE:
9111 /* This const void * is part of the current ABI, but we're not actually
9112 using it. */
9113 args->quick_push (build_zero_cst (ptr_type_node));
9114 break;
9115 case BUILT_IN_GOACC_DATA_START:
9116 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9117 case BUILT_IN_GOACC_PARALLEL:
9118 case BUILT_IN_GOACC_UPDATE:
9119 break;
9120 default:
9121 gcc_unreachable ();
9123 args->quick_push (t1);
9124 args->quick_push (t2);
9125 args->quick_push (t3);
9126 args->quick_push (t4);
9127 switch (start_ix)
9129 case BUILT_IN_GOACC_DATA_START:
9130 case BUILT_IN_GOMP_TARGET:
9131 case BUILT_IN_GOMP_TARGET_DATA:
9132 case BUILT_IN_GOMP_TARGET_UPDATE:
9133 break;
9134 case BUILT_IN_GOACC_PARALLEL:
9136 tree t_num_gangs, t_num_workers, t_vector_length;
9138 /* Default values for num_gangs, num_workers, and vector_length. */
9139 t_num_gangs = t_num_workers = t_vector_length
9140 = fold_convert_loc (gimple_location (entry_stmt),
9141 integer_type_node, integer_one_node);
9142 /* ..., but if present, use the value specified by the respective
9143 clause, making sure that are of the correct type. */
9144 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9145 if (c)
9146 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9147 integer_type_node,
9148 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9149 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9150 if (c)
9151 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9152 integer_type_node,
9153 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9154 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9155 if (c)
9156 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9157 integer_type_node,
9158 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9159 args->quick_push (t_num_gangs);
9160 args->quick_push (t_num_workers);
9161 args->quick_push (t_vector_length);
9163 /* FALLTHRU */
9164 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9165 case BUILT_IN_GOACC_UPDATE:
9167 tree t_async;
9168 int t_wait_idx;
9170 /* Default values for t_async. */
9171 t_async = fold_convert_loc (gimple_location (entry_stmt),
9172 integer_type_node,
9173 build_int_cst (integer_type_node,
9174 GOMP_ASYNC_SYNC));
9175 /* ..., but if present, use the value specified by the respective
9176 clause, making sure that is of the correct type. */
9177 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9178 if (c)
9179 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9180 integer_type_node,
9181 OMP_CLAUSE_ASYNC_EXPR (c));
9183 args->quick_push (t_async);
9184 /* Save the index, and... */
9185 t_wait_idx = args->length ();
9186 /* ... push a default value. */
9187 args->quick_push (fold_convert_loc (gimple_location (entry_stmt),
9188 integer_type_node,
9189 integer_zero_node));
9190 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9191 if (c)
9193 int n = 0;
9195 for (; c; c = OMP_CLAUSE_CHAIN (c))
9197 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9199 args->safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9200 integer_type_node,
9201 OMP_CLAUSE_WAIT_EXPR (c)));
9202 n++;
9206 /* Now that we know the number, replace the default value. */
9207 args->ordered_remove (t_wait_idx);
9208 args->quick_insert (t_wait_idx,
9209 fold_convert_loc (gimple_location (entry_stmt),
9210 integer_type_node,
9211 build_int_cst (integer_type_node, n)));
9214 break;
9215 default:
9216 gcc_unreachable ();
9219 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), *args);
9220 args->release ();
9221 gimple_set_location (g, gimple_location (entry_stmt));
9222 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9223 if (!offloaded)
9225 g = gsi_stmt (gsi);
9226 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9227 gsi_remove (&gsi, true);
9229 if (data_region
9230 && region->exit)
9232 gsi = gsi_last_bb (region->exit);
9233 g = gsi_stmt (gsi);
9234 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9235 gsi_remove (&gsi, true);
9240 /* Expand the parallel region tree rooted at REGION. Expansion
9241 proceeds in depth-first order. Innermost regions are expanded
9242 first. This way, parallel regions that require a new function to
9243 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9244 internal dependencies in their body. */
9246 static void
9247 expand_omp (struct omp_region *region)
9249 while (region)
9251 location_t saved_location;
9252 gimple inner_stmt = NULL;
9254 /* First, determine whether this is a combined parallel+workshare
9255 region. */
9256 if (region->type == GIMPLE_OMP_PARALLEL)
9257 determine_parallel_type (region);
9259 if (region->type == GIMPLE_OMP_FOR
9260 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9261 inner_stmt = last_stmt (region->inner->entry);
9263 if (region->inner)
9264 expand_omp (region->inner);
9266 saved_location = input_location;
9267 if (gimple_has_location (last_stmt (region->entry)))
9268 input_location = gimple_location (last_stmt (region->entry));
9270 switch (region->type)
9272 case GIMPLE_OMP_PARALLEL:
9273 case GIMPLE_OMP_TASK:
9274 expand_omp_taskreg (region);
9275 break;
9277 case GIMPLE_OMP_FOR:
9278 expand_omp_for (region, inner_stmt);
9279 break;
9281 case GIMPLE_OMP_SECTIONS:
9282 expand_omp_sections (region);
9283 break;
9285 case GIMPLE_OMP_SECTION:
9286 /* Individual omp sections are handled together with their
9287 parent GIMPLE_OMP_SECTIONS region. */
9288 break;
9290 case GIMPLE_OMP_SINGLE:
9291 expand_omp_single (region);
9292 break;
9294 case GIMPLE_OMP_MASTER:
9295 case GIMPLE_OMP_TASKGROUP:
9296 case GIMPLE_OMP_ORDERED:
9297 case GIMPLE_OMP_CRITICAL:
9298 case GIMPLE_OMP_TEAMS:
9299 expand_omp_synch (region);
9300 break;
9302 case GIMPLE_OMP_ATOMIC_LOAD:
9303 expand_omp_atomic (region);
9304 break;
9306 case GIMPLE_OMP_TARGET:
9307 expand_omp_target (region);
9308 break;
9310 default:
9311 gcc_unreachable ();
9314 input_location = saved_location;
9315 region = region->next;
9320 /* Helper for build_omp_regions. Scan the dominator tree starting at
9321 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9322 true, the function ends once a single tree is built (otherwise, whole
9323 forest of OMP constructs may be built). */
9325 static void
9326 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9327 bool single_tree)
9329 gimple_stmt_iterator gsi;
9330 gimple stmt;
9331 basic_block son;
9333 gsi = gsi_last_bb (bb);
9334 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9336 struct omp_region *region;
9337 enum gimple_code code;
9339 stmt = gsi_stmt (gsi);
9340 code = gimple_code (stmt);
9341 if (code == GIMPLE_OMP_RETURN)
9343 /* STMT is the return point out of region PARENT. Mark it
9344 as the exit point and make PARENT the immediately
9345 enclosing region. */
9346 gcc_assert (parent);
9347 region = parent;
9348 region->exit = bb;
9349 parent = parent->outer;
9351 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9353 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9354 GIMPLE_OMP_RETURN, but matches with
9355 GIMPLE_OMP_ATOMIC_LOAD. */
9356 gcc_assert (parent);
9357 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9358 region = parent;
9359 region->exit = bb;
9360 parent = parent->outer;
9362 else if (code == GIMPLE_OMP_CONTINUE)
9364 gcc_assert (parent);
9365 parent->cont = bb;
9367 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9369 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9370 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9372 else
9374 region = new_omp_region (bb, code, parent);
9375 /* Otherwise... */
9376 if (code == GIMPLE_OMP_TARGET)
9378 switch (gimple_omp_target_kind (stmt))
9380 case GF_OMP_TARGET_KIND_REGION:
9381 case GF_OMP_TARGET_KIND_DATA:
9382 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9383 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9384 case GF_OMP_TARGET_KIND_OACC_DATA:
9385 break;
9386 case GF_OMP_TARGET_KIND_UPDATE:
9387 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9388 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9389 /* ..., other than for those stand-alone directives... */
9390 region = NULL;
9391 break;
9392 default:
9393 gcc_unreachable ();
9396 /* ..., this directive becomes the parent for a new region. */
9397 if (region)
9398 parent = region;
9402 if (single_tree && !parent)
9403 return;
9405 for (son = first_dom_son (CDI_DOMINATORS, bb);
9406 son;
9407 son = next_dom_son (CDI_DOMINATORS, son))
9408 build_omp_regions_1 (son, parent, single_tree);
9411 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9412 root_omp_region. */
9414 static void
9415 build_omp_regions_root (basic_block root)
9417 gcc_assert (root_omp_region == NULL);
9418 build_omp_regions_1 (root, NULL, true);
9419 gcc_assert (root_omp_region != NULL);
9422 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9424 void
9425 omp_expand_local (basic_block head)
9427 build_omp_regions_root (head);
9428 if (dump_file && (dump_flags & TDF_DETAILS))
9430 fprintf (dump_file, "\nOMP region tree\n\n");
9431 dump_omp_region (dump_file, root_omp_region, 0);
9432 fprintf (dump_file, "\n");
9435 remove_exit_barriers (root_omp_region);
9436 expand_omp (root_omp_region);
9438 free_omp_regions ();
9441 /* Scan the CFG and build a tree of OMP regions. Return the root of
9442 the OMP region tree. */
9444 static void
9445 build_omp_regions (void)
9447 gcc_assert (root_omp_region == NULL);
9448 calculate_dominance_info (CDI_DOMINATORS);
9449 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9452 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9454 static unsigned int
9455 execute_expand_omp (void)
9457 build_omp_regions ();
9459 if (!root_omp_region)
9460 return 0;
9462 if (dump_file)
9464 fprintf (dump_file, "\nOMP region tree\n\n");
9465 dump_omp_region (dump_file, root_omp_region, 0);
9466 fprintf (dump_file, "\n");
9469 remove_exit_barriers (root_omp_region);
9471 expand_omp (root_omp_region);
9473 cleanup_tree_cfg ();
9475 free_omp_regions ();
9477 return 0;
9480 /* OMP expansion -- the default pass, run before creation of SSA form. */
9482 namespace {
9484 const pass_data pass_data_expand_omp =
9486 GIMPLE_PASS, /* type */
9487 "ompexp", /* name */
9488 OPTGROUP_NONE, /* optinfo_flags */
9489 TV_NONE, /* tv_id */
9490 PROP_gimple_any, /* properties_required */
9491 PROP_gimple_eomp, /* properties_provided */
9492 0, /* properties_destroyed */
9493 0, /* todo_flags_start */
9494 0, /* todo_flags_finish */
9497 class pass_expand_omp : public gimple_opt_pass
9499 public:
9500 pass_expand_omp (gcc::context *ctxt)
9501 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9504 /* opt_pass methods: */
9505 virtual unsigned int execute (function *)
9507 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9508 || flag_openmp_simd != 0)
9509 && !seen_error ());
9511 /* This pass always runs, to provide PROP_gimple_eomp.
9512 But often, there is nothing to do. */
9513 if (!gate)
9514 return 0;
9516 return execute_expand_omp ();
9519 }; // class pass_expand_omp
9521 } // anon namespace
9523 gimple_opt_pass *
9524 make_pass_expand_omp (gcc::context *ctxt)
9526 return new pass_expand_omp (ctxt);
9529 namespace {
9531 const pass_data pass_data_expand_omp_ssa =
9533 GIMPLE_PASS, /* type */
9534 "ompexpssa", /* name */
9535 OPTGROUP_NONE, /* optinfo_flags */
9536 TV_NONE, /* tv_id */
9537 PROP_cfg | PROP_ssa, /* properties_required */
9538 PROP_gimple_eomp, /* properties_provided */
9539 0, /* properties_destroyed */
9540 0, /* todo_flags_start */
9541 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9544 class pass_expand_omp_ssa : public gimple_opt_pass
9546 public:
9547 pass_expand_omp_ssa (gcc::context *ctxt)
9548 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9551 /* opt_pass methods: */
9552 virtual bool gate (function *fun)
9554 return !(fun->curr_properties & PROP_gimple_eomp);
9556 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9558 }; // class pass_expand_omp_ssa
9560 } // anon namespace
9562 gimple_opt_pass *
9563 make_pass_expand_omp_ssa (gcc::context *ctxt)
9565 return new pass_expand_omp_ssa (ctxt);
9568 /* Routines to lower OMP directives into OMP-GIMPLE. */
9570 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9571 convert it to gimple. */
9572 static void
9573 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9575 gimple stmt;
9577 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9579 stmt = gimple_build_assign (dest, op, dest, src);
9580 gimple_seq_add_stmt (seq, stmt);
9581 return;
9584 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9585 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9586 gimplify_assign (t, rdest, seq);
9587 rdest = t;
9589 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9590 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9591 gimplify_assign (t, idest, seq);
9592 idest = t;
9594 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9595 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9596 gimplify_assign (t, rsrc, seq);
9597 rsrc = t;
9599 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9600 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9601 gimplify_assign (t, isrc, seq);
9602 isrc = t;
9604 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9605 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9606 tree result;
9608 if (op == PLUS_EXPR)
9610 stmt = gimple_build_assign (r, op, rdest, rsrc);
9611 gimple_seq_add_stmt (seq, stmt);
9613 stmt = gimple_build_assign (i, op, idest, isrc);
9614 gimple_seq_add_stmt (seq, stmt);
9616 else if (op == MULT_EXPR)
9618 /* Let x = a + ib = dest, y = c + id = src.
9619 x * y = (ac - bd) + i(ad + bc) */
9620 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9621 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9622 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9623 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9625 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9626 gimple_seq_add_stmt (seq, stmt);
9628 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9629 gimple_seq_add_stmt (seq, stmt);
9631 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9632 gimple_seq_add_stmt (seq, stmt);
9634 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9635 gimple_seq_add_stmt (seq, stmt);
9637 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9638 gimple_seq_add_stmt (seq, stmt);
9640 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9641 gimple_seq_add_stmt (seq, stmt);
9643 else
9644 gcc_unreachable ();
9646 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9647 gimplify_assign (dest, result, seq);
9650 /* Helper function to initialize local data for the reduction arrays.
9651 The reduction arrays need to be placed inside the calling function
9652 for accelerators, or else the host won't be able to preform the final
9653 reduction. */
9655 static void
9656 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9657 gimple_seq *stmt_seqp, omp_context *ctx)
9659 tree c, t, oc;
9660 gimple stmt;
9661 omp_context *octx;
9663 /* Find the innermost OpenACC parallel context. */
9664 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9665 && (gimple_omp_target_kind (ctx->stmt)
9666 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9667 octx = ctx;
9668 else
9669 octx = ctx->outer;
9670 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9671 && (gimple_omp_target_kind (octx->stmt)
9672 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9674 /* Extract the clauses. */
9675 oc = gimple_omp_target_clauses (octx->stmt);
9677 /* Find the last outer clause. */
9678 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9681 /* Allocate arrays for each reduction variable. */
9682 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9684 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9685 continue;
9687 tree var = OMP_CLAUSE_DECL (c);
9688 tree type = get_base_type (var);
9689 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9690 ctx);
9691 tree size, call;
9693 /* Calculate size of the reduction array. */
9694 t = create_tmp_var (TREE_TYPE (nthreads));
9695 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9696 fold_convert (TREE_TYPE (nthreads),
9697 TYPE_SIZE_UNIT (type)));
9698 gimple_seq_add_stmt (stmt_seqp, stmt);
9700 size = create_tmp_var (sizetype);
9701 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9703 /* Now allocate memory for it. */
9704 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9705 stmt = gimple_build_call (call, 1, size);
9706 gimple_call_set_lhs (stmt, array);
9707 gimple_seq_add_stmt (stmt_seqp, stmt);
9709 /* Map this array into the accelerator. */
9711 /* Add the reduction array to the list of clauses. */
9712 tree x = array;
9713 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9714 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9715 OMP_CLAUSE_DECL (t) = x;
9716 OMP_CLAUSE_CHAIN (t) = NULL;
9717 if (oc)
9718 OMP_CLAUSE_CHAIN (oc) = t;
9719 else
9720 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9721 OMP_CLAUSE_SIZE (t) = size;
9722 oc = t;
9726 /* Helper function to process the array of partial reductions. Nthreads
9727 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9728 cannot be used here, because nthreads on the host may be different than
9729 on the accelerator. */
9731 static void
9732 oacc_finalize_reduction_data (tree clauses, tree nthreads,
9733 gimple_seq *stmt_seqp, omp_context *ctx)
9735 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9736 gimple stmt;
9738 /* Create for loop.
9740 let var = the original reduction variable
9741 let array = reduction variable array
9743 for (i = 0; i < nthreads; i++)
9744 var op= array[i]
9747 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9748 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9749 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9751 /* Create and initialize an index variable. */
9752 tree ix = create_tmp_var (sizetype);
9753 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9754 stmt_seqp);
9756 /* Insert the loop header label here. */
9757 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9759 /* Exit loop if ix >= nthreads. */
9760 x = create_tmp_var (sizetype);
9761 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9762 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9763 gimple_seq_add_stmt (stmt_seqp, stmt);
9765 /* Insert the loop body label here. */
9766 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9768 /* Collapse each reduction array, one element at a time. */
9769 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9771 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9772 continue;
9774 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9776 /* reduction(-:var) sums up the partial results, so it acts
9777 identically to reduction(+:var). */
9778 if (reduction_code == MINUS_EXPR)
9779 reduction_code = PLUS_EXPR;
9781 /* Set up reduction variable var. */
9782 var = OMP_CLAUSE_DECL (c);
9783 type = get_base_type (var);
9784 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9785 (OMP_CLAUSE_DECL (c)), ctx);
9787 /* Calculate the array offset. */
9788 tree offset = create_tmp_var (sizetype);
9789 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9790 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9791 gimple_seq_add_stmt (stmt_seqp, stmt);
9793 tree ptr = create_tmp_var (TREE_TYPE (array));
9794 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9795 gimple_seq_add_stmt (stmt_seqp, stmt);
9797 /* Extract array[ix] into mem. */
9798 tree mem = create_tmp_var (type);
9799 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9801 /* Find the original reduction variable. */
9802 if (is_reference (var))
9803 var = build_simple_mem_ref (var);
9805 tree t = create_tmp_var (type);
9807 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9808 gimplify_and_add (unshare_expr(x), stmt_seqp);
9810 /* var = var op mem */
9811 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9813 case TRUTH_ANDIF_EXPR:
9814 case TRUTH_ORIF_EXPR:
9815 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9816 t, mem);
9817 gimplify_and_add (t, stmt_seqp);
9818 break;
9819 default:
9820 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9821 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9822 stmt_seqp);
9825 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9826 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9827 gimplify_and_add (unshare_expr(x), stmt_seqp);
9830 /* Increment the induction variable. */
9831 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9832 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9833 gimple_seq_add_stmt (stmt_seqp, stmt);
9835 /* Go back to the top of the loop. */
9836 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9838 /* Place the loop exit label here. */
9839 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9842 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9843 scan that for reductions. */
9845 static void
9846 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9847 gimple_seq *out_stmt_seqp, omp_context *ctx)
9849 gimple_stmt_iterator gsi;
9850 gimple_seq inner = NULL;
9852 /* A collapse clause may have inserted a new bind block. */
9853 gsi = gsi_start (*body);
9854 while (!gsi_end_p (gsi))
9856 gimple stmt = gsi_stmt (gsi);
9857 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9859 inner = gimple_bind_body (bind_stmt);
9860 body = &inner;
9861 gsi = gsi_start (*body);
9863 else if (dyn_cast <gomp_for *> (stmt))
9864 break;
9865 else
9866 gsi_next (&gsi);
9869 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9871 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9872 enter, exit;
9873 bool reduction_found = false;
9875 gimple stmt = gsi_stmt (gsi);
9877 switch (gimple_code (stmt))
9879 case GIMPLE_OMP_FOR:
9880 clauses = gimple_omp_for_clauses (stmt);
9882 /* Search for a reduction clause. */
9883 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9884 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9886 reduction_found = true;
9887 break;
9890 if (!reduction_found)
9891 break;
9893 ctx = maybe_lookup_ctx (stmt);
9894 t = NULL_TREE;
9896 /* Extract the number of threads. */
9897 nthreads = create_tmp_var (sizetype);
9898 t = oacc_max_threads (ctx);
9899 gimplify_assign (nthreads, t, in_stmt_seqp);
9901 /* Determine if this is kernel will be executed on the host. */
9902 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9903 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9904 stmt = gimple_build_call (call, 0);
9905 gimple_call_set_lhs (stmt, acc_device);
9906 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9908 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9909 acc_device_host = create_tmp_var (integer_type_node,
9910 ".acc_device_host");
9911 gimplify_assign (acc_device_host,
9912 build_int_cst (integer_type_node,
9913 GOMP_DEVICE_HOST),
9914 in_stmt_seqp);
9916 enter = create_artificial_label (UNKNOWN_LOCATION);
9917 exit = create_artificial_label (UNKNOWN_LOCATION);
9919 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9920 enter, exit);
9921 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9922 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9923 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9924 integer_one_node),
9925 in_stmt_seqp);
9926 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9928 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9929 gimplify_assign (acc_device_host,
9930 build_int_cst (integer_type_node,
9931 GOMP_DEVICE_HOST_NONSHM),
9932 in_stmt_seqp);
9934 enter = create_artificial_label (UNKNOWN_LOCATION);
9935 exit = create_artificial_label (UNKNOWN_LOCATION);
9937 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9938 enter, exit);
9939 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9940 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9941 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9942 integer_one_node),
9943 in_stmt_seqp);
9944 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9946 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9947 ctx);
9948 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9949 break;
9950 default:
9951 // Scan for other directives which support reduction here.
9952 break;
9957 /* If ctx is a worksharing context inside of a cancellable parallel
9958 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9959 and conditional branch to parallel's cancel_label to handle
9960 cancellation in the implicit barrier. */
9962 static void
9963 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9965 gimple omp_return = gimple_seq_last_stmt (*body);
9966 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
9967 if (gimple_omp_return_nowait_p (omp_return))
9968 return;
9969 if (ctx->outer
9970 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
9971 && ctx->outer->cancellable)
9973 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
9974 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
9975 tree lhs = create_tmp_var (c_bool_type);
9976 gimple_omp_return_set_lhs (omp_return, lhs);
9977 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
9978 gimple g = gimple_build_cond (NE_EXPR, lhs,
9979 fold_convert (c_bool_type,
9980 boolean_false_node),
9981 ctx->outer->cancel_label, fallthru_label);
9982 gimple_seq_add_stmt (body, g);
9983 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
9987 /* Lower the OpenMP sections directive in the current statement in GSI_P.
9988 CTX is the enclosing OMP context for the current statement. */
9990 static void
9991 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
9993 tree block, control;
9994 gimple_stmt_iterator tgsi;
9995 gomp_sections *stmt;
9996 gimple t;
9997 gbind *new_stmt, *bind;
9998 gimple_seq ilist, dlist, olist, new_body;
10000 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
10002 push_gimplify_context ();
10004 dlist = NULL;
10005 ilist = NULL;
10006 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10007 &ilist, &dlist, ctx, NULL);
10009 new_body = gimple_omp_body (stmt);
10010 gimple_omp_set_body (stmt, NULL);
10011 tgsi = gsi_start (new_body);
10012 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10014 omp_context *sctx;
10015 gimple sec_start;
10017 sec_start = gsi_stmt (tgsi);
10018 sctx = maybe_lookup_ctx (sec_start);
10019 gcc_assert (sctx);
10021 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10022 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10023 GSI_CONTINUE_LINKING);
10024 gimple_omp_set_body (sec_start, NULL);
10026 if (gsi_one_before_end_p (tgsi))
10028 gimple_seq l = NULL;
10029 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10030 &l, ctx);
10031 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10032 gimple_omp_section_set_last (sec_start);
10035 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10036 GSI_CONTINUE_LINKING);
10039 block = make_node (BLOCK);
10040 bind = gimple_build_bind (NULL, new_body, block);
10042 olist = NULL;
10043 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10045 block = make_node (BLOCK);
10046 new_stmt = gimple_build_bind (NULL, NULL, block);
10047 gsi_replace (gsi_p, new_stmt, true);
10049 pop_gimplify_context (new_stmt);
10050 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10051 BLOCK_VARS (block) = gimple_bind_vars (bind);
10052 if (BLOCK_VARS (block))
10053 TREE_USED (block) = 1;
10055 new_body = NULL;
10056 gimple_seq_add_seq (&new_body, ilist);
10057 gimple_seq_add_stmt (&new_body, stmt);
10058 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10059 gimple_seq_add_stmt (&new_body, bind);
10061 control = create_tmp_var (unsigned_type_node, ".section");
10062 t = gimple_build_omp_continue (control, control);
10063 gimple_omp_sections_set_control (stmt, control);
10064 gimple_seq_add_stmt (&new_body, t);
10066 gimple_seq_add_seq (&new_body, olist);
10067 if (ctx->cancellable)
10068 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10069 gimple_seq_add_seq (&new_body, dlist);
10071 new_body = maybe_catch_exception (new_body);
10073 t = gimple_build_omp_return
10074 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10075 OMP_CLAUSE_NOWAIT));
10076 gimple_seq_add_stmt (&new_body, t);
10077 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10079 gimple_bind_set_body (new_stmt, new_body);
10083 /* A subroutine of lower_omp_single. Expand the simple form of
10084 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10086 if (GOMP_single_start ())
10087 BODY;
10088 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10090 FIXME. It may be better to delay expanding the logic of this until
10091 pass_expand_omp. The expanded logic may make the job more difficult
10092 to a synchronization analysis pass. */
10094 static void
10095 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10097 location_t loc = gimple_location (single_stmt);
10098 tree tlabel = create_artificial_label (loc);
10099 tree flabel = create_artificial_label (loc);
10100 gimple call, cond;
10101 tree lhs, decl;
10103 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10104 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10105 call = gimple_build_call (decl, 0);
10106 gimple_call_set_lhs (call, lhs);
10107 gimple_seq_add_stmt (pre_p, call);
10109 cond = gimple_build_cond (EQ_EXPR, lhs,
10110 fold_convert_loc (loc, TREE_TYPE (lhs),
10111 boolean_true_node),
10112 tlabel, flabel);
10113 gimple_seq_add_stmt (pre_p, cond);
10114 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10115 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10116 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10120 /* A subroutine of lower_omp_single. Expand the simple form of
10121 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10123 #pragma omp single copyprivate (a, b, c)
10125 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10128 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10130 BODY;
10131 copyout.a = a;
10132 copyout.b = b;
10133 copyout.c = c;
10134 GOMP_single_copy_end (&copyout);
10136 else
10138 a = copyout_p->a;
10139 b = copyout_p->b;
10140 c = copyout_p->c;
10142 GOMP_barrier ();
10145 FIXME. It may be better to delay expanding the logic of this until
10146 pass_expand_omp. The expanded logic may make the job more difficult
10147 to a synchronization analysis pass. */
10149 static void
10150 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10151 omp_context *ctx)
10153 tree ptr_type, t, l0, l1, l2, bfn_decl;
10154 gimple_seq copyin_seq;
10155 location_t loc = gimple_location (single_stmt);
10157 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10159 ptr_type = build_pointer_type (ctx->record_type);
10160 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10162 l0 = create_artificial_label (loc);
10163 l1 = create_artificial_label (loc);
10164 l2 = create_artificial_label (loc);
10166 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10167 t = build_call_expr_loc (loc, bfn_decl, 0);
10168 t = fold_convert_loc (loc, ptr_type, t);
10169 gimplify_assign (ctx->receiver_decl, t, pre_p);
10171 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10172 build_int_cst (ptr_type, 0));
10173 t = build3 (COND_EXPR, void_type_node, t,
10174 build_and_jump (&l0), build_and_jump (&l1));
10175 gimplify_and_add (t, pre_p);
10177 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10179 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10181 copyin_seq = NULL;
10182 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10183 &copyin_seq, ctx);
10185 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10186 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10187 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10188 gimplify_and_add (t, pre_p);
10190 t = build_and_jump (&l2);
10191 gimplify_and_add (t, pre_p);
10193 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10195 gimple_seq_add_seq (pre_p, copyin_seq);
10197 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10201 /* Expand code for an OpenMP single directive. */
10203 static void
10204 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10206 tree block;
10207 gimple t;
10208 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10209 gbind *bind;
10210 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10212 push_gimplify_context ();
10214 block = make_node (BLOCK);
10215 bind = gimple_build_bind (NULL, NULL, block);
10216 gsi_replace (gsi_p, bind, true);
10217 bind_body = NULL;
10218 dlist = NULL;
10219 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10220 &bind_body, &dlist, ctx, NULL);
10221 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10223 gimple_seq_add_stmt (&bind_body, single_stmt);
10225 if (ctx->record_type)
10226 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10227 else
10228 lower_omp_single_simple (single_stmt, &bind_body);
10230 gimple_omp_set_body (single_stmt, NULL);
10232 gimple_seq_add_seq (&bind_body, dlist);
10234 bind_body = maybe_catch_exception (bind_body);
10236 t = gimple_build_omp_return
10237 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10238 OMP_CLAUSE_NOWAIT));
10239 gimple_seq_add_stmt (&bind_body_tail, t);
10240 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10241 if (ctx->record_type)
10243 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10244 tree clobber = build_constructor (ctx->record_type, NULL);
10245 TREE_THIS_VOLATILE (clobber) = 1;
10246 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10247 clobber), GSI_SAME_STMT);
10249 gimple_seq_add_seq (&bind_body, bind_body_tail);
10250 gimple_bind_set_body (bind, bind_body);
10252 pop_gimplify_context (bind);
10254 gimple_bind_append_vars (bind, ctx->block_vars);
10255 BLOCK_VARS (block) = ctx->block_vars;
10256 if (BLOCK_VARS (block))
10257 TREE_USED (block) = 1;
10261 /* Expand code for an OpenMP master directive. */
10263 static void
10264 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10266 tree block, lab = NULL, x, bfn_decl;
10267 gimple stmt = gsi_stmt (*gsi_p);
10268 gbind *bind;
10269 location_t loc = gimple_location (stmt);
10270 gimple_seq tseq;
10272 push_gimplify_context ();
10274 block = make_node (BLOCK);
10275 bind = gimple_build_bind (NULL, NULL, block);
10276 gsi_replace (gsi_p, bind, true);
10277 gimple_bind_add_stmt (bind, stmt);
10279 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10280 x = build_call_expr_loc (loc, bfn_decl, 0);
10281 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10282 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10283 tseq = NULL;
10284 gimplify_and_add (x, &tseq);
10285 gimple_bind_add_seq (bind, tseq);
10287 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10288 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10289 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10290 gimple_omp_set_body (stmt, NULL);
10292 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10294 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10296 pop_gimplify_context (bind);
10298 gimple_bind_append_vars (bind, ctx->block_vars);
10299 BLOCK_VARS (block) = ctx->block_vars;
10303 /* Expand code for an OpenMP taskgroup directive. */
10305 static void
10306 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10308 gimple stmt = gsi_stmt (*gsi_p);
10309 gcall *x;
10310 gbind *bind;
10311 tree block = make_node (BLOCK);
10313 bind = gimple_build_bind (NULL, NULL, block);
10314 gsi_replace (gsi_p, bind, true);
10315 gimple_bind_add_stmt (bind, stmt);
10317 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10319 gimple_bind_add_stmt (bind, x);
10321 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10322 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10323 gimple_omp_set_body (stmt, NULL);
10325 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10327 gimple_bind_append_vars (bind, ctx->block_vars);
10328 BLOCK_VARS (block) = ctx->block_vars;
10332 /* Expand code for an OpenMP ordered directive. */
10334 static void
10335 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10337 tree block;
10338 gimple stmt = gsi_stmt (*gsi_p);
10339 gcall *x;
10340 gbind *bind;
10342 push_gimplify_context ();
10344 block = make_node (BLOCK);
10345 bind = gimple_build_bind (NULL, NULL, block);
10346 gsi_replace (gsi_p, bind, true);
10347 gimple_bind_add_stmt (bind, stmt);
10349 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10351 gimple_bind_add_stmt (bind, x);
10353 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10354 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10355 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10356 gimple_omp_set_body (stmt, NULL);
10358 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10359 gimple_bind_add_stmt (bind, x);
10361 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10363 pop_gimplify_context (bind);
10365 gimple_bind_append_vars (bind, ctx->block_vars);
10366 BLOCK_VARS (block) = gimple_bind_vars (bind);
10370 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10371 substitution of a couple of function calls. But in the NAMED case,
10372 requires that languages coordinate a symbol name. It is therefore
10373 best put here in common code. */
10375 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10377 static void
10378 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10380 tree block;
10381 tree name, lock, unlock;
10382 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10383 gbind *bind;
10384 location_t loc = gimple_location (stmt);
10385 gimple_seq tbody;
10387 name = gimple_omp_critical_name (stmt);
10388 if (name)
10390 tree decl;
10392 if (!critical_name_mutexes)
10393 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10395 tree *n = critical_name_mutexes->get (name);
10396 if (n == NULL)
10398 char *new_str;
10400 decl = create_tmp_var_raw (ptr_type_node);
10402 new_str = ACONCAT ((".gomp_critical_user_",
10403 IDENTIFIER_POINTER (name), NULL));
10404 DECL_NAME (decl) = get_identifier (new_str);
10405 TREE_PUBLIC (decl) = 1;
10406 TREE_STATIC (decl) = 1;
10407 DECL_COMMON (decl) = 1;
10408 DECL_ARTIFICIAL (decl) = 1;
10409 DECL_IGNORED_P (decl) = 1;
10411 varpool_node::finalize_decl (decl);
10413 critical_name_mutexes->put (name, decl);
10415 else
10416 decl = *n;
10418 /* If '#pragma omp critical' is inside offloaded region or
10419 inside function marked as offloadable, the symbol must be
10420 marked as offloadable too. */
10421 omp_context *octx;
10422 if (cgraph_node::get (current_function_decl)->offloadable)
10423 varpool_node::get_create (decl)->offloadable = 1;
10424 else
10425 for (octx = ctx->outer; octx; octx = octx->outer)
10426 if (is_gimple_omp_offloaded (octx->stmt))
10428 varpool_node::get_create (decl)->offloadable = 1;
10429 break;
10432 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10433 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10435 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10436 unlock = build_call_expr_loc (loc, unlock, 1,
10437 build_fold_addr_expr_loc (loc, decl));
10439 else
10441 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10442 lock = build_call_expr_loc (loc, lock, 0);
10444 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10445 unlock = build_call_expr_loc (loc, unlock, 0);
10448 push_gimplify_context ();
10450 block = make_node (BLOCK);
10451 bind = gimple_build_bind (NULL, NULL, block);
10452 gsi_replace (gsi_p, bind, true);
10453 gimple_bind_add_stmt (bind, stmt);
10455 tbody = gimple_bind_body (bind);
10456 gimplify_and_add (lock, &tbody);
10457 gimple_bind_set_body (bind, tbody);
10459 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10460 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10461 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10462 gimple_omp_set_body (stmt, NULL);
10464 tbody = gimple_bind_body (bind);
10465 gimplify_and_add (unlock, &tbody);
10466 gimple_bind_set_body (bind, tbody);
10468 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10470 pop_gimplify_context (bind);
10471 gimple_bind_append_vars (bind, ctx->block_vars);
10472 BLOCK_VARS (block) = gimple_bind_vars (bind);
10476 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10477 for a lastprivate clause. Given a loop control predicate of (V
10478 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10479 is appended to *DLIST, iterator initialization is appended to
10480 *BODY_P. */
10482 static void
10483 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10484 gimple_seq *dlist, struct omp_context *ctx)
10486 tree clauses, cond, vinit;
10487 enum tree_code cond_code;
10488 gimple_seq stmts;
10490 cond_code = fd->loop.cond_code;
10491 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10493 /* When possible, use a strict equality expression. This can let VRP
10494 type optimizations deduce the value and remove a copy. */
10495 if (tree_fits_shwi_p (fd->loop.step))
10497 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10498 if (step == 1 || step == -1)
10499 cond_code = EQ_EXPR;
10502 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
10504 clauses = gimple_omp_for_clauses (fd->for_stmt);
10505 stmts = NULL;
10506 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10507 if (!gimple_seq_empty_p (stmts))
10509 gimple_seq_add_seq (&stmts, *dlist);
10510 *dlist = stmts;
10512 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10513 vinit = fd->loop.n1;
10514 if (cond_code == EQ_EXPR
10515 && tree_fits_shwi_p (fd->loop.n2)
10516 && ! integer_zerop (fd->loop.n2))
10517 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10518 else
10519 vinit = unshare_expr (vinit);
10521 /* Initialize the iterator variable, so that threads that don't execute
10522 any iterations don't execute the lastprivate clauses by accident. */
10523 gimplify_assign (fd->loop.v, vinit, body_p);
10528 /* Lower code for an OMP loop directive. */
10530 static void
10531 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10533 tree *rhs_p, block;
10534 struct omp_for_data fd, *fdp = NULL;
10535 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10536 gbind *new_stmt;
10537 gimple_seq omp_for_body, body, dlist;
10538 size_t i;
10540 push_gimplify_context ();
10542 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10544 block = make_node (BLOCK);
10545 new_stmt = gimple_build_bind (NULL, NULL, block);
10546 /* Replace at gsi right away, so that 'stmt' is no member
10547 of a sequence anymore as we're going to add to to a different
10548 one below. */
10549 gsi_replace (gsi_p, new_stmt, true);
10551 /* Move declaration of temporaries in the loop body before we make
10552 it go away. */
10553 omp_for_body = gimple_omp_body (stmt);
10554 if (!gimple_seq_empty_p (omp_for_body)
10555 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10557 gbind *inner_bind
10558 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10559 tree vars = gimple_bind_vars (inner_bind);
10560 gimple_bind_append_vars (new_stmt, vars);
10561 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10562 keep them on the inner_bind and it's block. */
10563 gimple_bind_set_vars (inner_bind, NULL_TREE);
10564 if (gimple_bind_block (inner_bind))
10565 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10568 if (gimple_omp_for_combined_into_p (stmt))
10570 extract_omp_for_data (stmt, &fd, NULL);
10571 fdp = &fd;
10573 /* We need two temporaries with fd.loop.v type (istart/iend)
10574 and then (fd.collapse - 1) temporaries with the same
10575 type for count2 ... countN-1 vars if not constant. */
10576 size_t count = 2;
10577 tree type = fd.iter_type;
10578 if (fd.collapse > 1
10579 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10580 count += fd.collapse - 1;
10581 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10582 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10583 tree clauses = *pc;
10584 if (parallel_for)
10585 outerc
10586 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10587 OMP_CLAUSE__LOOPTEMP_);
10588 for (i = 0; i < count; i++)
10590 tree temp;
10591 if (parallel_for)
10593 gcc_assert (outerc);
10594 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10595 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10596 OMP_CLAUSE__LOOPTEMP_);
10598 else
10600 temp = create_tmp_var (type);
10601 insert_decl_map (&ctx->outer->cb, temp, temp);
10603 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10604 OMP_CLAUSE_DECL (*pc) = temp;
10605 pc = &OMP_CLAUSE_CHAIN (*pc);
10607 *pc = clauses;
10610 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10611 dlist = NULL;
10612 body = NULL;
10613 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10614 fdp);
10615 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10617 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10619 /* Lower the header expressions. At this point, we can assume that
10620 the header is of the form:
10622 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10624 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10625 using the .omp_data_s mapping, if needed. */
10626 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10628 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10629 if (!is_gimple_min_invariant (*rhs_p))
10630 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10632 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10633 if (!is_gimple_min_invariant (*rhs_p))
10634 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10636 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10637 if (!is_gimple_min_invariant (*rhs_p))
10638 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10641 /* Once lowered, extract the bounds and clauses. */
10642 extract_omp_for_data (stmt, &fd, NULL);
10644 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10646 gimple_seq_add_stmt (&body, stmt);
10647 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10649 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10650 fd.loop.v));
10652 /* After the loop, add exit clauses. */
10653 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10655 if (ctx->cancellable)
10656 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10658 gimple_seq_add_seq (&body, dlist);
10660 body = maybe_catch_exception (body);
10662 /* Region exit marker goes at the end of the loop body. */
10663 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10664 maybe_add_implicit_barrier_cancel (ctx, &body);
10665 pop_gimplify_context (new_stmt);
10667 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10668 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10669 if (BLOCK_VARS (block))
10670 TREE_USED (block) = 1;
10672 gimple_bind_set_body (new_stmt, body);
10673 gimple_omp_set_body (stmt, NULL);
10674 gimple_omp_for_set_pre_body (stmt, NULL);
10677 /* Callback for walk_stmts. Check if the current statement only contains
10678 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10680 static tree
10681 check_combined_parallel (gimple_stmt_iterator *gsi_p,
10682 bool *handled_ops_p,
10683 struct walk_stmt_info *wi)
10685 int *info = (int *) wi->info;
10686 gimple stmt = gsi_stmt (*gsi_p);
10688 *handled_ops_p = true;
10689 switch (gimple_code (stmt))
10691 WALK_SUBSTMTS;
10693 case GIMPLE_OMP_FOR:
10694 case GIMPLE_OMP_SECTIONS:
10695 *info = *info == 0 ? 1 : -1;
10696 break;
10697 default:
10698 *info = -1;
10699 break;
10701 return NULL;
10704 struct omp_taskcopy_context
10706 /* This field must be at the beginning, as we do "inheritance": Some
10707 callback functions for tree-inline.c (e.g., omp_copy_decl)
10708 receive a copy_body_data pointer that is up-casted to an
10709 omp_context pointer. */
10710 copy_body_data cb;
10711 omp_context *ctx;
10714 static tree
10715 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10717 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10719 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10720 return create_tmp_var (TREE_TYPE (var));
10722 return var;
10725 static tree
10726 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10728 tree name, new_fields = NULL, type, f;
10730 type = lang_hooks.types.make_type (RECORD_TYPE);
10731 name = DECL_NAME (TYPE_NAME (orig_type));
10732 name = build_decl (gimple_location (tcctx->ctx->stmt),
10733 TYPE_DECL, name, type);
10734 TYPE_NAME (type) = name;
10736 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10738 tree new_f = copy_node (f);
10739 DECL_CONTEXT (new_f) = type;
10740 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10741 TREE_CHAIN (new_f) = new_fields;
10742 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10743 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10744 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10745 &tcctx->cb, NULL);
10746 new_fields = new_f;
10747 tcctx->cb.decl_map->put (f, new_f);
10749 TYPE_FIELDS (type) = nreverse (new_fields);
10750 layout_type (type);
10751 return type;
10754 /* Create task copyfn. */
10756 static void
10757 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
10759 struct function *child_cfun;
10760 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10761 tree record_type, srecord_type, bind, list;
10762 bool record_needs_remap = false, srecord_needs_remap = false;
10763 splay_tree_node n;
10764 struct omp_taskcopy_context tcctx;
10765 location_t loc = gimple_location (task_stmt);
10767 child_fn = gimple_omp_task_copy_fn (task_stmt);
10768 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10769 gcc_assert (child_cfun->cfg == NULL);
10770 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10772 /* Reset DECL_CONTEXT on function arguments. */
10773 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10774 DECL_CONTEXT (t) = child_fn;
10776 /* Populate the function. */
10777 push_gimplify_context ();
10778 push_cfun (child_cfun);
10780 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10781 TREE_SIDE_EFFECTS (bind) = 1;
10782 list = NULL;
10783 DECL_SAVED_TREE (child_fn) = bind;
10784 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10786 /* Remap src and dst argument types if needed. */
10787 record_type = ctx->record_type;
10788 srecord_type = ctx->srecord_type;
10789 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10790 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10792 record_needs_remap = true;
10793 break;
10795 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10796 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10798 srecord_needs_remap = true;
10799 break;
10802 if (record_needs_remap || srecord_needs_remap)
10804 memset (&tcctx, '\0', sizeof (tcctx));
10805 tcctx.cb.src_fn = ctx->cb.src_fn;
10806 tcctx.cb.dst_fn = child_fn;
10807 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
10808 gcc_checking_assert (tcctx.cb.src_node);
10809 tcctx.cb.dst_node = tcctx.cb.src_node;
10810 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10811 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10812 tcctx.cb.eh_lp_nr = 0;
10813 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10814 tcctx.cb.decl_map = new hash_map<tree, tree>;
10815 tcctx.ctx = ctx;
10817 if (record_needs_remap)
10818 record_type = task_copyfn_remap_type (&tcctx, record_type);
10819 if (srecord_needs_remap)
10820 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10822 else
10823 tcctx.cb.decl_map = NULL;
10825 arg = DECL_ARGUMENTS (child_fn);
10826 TREE_TYPE (arg) = build_pointer_type (record_type);
10827 sarg = DECL_CHAIN (arg);
10828 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10830 /* First pass: initialize temporaries used in record_type and srecord_type
10831 sizes and field offsets. */
10832 if (tcctx.cb.decl_map)
10833 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10834 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10836 tree *p;
10838 decl = OMP_CLAUSE_DECL (c);
10839 p = tcctx.cb.decl_map->get (decl);
10840 if (p == NULL)
10841 continue;
10842 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10843 sf = (tree) n->value;
10844 sf = *tcctx.cb.decl_map->get (sf);
10845 src = build_simple_mem_ref_loc (loc, sarg);
10846 src = omp_build_component_ref (src, sf);
10847 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10848 append_to_statement_list (t, &list);
10851 /* Second pass: copy shared var pointers and copy construct non-VLA
10852 firstprivate vars. */
10853 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10854 switch (OMP_CLAUSE_CODE (c))
10856 case OMP_CLAUSE_SHARED:
10857 decl = OMP_CLAUSE_DECL (c);
10858 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10859 if (n == NULL)
10860 break;
10861 f = (tree) n->value;
10862 if (tcctx.cb.decl_map)
10863 f = *tcctx.cb.decl_map->get (f);
10864 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10865 sf = (tree) n->value;
10866 if (tcctx.cb.decl_map)
10867 sf = *tcctx.cb.decl_map->get (sf);
10868 src = build_simple_mem_ref_loc (loc, sarg);
10869 src = omp_build_component_ref (src, sf);
10870 dst = build_simple_mem_ref_loc (loc, arg);
10871 dst = omp_build_component_ref (dst, f);
10872 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10873 append_to_statement_list (t, &list);
10874 break;
10875 case OMP_CLAUSE_FIRSTPRIVATE:
10876 decl = OMP_CLAUSE_DECL (c);
10877 if (is_variable_sized (decl))
10878 break;
10879 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10880 if (n == NULL)
10881 break;
10882 f = (tree) n->value;
10883 if (tcctx.cb.decl_map)
10884 f = *tcctx.cb.decl_map->get (f);
10885 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10886 if (n != NULL)
10888 sf = (tree) n->value;
10889 if (tcctx.cb.decl_map)
10890 sf = *tcctx.cb.decl_map->get (sf);
10891 src = build_simple_mem_ref_loc (loc, sarg);
10892 src = omp_build_component_ref (src, sf);
10893 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
10894 src = build_simple_mem_ref_loc (loc, src);
10896 else
10897 src = decl;
10898 dst = build_simple_mem_ref_loc (loc, arg);
10899 dst = omp_build_component_ref (dst, f);
10900 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10901 append_to_statement_list (t, &list);
10902 break;
10903 case OMP_CLAUSE_PRIVATE:
10904 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10905 break;
10906 decl = OMP_CLAUSE_DECL (c);
10907 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10908 f = (tree) n->value;
10909 if (tcctx.cb.decl_map)
10910 f = *tcctx.cb.decl_map->get (f);
10911 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10912 if (n != NULL)
10914 sf = (tree) n->value;
10915 if (tcctx.cb.decl_map)
10916 sf = *tcctx.cb.decl_map->get (sf);
10917 src = build_simple_mem_ref_loc (loc, sarg);
10918 src = omp_build_component_ref (src, sf);
10919 if (use_pointer_for_field (decl, NULL))
10920 src = build_simple_mem_ref_loc (loc, src);
10922 else
10923 src = decl;
10924 dst = build_simple_mem_ref_loc (loc, arg);
10925 dst = omp_build_component_ref (dst, f);
10926 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10927 append_to_statement_list (t, &list);
10928 break;
10929 default:
10930 break;
10933 /* Last pass: handle VLA firstprivates. */
10934 if (tcctx.cb.decl_map)
10935 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10936 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10938 tree ind, ptr, df;
10940 decl = OMP_CLAUSE_DECL (c);
10941 if (!is_variable_sized (decl))
10942 continue;
10943 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10944 if (n == NULL)
10945 continue;
10946 f = (tree) n->value;
10947 f = *tcctx.cb.decl_map->get (f);
10948 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10949 ind = DECL_VALUE_EXPR (decl);
10950 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10951 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10952 n = splay_tree_lookup (ctx->sfield_map,
10953 (splay_tree_key) TREE_OPERAND (ind, 0));
10954 sf = (tree) n->value;
10955 sf = *tcctx.cb.decl_map->get (sf);
10956 src = build_simple_mem_ref_loc (loc, sarg);
10957 src = omp_build_component_ref (src, sf);
10958 src = build_simple_mem_ref_loc (loc, src);
10959 dst = build_simple_mem_ref_loc (loc, arg);
10960 dst = omp_build_component_ref (dst, f);
10961 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10962 append_to_statement_list (t, &list);
10963 n = splay_tree_lookup (ctx->field_map,
10964 (splay_tree_key) TREE_OPERAND (ind, 0));
10965 df = (tree) n->value;
10966 df = *tcctx.cb.decl_map->get (df);
10967 ptr = build_simple_mem_ref_loc (loc, arg);
10968 ptr = omp_build_component_ref (ptr, df);
10969 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
10970 build_fold_addr_expr_loc (loc, dst));
10971 append_to_statement_list (t, &list);
10974 t = build1 (RETURN_EXPR, void_type_node, NULL);
10975 append_to_statement_list (t, &list);
10977 if (tcctx.cb.decl_map)
10978 delete tcctx.cb.decl_map;
10979 pop_gimplify_context (NULL);
10980 BIND_EXPR_BODY (bind) = list;
10981 pop_cfun ();
10984 static void
10985 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
10987 tree c, clauses;
10988 gimple g;
10989 size_t n_in = 0, n_out = 0, idx = 2, i;
10991 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
10992 OMP_CLAUSE_DEPEND);
10993 gcc_assert (clauses);
10994 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10995 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
10996 switch (OMP_CLAUSE_DEPEND_KIND (c))
10998 case OMP_CLAUSE_DEPEND_IN:
10999 n_in++;
11000 break;
11001 case OMP_CLAUSE_DEPEND_OUT:
11002 case OMP_CLAUSE_DEPEND_INOUT:
11003 n_out++;
11004 break;
11005 default:
11006 gcc_unreachable ();
11008 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11009 tree array = create_tmp_var (type);
11010 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11011 NULL_TREE);
11012 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11013 gimple_seq_add_stmt (iseq, g);
11014 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11015 NULL_TREE);
11016 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11017 gimple_seq_add_stmt (iseq, g);
11018 for (i = 0; i < 2; i++)
11020 if ((i ? n_in : n_out) == 0)
11021 continue;
11022 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11023 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11024 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11026 tree t = OMP_CLAUSE_DECL (c);
11027 t = fold_convert (ptr_type_node, t);
11028 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11029 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11030 NULL_TREE, NULL_TREE);
11031 g = gimple_build_assign (r, t);
11032 gimple_seq_add_stmt (iseq, g);
11035 tree *p = gimple_omp_task_clauses_ptr (stmt);
11036 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11037 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11038 OMP_CLAUSE_CHAIN (c) = *p;
11039 *p = c;
11040 tree clobber = build_constructor (type, NULL);
11041 TREE_THIS_VOLATILE (clobber) = 1;
11042 g = gimple_build_assign (array, clobber);
11043 gimple_seq_add_stmt (oseq, g);
11046 /* Lower the OpenMP parallel or task directive in the current statement
11047 in GSI_P. CTX holds context information for the directive. */
11049 static void
11050 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11052 tree clauses;
11053 tree child_fn, t;
11054 gimple stmt = gsi_stmt (*gsi_p);
11055 gbind *par_bind, *bind, *dep_bind = NULL;
11056 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11057 location_t loc = gimple_location (stmt);
11059 clauses = gimple_omp_taskreg_clauses (stmt);
11060 par_bind
11061 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11062 par_body = gimple_bind_body (par_bind);
11063 child_fn = ctx->cb.dst_fn;
11064 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11065 && !gimple_omp_parallel_combined_p (stmt))
11067 struct walk_stmt_info wi;
11068 int ws_num = 0;
11070 memset (&wi, 0, sizeof (wi));
11071 wi.info = &ws_num;
11072 wi.val_only = true;
11073 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11074 if (ws_num == 1)
11075 gimple_omp_parallel_set_combined_p (stmt, true);
11077 gimple_seq dep_ilist = NULL;
11078 gimple_seq dep_olist = NULL;
11079 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11080 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11082 push_gimplify_context ();
11083 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11084 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11087 if (ctx->srecord_type)
11088 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11090 push_gimplify_context ();
11092 par_olist = NULL;
11093 par_ilist = NULL;
11094 par_rlist = NULL;
11095 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11096 lower_omp (&par_body, ctx);
11097 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11098 lower_reduction_clauses (clauses, &par_rlist, ctx);
11100 /* Declare all the variables created by mapping and the variables
11101 declared in the scope of the parallel body. */
11102 record_vars_into (ctx->block_vars, child_fn);
11103 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11105 if (ctx->record_type)
11107 ctx->sender_decl
11108 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11109 : ctx->record_type, ".omp_data_o");
11110 DECL_NAMELESS (ctx->sender_decl) = 1;
11111 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11112 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11115 olist = NULL;
11116 ilist = NULL;
11117 lower_send_clauses (clauses, &ilist, &olist, ctx);
11118 lower_send_shared_vars (&ilist, &olist, ctx);
11120 if (ctx->record_type)
11122 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11123 TREE_THIS_VOLATILE (clobber) = 1;
11124 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11125 clobber));
11128 /* Once all the expansions are done, sequence all the different
11129 fragments inside gimple_omp_body. */
11131 new_body = NULL;
11133 if (ctx->record_type)
11135 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11136 /* fixup_child_record_type might have changed receiver_decl's type. */
11137 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11138 gimple_seq_add_stmt (&new_body,
11139 gimple_build_assign (ctx->receiver_decl, t));
11142 gimple_seq_add_seq (&new_body, par_ilist);
11143 gimple_seq_add_seq (&new_body, par_body);
11144 gimple_seq_add_seq (&new_body, par_rlist);
11145 if (ctx->cancellable)
11146 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11147 gimple_seq_add_seq (&new_body, par_olist);
11148 new_body = maybe_catch_exception (new_body);
11149 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11150 gimple_omp_set_body (stmt, new_body);
11152 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11153 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11154 gimple_bind_add_seq (bind, ilist);
11155 gimple_bind_add_stmt (bind, stmt);
11156 gimple_bind_add_seq (bind, olist);
11158 pop_gimplify_context (NULL);
11160 if (dep_bind)
11162 gimple_bind_add_seq (dep_bind, dep_ilist);
11163 gimple_bind_add_stmt (dep_bind, bind);
11164 gimple_bind_add_seq (dep_bind, dep_olist);
11165 pop_gimplify_context (dep_bind);
11169 /* Lower the GIMPLE_OMP_TARGET in the current statement
11170 in GSI_P. CTX holds context information for the directive. */
11172 static void
11173 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11175 tree clauses;
11176 tree child_fn, t, c;
11177 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11178 gbind *tgt_bind, *bind;
11179 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11180 location_t loc = gimple_location (stmt);
11181 bool offloaded, data_region;
11182 unsigned int map_cnt = 0;
11184 offloaded = is_gimple_omp_offloaded (stmt);
11185 switch (gimple_omp_target_kind (stmt))
11187 case GF_OMP_TARGET_KIND_REGION:
11188 case GF_OMP_TARGET_KIND_UPDATE:
11189 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11190 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11191 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11192 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11193 data_region = false;
11194 break;
11195 case GF_OMP_TARGET_KIND_DATA:
11196 case GF_OMP_TARGET_KIND_OACC_DATA:
11197 data_region = true;
11198 break;
11199 default:
11200 gcc_unreachable ();
11203 clauses = gimple_omp_target_clauses (stmt);
11205 tgt_bind = NULL;
11206 tgt_body = NULL;
11207 if (offloaded)
11209 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11210 tgt_body = gimple_bind_body (tgt_bind);
11212 else if (data_region)
11213 tgt_body = gimple_omp_body (stmt);
11214 child_fn = ctx->cb.dst_fn;
11216 push_gimplify_context ();
11218 irlist = NULL;
11219 orlist = NULL;
11220 if (offloaded
11221 && is_gimple_omp_oacc (stmt))
11222 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11224 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11225 switch (OMP_CLAUSE_CODE (c))
11227 tree var, x;
11229 default:
11230 break;
11231 case OMP_CLAUSE_MAP:
11232 #ifdef ENABLE_CHECKING
11233 /* First check what we're prepared to handle in the following. */
11234 switch (OMP_CLAUSE_MAP_KIND (c))
11236 case GOMP_MAP_ALLOC:
11237 case GOMP_MAP_TO:
11238 case GOMP_MAP_FROM:
11239 case GOMP_MAP_TOFROM:
11240 case GOMP_MAP_POINTER:
11241 case GOMP_MAP_TO_PSET:
11242 break;
11243 case GOMP_MAP_FORCE_ALLOC:
11244 case GOMP_MAP_FORCE_TO:
11245 case GOMP_MAP_FORCE_FROM:
11246 case GOMP_MAP_FORCE_TOFROM:
11247 case GOMP_MAP_FORCE_PRESENT:
11248 case GOMP_MAP_FORCE_DEALLOC:
11249 case GOMP_MAP_FORCE_DEVICEPTR:
11250 gcc_assert (is_gimple_omp_oacc (stmt));
11251 break;
11252 default:
11253 gcc_unreachable ();
11255 #endif
11256 /* FALLTHRU */
11257 case OMP_CLAUSE_TO:
11258 case OMP_CLAUSE_FROM:
11259 var = OMP_CLAUSE_DECL (c);
11260 if (!DECL_P (var))
11262 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11263 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11264 map_cnt++;
11265 continue;
11268 if (DECL_SIZE (var)
11269 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11271 tree var2 = DECL_VALUE_EXPR (var);
11272 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11273 var2 = TREE_OPERAND (var2, 0);
11274 gcc_assert (DECL_P (var2));
11275 var = var2;
11278 if (!maybe_lookup_field (var, ctx))
11279 continue;
11281 if (offloaded)
11283 x = build_receiver_ref (var, true, ctx);
11284 tree new_var = lookup_decl (var, ctx);
11285 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11286 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11287 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11288 x = build_simple_mem_ref (x);
11289 SET_DECL_VALUE_EXPR (new_var, x);
11290 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11292 map_cnt++;
11295 if (offloaded)
11297 target_nesting_level++;
11298 lower_omp (&tgt_body, ctx);
11299 target_nesting_level--;
11301 else if (data_region)
11302 lower_omp (&tgt_body, ctx);
11304 if (offloaded)
11306 /* Declare all the variables created by mapping and the variables
11307 declared in the scope of the target body. */
11308 record_vars_into (ctx->block_vars, child_fn);
11309 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11312 olist = NULL;
11313 ilist = NULL;
11314 if (ctx->record_type)
11316 ctx->sender_decl
11317 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11318 DECL_NAMELESS (ctx->sender_decl) = 1;
11319 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11320 t = make_tree_vec (3);
11321 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11322 TREE_VEC_ELT (t, 1)
11323 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11324 ".omp_data_sizes");
11325 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11326 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11327 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11328 tree tkind_type;
11329 int talign_shift;
11330 if (is_gimple_omp_oacc (stmt))
11332 tkind_type = short_unsigned_type_node;
11333 talign_shift = 8;
11335 else
11337 tkind_type = unsigned_char_type_node;
11338 talign_shift = 3;
11340 TREE_VEC_ELT (t, 2)
11341 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11342 ".omp_data_kinds");
11343 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11344 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11345 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11346 gimple_omp_target_set_data_arg (stmt, t);
11348 vec<constructor_elt, va_gc> *vsize;
11349 vec<constructor_elt, va_gc> *vkind;
11350 vec_alloc (vsize, map_cnt);
11351 vec_alloc (vkind, map_cnt);
11352 unsigned int map_idx = 0;
11354 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11355 switch (OMP_CLAUSE_CODE (c))
11357 tree ovar, nc;
11359 default:
11360 break;
11361 case OMP_CLAUSE_MAP:
11362 case OMP_CLAUSE_TO:
11363 case OMP_CLAUSE_FROM:
11364 nc = c;
11365 ovar = OMP_CLAUSE_DECL (c);
11366 if (!DECL_P (ovar))
11368 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11369 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11371 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11372 == get_base_address (ovar));
11373 nc = OMP_CLAUSE_CHAIN (c);
11374 ovar = OMP_CLAUSE_DECL (nc);
11376 else
11378 tree x = build_sender_ref (ovar, ctx);
11379 tree v
11380 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11381 gimplify_assign (x, v, &ilist);
11382 nc = NULL_TREE;
11385 else
11387 if (DECL_SIZE (ovar)
11388 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11390 tree ovar2 = DECL_VALUE_EXPR (ovar);
11391 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11392 ovar2 = TREE_OPERAND (ovar2, 0);
11393 gcc_assert (DECL_P (ovar2));
11394 ovar = ovar2;
11396 if (!maybe_lookup_field (ovar, ctx))
11397 continue;
11400 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11401 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11402 talign = DECL_ALIGN_UNIT (ovar);
11403 if (nc)
11405 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11406 tree x = build_sender_ref (ovar, ctx);
11407 if (maybe_lookup_oacc_reduction (var, ctx))
11409 gcc_checking_assert (offloaded
11410 && is_gimple_omp_oacc (stmt));
11411 gimplify_assign (x, var, &ilist);
11413 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11414 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11415 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11416 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11418 gcc_assert (offloaded);
11419 tree avar
11420 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11421 mark_addressable (avar);
11422 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11423 talign = DECL_ALIGN_UNIT (avar);
11424 avar = build_fold_addr_expr (avar);
11425 gimplify_assign (x, avar, &ilist);
11427 else if (is_gimple_reg (var))
11429 gcc_assert (offloaded);
11430 tree avar = create_tmp_var (TREE_TYPE (var));
11431 mark_addressable (avar);
11432 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11433 if (GOMP_MAP_COPY_TO_P (map_kind)
11434 || map_kind == GOMP_MAP_POINTER
11435 || map_kind == GOMP_MAP_TO_PSET
11436 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11437 gimplify_assign (avar, var, &ilist);
11438 avar = build_fold_addr_expr (avar);
11439 gimplify_assign (x, avar, &ilist);
11440 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11441 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11442 && !TYPE_READONLY (TREE_TYPE (var)))
11444 x = build_sender_ref (ovar, ctx);
11445 x = build_simple_mem_ref (x);
11446 gimplify_assign (var, x, &olist);
11449 else
11451 var = build_fold_addr_expr (var);
11452 gimplify_assign (x, var, &ilist);
11455 tree s = OMP_CLAUSE_SIZE (c);
11456 if (s == NULL_TREE)
11457 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11458 s = fold_convert (size_type_node, s);
11459 tree purpose = size_int (map_idx++);
11460 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11461 if (TREE_CODE (s) != INTEGER_CST)
11462 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11464 unsigned HOST_WIDE_INT tkind;
11465 switch (OMP_CLAUSE_CODE (c))
11467 case OMP_CLAUSE_MAP:
11468 tkind = OMP_CLAUSE_MAP_KIND (c);
11469 break;
11470 case OMP_CLAUSE_TO:
11471 tkind = GOMP_MAP_TO;
11472 break;
11473 case OMP_CLAUSE_FROM:
11474 tkind = GOMP_MAP_FROM;
11475 break;
11476 default:
11477 gcc_unreachable ();
11479 gcc_checking_assert (tkind
11480 < (HOST_WIDE_INT_C (1U) << talign_shift));
11481 talign = ceil_log2 (talign);
11482 tkind |= talign << talign_shift;
11483 gcc_checking_assert (tkind
11484 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11485 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11486 build_int_cstu (tkind_type, tkind));
11487 if (nc && nc != c)
11488 c = nc;
11491 gcc_assert (map_idx == map_cnt);
11493 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11494 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11495 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11496 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11497 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11499 gimple_seq initlist = NULL;
11500 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11501 TREE_VEC_ELT (t, 1)),
11502 &initlist, true, NULL_TREE);
11503 gimple_seq_add_seq (&ilist, initlist);
11505 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11506 NULL);
11507 TREE_THIS_VOLATILE (clobber) = 1;
11508 gimple_seq_add_stmt (&olist,
11509 gimple_build_assign (TREE_VEC_ELT (t, 1),
11510 clobber));
11513 tree clobber = build_constructor (ctx->record_type, NULL);
11514 TREE_THIS_VOLATILE (clobber) = 1;
11515 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11516 clobber));
11519 /* Once all the expansions are done, sequence all the different
11520 fragments inside gimple_omp_body. */
11522 new_body = NULL;
11524 if (offloaded
11525 && ctx->record_type)
11527 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11528 /* fixup_child_record_type might have changed receiver_decl's type. */
11529 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11530 gimple_seq_add_stmt (&new_body,
11531 gimple_build_assign (ctx->receiver_decl, t));
11534 if (offloaded)
11536 gimple_seq_add_seq (&new_body, tgt_body);
11537 new_body = maybe_catch_exception (new_body);
11539 else if (data_region)
11540 new_body = tgt_body;
11541 if (offloaded || data_region)
11543 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11544 gimple_omp_set_body (stmt, new_body);
11547 bind = gimple_build_bind (NULL, NULL,
11548 tgt_bind ? gimple_bind_block (tgt_bind)
11549 : NULL_TREE);
11550 gsi_replace (gsi_p, bind, true);
11551 gimple_bind_add_seq (bind, irlist);
11552 gimple_bind_add_seq (bind, ilist);
11553 gimple_bind_add_stmt (bind, stmt);
11554 gimple_bind_add_seq (bind, olist);
11555 gimple_bind_add_seq (bind, orlist);
11557 pop_gimplify_context (NULL);
11560 /* Expand code for an OpenMP teams directive. */
11562 static void
11563 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11565 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11566 push_gimplify_context ();
11568 tree block = make_node (BLOCK);
11569 gbind *bind = gimple_build_bind (NULL, NULL, block);
11570 gsi_replace (gsi_p, bind, true);
11571 gimple_seq bind_body = NULL;
11572 gimple_seq dlist = NULL;
11573 gimple_seq olist = NULL;
11575 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11576 OMP_CLAUSE_NUM_TEAMS);
11577 if (num_teams == NULL_TREE)
11578 num_teams = build_int_cst (unsigned_type_node, 0);
11579 else
11581 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11582 num_teams = fold_convert (unsigned_type_node, num_teams);
11583 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11585 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11586 OMP_CLAUSE_THREAD_LIMIT);
11587 if (thread_limit == NULL_TREE)
11588 thread_limit = build_int_cst (unsigned_type_node, 0);
11589 else
11591 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11592 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11593 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11594 fb_rvalue);
11597 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11598 &bind_body, &dlist, ctx, NULL);
11599 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11600 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11601 gimple_seq_add_stmt (&bind_body, teams_stmt);
11603 location_t loc = gimple_location (teams_stmt);
11604 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11605 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11606 gimple_set_location (call, loc);
11607 gimple_seq_add_stmt (&bind_body, call);
11609 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11610 gimple_omp_set_body (teams_stmt, NULL);
11611 gimple_seq_add_seq (&bind_body, olist);
11612 gimple_seq_add_seq (&bind_body, dlist);
11613 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11614 gimple_bind_set_body (bind, bind_body);
11616 pop_gimplify_context (bind);
11618 gimple_bind_append_vars (bind, ctx->block_vars);
11619 BLOCK_VARS (block) = ctx->block_vars;
11620 if (BLOCK_VARS (block))
11621 TREE_USED (block) = 1;
11625 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11626 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11627 of OMP context, but with task_shared_vars set. */
11629 static tree
11630 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11631 void *data)
11633 tree t = *tp;
11635 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11636 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11637 return t;
11639 if (task_shared_vars
11640 && DECL_P (t)
11641 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11642 return t;
11644 /* If a global variable has been privatized, TREE_CONSTANT on
11645 ADDR_EXPR might be wrong. */
11646 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11647 recompute_tree_invariant_for_addr_expr (t);
11649 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11650 return NULL_TREE;
11653 static void
11654 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11656 gimple stmt = gsi_stmt (*gsi_p);
11657 struct walk_stmt_info wi;
11658 gcall *call_stmt;
11660 if (gimple_has_location (stmt))
11661 input_location = gimple_location (stmt);
11663 if (task_shared_vars)
11664 memset (&wi, '\0', sizeof (wi));
11666 /* If we have issued syntax errors, avoid doing any heavy lifting.
11667 Just replace the OMP directives with a NOP to avoid
11668 confusing RTL expansion. */
11669 if (seen_error () && is_gimple_omp (stmt))
11671 gsi_replace (gsi_p, gimple_build_nop (), true);
11672 return;
11675 switch (gimple_code (stmt))
11677 case GIMPLE_COND:
11679 gcond *cond_stmt = as_a <gcond *> (stmt);
11680 if ((ctx || task_shared_vars)
11681 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11682 lower_omp_regimplify_p,
11683 ctx ? NULL : &wi, NULL)
11684 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11685 lower_omp_regimplify_p,
11686 ctx ? NULL : &wi, NULL)))
11687 gimple_regimplify_operands (cond_stmt, gsi_p);
11689 break;
11690 case GIMPLE_CATCH:
11691 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
11692 break;
11693 case GIMPLE_EH_FILTER:
11694 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
11695 break;
11696 case GIMPLE_TRY:
11697 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11698 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
11699 break;
11700 case GIMPLE_TRANSACTION:
11701 lower_omp (gimple_transaction_body_ptr (
11702 as_a <gtransaction *> (stmt)),
11703 ctx);
11704 break;
11705 case GIMPLE_BIND:
11706 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
11707 break;
11708 case GIMPLE_OMP_PARALLEL:
11709 case GIMPLE_OMP_TASK:
11710 ctx = maybe_lookup_ctx (stmt);
11711 gcc_assert (ctx);
11712 if (ctx->cancellable)
11713 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11714 lower_omp_taskreg (gsi_p, ctx);
11715 break;
11716 case GIMPLE_OMP_FOR:
11717 ctx = maybe_lookup_ctx (stmt);
11718 gcc_assert (ctx);
11719 if (ctx->cancellable)
11720 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11721 lower_omp_for (gsi_p, ctx);
11722 break;
11723 case GIMPLE_OMP_SECTIONS:
11724 ctx = maybe_lookup_ctx (stmt);
11725 gcc_assert (ctx);
11726 if (ctx->cancellable)
11727 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11728 lower_omp_sections (gsi_p, ctx);
11729 break;
11730 case GIMPLE_OMP_SINGLE:
11731 ctx = maybe_lookup_ctx (stmt);
11732 gcc_assert (ctx);
11733 lower_omp_single (gsi_p, ctx);
11734 break;
11735 case GIMPLE_OMP_MASTER:
11736 ctx = maybe_lookup_ctx (stmt);
11737 gcc_assert (ctx);
11738 lower_omp_master (gsi_p, ctx);
11739 break;
11740 case GIMPLE_OMP_TASKGROUP:
11741 ctx = maybe_lookup_ctx (stmt);
11742 gcc_assert (ctx);
11743 lower_omp_taskgroup (gsi_p, ctx);
11744 break;
11745 case GIMPLE_OMP_ORDERED:
11746 ctx = maybe_lookup_ctx (stmt);
11747 gcc_assert (ctx);
11748 lower_omp_ordered (gsi_p, ctx);
11749 break;
11750 case GIMPLE_OMP_CRITICAL:
11751 ctx = maybe_lookup_ctx (stmt);
11752 gcc_assert (ctx);
11753 lower_omp_critical (gsi_p, ctx);
11754 break;
11755 case GIMPLE_OMP_ATOMIC_LOAD:
11756 if ((ctx || task_shared_vars)
11757 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11758 as_a <gomp_atomic_load *> (stmt)),
11759 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11760 gimple_regimplify_operands (stmt, gsi_p);
11761 break;
11762 case GIMPLE_OMP_TARGET:
11763 ctx = maybe_lookup_ctx (stmt);
11764 gcc_assert (ctx);
11765 lower_omp_target (gsi_p, ctx);
11766 break;
11767 case GIMPLE_OMP_TEAMS:
11768 ctx = maybe_lookup_ctx (stmt);
11769 gcc_assert (ctx);
11770 lower_omp_teams (gsi_p, ctx);
11771 break;
11772 case GIMPLE_CALL:
11773 tree fndecl;
11774 call_stmt = as_a <gcall *> (stmt);
11775 fndecl = gimple_call_fndecl (call_stmt);
11776 if (fndecl
11777 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11778 switch (DECL_FUNCTION_CODE (fndecl))
11780 case BUILT_IN_GOMP_BARRIER:
11781 if (ctx == NULL)
11782 break;
11783 /* FALLTHRU */
11784 case BUILT_IN_GOMP_CANCEL:
11785 case BUILT_IN_GOMP_CANCELLATION_POINT:
11786 omp_context *cctx;
11787 cctx = ctx;
11788 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11789 cctx = cctx->outer;
11790 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
11791 if (!cctx->cancellable)
11793 if (DECL_FUNCTION_CODE (fndecl)
11794 == BUILT_IN_GOMP_CANCELLATION_POINT)
11796 stmt = gimple_build_nop ();
11797 gsi_replace (gsi_p, stmt, false);
11799 break;
11801 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11803 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
11804 gimple_call_set_fndecl (call_stmt, fndecl);
11805 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
11807 tree lhs;
11808 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
11809 gimple_call_set_lhs (call_stmt, lhs);
11810 tree fallthru_label;
11811 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11812 gimple g;
11813 g = gimple_build_label (fallthru_label);
11814 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11815 g = gimple_build_cond (NE_EXPR, lhs,
11816 fold_convert (TREE_TYPE (lhs),
11817 boolean_false_node),
11818 cctx->cancel_label, fallthru_label);
11819 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11820 break;
11821 default:
11822 break;
11824 /* FALLTHRU */
11825 default:
11826 if ((ctx || task_shared_vars)
11827 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11828 ctx ? NULL : &wi))
11830 /* Just remove clobbers, this should happen only if we have
11831 "privatized" local addressable variables in SIMD regions,
11832 the clobber isn't needed in that case and gimplifying address
11833 of the ARRAY_REF into a pointer and creating MEM_REF based
11834 clobber would create worse code than we get with the clobber
11835 dropped. */
11836 if (gimple_clobber_p (stmt))
11838 gsi_replace (gsi_p, gimple_build_nop (), true);
11839 break;
11841 gimple_regimplify_operands (stmt, gsi_p);
11843 break;
11847 static void
11848 lower_omp (gimple_seq *body, omp_context *ctx)
11850 location_t saved_location = input_location;
11851 gimple_stmt_iterator gsi;
11852 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11853 lower_omp_1 (&gsi, ctx);
11854 /* During gimplification, we haven't folded statments inside offloading
11855 regions (gimplify.c:maybe_fold_stmt); do that now. */
11856 if (target_nesting_level)
11857 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11858 fold_stmt (&gsi);
11859 input_location = saved_location;
11862 /* Main entry point. */
11864 static unsigned int
11865 execute_lower_omp (void)
11867 gimple_seq body;
11868 int i;
11869 omp_context *ctx;
11871 /* This pass always runs, to provide PROP_gimple_lomp.
11872 But often, there is nothing to do. */
11873 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11874 && flag_openmp_simd == 0)
11875 return 0;
11877 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11878 delete_omp_context);
11880 body = gimple_body (current_function_decl);
11881 scan_omp (&body, NULL);
11882 gcc_assert (taskreg_nesting_level == 0);
11883 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11884 finish_taskreg_scan (ctx);
11885 taskreg_contexts.release ();
11887 if (all_contexts->root)
11889 if (task_shared_vars)
11890 push_gimplify_context ();
11891 lower_omp (&body, NULL);
11892 if (task_shared_vars)
11893 pop_gimplify_context (NULL);
11896 if (all_contexts)
11898 splay_tree_delete (all_contexts);
11899 all_contexts = NULL;
11901 BITMAP_FREE (task_shared_vars);
11902 return 0;
11905 namespace {
11907 const pass_data pass_data_lower_omp =
11909 GIMPLE_PASS, /* type */
11910 "omplower", /* name */
11911 OPTGROUP_NONE, /* optinfo_flags */
11912 TV_NONE, /* tv_id */
11913 PROP_gimple_any, /* properties_required */
11914 PROP_gimple_lomp, /* properties_provided */
11915 0, /* properties_destroyed */
11916 0, /* todo_flags_start */
11917 0, /* todo_flags_finish */
11920 class pass_lower_omp : public gimple_opt_pass
11922 public:
11923 pass_lower_omp (gcc::context *ctxt)
11924 : gimple_opt_pass (pass_data_lower_omp, ctxt)
11927 /* opt_pass methods: */
11928 virtual unsigned int execute (function *) { return execute_lower_omp (); }
11930 }; // class pass_lower_omp
11932 } // anon namespace
11934 gimple_opt_pass *
11935 make_pass_lower_omp (gcc::context *ctxt)
11937 return new pass_lower_omp (ctxt);
11940 /* The following is a utility to diagnose structured block violations.
11941 It is not part of the "omplower" pass, as that's invoked too late. It
11942 should be invoked by the respective front ends after gimplification. */
11944 static splay_tree all_labels;
11946 /* Check for mismatched contexts and generate an error if needed. Return
11947 true if an error is detected. */
11949 static bool
11950 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
11951 gimple branch_ctx, gimple label_ctx)
11953 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
11954 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
11956 if (label_ctx == branch_ctx)
11957 return false;
11959 const char* kind = NULL;
11961 if (flag_cilkplus)
11963 if ((branch_ctx
11964 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
11965 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
11966 || (label_ctx
11967 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
11968 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
11969 kind = "Cilk Plus";
11971 if (flag_openacc)
11973 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
11974 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
11976 gcc_checking_assert (kind == NULL);
11977 kind = "OpenACC";
11980 if (kind == NULL)
11982 gcc_checking_assert (flag_openmp);
11983 kind = "OpenMP";
11987 Previously we kept track of the label's entire context in diagnose_sb_[12]
11988 so we could traverse it and issue a correct "exit" or "enter" error
11989 message upon a structured block violation.
11991 We built the context by building a list with tree_cons'ing, but there is
11992 no easy counterpart in gimple tuples. It seems like far too much work
11993 for issuing exit/enter error messages. If someone really misses the
11994 distinct error message... patches welcome.
11997 #if 0
11998 /* Try to avoid confusing the user by producing and error message
11999 with correct "exit" or "enter" verbiage. We prefer "exit"
12000 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12001 if (branch_ctx == NULL)
12002 exit_p = false;
12003 else
12005 while (label_ctx)
12007 if (TREE_VALUE (label_ctx) == branch_ctx)
12009 exit_p = false;
12010 break;
12012 label_ctx = TREE_CHAIN (label_ctx);
12016 if (exit_p)
12017 error ("invalid exit from %s structured block", kind);
12018 else
12019 error ("invalid entry to %s structured block", kind);
12020 #endif
12022 /* If it's obvious we have an invalid entry, be specific about the error. */
12023 if (branch_ctx == NULL)
12024 error ("invalid entry to %s structured block", kind);
12025 else
12027 /* Otherwise, be vague and lazy, but efficient. */
12028 error ("invalid branch to/from %s structured block", kind);
12031 gsi_replace (gsi_p, gimple_build_nop (), false);
12032 return true;
12035 /* Pass 1: Create a minimal tree of structured blocks, and record
12036 where each label is found. */
12038 static tree
12039 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12040 struct walk_stmt_info *wi)
12042 gimple context = (gimple) wi->info;
12043 gimple inner_context;
12044 gimple stmt = gsi_stmt (*gsi_p);
12046 *handled_ops_p = true;
12048 switch (gimple_code (stmt))
12050 WALK_SUBSTMTS;
12052 case GIMPLE_OMP_PARALLEL:
12053 case GIMPLE_OMP_TASK:
12054 case GIMPLE_OMP_SECTIONS:
12055 case GIMPLE_OMP_SINGLE:
12056 case GIMPLE_OMP_SECTION:
12057 case GIMPLE_OMP_MASTER:
12058 case GIMPLE_OMP_ORDERED:
12059 case GIMPLE_OMP_CRITICAL:
12060 case GIMPLE_OMP_TARGET:
12061 case GIMPLE_OMP_TEAMS:
12062 case GIMPLE_OMP_TASKGROUP:
12063 /* The minimal context here is just the current OMP construct. */
12064 inner_context = stmt;
12065 wi->info = inner_context;
12066 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12067 wi->info = context;
12068 break;
12070 case GIMPLE_OMP_FOR:
12071 inner_context = stmt;
12072 wi->info = inner_context;
12073 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12074 walk them. */
12075 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12076 diagnose_sb_1, NULL, wi);
12077 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12078 wi->info = context;
12079 break;
12081 case GIMPLE_LABEL:
12082 splay_tree_insert (all_labels,
12083 (splay_tree_key) gimple_label_label (
12084 as_a <glabel *> (stmt)),
12085 (splay_tree_value) context);
12086 break;
12088 default:
12089 break;
12092 return NULL_TREE;
12095 /* Pass 2: Check each branch and see if its context differs from that of
12096 the destination label's context. */
12098 static tree
12099 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12100 struct walk_stmt_info *wi)
12102 gimple context = (gimple) wi->info;
12103 splay_tree_node n;
12104 gimple stmt = gsi_stmt (*gsi_p);
12106 *handled_ops_p = true;
12108 switch (gimple_code (stmt))
12110 WALK_SUBSTMTS;
12112 case GIMPLE_OMP_PARALLEL:
12113 case GIMPLE_OMP_TASK:
12114 case GIMPLE_OMP_SECTIONS:
12115 case GIMPLE_OMP_SINGLE:
12116 case GIMPLE_OMP_SECTION:
12117 case GIMPLE_OMP_MASTER:
12118 case GIMPLE_OMP_ORDERED:
12119 case GIMPLE_OMP_CRITICAL:
12120 case GIMPLE_OMP_TARGET:
12121 case GIMPLE_OMP_TEAMS:
12122 case GIMPLE_OMP_TASKGROUP:
12123 wi->info = stmt;
12124 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12125 wi->info = context;
12126 break;
12128 case GIMPLE_OMP_FOR:
12129 wi->info = stmt;
12130 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12131 walk them. */
12132 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12133 diagnose_sb_2, NULL, wi);
12134 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12135 wi->info = context;
12136 break;
12138 case GIMPLE_COND:
12140 gcond *cond_stmt = as_a <gcond *> (stmt);
12141 tree lab = gimple_cond_true_label (cond_stmt);
12142 if (lab)
12144 n = splay_tree_lookup (all_labels,
12145 (splay_tree_key) lab);
12146 diagnose_sb_0 (gsi_p, context,
12147 n ? (gimple) n->value : NULL);
12149 lab = gimple_cond_false_label (cond_stmt);
12150 if (lab)
12152 n = splay_tree_lookup (all_labels,
12153 (splay_tree_key) lab);
12154 diagnose_sb_0 (gsi_p, context,
12155 n ? (gimple) n->value : NULL);
12158 break;
12160 case GIMPLE_GOTO:
12162 tree lab = gimple_goto_dest (stmt);
12163 if (TREE_CODE (lab) != LABEL_DECL)
12164 break;
12166 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12167 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
12169 break;
12171 case GIMPLE_SWITCH:
12173 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12174 unsigned int i;
12175 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12177 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12178 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12179 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
12180 break;
12183 break;
12185 case GIMPLE_RETURN:
12186 diagnose_sb_0 (gsi_p, context, NULL);
12187 break;
12189 default:
12190 break;
12193 return NULL_TREE;
12196 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12197 GIMPLE_* codes. */
12198 bool
12199 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12200 int *region_idx)
12202 gimple last = last_stmt (bb);
12203 enum gimple_code code = gimple_code (last);
12204 struct omp_region *cur_region = *region;
12205 bool fallthru = false;
12207 switch (code)
12209 case GIMPLE_OMP_PARALLEL:
12210 case GIMPLE_OMP_TASK:
12211 case GIMPLE_OMP_FOR:
12212 case GIMPLE_OMP_SINGLE:
12213 case GIMPLE_OMP_TEAMS:
12214 case GIMPLE_OMP_MASTER:
12215 case GIMPLE_OMP_TASKGROUP:
12216 case GIMPLE_OMP_ORDERED:
12217 case GIMPLE_OMP_CRITICAL:
12218 case GIMPLE_OMP_SECTION:
12219 cur_region = new_omp_region (bb, code, cur_region);
12220 fallthru = true;
12221 break;
12223 case GIMPLE_OMP_TARGET:
12224 cur_region = new_omp_region (bb, code, cur_region);
12225 fallthru = true;
12226 switch (gimple_omp_target_kind (last))
12228 case GF_OMP_TARGET_KIND_REGION:
12229 case GF_OMP_TARGET_KIND_DATA:
12230 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12231 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12232 case GF_OMP_TARGET_KIND_OACC_DATA:
12233 break;
12234 case GF_OMP_TARGET_KIND_UPDATE:
12235 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12236 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12237 cur_region = cur_region->outer;
12238 break;
12239 default:
12240 gcc_unreachable ();
12242 break;
12244 case GIMPLE_OMP_SECTIONS:
12245 cur_region = new_omp_region (bb, code, cur_region);
12246 fallthru = true;
12247 break;
12249 case GIMPLE_OMP_SECTIONS_SWITCH:
12250 fallthru = false;
12251 break;
12253 case GIMPLE_OMP_ATOMIC_LOAD:
12254 case GIMPLE_OMP_ATOMIC_STORE:
12255 fallthru = true;
12256 break;
12258 case GIMPLE_OMP_RETURN:
12259 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12260 somewhere other than the next block. This will be
12261 created later. */
12262 cur_region->exit = bb;
12263 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12264 cur_region = cur_region->outer;
12265 break;
12267 case GIMPLE_OMP_CONTINUE:
12268 cur_region->cont = bb;
12269 switch (cur_region->type)
12271 case GIMPLE_OMP_FOR:
12272 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12273 succs edges as abnormal to prevent splitting
12274 them. */
12275 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12276 /* Make the loopback edge. */
12277 make_edge (bb, single_succ (cur_region->entry),
12278 EDGE_ABNORMAL);
12280 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12281 corresponds to the case that the body of the loop
12282 is not executed at all. */
12283 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12284 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12285 fallthru = false;
12286 break;
12288 case GIMPLE_OMP_SECTIONS:
12289 /* Wire up the edges into and out of the nested sections. */
12291 basic_block switch_bb = single_succ (cur_region->entry);
12293 struct omp_region *i;
12294 for (i = cur_region->inner; i ; i = i->next)
12296 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12297 make_edge (switch_bb, i->entry, 0);
12298 make_edge (i->exit, bb, EDGE_FALLTHRU);
12301 /* Make the loopback edge to the block with
12302 GIMPLE_OMP_SECTIONS_SWITCH. */
12303 make_edge (bb, switch_bb, 0);
12305 /* Make the edge from the switch to exit. */
12306 make_edge (switch_bb, bb->next_bb, 0);
12307 fallthru = false;
12309 break;
12311 default:
12312 gcc_unreachable ();
12314 break;
12316 default:
12317 gcc_unreachable ();
12320 if (*region != cur_region)
12322 *region = cur_region;
12323 if (cur_region)
12324 *region_idx = cur_region->entry->index;
12325 else
12326 *region_idx = 0;
12329 return fallthru;
12332 static unsigned int
12333 diagnose_omp_structured_block_errors (void)
12335 struct walk_stmt_info wi;
12336 gimple_seq body = gimple_body (current_function_decl);
12338 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12340 memset (&wi, 0, sizeof (wi));
12341 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12343 memset (&wi, 0, sizeof (wi));
12344 wi.want_locations = true;
12345 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12347 gimple_set_body (current_function_decl, body);
12349 splay_tree_delete (all_labels);
12350 all_labels = NULL;
12352 return 0;
12355 namespace {
12357 const pass_data pass_data_diagnose_omp_blocks =
12359 GIMPLE_PASS, /* type */
12360 "*diagnose_omp_blocks", /* name */
12361 OPTGROUP_NONE, /* optinfo_flags */
12362 TV_NONE, /* tv_id */
12363 PROP_gimple_any, /* properties_required */
12364 0, /* properties_provided */
12365 0, /* properties_destroyed */
12366 0, /* todo_flags_start */
12367 0, /* todo_flags_finish */
12370 class pass_diagnose_omp_blocks : public gimple_opt_pass
12372 public:
12373 pass_diagnose_omp_blocks (gcc::context *ctxt)
12374 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12377 /* opt_pass methods: */
12378 virtual bool gate (function *)
12380 return flag_cilkplus || flag_openacc || flag_openmp;
12382 virtual unsigned int execute (function *)
12384 return diagnose_omp_structured_block_errors ();
12387 }; // class pass_diagnose_omp_blocks
12389 } // anon namespace
12391 gimple_opt_pass *
12392 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12394 return new pass_diagnose_omp_blocks (ctxt);
12397 /* SIMD clone supporting code. */
12399 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12400 of arguments to reserve space for. */
12402 static struct cgraph_simd_clone *
12403 simd_clone_struct_alloc (int nargs)
12405 struct cgraph_simd_clone *clone_info;
12406 size_t len = (sizeof (struct cgraph_simd_clone)
12407 + nargs * sizeof (struct cgraph_simd_clone_arg));
12408 clone_info = (struct cgraph_simd_clone *)
12409 ggc_internal_cleared_alloc (len);
12410 return clone_info;
12413 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12415 static inline void
12416 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12417 struct cgraph_simd_clone *from)
12419 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12420 + ((from->nargs - from->inbranch)
12421 * sizeof (struct cgraph_simd_clone_arg))));
12424 /* Return vector of parameter types of function FNDECL. This uses
12425 TYPE_ARG_TYPES if available, otherwise falls back to types of
12426 DECL_ARGUMENTS types. */
12428 vec<tree>
12429 simd_clone_vector_of_formal_parm_types (tree fndecl)
12431 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12432 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12433 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12434 unsigned int i;
12435 tree arg;
12436 FOR_EACH_VEC_ELT (args, i, arg)
12437 args[i] = TREE_TYPE (args[i]);
12438 return args;
12441 /* Given a simd function in NODE, extract the simd specific
12442 information from the OMP clauses passed in CLAUSES, and return
12443 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12444 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12445 otherwise set to FALSE. */
12447 static struct cgraph_simd_clone *
12448 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12449 bool *inbranch_specified)
12451 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12452 tree t;
12453 int n;
12454 *inbranch_specified = false;
12456 n = args.length ();
12457 if (n > 0 && args.last () == void_type_node)
12458 n--;
12460 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12461 be cloned have a distinctive artificial label in addition to "omp
12462 declare simd". */
12463 bool cilk_clone
12464 = (flag_cilkplus
12465 && lookup_attribute ("cilk simd function",
12466 DECL_ATTRIBUTES (node->decl)));
12468 /* Allocate one more than needed just in case this is an in-branch
12469 clone which will require a mask argument. */
12470 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12471 clone_info->nargs = n;
12472 clone_info->cilk_elemental = cilk_clone;
12474 if (!clauses)
12476 args.release ();
12477 return clone_info;
12479 clauses = TREE_VALUE (clauses);
12480 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12481 return clone_info;
12483 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12485 switch (OMP_CLAUSE_CODE (t))
12487 case OMP_CLAUSE_INBRANCH:
12488 clone_info->inbranch = 1;
12489 *inbranch_specified = true;
12490 break;
12491 case OMP_CLAUSE_NOTINBRANCH:
12492 clone_info->inbranch = 0;
12493 *inbranch_specified = true;
12494 break;
12495 case OMP_CLAUSE_SIMDLEN:
12496 clone_info->simdlen
12497 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12498 break;
12499 case OMP_CLAUSE_LINEAR:
12501 tree decl = OMP_CLAUSE_DECL (t);
12502 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12503 int argno = TREE_INT_CST_LOW (decl);
12504 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12506 clone_info->args[argno].arg_type
12507 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12508 clone_info->args[argno].linear_step = tree_to_shwi (step);
12509 gcc_assert (clone_info->args[argno].linear_step >= 0
12510 && clone_info->args[argno].linear_step < n);
12512 else
12514 if (POINTER_TYPE_P (args[argno]))
12515 step = fold_convert (ssizetype, step);
12516 if (!tree_fits_shwi_p (step))
12518 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12519 "ignoring large linear step");
12520 args.release ();
12521 return NULL;
12523 else if (integer_zerop (step))
12525 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12526 "ignoring zero linear step");
12527 args.release ();
12528 return NULL;
12530 else
12532 clone_info->args[argno].arg_type
12533 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12534 clone_info->args[argno].linear_step = tree_to_shwi (step);
12537 break;
12539 case OMP_CLAUSE_UNIFORM:
12541 tree decl = OMP_CLAUSE_DECL (t);
12542 int argno = tree_to_uhwi (decl);
12543 clone_info->args[argno].arg_type
12544 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12545 break;
12547 case OMP_CLAUSE_ALIGNED:
12549 tree decl = OMP_CLAUSE_DECL (t);
12550 int argno = tree_to_uhwi (decl);
12551 clone_info->args[argno].alignment
12552 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12553 break;
12555 default:
12556 break;
12559 args.release ();
12560 return clone_info;
12563 /* Given a SIMD clone in NODE, calculate the characteristic data
12564 type and return the coresponding type. The characteristic data
12565 type is computed as described in the Intel Vector ABI. */
12567 static tree
12568 simd_clone_compute_base_data_type (struct cgraph_node *node,
12569 struct cgraph_simd_clone *clone_info)
12571 tree type = integer_type_node;
12572 tree fndecl = node->decl;
12574 /* a) For non-void function, the characteristic data type is the
12575 return type. */
12576 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12577 type = TREE_TYPE (TREE_TYPE (fndecl));
12579 /* b) If the function has any non-uniform, non-linear parameters,
12580 then the characteristic data type is the type of the first
12581 such parameter. */
12582 else
12584 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12585 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12586 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12588 type = map[i];
12589 break;
12591 map.release ();
12594 /* c) If the characteristic data type determined by a) or b) above
12595 is struct, union, or class type which is pass-by-value (except
12596 for the type that maps to the built-in complex data type), the
12597 characteristic data type is int. */
12598 if (RECORD_OR_UNION_TYPE_P (type)
12599 && !aggregate_value_p (type, NULL)
12600 && TREE_CODE (type) != COMPLEX_TYPE)
12601 return integer_type_node;
12603 /* d) If none of the above three classes is applicable, the
12604 characteristic data type is int. */
12606 return type;
12608 /* e) For Intel Xeon Phi native and offload compilation, if the
12609 resulting characteristic data type is 8-bit or 16-bit integer
12610 data type, the characteristic data type is int. */
12611 /* Well, we don't handle Xeon Phi yet. */
12614 static tree
12615 simd_clone_mangle (struct cgraph_node *node,
12616 struct cgraph_simd_clone *clone_info)
12618 char vecsize_mangle = clone_info->vecsize_mangle;
12619 char mask = clone_info->inbranch ? 'M' : 'N';
12620 unsigned int simdlen = clone_info->simdlen;
12621 unsigned int n;
12622 pretty_printer pp;
12624 gcc_assert (vecsize_mangle && simdlen);
12626 pp_string (&pp, "_ZGV");
12627 pp_character (&pp, vecsize_mangle);
12628 pp_character (&pp, mask);
12629 pp_decimal_int (&pp, simdlen);
12631 for (n = 0; n < clone_info->nargs; ++n)
12633 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12635 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12636 pp_character (&pp, 'u');
12637 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12639 gcc_assert (arg.linear_step != 0);
12640 pp_character (&pp, 'l');
12641 if (arg.linear_step > 1)
12642 pp_unsigned_wide_integer (&pp, arg.linear_step);
12643 else if (arg.linear_step < 0)
12645 pp_character (&pp, 'n');
12646 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12647 arg.linear_step));
12650 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12652 pp_character (&pp, 's');
12653 pp_unsigned_wide_integer (&pp, arg.linear_step);
12655 else
12656 pp_character (&pp, 'v');
12657 if (arg.alignment)
12659 pp_character (&pp, 'a');
12660 pp_decimal_int (&pp, arg.alignment);
12664 pp_underscore (&pp);
12665 pp_string (&pp,
12666 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
12667 const char *str = pp_formatted_text (&pp);
12669 /* If there already is a SIMD clone with the same mangled name, don't
12670 add another one. This can happen e.g. for
12671 #pragma omp declare simd
12672 #pragma omp declare simd simdlen(8)
12673 int foo (int, int);
12674 if the simdlen is assumed to be 8 for the first one, etc. */
12675 for (struct cgraph_node *clone = node->simd_clones; clone;
12676 clone = clone->simdclone->next_clone)
12677 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12678 str) == 0)
12679 return NULL_TREE;
12681 return get_identifier (str);
12684 /* Create a simd clone of OLD_NODE and return it. */
12686 static struct cgraph_node *
12687 simd_clone_create (struct cgraph_node *old_node)
12689 struct cgraph_node *new_node;
12690 if (old_node->definition)
12692 if (!old_node->has_gimple_body_p ())
12693 return NULL;
12694 old_node->get_body ();
12695 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12696 false, NULL, NULL,
12697 "simdclone");
12699 else
12701 tree old_decl = old_node->decl;
12702 tree new_decl = copy_node (old_node->decl);
12703 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12704 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12705 SET_DECL_RTL (new_decl, NULL);
12706 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12707 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
12708 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
12709 symtab->call_cgraph_insertion_hooks (new_node);
12711 if (new_node == NULL)
12712 return new_node;
12714 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12716 /* The function cgraph_function_versioning () will force the new
12717 symbol local. Undo this, and inherit external visability from
12718 the old node. */
12719 new_node->local.local = old_node->local.local;
12720 new_node->externally_visible = old_node->externally_visible;
12722 return new_node;
12725 /* Adjust the return type of the given function to its appropriate
12726 vector counterpart. Returns a simd array to be used throughout the
12727 function as a return value. */
12729 static tree
12730 simd_clone_adjust_return_type (struct cgraph_node *node)
12732 tree fndecl = node->decl;
12733 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12734 unsigned int veclen;
12735 tree t;
12737 /* Adjust the function return type. */
12738 if (orig_rettype == void_type_node)
12739 return NULL_TREE;
12740 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
12741 t = TREE_TYPE (TREE_TYPE (fndecl));
12742 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
12743 veclen = node->simdclone->vecsize_int;
12744 else
12745 veclen = node->simdclone->vecsize_float;
12746 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
12747 if (veclen > node->simdclone->simdlen)
12748 veclen = node->simdclone->simdlen;
12749 if (POINTER_TYPE_P (t))
12750 t = pointer_sized_int_node;
12751 if (veclen == node->simdclone->simdlen)
12752 t = build_vector_type (t, node->simdclone->simdlen);
12753 else
12755 t = build_vector_type (t, veclen);
12756 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
12758 TREE_TYPE (TREE_TYPE (fndecl)) = t;
12759 if (!node->definition)
12760 return NULL_TREE;
12762 t = DECL_RESULT (fndecl);
12763 /* Adjust the DECL_RESULT. */
12764 gcc_assert (TREE_TYPE (t) != void_type_node);
12765 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12766 relayout_decl (t);
12768 tree atype = build_array_type_nelts (orig_rettype,
12769 node->simdclone->simdlen);
12770 if (veclen != node->simdclone->simdlen)
12771 return build1 (VIEW_CONVERT_EXPR, atype, t);
12773 /* Set up a SIMD array to use as the return value. */
12774 tree retval = create_tmp_var_raw (atype, "retval");
12775 gimple_add_tmp_var (retval);
12776 return retval;
12779 /* Each vector argument has a corresponding array to be used locally
12780 as part of the eventual loop. Create such temporary array and
12781 return it.
12783 PREFIX is the prefix to be used for the temporary.
12785 TYPE is the inner element type.
12787 SIMDLEN is the number of elements. */
12789 static tree
12790 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12792 tree atype = build_array_type_nelts (type, simdlen);
12793 tree avar = create_tmp_var_raw (atype, prefix);
12794 gimple_add_tmp_var (avar);
12795 return avar;
12798 /* Modify the function argument types to their corresponding vector
12799 counterparts if appropriate. Also, create one array for each simd
12800 argument to be used locally when using the function arguments as
12801 part of the loop.
12803 NODE is the function whose arguments are to be adjusted.
12805 Returns an adjustment vector that will be filled describing how the
12806 argument types will be adjusted. */
12808 static ipa_parm_adjustment_vec
12809 simd_clone_adjust_argument_types (struct cgraph_node *node)
12811 vec<tree> args;
12812 ipa_parm_adjustment_vec adjustments;
12814 if (node->definition)
12815 args = ipa_get_vector_of_formal_parms (node->decl);
12816 else
12817 args = simd_clone_vector_of_formal_parm_types (node->decl);
12818 adjustments.create (args.length ());
12819 unsigned i, j, veclen;
12820 struct ipa_parm_adjustment adj;
12821 for (i = 0; i < node->simdclone->nargs; ++i)
12823 memset (&adj, 0, sizeof (adj));
12824 tree parm = args[i];
12825 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12826 adj.base_index = i;
12827 adj.base = parm;
12829 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12830 node->simdclone->args[i].orig_type = parm_type;
12832 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12834 /* No adjustment necessary for scalar arguments. */
12835 adj.op = IPA_PARM_OP_COPY;
12837 else
12839 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12840 veclen = node->simdclone->vecsize_int;
12841 else
12842 veclen = node->simdclone->vecsize_float;
12843 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12844 if (veclen > node->simdclone->simdlen)
12845 veclen = node->simdclone->simdlen;
12846 adj.arg_prefix = "simd";
12847 if (POINTER_TYPE_P (parm_type))
12848 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12849 else
12850 adj.type = build_vector_type (parm_type, veclen);
12851 node->simdclone->args[i].vector_type = adj.type;
12852 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12854 adjustments.safe_push (adj);
12855 if (j == veclen)
12857 memset (&adj, 0, sizeof (adj));
12858 adj.op = IPA_PARM_OP_NEW;
12859 adj.arg_prefix = "simd";
12860 adj.base_index = i;
12861 adj.type = node->simdclone->args[i].vector_type;
12865 if (node->definition)
12866 node->simdclone->args[i].simd_array
12867 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12868 parm_type, node->simdclone->simdlen);
12870 adjustments.safe_push (adj);
12873 if (node->simdclone->inbranch)
12875 tree base_type
12876 = simd_clone_compute_base_data_type (node->simdclone->origin,
12877 node->simdclone);
12879 memset (&adj, 0, sizeof (adj));
12880 adj.op = IPA_PARM_OP_NEW;
12881 adj.arg_prefix = "mask";
12883 adj.base_index = i;
12884 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12885 veclen = node->simdclone->vecsize_int;
12886 else
12887 veclen = node->simdclone->vecsize_float;
12888 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12889 if (veclen > node->simdclone->simdlen)
12890 veclen = node->simdclone->simdlen;
12891 if (POINTER_TYPE_P (base_type))
12892 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12893 else
12894 adj.type = build_vector_type (base_type, veclen);
12895 adjustments.safe_push (adj);
12897 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12898 adjustments.safe_push (adj);
12900 /* We have previously allocated one extra entry for the mask. Use
12901 it and fill it. */
12902 struct cgraph_simd_clone *sc = node->simdclone;
12903 sc->nargs++;
12904 if (node->definition)
12906 sc->args[i].orig_arg
12907 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12908 sc->args[i].simd_array
12909 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12911 sc->args[i].orig_type = base_type;
12912 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12915 if (node->definition)
12916 ipa_modify_formal_parameters (node->decl, adjustments);
12917 else
12919 tree new_arg_types = NULL_TREE, new_reversed;
12920 bool last_parm_void = false;
12921 if (args.length () > 0 && args.last () == void_type_node)
12922 last_parm_void = true;
12924 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12925 j = adjustments.length ();
12926 for (i = 0; i < j; i++)
12928 struct ipa_parm_adjustment *adj = &adjustments[i];
12929 tree ptype;
12930 if (adj->op == IPA_PARM_OP_COPY)
12931 ptype = args[adj->base_index];
12932 else
12933 ptype = adj->type;
12934 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12936 new_reversed = nreverse (new_arg_types);
12937 if (last_parm_void)
12939 if (new_reversed)
12940 TREE_CHAIN (new_arg_types) = void_list_node;
12941 else
12942 new_reversed = void_list_node;
12945 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
12946 TYPE_ARG_TYPES (new_type) = new_reversed;
12947 TREE_TYPE (node->decl) = new_type;
12949 adjustments.release ();
12951 args.release ();
12952 return adjustments;
12955 /* Initialize and copy the function arguments in NODE to their
12956 corresponding local simd arrays. Returns a fresh gimple_seq with
12957 the instruction sequence generated. */
12959 static gimple_seq
12960 simd_clone_init_simd_arrays (struct cgraph_node *node,
12961 ipa_parm_adjustment_vec adjustments)
12963 gimple_seq seq = NULL;
12964 unsigned i = 0, j = 0, k;
12966 for (tree arg = DECL_ARGUMENTS (node->decl);
12967 arg;
12968 arg = DECL_CHAIN (arg), i++, j++)
12970 if (adjustments[j].op == IPA_PARM_OP_COPY)
12971 continue;
12973 node->simdclone->args[i].vector_arg = arg;
12975 tree array = node->simdclone->args[i].simd_array;
12976 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
12978 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
12979 tree ptr = build_fold_addr_expr (array);
12980 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
12981 build_int_cst (ptype, 0));
12982 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
12983 gimplify_and_add (t, &seq);
12985 else
12987 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
12988 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
12989 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
12991 tree ptr = build_fold_addr_expr (array);
12992 int elemsize;
12993 if (k)
12995 arg = DECL_CHAIN (arg);
12996 j++;
12998 elemsize
12999 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13000 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13001 build_int_cst (ptype, k * elemsize));
13002 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13003 gimplify_and_add (t, &seq);
13007 return seq;
13010 /* Callback info for ipa_simd_modify_stmt_ops below. */
13012 struct modify_stmt_info {
13013 ipa_parm_adjustment_vec adjustments;
13014 gimple stmt;
13015 /* True if the parent statement was modified by
13016 ipa_simd_modify_stmt_ops. */
13017 bool modified;
13020 /* Callback for walk_gimple_op.
13022 Adjust operands from a given statement as specified in the
13023 adjustments vector in the callback data. */
13025 static tree
13026 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13028 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13029 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13030 tree *orig_tp = tp;
13031 if (TREE_CODE (*tp) == ADDR_EXPR)
13032 tp = &TREE_OPERAND (*tp, 0);
13033 struct ipa_parm_adjustment *cand = NULL;
13034 if (TREE_CODE (*tp) == PARM_DECL)
13035 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13036 else
13038 if (TYPE_P (*tp))
13039 *walk_subtrees = 0;
13042 tree repl = NULL_TREE;
13043 if (cand)
13044 repl = unshare_expr (cand->new_decl);
13045 else
13047 if (tp != orig_tp)
13049 *walk_subtrees = 0;
13050 bool modified = info->modified;
13051 info->modified = false;
13052 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13053 if (!info->modified)
13055 info->modified = modified;
13056 return NULL_TREE;
13058 info->modified = modified;
13059 repl = *tp;
13061 else
13062 return NULL_TREE;
13065 if (tp != orig_tp)
13067 repl = build_fold_addr_expr (repl);
13068 gimple stmt;
13069 if (is_gimple_debug (info->stmt))
13071 tree vexpr = make_node (DEBUG_EXPR_DECL);
13072 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13073 DECL_ARTIFICIAL (vexpr) = 1;
13074 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13075 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13076 repl = vexpr;
13078 else
13080 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13081 repl = gimple_assign_lhs (stmt);
13083 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13084 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13085 *orig_tp = repl;
13087 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13089 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13090 *tp = vce;
13092 else
13093 *tp = repl;
13095 info->modified = true;
13096 return NULL_TREE;
13099 /* Traverse the function body and perform all modifications as
13100 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13101 modified such that the replacement/reduction value will now be an
13102 offset into the corresponding simd_array.
13104 This function will replace all function argument uses with their
13105 corresponding simd array elements, and ajust the return values
13106 accordingly. */
13108 static void
13109 ipa_simd_modify_function_body (struct cgraph_node *node,
13110 ipa_parm_adjustment_vec adjustments,
13111 tree retval_array, tree iter)
13113 basic_block bb;
13114 unsigned int i, j, l;
13116 /* Re-use the adjustments array, but this time use it to replace
13117 every function argument use to an offset into the corresponding
13118 simd_array. */
13119 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13121 if (!node->simdclone->args[i].vector_arg)
13122 continue;
13124 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13125 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13126 adjustments[j].new_decl
13127 = build4 (ARRAY_REF,
13128 basetype,
13129 node->simdclone->args[i].simd_array,
13130 iter,
13131 NULL_TREE, NULL_TREE);
13132 if (adjustments[j].op == IPA_PARM_OP_NONE
13133 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13134 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13137 l = adjustments.length ();
13138 for (i = 1; i < num_ssa_names; i++)
13140 tree name = ssa_name (i);
13141 if (name
13142 && SSA_NAME_VAR (name)
13143 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13145 for (j = 0; j < l; j++)
13146 if (SSA_NAME_VAR (name) == adjustments[j].base
13147 && adjustments[j].new_decl)
13149 tree base_var;
13150 if (adjustments[j].new_ssa_base == NULL_TREE)
13152 base_var
13153 = copy_var_decl (adjustments[j].base,
13154 DECL_NAME (adjustments[j].base),
13155 TREE_TYPE (adjustments[j].base));
13156 adjustments[j].new_ssa_base = base_var;
13158 else
13159 base_var = adjustments[j].new_ssa_base;
13160 if (SSA_NAME_IS_DEFAULT_DEF (name))
13162 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13163 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13164 tree new_decl = unshare_expr (adjustments[j].new_decl);
13165 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13166 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13167 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13168 gimple stmt = gimple_build_assign (name, new_decl);
13169 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13171 else
13172 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13177 struct modify_stmt_info info;
13178 info.adjustments = adjustments;
13180 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13182 gimple_stmt_iterator gsi;
13184 gsi = gsi_start_bb (bb);
13185 while (!gsi_end_p (gsi))
13187 gimple stmt = gsi_stmt (gsi);
13188 info.stmt = stmt;
13189 struct walk_stmt_info wi;
13191 memset (&wi, 0, sizeof (wi));
13192 info.modified = false;
13193 wi.info = &info;
13194 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13196 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13198 tree retval = gimple_return_retval (return_stmt);
13199 if (!retval)
13201 gsi_remove (&gsi, true);
13202 continue;
13205 /* Replace `return foo' with `retval_array[iter] = foo'. */
13206 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13207 retval_array, iter, NULL, NULL);
13208 stmt = gimple_build_assign (ref, retval);
13209 gsi_replace (&gsi, stmt, true);
13210 info.modified = true;
13213 if (info.modified)
13215 update_stmt (stmt);
13216 if (maybe_clean_eh_stmt (stmt))
13217 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13219 gsi_next (&gsi);
13224 /* Adjust the argument types in NODE to their appropriate vector
13225 counterparts. */
13227 static void
13228 simd_clone_adjust (struct cgraph_node *node)
13230 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13232 targetm.simd_clone.adjust (node);
13234 tree retval = simd_clone_adjust_return_type (node);
13235 ipa_parm_adjustment_vec adjustments
13236 = simd_clone_adjust_argument_types (node);
13238 push_gimplify_context ();
13240 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13242 /* Adjust all uses of vector arguments accordingly. Adjust all
13243 return values accordingly. */
13244 tree iter = create_tmp_var (unsigned_type_node, "iter");
13245 tree iter1 = make_ssa_name (iter);
13246 tree iter2 = make_ssa_name (iter);
13247 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13249 /* Initialize the iteration variable. */
13250 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13251 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13252 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13253 /* Insert the SIMD array and iv initialization at function
13254 entry. */
13255 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13257 pop_gimplify_context (NULL);
13259 /* Create a new BB right before the original exit BB, to hold the
13260 iteration increment and the condition/branch. */
13261 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13262 basic_block incr_bb = create_empty_bb (orig_exit);
13263 add_bb_to_loop (incr_bb, body_bb->loop_father);
13264 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13265 flag. Set it now to be a FALLTHRU_EDGE. */
13266 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13267 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13268 for (unsigned i = 0;
13269 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13271 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13272 redirect_edge_succ (e, incr_bb);
13274 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13275 e->probability = REG_BR_PROB_BASE;
13276 gsi = gsi_last_bb (incr_bb);
13277 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13278 build_int_cst (unsigned_type_node, 1));
13279 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13281 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13282 struct loop *loop = alloc_loop ();
13283 cfun->has_force_vectorize_loops = true;
13284 loop->safelen = node->simdclone->simdlen;
13285 loop->force_vectorize = true;
13286 loop->header = body_bb;
13288 /* Branch around the body if the mask applies. */
13289 if (node->simdclone->inbranch)
13291 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13292 tree mask_array
13293 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13294 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13295 tree aref = build4 (ARRAY_REF,
13296 TREE_TYPE (TREE_TYPE (mask_array)),
13297 mask_array, iter1,
13298 NULL, NULL);
13299 g = gimple_build_assign (mask, aref);
13300 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13301 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13302 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13304 aref = build1 (VIEW_CONVERT_EXPR,
13305 build_nonstandard_integer_type (bitsize, 0), mask);
13306 mask = make_ssa_name (TREE_TYPE (aref));
13307 g = gimple_build_assign (mask, aref);
13308 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13311 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13312 NULL, NULL);
13313 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13314 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13315 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13318 /* Generate the condition. */
13319 g = gimple_build_cond (LT_EXPR,
13320 iter2,
13321 build_int_cst (unsigned_type_node,
13322 node->simdclone->simdlen),
13323 NULL, NULL);
13324 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13325 e = split_block (incr_bb, gsi_stmt (gsi));
13326 basic_block latch_bb = e->dest;
13327 basic_block new_exit_bb;
13328 new_exit_bb = split_block (latch_bb, NULL)->dest;
13329 loop->latch = latch_bb;
13331 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13333 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13334 /* The successor of incr_bb is already pointing to latch_bb; just
13335 change the flags.
13336 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13337 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13339 gphi *phi = create_phi_node (iter1, body_bb);
13340 edge preheader_edge = find_edge (entry_bb, body_bb);
13341 edge latch_edge = single_succ_edge (latch_bb);
13342 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13343 UNKNOWN_LOCATION);
13344 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13346 /* Generate the new return. */
13347 gsi = gsi_last_bb (new_exit_bb);
13348 if (retval
13349 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13350 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13351 retval = TREE_OPERAND (retval, 0);
13352 else if (retval)
13354 retval = build1 (VIEW_CONVERT_EXPR,
13355 TREE_TYPE (TREE_TYPE (node->decl)),
13356 retval);
13357 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13358 false, GSI_CONTINUE_LINKING);
13360 g = gimple_build_return (retval);
13361 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13363 /* Handle aligned clauses by replacing default defs of the aligned
13364 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13365 lhs. Handle linear by adding PHIs. */
13366 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13367 if (node->simdclone->args[i].alignment
13368 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13369 && (node->simdclone->args[i].alignment
13370 & (node->simdclone->args[i].alignment - 1)) == 0
13371 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13372 == POINTER_TYPE)
13374 unsigned int alignment = node->simdclone->args[i].alignment;
13375 tree orig_arg = node->simdclone->args[i].orig_arg;
13376 tree def = ssa_default_def (cfun, orig_arg);
13377 if (def && !has_zero_uses (def))
13379 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13380 gimple_seq seq = NULL;
13381 bool need_cvt = false;
13382 gcall *call
13383 = gimple_build_call (fn, 2, def, size_int (alignment));
13384 g = call;
13385 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13386 ptr_type_node))
13387 need_cvt = true;
13388 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13389 gimple_call_set_lhs (g, t);
13390 gimple_seq_add_stmt_without_update (&seq, g);
13391 if (need_cvt)
13393 t = make_ssa_name (orig_arg);
13394 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13395 gimple_seq_add_stmt_without_update (&seq, g);
13397 gsi_insert_seq_on_edge_immediate
13398 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13400 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13401 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13402 entry_bb);
13403 node->create_edge (cgraph_node::get_create (fn),
13404 call, entry_bb->count, freq);
13406 imm_use_iterator iter;
13407 use_operand_p use_p;
13408 gimple use_stmt;
13409 tree repl = gimple_get_lhs (g);
13410 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13411 if (is_gimple_debug (use_stmt) || use_stmt == call)
13412 continue;
13413 else
13414 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13415 SET_USE (use_p, repl);
13418 else if (node->simdclone->args[i].arg_type
13419 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13421 tree orig_arg = node->simdclone->args[i].orig_arg;
13422 tree def = ssa_default_def (cfun, orig_arg);
13423 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13424 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13425 if (def && !has_zero_uses (def))
13427 iter1 = make_ssa_name (orig_arg);
13428 iter2 = make_ssa_name (orig_arg);
13429 phi = create_phi_node (iter1, body_bb);
13430 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13431 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13432 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13433 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13434 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13435 ? TREE_TYPE (orig_arg) : sizetype;
13436 tree addcst
13437 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13438 g = gimple_build_assign (iter2, code, iter1, addcst);
13439 gsi = gsi_last_bb (incr_bb);
13440 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13442 imm_use_iterator iter;
13443 use_operand_p use_p;
13444 gimple use_stmt;
13445 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13446 if (use_stmt == phi)
13447 continue;
13448 else
13449 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13450 SET_USE (use_p, iter1);
13454 calculate_dominance_info (CDI_DOMINATORS);
13455 add_loop (loop, loop->header->loop_father);
13456 update_ssa (TODO_update_ssa);
13458 pop_cfun ();
13461 /* If the function in NODE is tagged as an elemental SIMD function,
13462 create the appropriate SIMD clones. */
13464 static void
13465 expand_simd_clones (struct cgraph_node *node)
13467 tree attr = lookup_attribute ("omp declare simd",
13468 DECL_ATTRIBUTES (node->decl));
13469 if (attr == NULL_TREE
13470 || node->global.inlined_to
13471 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13472 return;
13474 /* Ignore
13475 #pragma omp declare simd
13476 extern int foo ();
13477 in C, there we don't know the argument types at all. */
13478 if (!node->definition
13479 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13480 return;
13484 /* Start with parsing the "omp declare simd" attribute(s). */
13485 bool inbranch_clause_specified;
13486 struct cgraph_simd_clone *clone_info
13487 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13488 &inbranch_clause_specified);
13489 if (clone_info == NULL)
13490 continue;
13492 int orig_simdlen = clone_info->simdlen;
13493 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13494 /* The target can return 0 (no simd clones should be created),
13495 1 (just one ISA of simd clones should be created) or higher
13496 count of ISA variants. In that case, clone_info is initialized
13497 for the first ISA variant. */
13498 int count
13499 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13500 base_type, 0);
13501 if (count == 0)
13502 continue;
13504 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13505 also create one inbranch and one !inbranch clone of it. */
13506 for (int i = 0; i < count * 2; i++)
13508 struct cgraph_simd_clone *clone = clone_info;
13509 if (inbranch_clause_specified && (i & 1) != 0)
13510 continue;
13512 if (i != 0)
13514 clone = simd_clone_struct_alloc (clone_info->nargs
13515 + ((i & 1) != 0));
13516 simd_clone_struct_copy (clone, clone_info);
13517 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13518 and simd_clone_adjust_argument_types did to the first
13519 clone's info. */
13520 clone->nargs -= clone_info->inbranch;
13521 clone->simdlen = orig_simdlen;
13522 /* And call the target hook again to get the right ISA. */
13523 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13524 base_type,
13525 i / 2);
13526 if ((i & 1) != 0)
13527 clone->inbranch = 1;
13530 /* simd_clone_mangle might fail if such a clone has been created
13531 already. */
13532 tree id = simd_clone_mangle (node, clone);
13533 if (id == NULL_TREE)
13534 continue;
13536 /* Only when we are sure we want to create the clone actually
13537 clone the function (or definitions) or create another
13538 extern FUNCTION_DECL (for prototypes without definitions). */
13539 struct cgraph_node *n = simd_clone_create (node);
13540 if (n == NULL)
13541 continue;
13543 n->simdclone = clone;
13544 clone->origin = node;
13545 clone->next_clone = NULL;
13546 if (node->simd_clones == NULL)
13548 clone->prev_clone = n;
13549 node->simd_clones = n;
13551 else
13553 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13554 clone->prev_clone->simdclone->next_clone = n;
13555 node->simd_clones->simdclone->prev_clone = n;
13557 symtab->change_decl_assembler_name (n->decl, id);
13558 /* And finally adjust the return type, parameters and for
13559 definitions also function body. */
13560 if (node->definition)
13561 simd_clone_adjust (n);
13562 else
13564 simd_clone_adjust_return_type (n);
13565 simd_clone_adjust_argument_types (n);
13569 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13572 /* Entry point for IPA simd clone creation pass. */
13574 static unsigned int
13575 ipa_omp_simd_clone (void)
13577 struct cgraph_node *node;
13578 FOR_EACH_FUNCTION (node)
13579 expand_simd_clones (node);
13580 return 0;
13583 namespace {
13585 const pass_data pass_data_omp_simd_clone =
13587 SIMPLE_IPA_PASS, /* type */
13588 "simdclone", /* name */
13589 OPTGROUP_NONE, /* optinfo_flags */
13590 TV_NONE, /* tv_id */
13591 ( PROP_ssa | PROP_cfg ), /* properties_required */
13592 0, /* properties_provided */
13593 0, /* properties_destroyed */
13594 0, /* todo_flags_start */
13595 0, /* todo_flags_finish */
13598 class pass_omp_simd_clone : public simple_ipa_opt_pass
13600 public:
13601 pass_omp_simd_clone(gcc::context *ctxt)
13602 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13605 /* opt_pass methods: */
13606 virtual bool gate (function *);
13607 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
13610 bool
13611 pass_omp_simd_clone::gate (function *)
13613 return ((flag_openmp || flag_openmp_simd
13614 || flag_cilkplus
13615 || (in_lto_p && !flag_wpa))
13616 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13619 } // anon namespace
13621 simple_ipa_opt_pass *
13622 make_pass_omp_simd_clone (gcc::context *ctxt)
13624 return new pass_omp_simd_clone (ctxt);
13627 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13628 adds their addresses and sizes to constructor-vector V_CTOR. */
13629 static void
13630 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13631 vec<constructor_elt, va_gc> *v_ctor)
13633 unsigned len = vec_safe_length (v_decls);
13634 for (unsigned i = 0; i < len; i++)
13636 tree it = (*v_decls)[i];
13637 bool is_function = TREE_CODE (it) != VAR_DECL;
13639 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13640 if (!is_function)
13641 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13642 fold_convert (const_ptr_type_node,
13643 DECL_SIZE_UNIT (it)));
13647 /* Create new symbols containing (address, size) pairs for global variables,
13648 marked with "omp declare target" attribute, as well as addresses for the
13649 functions, which are outlined offloading regions. */
13650 void
13651 omp_finish_file (void)
13653 unsigned num_funcs = vec_safe_length (offload_funcs);
13654 unsigned num_vars = vec_safe_length (offload_vars);
13656 if (num_funcs == 0 && num_vars == 0)
13657 return;
13659 if (targetm_common.have_named_sections)
13661 vec<constructor_elt, va_gc> *v_f, *v_v;
13662 vec_alloc (v_f, num_funcs);
13663 vec_alloc (v_v, num_vars * 2);
13665 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13666 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13668 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13669 num_vars * 2);
13670 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13671 num_funcs);
13672 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13673 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13674 tree ctor_v = build_constructor (vars_decl_type, v_v);
13675 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13676 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13677 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13678 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13679 get_identifier (".offload_func_table"),
13680 funcs_decl_type);
13681 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13682 get_identifier (".offload_var_table"),
13683 vars_decl_type);
13684 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13685 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13686 otherwise a joint table in a binary will contain padding between
13687 tables from multiple object files. */
13688 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13689 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13690 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13691 DECL_INITIAL (funcs_decl) = ctor_f;
13692 DECL_INITIAL (vars_decl) = ctor_v;
13693 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13694 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13696 varpool_node::finalize_decl (vars_decl);
13697 varpool_node::finalize_decl (funcs_decl);
13699 else
13701 for (unsigned i = 0; i < num_funcs; i++)
13703 tree it = (*offload_funcs)[i];
13704 targetm.record_offload_symbol (it);
13706 for (unsigned i = 0; i < num_vars; i++)
13708 tree it = (*offload_vars)[i];
13709 targetm.record_offload_symbol (it);
13714 #include "gt-omp-low.h"