Merged from trunk from revision r222717 up to r222905.
[official-gcc.git] / gcc / omp-low.c
blob0cb95b32973a823300d7b39251243c471b0496ba
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 || (gimple_omp_for_kind (for_stmt)
524 == GF_OMP_FOR_KIND_FOR));
525 break;
526 case LE_EXPR:
527 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
528 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
529 else
530 loop->n2 = fold_build2_loc (loc,
531 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
532 build_int_cst (TREE_TYPE (loop->n2), 1));
533 loop->cond_code = LT_EXPR;
534 break;
535 case GE_EXPR:
536 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
537 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
538 else
539 loop->n2 = fold_build2_loc (loc,
540 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
541 build_int_cst (TREE_TYPE (loop->n2), 1));
542 loop->cond_code = GT_EXPR;
543 break;
544 default:
545 gcc_unreachable ();
548 t = gimple_omp_for_incr (for_stmt, i);
549 gcc_assert (TREE_OPERAND (t, 0) == var);
550 switch (TREE_CODE (t))
552 case PLUS_EXPR:
553 loop->step = TREE_OPERAND (t, 1);
554 break;
555 case POINTER_PLUS_EXPR:
556 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
557 break;
558 case MINUS_EXPR:
559 loop->step = TREE_OPERAND (t, 1);
560 loop->step = fold_build1_loc (loc,
561 NEGATE_EXPR, TREE_TYPE (loop->step),
562 loop->step);
563 break;
564 default:
565 gcc_unreachable ();
568 if (simd
569 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
570 && !fd->have_ordered))
572 if (fd->collapse == 1)
573 iter_type = TREE_TYPE (loop->v);
574 else if (i == 0
575 || TYPE_PRECISION (iter_type)
576 < TYPE_PRECISION (TREE_TYPE (loop->v)))
577 iter_type
578 = build_nonstandard_integer_type
579 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
581 else if (iter_type != long_long_unsigned_type_node)
583 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
584 iter_type = long_long_unsigned_type_node;
585 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
586 && TYPE_PRECISION (TREE_TYPE (loop->v))
587 >= TYPE_PRECISION (iter_type))
589 tree n;
591 if (loop->cond_code == LT_EXPR)
592 n = fold_build2_loc (loc,
593 PLUS_EXPR, TREE_TYPE (loop->v),
594 loop->n2, loop->step);
595 else
596 n = loop->n1;
597 if (TREE_CODE (n) != INTEGER_CST
598 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
599 iter_type = long_long_unsigned_type_node;
601 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
602 > TYPE_PRECISION (iter_type))
604 tree n1, n2;
606 if (loop->cond_code == LT_EXPR)
608 n1 = loop->n1;
609 n2 = fold_build2_loc (loc,
610 PLUS_EXPR, TREE_TYPE (loop->v),
611 loop->n2, loop->step);
613 else
615 n1 = fold_build2_loc (loc,
616 MINUS_EXPR, TREE_TYPE (loop->v),
617 loop->n2, loop->step);
618 n2 = loop->n1;
620 if (TREE_CODE (n1) != INTEGER_CST
621 || TREE_CODE (n2) != INTEGER_CST
622 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
623 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
624 iter_type = long_long_unsigned_type_node;
628 if (collapse_count && *collapse_count == NULL)
630 t = fold_binary (loop->cond_code, boolean_type_node,
631 fold_convert (TREE_TYPE (loop->v), loop->n1),
632 fold_convert (TREE_TYPE (loop->v), loop->n2));
633 if (t && integer_zerop (t))
634 count = build_zero_cst (long_long_unsigned_type_node);
635 else if ((i == 0 || count != NULL_TREE)
636 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
637 && TREE_CONSTANT (loop->n1)
638 && TREE_CONSTANT (loop->n2)
639 && TREE_CODE (loop->step) == INTEGER_CST)
641 tree itype = TREE_TYPE (loop->v);
643 if (POINTER_TYPE_P (itype))
644 itype = signed_type_for (itype);
645 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
646 t = fold_build2_loc (loc,
647 PLUS_EXPR, itype,
648 fold_convert_loc (loc, itype, loop->step), t);
649 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
650 fold_convert_loc (loc, itype, loop->n2));
651 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
652 fold_convert_loc (loc, itype, loop->n1));
653 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
654 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
655 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
656 fold_build1_loc (loc, NEGATE_EXPR, itype,
657 fold_convert_loc (loc, itype,
658 loop->step)));
659 else
660 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
661 fold_convert_loc (loc, itype, loop->step));
662 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
663 if (count != NULL_TREE)
664 count = fold_build2_loc (loc,
665 MULT_EXPR, long_long_unsigned_type_node,
666 count, t);
667 else
668 count = t;
669 if (TREE_CODE (count) != INTEGER_CST)
670 count = NULL_TREE;
672 else if (count && !integer_zerop (count))
673 count = NULL_TREE;
677 if (count
678 && !simd
679 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
680 || fd->have_ordered))
682 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
683 iter_type = long_long_unsigned_type_node;
684 else
685 iter_type = long_integer_type_node;
687 else if (collapse_iter && *collapse_iter != NULL)
688 iter_type = TREE_TYPE (*collapse_iter);
689 fd->iter_type = iter_type;
690 if (collapse_iter && *collapse_iter == NULL)
691 *collapse_iter = create_tmp_var (iter_type, ".iter");
692 if (collapse_count && *collapse_count == NULL)
694 if (count)
695 *collapse_count = fold_convert_loc (loc, iter_type, count);
696 else
697 *collapse_count = create_tmp_var (iter_type, ".count");
700 if (fd->collapse > 1)
702 fd->loop.v = *collapse_iter;
703 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
704 fd->loop.n2 = *collapse_count;
705 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
706 fd->loop.cond_code = LT_EXPR;
709 /* For OpenACC loops, force a chunk size of one, as this avoids the default
710 scheduling where several subsequent iterations are being executed by the
711 same thread. */
712 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
714 gcc_assert (fd->chunk_size == NULL_TREE);
715 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
720 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
721 is the immediate dominator of PAR_ENTRY_BB, return true if there
722 are no data dependencies that would prevent expanding the parallel
723 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
725 When expanding a combined parallel+workshare region, the call to
726 the child function may need additional arguments in the case of
727 GIMPLE_OMP_FOR regions. In some cases, these arguments are
728 computed out of variables passed in from the parent to the child
729 via 'struct .omp_data_s'. For instance:
731 #pragma omp parallel for schedule (guided, i * 4)
732 for (j ...)
734 Is lowered into:
736 # BLOCK 2 (PAR_ENTRY_BB)
737 .omp_data_o.i = i;
738 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
740 # BLOCK 3 (WS_ENTRY_BB)
741 .omp_data_i = &.omp_data_o;
742 D.1667 = .omp_data_i->i;
743 D.1598 = D.1667 * 4;
744 #pragma omp for schedule (guided, D.1598)
746 When we outline the parallel region, the call to the child function
747 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
748 that value is computed *after* the call site. So, in principle we
749 cannot do the transformation.
751 To see whether the code in WS_ENTRY_BB blocks the combined
752 parallel+workshare call, we collect all the variables used in the
753 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
754 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
755 call.
757 FIXME. If we had the SSA form built at this point, we could merely
758 hoist the code in block 3 into block 2 and be done with it. But at
759 this point we don't have dataflow information and though we could
760 hack something up here, it is really not worth the aggravation. */
762 static bool
763 workshare_safe_to_combine_p (basic_block ws_entry_bb)
765 struct omp_for_data fd;
766 gimple ws_stmt = last_stmt (ws_entry_bb);
768 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
769 return true;
771 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
773 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
775 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
776 return false;
777 if (fd.iter_type != long_integer_type_node)
778 return false;
780 /* FIXME. We give up too easily here. If any of these arguments
781 are not constants, they will likely involve variables that have
782 been mapped into fields of .omp_data_s for sharing with the child
783 function. With appropriate data flow, it would be possible to
784 see through this. */
785 if (!is_gimple_min_invariant (fd.loop.n1)
786 || !is_gimple_min_invariant (fd.loop.n2)
787 || !is_gimple_min_invariant (fd.loop.step)
788 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
789 return false;
791 return true;
795 /* Collect additional arguments needed to emit a combined
796 parallel+workshare call. WS_STMT is the workshare directive being
797 expanded. */
799 static vec<tree, va_gc> *
800 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
802 tree t;
803 location_t loc = gimple_location (ws_stmt);
804 vec<tree, va_gc> *ws_args;
806 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
808 struct omp_for_data fd;
809 tree n1, n2;
811 extract_omp_for_data (for_stmt, &fd, NULL);
812 n1 = fd.loop.n1;
813 n2 = fd.loop.n2;
815 if (gimple_omp_for_combined_into_p (for_stmt))
817 tree innerc
818 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
819 OMP_CLAUSE__LOOPTEMP_);
820 gcc_assert (innerc);
821 n1 = OMP_CLAUSE_DECL (innerc);
822 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
823 OMP_CLAUSE__LOOPTEMP_);
824 gcc_assert (innerc);
825 n2 = OMP_CLAUSE_DECL (innerc);
828 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
830 t = fold_convert_loc (loc, long_integer_type_node, n1);
831 ws_args->quick_push (t);
833 t = fold_convert_loc (loc, long_integer_type_node, n2);
834 ws_args->quick_push (t);
836 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
837 ws_args->quick_push (t);
839 if (fd.chunk_size)
841 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
842 ws_args->quick_push (t);
845 return ws_args;
847 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
849 /* Number of sections is equal to the number of edges from the
850 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
851 the exit of the sections region. */
852 basic_block bb = single_succ (gimple_bb (ws_stmt));
853 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
854 vec_alloc (ws_args, 1);
855 ws_args->quick_push (t);
856 return ws_args;
859 gcc_unreachable ();
863 /* Discover whether REGION is a combined parallel+workshare region. */
865 static void
866 determine_parallel_type (struct omp_region *region)
868 basic_block par_entry_bb, par_exit_bb;
869 basic_block ws_entry_bb, ws_exit_bb;
871 if (region == NULL || region->inner == NULL
872 || region->exit == NULL || region->inner->exit == NULL
873 || region->inner->cont == NULL)
874 return;
876 /* We only support parallel+for and parallel+sections. */
877 if (region->type != GIMPLE_OMP_PARALLEL
878 || (region->inner->type != GIMPLE_OMP_FOR
879 && region->inner->type != GIMPLE_OMP_SECTIONS))
880 return;
882 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
883 WS_EXIT_BB -> PAR_EXIT_BB. */
884 par_entry_bb = region->entry;
885 par_exit_bb = region->exit;
886 ws_entry_bb = region->inner->entry;
887 ws_exit_bb = region->inner->exit;
889 if (single_succ (par_entry_bb) == ws_entry_bb
890 && single_succ (ws_exit_bb) == par_exit_bb
891 && workshare_safe_to_combine_p (ws_entry_bb)
892 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
893 || (last_and_only_stmt (ws_entry_bb)
894 && last_and_only_stmt (par_exit_bb))))
896 gimple par_stmt = last_stmt (par_entry_bb);
897 gimple ws_stmt = last_stmt (ws_entry_bb);
899 if (region->inner->type == GIMPLE_OMP_FOR)
901 /* If this is a combined parallel loop, we need to determine
902 whether or not to use the combined library calls. There
903 are two cases where we do not apply the transformation:
904 static loops and any kind of ordered loop. In the first
905 case, we already open code the loop so there is no need
906 to do anything else. In the latter case, the combined
907 parallel loop call would still need extra synchronization
908 to implement ordered semantics, so there would not be any
909 gain in using the combined call. */
910 tree clauses = gimple_omp_for_clauses (ws_stmt);
911 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
912 if (c == NULL
913 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
914 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
916 region->is_combined_parallel = false;
917 region->inner->is_combined_parallel = false;
918 return;
922 region->is_combined_parallel = true;
923 region->inner->is_combined_parallel = true;
924 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
929 /* Return true if EXPR is variable sized. */
931 static inline bool
932 is_variable_sized (const_tree expr)
934 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
937 /* Return true if DECL is a reference type. */
939 static inline bool
940 is_reference (tree decl)
942 return lang_hooks.decls.omp_privatize_by_reference (decl);
945 /* Return the type of a decl. If the decl is reference type,
946 return its base type. */
947 static inline tree
948 get_base_type (tree decl)
950 tree type = TREE_TYPE (decl);
951 if (is_reference (decl))
952 type = TREE_TYPE (type);
953 return type;
956 /* Lookup variables. The "maybe" form
957 allows for the variable form to not have been entered, otherwise we
958 assert that the variable must have been entered. */
960 static inline tree
961 lookup_decl (tree var, omp_context *ctx)
963 tree *n = ctx->cb.decl_map->get (var);
964 return *n;
967 static inline tree
968 maybe_lookup_decl (const_tree var, omp_context *ctx)
970 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
971 return n ? *n : NULL_TREE;
974 static inline tree
975 lookup_field (tree var, omp_context *ctx)
977 splay_tree_node n;
978 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
979 return (tree) n->value;
982 static inline tree
983 lookup_sfield (tree var, omp_context *ctx)
985 splay_tree_node n;
986 n = splay_tree_lookup (ctx->sfield_map
987 ? ctx->sfield_map : ctx->field_map,
988 (splay_tree_key) var);
989 return (tree) n->value;
992 static inline tree
993 maybe_lookup_field (tree var, omp_context *ctx)
995 splay_tree_node n;
996 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
997 return n ? (tree) n->value : NULL_TREE;
1000 static inline tree
1001 lookup_oacc_reduction (const char *id, omp_context *ctx)
1003 splay_tree_node n;
1004 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
1005 return (tree) n->value;
1008 static inline tree
1009 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
1011 splay_tree_node n = NULL;
1012 if (ctx->reduction_map)
1013 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
1014 return n ? (tree) n->value : NULL_TREE;
1017 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1018 the parallel context if DECL is to be shared. */
1020 static bool
1021 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1023 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1024 return true;
1026 /* We can only use copy-in/copy-out semantics for shared variables
1027 when we know the value is not accessible from an outer scope. */
1028 if (shared_ctx)
1030 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1032 /* ??? Trivially accessible from anywhere. But why would we even
1033 be passing an address in this case? Should we simply assert
1034 this to be false, or should we have a cleanup pass that removes
1035 these from the list of mappings? */
1036 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1037 return true;
1039 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1040 without analyzing the expression whether or not its location
1041 is accessible to anyone else. In the case of nested parallel
1042 regions it certainly may be. */
1043 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1044 return true;
1046 /* Do not use copy-in/copy-out for variables that have their
1047 address taken. */
1048 if (TREE_ADDRESSABLE (decl))
1049 return true;
1051 /* lower_send_shared_vars only uses copy-in, but not copy-out
1052 for these. */
1053 if (TREE_READONLY (decl)
1054 || ((TREE_CODE (decl) == RESULT_DECL
1055 || TREE_CODE (decl) == PARM_DECL)
1056 && DECL_BY_REFERENCE (decl)))
1057 return false;
1059 /* Disallow copy-in/out in nested parallel if
1060 decl is shared in outer parallel, otherwise
1061 each thread could store the shared variable
1062 in its own copy-in location, making the
1063 variable no longer really shared. */
1064 if (shared_ctx->is_nested)
1066 omp_context *up;
1068 for (up = shared_ctx->outer; up; up = up->outer)
1069 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1070 break;
1072 if (up)
1074 tree c;
1076 for (c = gimple_omp_taskreg_clauses (up->stmt);
1077 c; c = OMP_CLAUSE_CHAIN (c))
1078 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1079 && OMP_CLAUSE_DECL (c) == decl)
1080 break;
1082 if (c)
1083 goto maybe_mark_addressable_and_ret;
1087 /* For tasks avoid using copy-in/out. As tasks can be
1088 deferred or executed in different thread, when GOMP_task
1089 returns, the task hasn't necessarily terminated. */
1090 if (is_task_ctx (shared_ctx))
1092 tree outer;
1093 maybe_mark_addressable_and_ret:
1094 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1095 if (is_gimple_reg (outer))
1097 /* Taking address of OUTER in lower_send_shared_vars
1098 might need regimplification of everything that uses the
1099 variable. */
1100 if (!task_shared_vars)
1101 task_shared_vars = BITMAP_ALLOC (NULL);
1102 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1103 TREE_ADDRESSABLE (outer) = 1;
1105 return true;
1109 return false;
1112 /* Construct a new automatic decl similar to VAR. */
1114 static tree
1115 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1117 tree copy = copy_var_decl (var, name, type);
1119 DECL_CONTEXT (copy) = current_function_decl;
1120 DECL_CHAIN (copy) = ctx->block_vars;
1121 ctx->block_vars = copy;
1123 return copy;
1126 static tree
1127 omp_copy_decl_1 (tree var, omp_context *ctx)
1129 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1132 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1133 as appropriate. */
1134 static tree
1135 omp_build_component_ref (tree obj, tree field)
1137 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1138 if (TREE_THIS_VOLATILE (field))
1139 TREE_THIS_VOLATILE (ret) |= 1;
1140 if (TREE_READONLY (field))
1141 TREE_READONLY (ret) |= 1;
1142 return ret;
1145 /* Build tree nodes to access the field for VAR on the receiver side. */
1147 static tree
1148 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1150 tree x, field = lookup_field (var, ctx);
1152 /* If the receiver record type was remapped in the child function,
1153 remap the field into the new record type. */
1154 x = maybe_lookup_field (field, ctx);
1155 if (x != NULL)
1156 field = x;
1158 x = build_simple_mem_ref (ctx->receiver_decl);
1159 x = omp_build_component_ref (x, field);
1160 if (by_ref)
1161 x = build_simple_mem_ref (x);
1163 return x;
1166 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1167 of a parallel, this is a component reference; for workshare constructs
1168 this is some variable. */
1170 static tree
1171 build_outer_var_ref (tree var, omp_context *ctx)
1173 tree x;
1175 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1176 x = var;
1177 else if (is_variable_sized (var))
1179 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1180 x = build_outer_var_ref (x, ctx);
1181 x = build_simple_mem_ref (x);
1183 else if (is_taskreg_ctx (ctx))
1185 bool by_ref = use_pointer_for_field (var, NULL);
1186 x = build_receiver_ref (var, by_ref, ctx);
1188 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1189 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1191 /* #pragma omp simd isn't a worksharing construct, and can reference even
1192 private vars in its linear etc. clauses. */
1193 x = NULL_TREE;
1194 if (ctx->outer && is_taskreg_ctx (ctx))
1195 x = lookup_decl (var, ctx->outer);
1196 else if (ctx->outer)
1197 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1198 if (x == NULL_TREE)
1199 x = var;
1201 else if (ctx->outer)
1202 x = lookup_decl (var, ctx->outer);
1203 else if (is_reference (var))
1204 /* This can happen with orphaned constructs. If var is reference, it is
1205 possible it is shared and as such valid. */
1206 x = var;
1207 else
1208 gcc_unreachable ();
1210 if (is_reference (var))
1211 x = build_simple_mem_ref (x);
1213 return x;
1216 /* Build tree nodes to access the field for VAR on the sender side. */
1218 static tree
1219 build_sender_ref (tree var, omp_context *ctx)
1221 tree field = lookup_sfield (var, ctx);
1222 return omp_build_component_ref (ctx->sender_decl, field);
1225 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1227 static void
1228 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1230 tree field, type, sfield = NULL_TREE;
1232 gcc_assert ((mask & 1) == 0
1233 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1234 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1235 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1236 gcc_assert ((mask & 3) == 3
1237 || !is_gimple_omp_oacc (ctx->stmt));
1239 type = TREE_TYPE (var);
1240 if (mask & 4)
1242 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1243 type = build_pointer_type (build_pointer_type (type));
1245 else if (by_ref)
1246 type = build_pointer_type (type);
1247 else if ((mask & 3) == 1 && is_reference (var))
1248 type = TREE_TYPE (type);
1250 field = build_decl (DECL_SOURCE_LOCATION (var),
1251 FIELD_DECL, DECL_NAME (var), type);
1253 /* Remember what variable this field was created for. This does have a
1254 side effect of making dwarf2out ignore this member, so for helpful
1255 debugging we clear it later in delete_omp_context. */
1256 DECL_ABSTRACT_ORIGIN (field) = var;
1257 if (type == TREE_TYPE (var))
1259 DECL_ALIGN (field) = DECL_ALIGN (var);
1260 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1261 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1263 else
1264 DECL_ALIGN (field) = TYPE_ALIGN (type);
1266 if ((mask & 3) == 3)
1268 insert_field_into_struct (ctx->record_type, field);
1269 if (ctx->srecord_type)
1271 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1272 FIELD_DECL, DECL_NAME (var), type);
1273 DECL_ABSTRACT_ORIGIN (sfield) = var;
1274 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1275 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1276 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1277 insert_field_into_struct (ctx->srecord_type, sfield);
1280 else
1282 if (ctx->srecord_type == NULL_TREE)
1284 tree t;
1286 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1287 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1288 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1290 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1291 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1292 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1293 insert_field_into_struct (ctx->srecord_type, sfield);
1294 splay_tree_insert (ctx->sfield_map,
1295 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1296 (splay_tree_value) sfield);
1299 sfield = field;
1300 insert_field_into_struct ((mask & 1) ? ctx->record_type
1301 : ctx->srecord_type, field);
1304 if (mask & 1)
1305 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1306 (splay_tree_value) field);
1307 if ((mask & 2) && ctx->sfield_map)
1308 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1309 (splay_tree_value) sfield);
1312 static tree
1313 install_var_local (tree var, omp_context *ctx)
1315 tree new_var = omp_copy_decl_1 (var, ctx);
1316 insert_decl_map (&ctx->cb, var, new_var);
1317 return new_var;
1320 /* Adjust the replacement for DECL in CTX for the new context. This means
1321 copying the DECL_VALUE_EXPR, and fixing up the type. */
1323 static void
1324 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1326 tree new_decl, size;
1328 new_decl = lookup_decl (decl, ctx);
1330 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1332 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1333 && DECL_HAS_VALUE_EXPR_P (decl))
1335 tree ve = DECL_VALUE_EXPR (decl);
1336 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1337 SET_DECL_VALUE_EXPR (new_decl, ve);
1338 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1341 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1343 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1344 if (size == error_mark_node)
1345 size = TYPE_SIZE (TREE_TYPE (new_decl));
1346 DECL_SIZE (new_decl) = size;
1348 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1349 if (size == error_mark_node)
1350 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1351 DECL_SIZE_UNIT (new_decl) = size;
1355 /* The callback for remap_decl. Search all containing contexts for a
1356 mapping of the variable; this avoids having to duplicate the splay
1357 tree ahead of time. We know a mapping doesn't already exist in the
1358 given context. Create new mappings to implement default semantics. */
1360 static tree
1361 omp_copy_decl (tree var, copy_body_data *cb)
1363 omp_context *ctx = (omp_context *) cb;
1364 tree new_var;
1366 if (TREE_CODE (var) == LABEL_DECL)
1368 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1369 DECL_CONTEXT (new_var) = current_function_decl;
1370 insert_decl_map (&ctx->cb, var, new_var);
1371 return new_var;
1374 while (!is_taskreg_ctx (ctx))
1376 ctx = ctx->outer;
1377 if (ctx == NULL)
1378 return var;
1379 new_var = maybe_lookup_decl (var, ctx);
1380 if (new_var)
1381 return new_var;
1384 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1385 return var;
1387 return error_mark_node;
1391 /* Debugging dumps for parallel regions. */
1392 void dump_omp_region (FILE *, struct omp_region *, int);
1393 void debug_omp_region (struct omp_region *);
1394 void debug_all_omp_regions (void);
1396 /* Dump the parallel region tree rooted at REGION. */
1398 void
1399 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1401 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1402 gimple_code_name[region->type]);
1404 if (region->inner)
1405 dump_omp_region (file, region->inner, indent + 4);
1407 if (region->cont)
1409 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1410 region->cont->index);
1413 if (region->exit)
1414 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1415 region->exit->index);
1416 else
1417 fprintf (file, "%*s[no exit marker]\n", indent, "");
1419 if (region->next)
1420 dump_omp_region (file, region->next, indent);
1423 DEBUG_FUNCTION void
1424 debug_omp_region (struct omp_region *region)
1426 dump_omp_region (stderr, region, 0);
1429 DEBUG_FUNCTION void
1430 debug_all_omp_regions (void)
1432 dump_omp_region (stderr, root_omp_region, 0);
1436 /* Create a new parallel region starting at STMT inside region PARENT. */
1438 static struct omp_region *
1439 new_omp_region (basic_block bb, enum gimple_code type,
1440 struct omp_region *parent)
1442 struct omp_region *region = XCNEW (struct omp_region);
1444 region->outer = parent;
1445 region->entry = bb;
1446 region->type = type;
1448 if (parent)
1450 /* This is a nested region. Add it to the list of inner
1451 regions in PARENT. */
1452 region->next = parent->inner;
1453 parent->inner = region;
1455 else
1457 /* This is a toplevel region. Add it to the list of toplevel
1458 regions in ROOT_OMP_REGION. */
1459 region->next = root_omp_region;
1460 root_omp_region = region;
1463 return region;
1466 /* Release the memory associated with the region tree rooted at REGION. */
1468 static void
1469 free_omp_region_1 (struct omp_region *region)
1471 struct omp_region *i, *n;
1473 for (i = region->inner; i ; i = n)
1475 n = i->next;
1476 free_omp_region_1 (i);
1479 free (region);
1482 /* Release the memory for the entire omp region tree. */
1484 void
1485 free_omp_regions (void)
1487 struct omp_region *r, *n;
1488 for (r = root_omp_region; r ; r = n)
1490 n = r->next;
1491 free_omp_region_1 (r);
1493 root_omp_region = NULL;
1497 /* Create a new context, with OUTER_CTX being the surrounding context. */
1499 static omp_context *
1500 new_omp_context (gimple stmt, omp_context *outer_ctx)
1502 omp_context *ctx = XCNEW (omp_context);
1504 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1505 (splay_tree_value) ctx);
1506 ctx->stmt = stmt;
1508 if (outer_ctx)
1510 ctx->outer = outer_ctx;
1511 ctx->cb = outer_ctx->cb;
1512 ctx->cb.block = NULL;
1513 ctx->depth = outer_ctx->depth + 1;
1514 ctx->reduction_map = outer_ctx->reduction_map;
1516 else
1518 ctx->cb.src_fn = current_function_decl;
1519 ctx->cb.dst_fn = current_function_decl;
1520 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1521 gcc_checking_assert (ctx->cb.src_node);
1522 ctx->cb.dst_node = ctx->cb.src_node;
1523 ctx->cb.src_cfun = cfun;
1524 ctx->cb.copy_decl = omp_copy_decl;
1525 ctx->cb.eh_lp_nr = 0;
1526 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1527 ctx->depth = 1;
1530 ctx->cb.decl_map = new hash_map<tree, tree>;
1532 return ctx;
1535 static gimple_seq maybe_catch_exception (gimple_seq);
1537 /* Finalize task copyfn. */
1539 static void
1540 finalize_task_copyfn (gomp_task *task_stmt)
1542 struct function *child_cfun;
1543 tree child_fn;
1544 gimple_seq seq = NULL, new_seq;
1545 gbind *bind;
1547 child_fn = gimple_omp_task_copy_fn (task_stmt);
1548 if (child_fn == NULL_TREE)
1549 return;
1551 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1552 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1554 push_cfun (child_cfun);
1555 bind = gimplify_body (child_fn, false);
1556 gimple_seq_add_stmt (&seq, bind);
1557 new_seq = maybe_catch_exception (seq);
1558 if (new_seq != seq)
1560 bind = gimple_build_bind (NULL, new_seq, NULL);
1561 seq = NULL;
1562 gimple_seq_add_stmt (&seq, bind);
1564 gimple_set_body (child_fn, seq);
1565 pop_cfun ();
1567 /* Inform the callgraph about the new function. */
1568 cgraph_node::add_new_function (child_fn, false);
1569 cgraph_node::get (child_fn)->parallelized_function = 1;
1572 /* Destroy a omp_context data structures. Called through the splay tree
1573 value delete callback. */
1575 static void
1576 delete_omp_context (splay_tree_value value)
1578 omp_context *ctx = (omp_context *) value;
1580 delete ctx->cb.decl_map;
1582 if (ctx->field_map)
1583 splay_tree_delete (ctx->field_map);
1584 if (ctx->sfield_map)
1585 splay_tree_delete (ctx->sfield_map);
1586 /* Reduction map is copied to nested contexts, so only delete it in the
1587 owner. */
1588 if (ctx->reduction_map
1589 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1590 && is_gimple_omp_offloaded (ctx->stmt)
1591 && is_gimple_omp_oacc (ctx->stmt))
1592 splay_tree_delete (ctx->reduction_map);
1594 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1595 it produces corrupt debug information. */
1596 if (ctx->record_type)
1598 tree t;
1599 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1600 DECL_ABSTRACT_ORIGIN (t) = NULL;
1602 if (ctx->srecord_type)
1604 tree t;
1605 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1606 DECL_ABSTRACT_ORIGIN (t) = NULL;
1609 if (is_task_ctx (ctx))
1610 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1612 XDELETE (ctx);
1615 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1616 context. */
1618 static void
1619 fixup_child_record_type (omp_context *ctx)
1621 tree f, type = ctx->record_type;
1623 /* ??? It isn't sufficient to just call remap_type here, because
1624 variably_modified_type_p doesn't work the way we expect for
1625 record types. Testing each field for whether it needs remapping
1626 and creating a new record by hand works, however. */
1627 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1628 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1629 break;
1630 if (f)
1632 tree name, new_fields = NULL;
1634 type = lang_hooks.types.make_type (RECORD_TYPE);
1635 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1636 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1637 TYPE_DECL, name, type);
1638 TYPE_NAME (type) = name;
1640 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1642 tree new_f = copy_node (f);
1643 DECL_CONTEXT (new_f) = type;
1644 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1645 DECL_CHAIN (new_f) = new_fields;
1646 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1647 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1648 &ctx->cb, NULL);
1649 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1650 &ctx->cb, NULL);
1651 new_fields = new_f;
1653 /* Arrange to be able to look up the receiver field
1654 given the sender field. */
1655 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1656 (splay_tree_value) new_f);
1658 TYPE_FIELDS (type) = nreverse (new_fields);
1659 layout_type (type);
1662 TREE_TYPE (ctx->receiver_decl)
1663 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1666 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1667 specified by CLAUSES. */
1669 static void
1670 scan_sharing_clauses (tree clauses, omp_context *ctx)
1672 tree c, decl;
1673 bool scan_array_reductions = false;
1675 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1677 bool by_ref;
1679 switch (OMP_CLAUSE_CODE (c))
1681 case OMP_CLAUSE_PRIVATE:
1682 decl = OMP_CLAUSE_DECL (c);
1683 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1684 goto do_private;
1685 else if (!is_variable_sized (decl))
1686 install_var_local (decl, ctx);
1687 break;
1689 case OMP_CLAUSE_SHARED:
1690 decl = OMP_CLAUSE_DECL (c);
1691 /* Ignore shared directives in teams construct. */
1692 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1694 /* Global variables don't need to be copied,
1695 the receiver side will use them directly. */
1696 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1697 if (is_global_var (odecl))
1698 break;
1699 insert_decl_map (&ctx->cb, decl, odecl);
1700 break;
1702 gcc_assert (is_taskreg_ctx (ctx));
1703 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1704 || !is_variable_sized (decl));
1705 /* Global variables don't need to be copied,
1706 the receiver side will use them directly. */
1707 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1708 break;
1709 by_ref = use_pointer_for_field (decl, ctx);
1710 if (! TREE_READONLY (decl)
1711 || TREE_ADDRESSABLE (decl)
1712 || by_ref
1713 || is_reference (decl))
1715 install_var_field (decl, by_ref, 3, ctx);
1716 install_var_local (decl, ctx);
1717 break;
1719 /* We don't need to copy const scalar vars back. */
1720 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1721 goto do_private;
1723 case OMP_CLAUSE_LASTPRIVATE:
1724 /* Let the corresponding firstprivate clause create
1725 the variable. */
1726 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1727 break;
1728 /* FALLTHRU */
1730 case OMP_CLAUSE_FIRSTPRIVATE:
1731 if (is_gimple_omp_oacc (ctx->stmt))
1733 sorry ("clause not supported yet");
1734 break;
1736 /* FALLTHRU */
1737 case OMP_CLAUSE_REDUCTION:
1738 case OMP_CLAUSE_LINEAR:
1739 decl = OMP_CLAUSE_DECL (c);
1740 do_private:
1741 if (is_variable_sized (decl))
1743 if (is_task_ctx (ctx))
1744 install_var_field (decl, false, 1, ctx);
1745 break;
1747 else if (is_taskreg_ctx (ctx))
1749 bool global
1750 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1751 by_ref = use_pointer_for_field (decl, NULL);
1753 if (is_task_ctx (ctx)
1754 && (global || by_ref || is_reference (decl)))
1756 install_var_field (decl, false, 1, ctx);
1757 if (!global)
1758 install_var_field (decl, by_ref, 2, ctx);
1760 else if (!global)
1761 install_var_field (decl, by_ref, 3, ctx);
1763 install_var_local (decl, ctx);
1764 if (is_gimple_omp_oacc (ctx->stmt)
1765 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1767 /* Create a decl for the reduction array. */
1768 tree var = OMP_CLAUSE_DECL (c);
1769 tree type = get_base_type (var);
1770 tree ptype = build_pointer_type (type);
1771 tree array = create_tmp_var (ptype,
1772 oacc_get_reduction_array_id (var));
1773 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1774 install_var_field (array, true, 3, c);
1775 install_var_local (array, c);
1777 /* Insert it into the current context. */
1778 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1779 oacc_get_reduction_array_id (var),
1780 (splay_tree_value) array);
1781 splay_tree_insert (ctx->reduction_map,
1782 (splay_tree_key) array,
1783 (splay_tree_value) array);
1785 break;
1787 case OMP_CLAUSE__LOOPTEMP_:
1788 gcc_assert (is_parallel_ctx (ctx));
1789 decl = OMP_CLAUSE_DECL (c);
1790 install_var_field (decl, false, 3, ctx);
1791 install_var_local (decl, ctx);
1792 break;
1794 case OMP_CLAUSE_COPYPRIVATE:
1795 case OMP_CLAUSE_COPYIN:
1796 decl = OMP_CLAUSE_DECL (c);
1797 by_ref = use_pointer_for_field (decl, NULL);
1798 install_var_field (decl, by_ref, 3, ctx);
1799 break;
1801 case OMP_CLAUSE_DEFAULT:
1802 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1803 break;
1805 case OMP_CLAUSE_FINAL:
1806 case OMP_CLAUSE_IF:
1807 case OMP_CLAUSE_NUM_THREADS:
1808 case OMP_CLAUSE_NUM_TEAMS:
1809 case OMP_CLAUSE_THREAD_LIMIT:
1810 case OMP_CLAUSE_DEVICE:
1811 case OMP_CLAUSE_SCHEDULE:
1812 case OMP_CLAUSE_DIST_SCHEDULE:
1813 case OMP_CLAUSE_DEPEND:
1814 case OMP_CLAUSE__CILK_FOR_COUNT_:
1815 case OMP_CLAUSE_NUM_GANGS:
1816 case OMP_CLAUSE_NUM_WORKERS:
1817 case OMP_CLAUSE_VECTOR_LENGTH:
1818 if (ctx->outer)
1819 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1820 break;
1822 case OMP_CLAUSE_TO:
1823 case OMP_CLAUSE_FROM:
1824 case OMP_CLAUSE_MAP:
1825 if (ctx->outer)
1826 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1827 decl = OMP_CLAUSE_DECL (c);
1828 /* Global variables with "omp declare target" attribute
1829 don't need to be copied, the receiver side will use them
1830 directly. */
1831 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1832 && DECL_P (decl)
1833 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1834 && varpool_node::get_create (decl)->offloadable)
1835 break;
1836 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1837 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
1839 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1840 not offloaded; there is nothing to map for those. */
1841 if (!is_gimple_omp_offloaded (ctx->stmt)
1842 && !POINTER_TYPE_P (TREE_TYPE (decl))
1843 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
1844 break;
1846 if (DECL_P (decl))
1848 if (DECL_SIZE (decl)
1849 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1851 tree decl2 = DECL_VALUE_EXPR (decl);
1852 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1853 decl2 = TREE_OPERAND (decl2, 0);
1854 gcc_assert (DECL_P (decl2));
1855 install_var_field (decl2, true, 3, ctx);
1856 install_var_local (decl2, ctx);
1857 install_var_local (decl, ctx);
1859 else
1861 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1862 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1863 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1864 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1865 install_var_field (decl, true, 7, ctx);
1866 else
1867 install_var_field (decl, true, 3, ctx);
1868 if (is_gimple_omp_offloaded (ctx->stmt))
1869 install_var_local (decl, ctx);
1872 else
1874 tree base = get_base_address (decl);
1875 tree nc = OMP_CLAUSE_CHAIN (c);
1876 if (DECL_P (base)
1877 && nc != NULL_TREE
1878 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1879 && OMP_CLAUSE_DECL (nc) == base
1880 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1881 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1883 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1884 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1886 else
1888 if (ctx->outer)
1890 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1891 decl = OMP_CLAUSE_DECL (c);
1893 gcc_assert (!splay_tree_lookup (ctx->field_map,
1894 (splay_tree_key) decl));
1895 tree field
1896 = build_decl (OMP_CLAUSE_LOCATION (c),
1897 FIELD_DECL, NULL_TREE, ptr_type_node);
1898 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1899 insert_field_into_struct (ctx->record_type, field);
1900 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1901 (splay_tree_value) field);
1904 break;
1906 case OMP_CLAUSE_NOWAIT:
1907 case OMP_CLAUSE_ORDERED:
1908 case OMP_CLAUSE_COLLAPSE:
1909 case OMP_CLAUSE_UNTIED:
1910 case OMP_CLAUSE_MERGEABLE:
1911 case OMP_CLAUSE_PROC_BIND:
1912 case OMP_CLAUSE_SAFELEN:
1913 case OMP_CLAUSE_ASYNC:
1914 case OMP_CLAUSE_WAIT:
1915 case OMP_CLAUSE_GANG:
1916 case OMP_CLAUSE_WORKER:
1917 case OMP_CLAUSE_VECTOR:
1918 break;
1920 case OMP_CLAUSE_ALIGNED:
1921 decl = OMP_CLAUSE_DECL (c);
1922 if (is_global_var (decl)
1923 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1924 install_var_local (decl, ctx);
1925 break;
1927 case OMP_CLAUSE_DEVICE_RESIDENT:
1928 case OMP_CLAUSE_USE_DEVICE:
1929 case OMP_CLAUSE__CACHE_:
1930 case OMP_CLAUSE_INDEPENDENT:
1931 case OMP_CLAUSE_AUTO:
1932 case OMP_CLAUSE_SEQ:
1933 sorry ("Clause not supported yet");
1934 break;
1936 default:
1937 gcc_unreachable ();
1941 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1943 switch (OMP_CLAUSE_CODE (c))
1945 case OMP_CLAUSE_LASTPRIVATE:
1946 /* Let the corresponding firstprivate clause create
1947 the variable. */
1948 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1949 scan_array_reductions = true;
1950 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1951 break;
1952 /* FALLTHRU */
1954 case OMP_CLAUSE_FIRSTPRIVATE:
1955 if (is_gimple_omp_oacc (ctx->stmt))
1957 sorry ("clause not supported yet");
1958 break;
1960 /* FALLTHRU */
1961 case OMP_CLAUSE_PRIVATE:
1962 case OMP_CLAUSE_REDUCTION:
1963 case OMP_CLAUSE_LINEAR:
1964 decl = OMP_CLAUSE_DECL (c);
1965 if (is_variable_sized (decl))
1966 install_var_local (decl, ctx);
1967 fixup_remapped_decl (decl, ctx,
1968 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1969 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1970 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1971 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1972 scan_array_reductions = true;
1973 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1974 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1975 scan_array_reductions = true;
1976 break;
1978 case OMP_CLAUSE_SHARED:
1979 /* Ignore shared directives in teams construct. */
1980 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1981 break;
1982 decl = OMP_CLAUSE_DECL (c);
1983 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1984 fixup_remapped_decl (decl, ctx, false);
1985 break;
1987 case OMP_CLAUSE_MAP:
1988 if (!is_gimple_omp_offloaded (ctx->stmt))
1989 break;
1990 decl = OMP_CLAUSE_DECL (c);
1991 if (DECL_P (decl)
1992 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1993 && varpool_node::get_create (decl)->offloadable)
1994 break;
1995 if (DECL_P (decl))
1997 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1998 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1999 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2001 tree new_decl = lookup_decl (decl, ctx);
2002 TREE_TYPE (new_decl)
2003 = remap_type (TREE_TYPE (decl), &ctx->cb);
2005 else if (DECL_SIZE (decl)
2006 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2008 tree decl2 = DECL_VALUE_EXPR (decl);
2009 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2010 decl2 = TREE_OPERAND (decl2, 0);
2011 gcc_assert (DECL_P (decl2));
2012 fixup_remapped_decl (decl2, ctx, false);
2013 fixup_remapped_decl (decl, ctx, true);
2015 else
2016 fixup_remapped_decl (decl, ctx, false);
2018 break;
2020 case OMP_CLAUSE_COPYPRIVATE:
2021 case OMP_CLAUSE_COPYIN:
2022 case OMP_CLAUSE_DEFAULT:
2023 case OMP_CLAUSE_IF:
2024 case OMP_CLAUSE_NUM_THREADS:
2025 case OMP_CLAUSE_NUM_TEAMS:
2026 case OMP_CLAUSE_THREAD_LIMIT:
2027 case OMP_CLAUSE_DEVICE:
2028 case OMP_CLAUSE_SCHEDULE:
2029 case OMP_CLAUSE_DIST_SCHEDULE:
2030 case OMP_CLAUSE_NOWAIT:
2031 case OMP_CLAUSE_ORDERED:
2032 case OMP_CLAUSE_COLLAPSE:
2033 case OMP_CLAUSE_UNTIED:
2034 case OMP_CLAUSE_FINAL:
2035 case OMP_CLAUSE_MERGEABLE:
2036 case OMP_CLAUSE_PROC_BIND:
2037 case OMP_CLAUSE_SAFELEN:
2038 case OMP_CLAUSE_ALIGNED:
2039 case OMP_CLAUSE_DEPEND:
2040 case OMP_CLAUSE__LOOPTEMP_:
2041 case OMP_CLAUSE_TO:
2042 case OMP_CLAUSE_FROM:
2043 case OMP_CLAUSE__CILK_FOR_COUNT_:
2044 case OMP_CLAUSE_ASYNC:
2045 case OMP_CLAUSE_WAIT:
2046 case OMP_CLAUSE_NUM_GANGS:
2047 case OMP_CLAUSE_NUM_WORKERS:
2048 case OMP_CLAUSE_VECTOR_LENGTH:
2049 case OMP_CLAUSE_GANG:
2050 case OMP_CLAUSE_WORKER:
2051 case OMP_CLAUSE_VECTOR:
2052 break;
2054 case OMP_CLAUSE_DEVICE_RESIDENT:
2055 case OMP_CLAUSE_USE_DEVICE:
2056 case OMP_CLAUSE__CACHE_:
2057 case OMP_CLAUSE_INDEPENDENT:
2058 case OMP_CLAUSE_AUTO:
2059 case OMP_CLAUSE_SEQ:
2060 sorry ("Clause not supported yet");
2061 break;
2063 default:
2064 gcc_unreachable ();
2068 gcc_checking_assert (!scan_array_reductions
2069 || !is_gimple_omp_oacc (ctx->stmt));
2070 if (scan_array_reductions)
2071 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2072 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2073 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2075 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2076 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2078 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2079 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2080 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2081 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2082 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2083 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2086 /* Create a new name for omp child function. Returns an identifier. If
2087 IS_CILK_FOR is true then the suffix for the child function is
2088 "_cilk_for_fn." */
2090 static tree
2091 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2093 if (is_cilk_for)
2094 return clone_function_name (current_function_decl, "_cilk_for_fn");
2095 return clone_function_name (current_function_decl,
2096 task_copy ? "_omp_cpyfn" : "_omp_fn");
2099 /* Returns the type of the induction variable for the child function for
2100 _Cilk_for and the types for _high and _low variables based on TYPE. */
2102 static tree
2103 cilk_for_check_loop_diff_type (tree type)
2105 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2107 if (TYPE_UNSIGNED (type))
2108 return uint32_type_node;
2109 else
2110 return integer_type_node;
2112 else
2114 if (TYPE_UNSIGNED (type))
2115 return uint64_type_node;
2116 else
2117 return long_long_integer_type_node;
2121 /* Build a decl for the omp child function. It'll not contain a body
2122 yet, just the bare decl. */
2124 static void
2125 create_omp_child_function (omp_context *ctx, bool task_copy)
2127 tree decl, type, name, t;
2129 tree cilk_for_count
2130 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2131 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2132 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2133 tree cilk_var_type = NULL_TREE;
2135 name = create_omp_child_function_name (task_copy,
2136 cilk_for_count != NULL_TREE);
2137 if (task_copy)
2138 type = build_function_type_list (void_type_node, ptr_type_node,
2139 ptr_type_node, NULL_TREE);
2140 else if (cilk_for_count)
2142 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2143 cilk_var_type = cilk_for_check_loop_diff_type (type);
2144 type = build_function_type_list (void_type_node, ptr_type_node,
2145 cilk_var_type, cilk_var_type, NULL_TREE);
2147 else
2148 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2150 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2152 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2153 || !task_copy);
2154 if (!task_copy)
2155 ctx->cb.dst_fn = decl;
2156 else
2157 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2159 TREE_STATIC (decl) = 1;
2160 TREE_USED (decl) = 1;
2161 DECL_ARTIFICIAL (decl) = 1;
2162 DECL_IGNORED_P (decl) = 0;
2163 TREE_PUBLIC (decl) = 0;
2164 DECL_UNINLINABLE (decl) = 1;
2165 DECL_EXTERNAL (decl) = 0;
2166 DECL_CONTEXT (decl) = NULL_TREE;
2167 DECL_INITIAL (decl) = make_node (BLOCK);
2168 if (cgraph_node::get (current_function_decl)->offloadable)
2169 cgraph_node::get_create (decl)->offloadable = 1;
2170 else
2172 omp_context *octx;
2173 for (octx = ctx; octx; octx = octx->outer)
2174 if (is_gimple_omp_offloaded (octx->stmt))
2176 cgraph_node::get_create (decl)->offloadable = 1;
2177 #ifdef ENABLE_OFFLOADING
2178 g->have_offload = true;
2179 #endif
2180 break;
2184 if (cgraph_node::get_create (decl)->offloadable
2185 && !lookup_attribute ("omp declare target",
2186 DECL_ATTRIBUTES (current_function_decl)))
2187 DECL_ATTRIBUTES (decl)
2188 = tree_cons (get_identifier ("omp target entrypoint"),
2189 NULL_TREE, DECL_ATTRIBUTES (decl));
2191 t = build_decl (DECL_SOURCE_LOCATION (decl),
2192 RESULT_DECL, NULL_TREE, void_type_node);
2193 DECL_ARTIFICIAL (t) = 1;
2194 DECL_IGNORED_P (t) = 1;
2195 DECL_CONTEXT (t) = decl;
2196 DECL_RESULT (decl) = t;
2198 /* _Cilk_for's child function requires two extra parameters called
2199 __low and __high that are set the by Cilk runtime when it calls this
2200 function. */
2201 if (cilk_for_count)
2203 t = build_decl (DECL_SOURCE_LOCATION (decl),
2204 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2205 DECL_ARTIFICIAL (t) = 1;
2206 DECL_NAMELESS (t) = 1;
2207 DECL_ARG_TYPE (t) = ptr_type_node;
2208 DECL_CONTEXT (t) = current_function_decl;
2209 TREE_USED (t) = 1;
2210 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2211 DECL_ARGUMENTS (decl) = t;
2213 t = build_decl (DECL_SOURCE_LOCATION (decl),
2214 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2215 DECL_ARTIFICIAL (t) = 1;
2216 DECL_NAMELESS (t) = 1;
2217 DECL_ARG_TYPE (t) = ptr_type_node;
2218 DECL_CONTEXT (t) = current_function_decl;
2219 TREE_USED (t) = 1;
2220 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2221 DECL_ARGUMENTS (decl) = t;
2224 tree data_name = get_identifier (".omp_data_i");
2225 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2226 ptr_type_node);
2227 DECL_ARTIFICIAL (t) = 1;
2228 DECL_NAMELESS (t) = 1;
2229 DECL_ARG_TYPE (t) = ptr_type_node;
2230 DECL_CONTEXT (t) = current_function_decl;
2231 TREE_USED (t) = 1;
2232 if (cilk_for_count)
2233 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2234 DECL_ARGUMENTS (decl) = t;
2235 if (!task_copy)
2236 ctx->receiver_decl = t;
2237 else
2239 t = build_decl (DECL_SOURCE_LOCATION (decl),
2240 PARM_DECL, get_identifier (".omp_data_o"),
2241 ptr_type_node);
2242 DECL_ARTIFICIAL (t) = 1;
2243 DECL_NAMELESS (t) = 1;
2244 DECL_ARG_TYPE (t) = ptr_type_node;
2245 DECL_CONTEXT (t) = current_function_decl;
2246 TREE_USED (t) = 1;
2247 TREE_ADDRESSABLE (t) = 1;
2248 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2249 DECL_ARGUMENTS (decl) = t;
2252 /* Allocate memory for the function structure. The call to
2253 allocate_struct_function clobbers CFUN, so we need to restore
2254 it afterward. */
2255 push_struct_function (decl);
2256 cfun->function_end_locus = gimple_location (ctx->stmt);
2257 pop_cfun ();
2260 /* Callback for walk_gimple_seq. Check if combined parallel
2261 contains gimple_omp_for_combined_into_p OMP_FOR. */
2263 static tree
2264 find_combined_for (gimple_stmt_iterator *gsi_p,
2265 bool *handled_ops_p,
2266 struct walk_stmt_info *wi)
2268 gimple stmt = gsi_stmt (*gsi_p);
2270 *handled_ops_p = true;
2271 switch (gimple_code (stmt))
2273 WALK_SUBSTMTS;
2275 case GIMPLE_OMP_FOR:
2276 if (gimple_omp_for_combined_into_p (stmt)
2277 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2279 wi->info = stmt;
2280 return integer_zero_node;
2282 break;
2283 default:
2284 break;
2286 return NULL;
2289 /* Scan an OpenMP parallel directive. */
2291 static void
2292 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2294 omp_context *ctx;
2295 tree name;
2296 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2298 /* Ignore parallel directives with empty bodies, unless there
2299 are copyin clauses. */
2300 if (optimize > 0
2301 && empty_body_p (gimple_omp_body (stmt))
2302 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2303 OMP_CLAUSE_COPYIN) == NULL)
2305 gsi_replace (gsi, gimple_build_nop (), false);
2306 return;
2309 if (gimple_omp_parallel_combined_p (stmt))
2311 struct walk_stmt_info wi;
2313 memset (&wi, 0, sizeof (wi));
2314 wi.val_only = true;
2315 walk_gimple_seq (gimple_omp_body (stmt),
2316 find_combined_for, NULL, &wi);
2317 if (wi.info)
2319 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2320 struct omp_for_data fd;
2321 extract_omp_for_data (for_stmt, &fd, NULL);
2322 /* We need two temporaries with fd.loop.v type (istart/iend)
2323 and then (fd.collapse - 1) temporaries with the same
2324 type for count2 ... countN-1 vars if not constant. */
2325 size_t count = 2, i;
2326 tree type = fd.iter_type;
2327 if (fd.collapse > 1
2328 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2329 count += fd.collapse - 1;
2330 for (i = 0; i < count; i++)
2332 tree temp = create_tmp_var (type);
2333 tree c = build_omp_clause (UNKNOWN_LOCATION,
2334 OMP_CLAUSE__LOOPTEMP_);
2335 insert_decl_map (&outer_ctx->cb, temp, temp);
2336 OMP_CLAUSE_DECL (c) = temp;
2337 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2338 gimple_omp_parallel_set_clauses (stmt, c);
2343 ctx = new_omp_context (stmt, outer_ctx);
2344 taskreg_contexts.safe_push (ctx);
2345 if (taskreg_nesting_level > 1)
2346 ctx->is_nested = true;
2347 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2348 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2349 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2350 name = create_tmp_var_name (".omp_data_s");
2351 name = build_decl (gimple_location (stmt),
2352 TYPE_DECL, name, ctx->record_type);
2353 DECL_ARTIFICIAL (name) = 1;
2354 DECL_NAMELESS (name) = 1;
2355 TYPE_NAME (ctx->record_type) = name;
2356 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2357 create_omp_child_function (ctx, false);
2358 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2360 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2361 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2363 if (TYPE_FIELDS (ctx->record_type) == NULL)
2364 ctx->record_type = ctx->receiver_decl = NULL;
2367 /* Scan an OpenMP task directive. */
2369 static void
2370 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2372 omp_context *ctx;
2373 tree name, t;
2374 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2376 /* Ignore task directives with empty bodies. */
2377 if (optimize > 0
2378 && empty_body_p (gimple_omp_body (stmt)))
2380 gsi_replace (gsi, gimple_build_nop (), false);
2381 return;
2384 ctx = new_omp_context (stmt, outer_ctx);
2385 taskreg_contexts.safe_push (ctx);
2386 if (taskreg_nesting_level > 1)
2387 ctx->is_nested = true;
2388 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2389 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2390 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2391 name = create_tmp_var_name (".omp_data_s");
2392 name = build_decl (gimple_location (stmt),
2393 TYPE_DECL, name, ctx->record_type);
2394 DECL_ARTIFICIAL (name) = 1;
2395 DECL_NAMELESS (name) = 1;
2396 TYPE_NAME (ctx->record_type) = name;
2397 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2398 create_omp_child_function (ctx, false);
2399 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2401 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2403 if (ctx->srecord_type)
2405 name = create_tmp_var_name (".omp_data_a");
2406 name = build_decl (gimple_location (stmt),
2407 TYPE_DECL, name, ctx->srecord_type);
2408 DECL_ARTIFICIAL (name) = 1;
2409 DECL_NAMELESS (name) = 1;
2410 TYPE_NAME (ctx->srecord_type) = name;
2411 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2412 create_omp_child_function (ctx, true);
2415 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2417 if (TYPE_FIELDS (ctx->record_type) == NULL)
2419 ctx->record_type = ctx->receiver_decl = NULL;
2420 t = build_int_cst (long_integer_type_node, 0);
2421 gimple_omp_task_set_arg_size (stmt, t);
2422 t = build_int_cst (long_integer_type_node, 1);
2423 gimple_omp_task_set_arg_align (stmt, t);
2428 /* If any decls have been made addressable during scan_omp,
2429 adjust their fields if needed, and layout record types
2430 of parallel/task constructs. */
2432 static void
2433 finish_taskreg_scan (omp_context *ctx)
2435 if (ctx->record_type == NULL_TREE)
2436 return;
2438 /* If any task_shared_vars were needed, verify all
2439 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2440 statements if use_pointer_for_field hasn't changed
2441 because of that. If it did, update field types now. */
2442 if (task_shared_vars)
2444 tree c;
2446 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2447 c; c = OMP_CLAUSE_CHAIN (c))
2448 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2450 tree decl = OMP_CLAUSE_DECL (c);
2452 /* Global variables don't need to be copied,
2453 the receiver side will use them directly. */
2454 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2455 continue;
2456 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2457 || !use_pointer_for_field (decl, ctx))
2458 continue;
2459 tree field = lookup_field (decl, ctx);
2460 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2461 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2462 continue;
2463 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2464 TREE_THIS_VOLATILE (field) = 0;
2465 DECL_USER_ALIGN (field) = 0;
2466 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2467 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2468 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2469 if (ctx->srecord_type)
2471 tree sfield = lookup_sfield (decl, ctx);
2472 TREE_TYPE (sfield) = TREE_TYPE (field);
2473 TREE_THIS_VOLATILE (sfield) = 0;
2474 DECL_USER_ALIGN (sfield) = 0;
2475 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2476 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2477 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2482 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2484 layout_type (ctx->record_type);
2485 fixup_child_record_type (ctx);
2487 else
2489 location_t loc = gimple_location (ctx->stmt);
2490 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2491 /* Move VLA fields to the end. */
2492 p = &TYPE_FIELDS (ctx->record_type);
2493 while (*p)
2494 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2495 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2497 *q = *p;
2498 *p = TREE_CHAIN (*p);
2499 TREE_CHAIN (*q) = NULL_TREE;
2500 q = &TREE_CHAIN (*q);
2502 else
2503 p = &DECL_CHAIN (*p);
2504 *p = vla_fields;
2505 layout_type (ctx->record_type);
2506 fixup_child_record_type (ctx);
2507 if (ctx->srecord_type)
2508 layout_type (ctx->srecord_type);
2509 tree t = fold_convert_loc (loc, long_integer_type_node,
2510 TYPE_SIZE_UNIT (ctx->record_type));
2511 gimple_omp_task_set_arg_size (ctx->stmt, t);
2512 t = build_int_cst (long_integer_type_node,
2513 TYPE_ALIGN_UNIT (ctx->record_type));
2514 gimple_omp_task_set_arg_align (ctx->stmt, t);
2519 static omp_context *
2520 enclosing_target_ctx (omp_context *ctx)
2522 while (ctx != NULL
2523 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2524 ctx = ctx->outer;
2525 gcc_assert (ctx != NULL);
2526 return ctx;
2529 static bool
2530 oacc_loop_or_target_p (gimple stmt)
2532 enum gimple_code outer_type = gimple_code (stmt);
2533 return ((outer_type == GIMPLE_OMP_TARGET
2534 && ((gimple_omp_target_kind (stmt)
2535 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2536 || (gimple_omp_target_kind (stmt)
2537 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2538 || (outer_type == GIMPLE_OMP_FOR
2539 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2542 /* Scan a GIMPLE_OMP_FOR. */
2544 static void
2545 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2547 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
2548 omp_context *ctx;
2549 size_t i;
2550 tree clauses = gimple_omp_for_clauses (stmt);
2552 if (outer_ctx)
2553 outer_type = gimple_code (outer_ctx->stmt);
2555 ctx = new_omp_context (stmt, outer_ctx);
2557 if (is_gimple_omp_oacc (stmt))
2559 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2560 ctx->gwv_this = outer_ctx->gwv_this;
2561 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2563 int val;
2564 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2565 val = MASK_GANG;
2566 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2567 val = MASK_WORKER;
2568 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2569 val = MASK_VECTOR;
2570 else
2571 continue;
2572 ctx->gwv_this |= val;
2573 if (!outer_ctx)
2575 /* Skip; not nested inside a region. */
2576 continue;
2578 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2580 /* Skip; not nested inside an OpenACC region. */
2581 continue;
2583 if (outer_type == GIMPLE_OMP_FOR)
2584 outer_ctx->gwv_below |= val;
2585 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2587 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2588 if (gimple_omp_target_kind (enclosing->stmt)
2589 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2590 error_at (gimple_location (stmt),
2591 "no arguments allowed to gang, worker and vector clauses inside parallel");
2596 scan_sharing_clauses (clauses, ctx);
2598 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2599 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2601 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2602 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2603 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2604 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2606 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2608 if (is_gimple_omp_oacc (stmt))
2610 if (ctx->gwv_this & ctx->gwv_below)
2611 error_at (gimple_location (stmt),
2612 "gang, worker and vector may occur only once in a loop nest");
2613 else if (ctx->gwv_below != 0
2614 && ctx->gwv_this > ctx->gwv_below)
2615 error_at (gimple_location (stmt),
2616 "gang, worker and vector must occur in this order in a loop nest");
2617 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2618 outer_ctx->gwv_below |= ctx->gwv_below;
2622 /* Scan an OpenMP sections directive. */
2624 static void
2625 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2627 omp_context *ctx;
2629 ctx = new_omp_context (stmt, outer_ctx);
2630 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2631 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2634 /* Scan an OpenMP single directive. */
2636 static void
2637 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2639 omp_context *ctx;
2640 tree name;
2642 ctx = new_omp_context (stmt, outer_ctx);
2643 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2644 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2645 name = create_tmp_var_name (".omp_copy_s");
2646 name = build_decl (gimple_location (stmt),
2647 TYPE_DECL, name, ctx->record_type);
2648 TYPE_NAME (ctx->record_type) = name;
2650 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2651 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2653 if (TYPE_FIELDS (ctx->record_type) == NULL)
2654 ctx->record_type = NULL;
2655 else
2656 layout_type (ctx->record_type);
2659 /* Scan a GIMPLE_OMP_TARGET. */
2661 static void
2662 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2664 omp_context *ctx;
2665 tree name;
2666 bool offloaded = is_gimple_omp_offloaded (stmt);
2667 tree clauses = gimple_omp_target_clauses (stmt);
2669 ctx = new_omp_context (stmt, outer_ctx);
2670 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2671 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2672 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2673 name = create_tmp_var_name (".omp_data_t");
2674 name = build_decl (gimple_location (stmt),
2675 TYPE_DECL, name, ctx->record_type);
2676 DECL_ARTIFICIAL (name) = 1;
2677 DECL_NAMELESS (name) = 1;
2678 TYPE_NAME (ctx->record_type) = name;
2679 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2680 if (offloaded)
2682 if (is_gimple_omp_oacc (stmt))
2683 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2684 0, 0);
2686 create_omp_child_function (ctx, false);
2687 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2690 if (is_gimple_omp_oacc (stmt))
2692 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2694 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2695 ctx->gwv_this |= MASK_GANG;
2696 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2697 ctx->gwv_this |= MASK_WORKER;
2698 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2699 ctx->gwv_this |= MASK_VECTOR;
2703 scan_sharing_clauses (clauses, ctx);
2704 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2706 if (TYPE_FIELDS (ctx->record_type) == NULL)
2707 ctx->record_type = ctx->receiver_decl = NULL;
2708 else
2710 TYPE_FIELDS (ctx->record_type)
2711 = nreverse (TYPE_FIELDS (ctx->record_type));
2712 #ifdef ENABLE_CHECKING
2713 tree field;
2714 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2715 for (field = TYPE_FIELDS (ctx->record_type);
2716 field;
2717 field = DECL_CHAIN (field))
2718 gcc_assert (DECL_ALIGN (field) == align);
2719 #endif
2720 layout_type (ctx->record_type);
2721 if (offloaded)
2722 fixup_child_record_type (ctx);
2726 /* Scan an OpenMP teams directive. */
2728 static void
2729 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2731 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2732 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2733 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2736 /* Check nesting restrictions. */
2737 static bool
2738 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2740 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2741 inside an OpenACC CTX. */
2742 if (!(is_gimple_omp (stmt)
2743 && is_gimple_omp_oacc (stmt)))
2745 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2746 if (is_gimple_omp (ctx_->stmt)
2747 && is_gimple_omp_oacc (ctx_->stmt))
2749 error_at (gimple_location (stmt),
2750 "non-OpenACC construct inside of OpenACC region");
2751 return false;
2755 if (ctx != NULL)
2757 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2758 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2760 error_at (gimple_location (stmt),
2761 "OpenMP constructs may not be nested inside simd region");
2762 return false;
2764 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2766 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2767 || (gimple_omp_for_kind (stmt)
2768 != GF_OMP_FOR_KIND_DISTRIBUTE))
2769 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2771 error_at (gimple_location (stmt),
2772 "only distribute or parallel constructs are allowed to "
2773 "be closely nested inside teams construct");
2774 return false;
2778 switch (gimple_code (stmt))
2780 case GIMPLE_OMP_FOR:
2781 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2782 return true;
2783 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2785 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2787 error_at (gimple_location (stmt),
2788 "distribute construct must be closely nested inside "
2789 "teams construct");
2790 return false;
2792 return true;
2794 /* FALLTHRU */
2795 case GIMPLE_CALL:
2796 if (is_gimple_call (stmt)
2797 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2798 == BUILT_IN_GOMP_CANCEL
2799 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2800 == BUILT_IN_GOMP_CANCELLATION_POINT))
2802 const char *bad = NULL;
2803 const char *kind = NULL;
2804 if (ctx == NULL)
2806 error_at (gimple_location (stmt), "orphaned %qs construct",
2807 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2808 == BUILT_IN_GOMP_CANCEL
2809 ? "#pragma omp cancel"
2810 : "#pragma omp cancellation point");
2811 return false;
2813 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2814 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2815 : 0)
2817 case 1:
2818 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2819 bad = "#pragma omp parallel";
2820 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2821 == BUILT_IN_GOMP_CANCEL
2822 && !integer_zerop (gimple_call_arg (stmt, 1)))
2823 ctx->cancellable = true;
2824 kind = "parallel";
2825 break;
2826 case 2:
2827 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2828 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2829 bad = "#pragma omp for";
2830 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2831 == BUILT_IN_GOMP_CANCEL
2832 && !integer_zerop (gimple_call_arg (stmt, 1)))
2834 ctx->cancellable = true;
2835 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2836 OMP_CLAUSE_NOWAIT))
2837 warning_at (gimple_location (stmt), 0,
2838 "%<#pragma omp cancel for%> inside "
2839 "%<nowait%> for construct");
2840 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2841 OMP_CLAUSE_ORDERED))
2842 warning_at (gimple_location (stmt), 0,
2843 "%<#pragma omp cancel for%> inside "
2844 "%<ordered%> for construct");
2846 kind = "for";
2847 break;
2848 case 4:
2849 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2850 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2851 bad = "#pragma omp sections";
2852 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2853 == BUILT_IN_GOMP_CANCEL
2854 && !integer_zerop (gimple_call_arg (stmt, 1)))
2856 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2858 ctx->cancellable = true;
2859 if (find_omp_clause (gimple_omp_sections_clauses
2860 (ctx->stmt),
2861 OMP_CLAUSE_NOWAIT))
2862 warning_at (gimple_location (stmt), 0,
2863 "%<#pragma omp cancel sections%> inside "
2864 "%<nowait%> sections construct");
2866 else
2868 gcc_assert (ctx->outer
2869 && gimple_code (ctx->outer->stmt)
2870 == GIMPLE_OMP_SECTIONS);
2871 ctx->outer->cancellable = true;
2872 if (find_omp_clause (gimple_omp_sections_clauses
2873 (ctx->outer->stmt),
2874 OMP_CLAUSE_NOWAIT))
2875 warning_at (gimple_location (stmt), 0,
2876 "%<#pragma omp cancel sections%> inside "
2877 "%<nowait%> sections construct");
2880 kind = "sections";
2881 break;
2882 case 8:
2883 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2884 bad = "#pragma omp task";
2885 else
2886 ctx->cancellable = true;
2887 kind = "taskgroup";
2888 break;
2889 default:
2890 error_at (gimple_location (stmt), "invalid arguments");
2891 return false;
2893 if (bad)
2895 error_at (gimple_location (stmt),
2896 "%<%s %s%> construct not closely nested inside of %qs",
2897 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2898 == BUILT_IN_GOMP_CANCEL
2899 ? "#pragma omp cancel"
2900 : "#pragma omp cancellation point", kind, bad);
2901 return false;
2904 /* FALLTHRU */
2905 case GIMPLE_OMP_SECTIONS:
2906 case GIMPLE_OMP_SINGLE:
2907 for (; ctx != NULL; ctx = ctx->outer)
2908 switch (gimple_code (ctx->stmt))
2910 case GIMPLE_OMP_FOR:
2911 case GIMPLE_OMP_SECTIONS:
2912 case GIMPLE_OMP_SINGLE:
2913 case GIMPLE_OMP_ORDERED:
2914 case GIMPLE_OMP_MASTER:
2915 case GIMPLE_OMP_TASK:
2916 case GIMPLE_OMP_CRITICAL:
2917 if (is_gimple_call (stmt))
2919 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2920 != BUILT_IN_GOMP_BARRIER)
2921 return true;
2922 error_at (gimple_location (stmt),
2923 "barrier region may not be closely nested inside "
2924 "of work-sharing, critical, ordered, master or "
2925 "explicit task region");
2926 return false;
2928 error_at (gimple_location (stmt),
2929 "work-sharing region may not be closely nested inside "
2930 "of work-sharing, critical, ordered, master or explicit "
2931 "task region");
2932 return false;
2933 case GIMPLE_OMP_PARALLEL:
2934 return true;
2935 default:
2936 break;
2938 break;
2939 case GIMPLE_OMP_MASTER:
2940 for (; ctx != NULL; ctx = ctx->outer)
2941 switch (gimple_code (ctx->stmt))
2943 case GIMPLE_OMP_FOR:
2944 case GIMPLE_OMP_SECTIONS:
2945 case GIMPLE_OMP_SINGLE:
2946 case GIMPLE_OMP_TASK:
2947 error_at (gimple_location (stmt),
2948 "master region may not be closely nested inside "
2949 "of work-sharing or explicit task region");
2950 return false;
2951 case GIMPLE_OMP_PARALLEL:
2952 return true;
2953 default:
2954 break;
2956 break;
2957 case GIMPLE_OMP_ORDERED:
2958 for (; ctx != NULL; ctx = ctx->outer)
2959 switch (gimple_code (ctx->stmt))
2961 case GIMPLE_OMP_CRITICAL:
2962 case GIMPLE_OMP_TASK:
2963 error_at (gimple_location (stmt),
2964 "ordered region may not be closely nested inside "
2965 "of critical or explicit task region");
2966 return false;
2967 case GIMPLE_OMP_FOR:
2968 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2969 OMP_CLAUSE_ORDERED) == NULL)
2971 error_at (gimple_location (stmt),
2972 "ordered region must be closely nested inside "
2973 "a loop region with an ordered clause");
2974 return false;
2976 return true;
2977 case GIMPLE_OMP_PARALLEL:
2978 error_at (gimple_location (stmt),
2979 "ordered region must be closely nested inside "
2980 "a loop region with an ordered clause");
2981 return false;
2982 default:
2983 break;
2985 break;
2986 case GIMPLE_OMP_CRITICAL:
2988 tree this_stmt_name
2989 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2990 for (; ctx != NULL; ctx = ctx->outer)
2991 if (gomp_critical *other_crit
2992 = dyn_cast <gomp_critical *> (ctx->stmt))
2993 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2995 error_at (gimple_location (stmt),
2996 "critical region may not be nested inside a critical "
2997 "region with the same name");
2998 return false;
3001 break;
3002 case GIMPLE_OMP_TEAMS:
3003 if (ctx == NULL
3004 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3005 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3007 error_at (gimple_location (stmt),
3008 "teams construct not closely nested inside of target "
3009 "region");
3010 return false;
3012 break;
3013 case GIMPLE_OMP_TARGET:
3014 for (; ctx != NULL; ctx = ctx->outer)
3016 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3018 if (is_gimple_omp (stmt)
3019 && is_gimple_omp_oacc (stmt)
3020 && is_gimple_omp (ctx->stmt))
3022 error_at (gimple_location (stmt),
3023 "OpenACC construct inside of non-OpenACC region");
3024 return false;
3026 continue;
3029 const char *stmt_name, *ctx_stmt_name;
3030 switch (gimple_omp_target_kind (stmt))
3032 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3033 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3034 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3035 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3036 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3037 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3038 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3039 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3040 default: gcc_unreachable ();
3042 switch (gimple_omp_target_kind (ctx->stmt))
3044 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3045 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3046 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3047 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3048 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3049 default: gcc_unreachable ();
3052 /* OpenACC/OpenMP mismatch? */
3053 if (is_gimple_omp_oacc (stmt)
3054 != is_gimple_omp_oacc (ctx->stmt))
3056 error_at (gimple_location (stmt),
3057 "%s %s construct inside of %s %s region",
3058 (is_gimple_omp_oacc (stmt)
3059 ? "OpenACC" : "OpenMP"), stmt_name,
3060 (is_gimple_omp_oacc (ctx->stmt)
3061 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3062 return false;
3064 if (is_gimple_omp_offloaded (ctx->stmt))
3066 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3067 if (is_gimple_omp_oacc (ctx->stmt))
3069 error_at (gimple_location (stmt),
3070 "%s construct inside of %s region",
3071 stmt_name, ctx_stmt_name);
3072 return false;
3074 else
3076 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3077 warning_at (gimple_location (stmt), 0,
3078 "%s construct inside of %s region",
3079 stmt_name, ctx_stmt_name);
3083 break;
3084 default:
3085 break;
3087 return true;
3091 /* Helper function scan_omp.
3093 Callback for walk_tree or operators in walk_gimple_stmt used to
3094 scan for OMP directives in TP. */
3096 static tree
3097 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3099 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3100 omp_context *ctx = (omp_context *) wi->info;
3101 tree t = *tp;
3103 switch (TREE_CODE (t))
3105 case VAR_DECL:
3106 case PARM_DECL:
3107 case LABEL_DECL:
3108 case RESULT_DECL:
3109 if (ctx)
3110 *tp = remap_decl (t, &ctx->cb);
3111 break;
3113 default:
3114 if (ctx && TYPE_P (t))
3115 *tp = remap_type (t, &ctx->cb);
3116 else if (!DECL_P (t))
3118 *walk_subtrees = 1;
3119 if (ctx)
3121 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3122 if (tem != TREE_TYPE (t))
3124 if (TREE_CODE (t) == INTEGER_CST)
3125 *tp = wide_int_to_tree (tem, t);
3126 else
3127 TREE_TYPE (t) = tem;
3131 break;
3134 return NULL_TREE;
3137 /* Return true if FNDECL is a setjmp or a longjmp. */
3139 static bool
3140 setjmp_or_longjmp_p (const_tree fndecl)
3142 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3143 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3144 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3145 return true;
3147 tree declname = DECL_NAME (fndecl);
3148 if (!declname)
3149 return false;
3150 const char *name = IDENTIFIER_POINTER (declname);
3151 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3155 /* Helper function for scan_omp.
3157 Callback for walk_gimple_stmt used to scan for OMP directives in
3158 the current statement in GSI. */
3160 static tree
3161 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3162 struct walk_stmt_info *wi)
3164 gimple stmt = gsi_stmt (*gsi);
3165 omp_context *ctx = (omp_context *) wi->info;
3167 if (gimple_has_location (stmt))
3168 input_location = gimple_location (stmt);
3170 /* Check the nesting restrictions. */
3171 bool remove = false;
3172 if (is_gimple_omp (stmt))
3173 remove = !check_omp_nesting_restrictions (stmt, ctx);
3174 else if (is_gimple_call (stmt))
3176 tree fndecl = gimple_call_fndecl (stmt);
3177 if (fndecl)
3179 if (setjmp_or_longjmp_p (fndecl)
3180 && ctx
3181 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3182 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3184 remove = true;
3185 error_at (gimple_location (stmt),
3186 "setjmp/longjmp inside simd construct");
3188 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3189 switch (DECL_FUNCTION_CODE (fndecl))
3191 case BUILT_IN_GOMP_BARRIER:
3192 case BUILT_IN_GOMP_CANCEL:
3193 case BUILT_IN_GOMP_CANCELLATION_POINT:
3194 case BUILT_IN_GOMP_TASKYIELD:
3195 case BUILT_IN_GOMP_TASKWAIT:
3196 case BUILT_IN_GOMP_TASKGROUP_START:
3197 case BUILT_IN_GOMP_TASKGROUP_END:
3198 remove = !check_omp_nesting_restrictions (stmt, ctx);
3199 break;
3200 default:
3201 break;
3205 if (remove)
3207 stmt = gimple_build_nop ();
3208 gsi_replace (gsi, stmt, false);
3211 *handled_ops_p = true;
3213 switch (gimple_code (stmt))
3215 case GIMPLE_OMP_PARALLEL:
3216 taskreg_nesting_level++;
3217 scan_omp_parallel (gsi, ctx);
3218 taskreg_nesting_level--;
3219 break;
3221 case GIMPLE_OMP_TASK:
3222 taskreg_nesting_level++;
3223 scan_omp_task (gsi, ctx);
3224 taskreg_nesting_level--;
3225 break;
3227 case GIMPLE_OMP_FOR:
3228 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3229 break;
3231 case GIMPLE_OMP_SECTIONS:
3232 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3233 break;
3235 case GIMPLE_OMP_SINGLE:
3236 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3237 break;
3239 case GIMPLE_OMP_SECTION:
3240 case GIMPLE_OMP_MASTER:
3241 case GIMPLE_OMP_TASKGROUP:
3242 case GIMPLE_OMP_ORDERED:
3243 case GIMPLE_OMP_CRITICAL:
3244 ctx = new_omp_context (stmt, ctx);
3245 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3246 break;
3248 case GIMPLE_OMP_TARGET:
3249 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3250 break;
3252 case GIMPLE_OMP_TEAMS:
3253 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3254 break;
3256 case GIMPLE_BIND:
3258 tree var;
3260 *handled_ops_p = false;
3261 if (ctx)
3262 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3263 var ;
3264 var = DECL_CHAIN (var))
3265 insert_decl_map (&ctx->cb, var, var);
3267 break;
3268 default:
3269 *handled_ops_p = false;
3270 break;
3273 return NULL_TREE;
3277 /* Scan all the statements starting at the current statement. CTX
3278 contains context information about the OMP directives and
3279 clauses found during the scan. */
3281 static void
3282 scan_omp (gimple_seq *body_p, omp_context *ctx)
3284 location_t saved_location;
3285 struct walk_stmt_info wi;
3287 memset (&wi, 0, sizeof (wi));
3288 wi.info = ctx;
3289 wi.want_locations = true;
3291 saved_location = input_location;
3292 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3293 input_location = saved_location;
3296 /* Re-gimplification and code generation routines. */
3298 /* Build a call to GOMP_barrier. */
3300 static gimple
3301 build_omp_barrier (tree lhs)
3303 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3304 : BUILT_IN_GOMP_BARRIER);
3305 gcall *g = gimple_build_call (fndecl, 0);
3306 if (lhs)
3307 gimple_call_set_lhs (g, lhs);
3308 return g;
3311 /* If a context was created for STMT when it was scanned, return it. */
3313 static omp_context *
3314 maybe_lookup_ctx (gimple stmt)
3316 splay_tree_node n;
3317 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3318 return n ? (omp_context *) n->value : NULL;
3322 /* Find the mapping for DECL in CTX or the immediately enclosing
3323 context that has a mapping for DECL.
3325 If CTX is a nested parallel directive, we may have to use the decl
3326 mappings created in CTX's parent context. Suppose that we have the
3327 following parallel nesting (variable UIDs showed for clarity):
3329 iD.1562 = 0;
3330 #omp parallel shared(iD.1562) -> outer parallel
3331 iD.1562 = iD.1562 + 1;
3333 #omp parallel shared (iD.1562) -> inner parallel
3334 iD.1562 = iD.1562 - 1;
3336 Each parallel structure will create a distinct .omp_data_s structure
3337 for copying iD.1562 in/out of the directive:
3339 outer parallel .omp_data_s.1.i -> iD.1562
3340 inner parallel .omp_data_s.2.i -> iD.1562
3342 A shared variable mapping will produce a copy-out operation before
3343 the parallel directive and a copy-in operation after it. So, in
3344 this case we would have:
3346 iD.1562 = 0;
3347 .omp_data_o.1.i = iD.1562;
3348 #omp parallel shared(iD.1562) -> outer parallel
3349 .omp_data_i.1 = &.omp_data_o.1
3350 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3352 .omp_data_o.2.i = iD.1562; -> **
3353 #omp parallel shared(iD.1562) -> inner parallel
3354 .omp_data_i.2 = &.omp_data_o.2
3355 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3358 ** This is a problem. The symbol iD.1562 cannot be referenced
3359 inside the body of the outer parallel region. But since we are
3360 emitting this copy operation while expanding the inner parallel
3361 directive, we need to access the CTX structure of the outer
3362 parallel directive to get the correct mapping:
3364 .omp_data_o.2.i = .omp_data_i.1->i
3366 Since there may be other workshare or parallel directives enclosing
3367 the parallel directive, it may be necessary to walk up the context
3368 parent chain. This is not a problem in general because nested
3369 parallelism happens only rarely. */
3371 static tree
3372 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3374 tree t;
3375 omp_context *up;
3377 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3378 t = maybe_lookup_decl (decl, up);
3380 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3382 return t ? t : decl;
3386 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3387 in outer contexts. */
3389 static tree
3390 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3392 tree t = NULL;
3393 omp_context *up;
3395 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3396 t = maybe_lookup_decl (decl, up);
3398 return t ? t : decl;
3402 /* Construct the initialization value for reduction CLAUSE. */
3404 tree
3405 omp_reduction_init (tree clause, tree type)
3407 location_t loc = OMP_CLAUSE_LOCATION (clause);
3408 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3410 case PLUS_EXPR:
3411 case MINUS_EXPR:
3412 case BIT_IOR_EXPR:
3413 case BIT_XOR_EXPR:
3414 case TRUTH_OR_EXPR:
3415 case TRUTH_ORIF_EXPR:
3416 case TRUTH_XOR_EXPR:
3417 case NE_EXPR:
3418 return build_zero_cst (type);
3420 case MULT_EXPR:
3421 case TRUTH_AND_EXPR:
3422 case TRUTH_ANDIF_EXPR:
3423 case EQ_EXPR:
3424 return fold_convert_loc (loc, type, integer_one_node);
3426 case BIT_AND_EXPR:
3427 return fold_convert_loc (loc, type, integer_minus_one_node);
3429 case MAX_EXPR:
3430 if (SCALAR_FLOAT_TYPE_P (type))
3432 REAL_VALUE_TYPE max, min;
3433 if (HONOR_INFINITIES (type))
3435 real_inf (&max);
3436 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3438 else
3439 real_maxval (&min, 1, TYPE_MODE (type));
3440 return build_real (type, min);
3442 else
3444 gcc_assert (INTEGRAL_TYPE_P (type));
3445 return TYPE_MIN_VALUE (type);
3448 case MIN_EXPR:
3449 if (SCALAR_FLOAT_TYPE_P (type))
3451 REAL_VALUE_TYPE max;
3452 if (HONOR_INFINITIES (type))
3453 real_inf (&max);
3454 else
3455 real_maxval (&max, 0, TYPE_MODE (type));
3456 return build_real (type, max);
3458 else
3460 gcc_assert (INTEGRAL_TYPE_P (type));
3461 return TYPE_MAX_VALUE (type);
3464 default:
3465 gcc_unreachable ();
3469 /* Return alignment to be assumed for var in CLAUSE, which should be
3470 OMP_CLAUSE_ALIGNED. */
3472 static tree
3473 omp_clause_aligned_alignment (tree clause)
3475 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3476 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3478 /* Otherwise return implementation defined alignment. */
3479 unsigned int al = 1;
3480 machine_mode mode, vmode;
3481 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3482 if (vs)
3483 vs = 1 << floor_log2 (vs);
3484 static enum mode_class classes[]
3485 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3486 for (int i = 0; i < 4; i += 2)
3487 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3488 mode != VOIDmode;
3489 mode = GET_MODE_WIDER_MODE (mode))
3491 vmode = targetm.vectorize.preferred_simd_mode (mode);
3492 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3493 continue;
3494 while (vs
3495 && GET_MODE_SIZE (vmode) < vs
3496 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3497 vmode = GET_MODE_2XWIDER_MODE (vmode);
3499 tree type = lang_hooks.types.type_for_mode (mode, 1);
3500 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3501 continue;
3502 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3503 / GET_MODE_SIZE (mode));
3504 if (TYPE_MODE (type) != vmode)
3505 continue;
3506 if (TYPE_ALIGN_UNIT (type) > al)
3507 al = TYPE_ALIGN_UNIT (type);
3509 return build_int_cst (integer_type_node, al);
3512 /* Return maximum possible vectorization factor for the target. */
3514 static int
3515 omp_max_vf (void)
3517 if (!optimize
3518 || optimize_debug
3519 || !flag_tree_loop_optimize
3520 || (!flag_tree_loop_vectorize
3521 && (global_options_set.x_flag_tree_loop_vectorize
3522 || global_options_set.x_flag_tree_vectorize)))
3523 return 1;
3525 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3526 if (vs)
3528 vs = 1 << floor_log2 (vs);
3529 return vs;
3531 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3532 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3533 return GET_MODE_NUNITS (vqimode);
3534 return 1;
3537 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3538 privatization. */
3540 static bool
3541 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3542 tree &idx, tree &lane, tree &ivar, tree &lvar)
3544 if (max_vf == 0)
3546 max_vf = omp_max_vf ();
3547 if (max_vf > 1)
3549 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3550 OMP_CLAUSE_SAFELEN);
3551 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3552 max_vf = 1;
3553 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3554 max_vf) == -1)
3555 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3557 if (max_vf > 1)
3559 idx = create_tmp_var (unsigned_type_node);
3560 lane = create_tmp_var (unsigned_type_node);
3563 if (max_vf == 1)
3564 return false;
3566 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3567 tree avar = create_tmp_var_raw (atype);
3568 if (TREE_ADDRESSABLE (new_var))
3569 TREE_ADDRESSABLE (avar) = 1;
3570 DECL_ATTRIBUTES (avar)
3571 = tree_cons (get_identifier ("omp simd array"), NULL,
3572 DECL_ATTRIBUTES (avar));
3573 gimple_add_tmp_var (avar);
3574 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3575 NULL_TREE, NULL_TREE);
3576 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3577 NULL_TREE, NULL_TREE);
3578 if (DECL_P (new_var))
3580 SET_DECL_VALUE_EXPR (new_var, lvar);
3581 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3583 return true;
3586 /* Helper function of lower_rec_input_clauses. For a reference
3587 in simd reduction, add an underlying variable it will reference. */
3589 static void
3590 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3592 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3593 if (TREE_CONSTANT (z))
3595 const char *name = NULL;
3596 if (DECL_NAME (new_vard))
3597 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3599 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3600 gimple_add_tmp_var (z);
3601 TREE_ADDRESSABLE (z) = 1;
3602 z = build_fold_addr_expr_loc (loc, z);
3603 gimplify_assign (new_vard, z, ilist);
3607 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3608 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3609 private variables. Initialization statements go in ILIST, while calls
3610 to destructors go in DLIST. */
3612 static void
3613 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3614 omp_context *ctx, struct omp_for_data *fd)
3616 tree c, dtor, copyin_seq, x, ptr;
3617 bool copyin_by_ref = false;
3618 bool lastprivate_firstprivate = false;
3619 bool reduction_omp_orig_ref = false;
3620 int pass;
3621 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3622 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3623 int max_vf = 0;
3624 tree lane = NULL_TREE, idx = NULL_TREE;
3625 tree ivar = NULL_TREE, lvar = NULL_TREE;
3626 gimple_seq llist[2] = { NULL, NULL };
3628 copyin_seq = NULL;
3630 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3631 with data sharing clauses referencing variable sized vars. That
3632 is unnecessarily hard to support and very unlikely to result in
3633 vectorized code anyway. */
3634 if (is_simd)
3635 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3636 switch (OMP_CLAUSE_CODE (c))
3638 case OMP_CLAUSE_LINEAR:
3639 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3640 max_vf = 1;
3641 /* FALLTHRU */
3642 case OMP_CLAUSE_REDUCTION:
3643 case OMP_CLAUSE_PRIVATE:
3644 case OMP_CLAUSE_FIRSTPRIVATE:
3645 case OMP_CLAUSE_LASTPRIVATE:
3646 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3647 max_vf = 1;
3648 break;
3649 default:
3650 continue;
3653 /* Do all the fixed sized types in the first pass, and the variable sized
3654 types in the second pass. This makes sure that the scalar arguments to
3655 the variable sized types are processed before we use them in the
3656 variable sized operations. */
3657 for (pass = 0; pass < 2; ++pass)
3659 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3661 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3662 tree var, new_var;
3663 bool by_ref;
3664 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3666 switch (c_kind)
3668 case OMP_CLAUSE_PRIVATE:
3669 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3670 continue;
3671 break;
3672 case OMP_CLAUSE_SHARED:
3673 /* Ignore shared directives in teams construct. */
3674 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3675 continue;
3676 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3678 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3679 continue;
3681 case OMP_CLAUSE_FIRSTPRIVATE:
3682 case OMP_CLAUSE_COPYIN:
3683 case OMP_CLAUSE_LINEAR:
3684 break;
3685 case OMP_CLAUSE_REDUCTION:
3686 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3687 reduction_omp_orig_ref = true;
3688 break;
3689 case OMP_CLAUSE__LOOPTEMP_:
3690 /* Handle _looptemp_ clauses only on parallel. */
3691 if (fd)
3692 continue;
3693 break;
3694 case OMP_CLAUSE_LASTPRIVATE:
3695 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3697 lastprivate_firstprivate = true;
3698 if (pass != 0)
3699 continue;
3701 /* Even without corresponding firstprivate, if
3702 decl is Fortran allocatable, it needs outer var
3703 reference. */
3704 else if (pass == 0
3705 && lang_hooks.decls.omp_private_outer_ref
3706 (OMP_CLAUSE_DECL (c)))
3707 lastprivate_firstprivate = true;
3708 break;
3709 case OMP_CLAUSE_ALIGNED:
3710 if (pass == 0)
3711 continue;
3712 var = OMP_CLAUSE_DECL (c);
3713 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3714 && !is_global_var (var))
3716 new_var = maybe_lookup_decl (var, ctx);
3717 if (new_var == NULL_TREE)
3718 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3719 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3720 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3721 omp_clause_aligned_alignment (c));
3722 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3723 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3724 gimplify_and_add (x, ilist);
3726 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3727 && is_global_var (var))
3729 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3730 new_var = lookup_decl (var, ctx);
3731 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3732 t = build_fold_addr_expr_loc (clause_loc, t);
3733 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3734 t = build_call_expr_loc (clause_loc, t2, 2, t,
3735 omp_clause_aligned_alignment (c));
3736 t = fold_convert_loc (clause_loc, ptype, t);
3737 x = create_tmp_var (ptype);
3738 t = build2 (MODIFY_EXPR, ptype, x, t);
3739 gimplify_and_add (t, ilist);
3740 t = build_simple_mem_ref_loc (clause_loc, x);
3741 SET_DECL_VALUE_EXPR (new_var, t);
3742 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3744 continue;
3745 default:
3746 continue;
3749 new_var = var = OMP_CLAUSE_DECL (c);
3750 if (c_kind != OMP_CLAUSE_COPYIN)
3751 new_var = lookup_decl (var, ctx);
3753 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3755 if (pass != 0)
3756 continue;
3758 else if (is_variable_sized (var))
3760 /* For variable sized types, we need to allocate the
3761 actual storage here. Call alloca and store the
3762 result in the pointer decl that we created elsewhere. */
3763 if (pass == 0)
3764 continue;
3766 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3768 gcall *stmt;
3769 tree tmp, atmp;
3771 ptr = DECL_VALUE_EXPR (new_var);
3772 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3773 ptr = TREE_OPERAND (ptr, 0);
3774 gcc_assert (DECL_P (ptr));
3775 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3777 /* void *tmp = __builtin_alloca */
3778 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3779 stmt = gimple_build_call (atmp, 1, x);
3780 tmp = create_tmp_var_raw (ptr_type_node);
3781 gimple_add_tmp_var (tmp);
3782 gimple_call_set_lhs (stmt, tmp);
3784 gimple_seq_add_stmt (ilist, stmt);
3786 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3787 gimplify_assign (ptr, x, ilist);
3790 else if (is_reference (var))
3792 /* For references that are being privatized for Fortran,
3793 allocate new backing storage for the new pointer
3794 variable. This allows us to avoid changing all the
3795 code that expects a pointer to something that expects
3796 a direct variable. */
3797 if (pass == 0)
3798 continue;
3800 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3801 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3803 x = build_receiver_ref (var, false, ctx);
3804 x = build_fold_addr_expr_loc (clause_loc, x);
3806 else if (TREE_CONSTANT (x))
3808 /* For reduction in SIMD loop, defer adding the
3809 initialization of the reference, because if we decide
3810 to use SIMD array for it, the initilization could cause
3811 expansion ICE. */
3812 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3813 x = NULL_TREE;
3814 else
3816 const char *name = NULL;
3817 if (DECL_NAME (var))
3818 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3820 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3821 name);
3822 gimple_add_tmp_var (x);
3823 TREE_ADDRESSABLE (x) = 1;
3824 x = build_fold_addr_expr_loc (clause_loc, x);
3827 else
3829 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3830 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3833 if (x)
3835 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3836 gimplify_assign (new_var, x, ilist);
3839 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3841 else if (c_kind == OMP_CLAUSE_REDUCTION
3842 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3844 if (pass == 0)
3845 continue;
3847 else if (pass != 0)
3848 continue;
3850 switch (OMP_CLAUSE_CODE (c))
3852 case OMP_CLAUSE_SHARED:
3853 /* Ignore shared directives in teams construct. */
3854 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3855 continue;
3856 /* Shared global vars are just accessed directly. */
3857 if (is_global_var (new_var))
3858 break;
3859 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3860 needs to be delayed until after fixup_child_record_type so
3861 that we get the correct type during the dereference. */
3862 by_ref = use_pointer_for_field (var, ctx);
3863 x = build_receiver_ref (var, by_ref, ctx);
3864 SET_DECL_VALUE_EXPR (new_var, x);
3865 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3867 /* ??? If VAR is not passed by reference, and the variable
3868 hasn't been initialized yet, then we'll get a warning for
3869 the store into the omp_data_s structure. Ideally, we'd be
3870 able to notice this and not store anything at all, but
3871 we're generating code too early. Suppress the warning. */
3872 if (!by_ref)
3873 TREE_NO_WARNING (var) = 1;
3874 break;
3876 case OMP_CLAUSE_LASTPRIVATE:
3877 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3878 break;
3879 /* FALLTHRU */
3881 case OMP_CLAUSE_PRIVATE:
3882 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3883 x = build_outer_var_ref (var, ctx);
3884 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3886 if (is_task_ctx (ctx))
3887 x = build_receiver_ref (var, false, ctx);
3888 else
3889 x = build_outer_var_ref (var, ctx);
3891 else
3892 x = NULL;
3893 do_private:
3894 tree nx;
3895 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3896 if (is_simd)
3898 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3899 if ((TREE_ADDRESSABLE (new_var) || nx || y
3900 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3901 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3902 idx, lane, ivar, lvar))
3904 if (nx)
3905 x = lang_hooks.decls.omp_clause_default_ctor
3906 (c, unshare_expr (ivar), x);
3907 if (nx && x)
3908 gimplify_and_add (x, &llist[0]);
3909 if (y)
3911 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3912 if (y)
3914 gimple_seq tseq = NULL;
3916 dtor = y;
3917 gimplify_stmt (&dtor, &tseq);
3918 gimple_seq_add_seq (&llist[1], tseq);
3921 break;
3924 if (nx)
3925 gimplify_and_add (nx, ilist);
3926 /* FALLTHRU */
3928 do_dtor:
3929 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3930 if (x)
3932 gimple_seq tseq = NULL;
3934 dtor = x;
3935 gimplify_stmt (&dtor, &tseq);
3936 gimple_seq_add_seq (dlist, tseq);
3938 break;
3940 case OMP_CLAUSE_LINEAR:
3941 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3942 goto do_firstprivate;
3943 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3944 x = NULL;
3945 else
3946 x = build_outer_var_ref (var, ctx);
3947 goto do_private;
3949 case OMP_CLAUSE_FIRSTPRIVATE:
3950 if (is_task_ctx (ctx))
3952 if (is_reference (var) || is_variable_sized (var))
3953 goto do_dtor;
3954 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3955 ctx))
3956 || use_pointer_for_field (var, NULL))
3958 x = build_receiver_ref (var, false, ctx);
3959 SET_DECL_VALUE_EXPR (new_var, x);
3960 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3961 goto do_dtor;
3964 do_firstprivate:
3965 x = build_outer_var_ref (var, ctx);
3966 if (is_simd)
3968 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3969 && gimple_omp_for_combined_into_p (ctx->stmt))
3971 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3972 tree stept = TREE_TYPE (t);
3973 tree ct = find_omp_clause (clauses,
3974 OMP_CLAUSE__LOOPTEMP_);
3975 gcc_assert (ct);
3976 tree l = OMP_CLAUSE_DECL (ct);
3977 tree n1 = fd->loop.n1;
3978 tree step = fd->loop.step;
3979 tree itype = TREE_TYPE (l);
3980 if (POINTER_TYPE_P (itype))
3981 itype = signed_type_for (itype);
3982 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3983 if (TYPE_UNSIGNED (itype)
3984 && fd->loop.cond_code == GT_EXPR)
3985 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3986 fold_build1 (NEGATE_EXPR, itype, l),
3987 fold_build1 (NEGATE_EXPR,
3988 itype, step));
3989 else
3990 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3991 t = fold_build2 (MULT_EXPR, stept,
3992 fold_convert (stept, l), t);
3994 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3996 x = lang_hooks.decls.omp_clause_linear_ctor
3997 (c, new_var, x, t);
3998 gimplify_and_add (x, ilist);
3999 goto do_dtor;
4002 if (POINTER_TYPE_P (TREE_TYPE (x)))
4003 x = fold_build2 (POINTER_PLUS_EXPR,
4004 TREE_TYPE (x), x, t);
4005 else
4006 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4009 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4010 || TREE_ADDRESSABLE (new_var))
4011 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4012 idx, lane, ivar, lvar))
4014 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4016 tree iv = create_tmp_var (TREE_TYPE (new_var));
4017 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4018 gimplify_and_add (x, ilist);
4019 gimple_stmt_iterator gsi
4020 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4021 gassign *g
4022 = gimple_build_assign (unshare_expr (lvar), iv);
4023 gsi_insert_before_without_update (&gsi, g,
4024 GSI_SAME_STMT);
4025 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4026 enum tree_code code = PLUS_EXPR;
4027 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4028 code = POINTER_PLUS_EXPR;
4029 g = gimple_build_assign (iv, code, iv, t);
4030 gsi_insert_before_without_update (&gsi, g,
4031 GSI_SAME_STMT);
4032 break;
4034 x = lang_hooks.decls.omp_clause_copy_ctor
4035 (c, unshare_expr (ivar), x);
4036 gimplify_and_add (x, &llist[0]);
4037 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4038 if (x)
4040 gimple_seq tseq = NULL;
4042 dtor = x;
4043 gimplify_stmt (&dtor, &tseq);
4044 gimple_seq_add_seq (&llist[1], tseq);
4046 break;
4049 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4050 gimplify_and_add (x, ilist);
4051 goto do_dtor;
4053 case OMP_CLAUSE__LOOPTEMP_:
4054 gcc_assert (is_parallel_ctx (ctx));
4055 x = build_outer_var_ref (var, ctx);
4056 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4057 gimplify_and_add (x, ilist);
4058 break;
4060 case OMP_CLAUSE_COPYIN:
4061 by_ref = use_pointer_for_field (var, NULL);
4062 x = build_receiver_ref (var, by_ref, ctx);
4063 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4064 append_to_statement_list (x, &copyin_seq);
4065 copyin_by_ref |= by_ref;
4066 break;
4068 case OMP_CLAUSE_REDUCTION:
4069 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4071 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4072 gimple tseq;
4073 x = build_outer_var_ref (var, ctx);
4075 if (is_reference (var)
4076 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4077 TREE_TYPE (x)))
4078 x = build_fold_addr_expr_loc (clause_loc, x);
4079 SET_DECL_VALUE_EXPR (placeholder, x);
4080 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4081 tree new_vard = new_var;
4082 if (is_reference (var))
4084 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4085 new_vard = TREE_OPERAND (new_var, 0);
4086 gcc_assert (DECL_P (new_vard));
4088 if (is_simd
4089 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4090 idx, lane, ivar, lvar))
4092 if (new_vard == new_var)
4094 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4095 SET_DECL_VALUE_EXPR (new_var, ivar);
4097 else
4099 SET_DECL_VALUE_EXPR (new_vard,
4100 build_fold_addr_expr (ivar));
4101 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4103 x = lang_hooks.decls.omp_clause_default_ctor
4104 (c, unshare_expr (ivar),
4105 build_outer_var_ref (var, ctx));
4106 if (x)
4107 gimplify_and_add (x, &llist[0]);
4108 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4110 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4111 lower_omp (&tseq, ctx);
4112 gimple_seq_add_seq (&llist[0], tseq);
4114 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4115 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4116 lower_omp (&tseq, ctx);
4117 gimple_seq_add_seq (&llist[1], tseq);
4118 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4119 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4120 if (new_vard == new_var)
4121 SET_DECL_VALUE_EXPR (new_var, lvar);
4122 else
4123 SET_DECL_VALUE_EXPR (new_vard,
4124 build_fold_addr_expr (lvar));
4125 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4126 if (x)
4128 tseq = NULL;
4129 dtor = x;
4130 gimplify_stmt (&dtor, &tseq);
4131 gimple_seq_add_seq (&llist[1], tseq);
4133 break;
4135 /* If this is a reference to constant size reduction var
4136 with placeholder, we haven't emitted the initializer
4137 for it because it is undesirable if SIMD arrays are used.
4138 But if they aren't used, we need to emit the deferred
4139 initialization now. */
4140 else if (is_reference (var) && is_simd)
4141 handle_simd_reference (clause_loc, new_vard, ilist);
4142 x = lang_hooks.decls.omp_clause_default_ctor
4143 (c, unshare_expr (new_var),
4144 build_outer_var_ref (var, ctx));
4145 if (x)
4146 gimplify_and_add (x, ilist);
4147 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4149 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4150 lower_omp (&tseq, ctx);
4151 gimple_seq_add_seq (ilist, tseq);
4153 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4154 if (is_simd)
4156 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4157 lower_omp (&tseq, ctx);
4158 gimple_seq_add_seq (dlist, tseq);
4159 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4161 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4162 goto do_dtor;
4164 else
4166 x = omp_reduction_init (c, TREE_TYPE (new_var));
4167 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4168 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4170 /* reduction(-:var) sums up the partial results, so it
4171 acts identically to reduction(+:var). */
4172 if (code == MINUS_EXPR)
4173 code = PLUS_EXPR;
4175 tree new_vard = new_var;
4176 if (is_simd && is_reference (var))
4178 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4179 new_vard = TREE_OPERAND (new_var, 0);
4180 gcc_assert (DECL_P (new_vard));
4182 if (is_simd
4183 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4184 idx, lane, ivar, lvar))
4186 tree ref = build_outer_var_ref (var, ctx);
4188 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4190 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4191 ref = build_outer_var_ref (var, ctx);
4192 gimplify_assign (ref, x, &llist[1]);
4194 if (new_vard != new_var)
4196 SET_DECL_VALUE_EXPR (new_vard,
4197 build_fold_addr_expr (lvar));
4198 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4201 else
4203 if (is_reference (var) && is_simd)
4204 handle_simd_reference (clause_loc, new_vard, ilist);
4205 gimplify_assign (new_var, x, ilist);
4206 if (is_simd)
4208 tree ref = build_outer_var_ref (var, ctx);
4210 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4211 ref = build_outer_var_ref (var, ctx);
4212 gimplify_assign (ref, x, dlist);
4216 break;
4218 default:
4219 gcc_unreachable ();
4224 if (lane)
4226 tree uid = create_tmp_var (ptr_type_node, "simduid");
4227 /* Don't want uninit warnings on simduid, it is always uninitialized,
4228 but we use it not for the value, but for the DECL_UID only. */
4229 TREE_NO_WARNING (uid) = 1;
4230 gimple g
4231 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4232 gimple_call_set_lhs (g, lane);
4233 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4234 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4235 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4236 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4237 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4238 gimple_omp_for_set_clauses (ctx->stmt, c);
4239 g = gimple_build_assign (lane, INTEGER_CST,
4240 build_int_cst (unsigned_type_node, 0));
4241 gimple_seq_add_stmt (ilist, g);
4242 for (int i = 0; i < 2; i++)
4243 if (llist[i])
4245 tree vf = create_tmp_var (unsigned_type_node);
4246 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4247 gimple_call_set_lhs (g, vf);
4248 gimple_seq *seq = i == 0 ? ilist : dlist;
4249 gimple_seq_add_stmt (seq, g);
4250 tree t = build_int_cst (unsigned_type_node, 0);
4251 g = gimple_build_assign (idx, INTEGER_CST, t);
4252 gimple_seq_add_stmt (seq, g);
4253 tree body = create_artificial_label (UNKNOWN_LOCATION);
4254 tree header = create_artificial_label (UNKNOWN_LOCATION);
4255 tree end = create_artificial_label (UNKNOWN_LOCATION);
4256 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4257 gimple_seq_add_stmt (seq, gimple_build_label (body));
4258 gimple_seq_add_seq (seq, llist[i]);
4259 t = build_int_cst (unsigned_type_node, 1);
4260 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4261 gimple_seq_add_stmt (seq, g);
4262 gimple_seq_add_stmt (seq, gimple_build_label (header));
4263 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4264 gimple_seq_add_stmt (seq, g);
4265 gimple_seq_add_stmt (seq, gimple_build_label (end));
4269 /* The copyin sequence is not to be executed by the main thread, since
4270 that would result in self-copies. Perhaps not visible to scalars,
4271 but it certainly is to C++ operator=. */
4272 if (copyin_seq)
4274 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4276 x = build2 (NE_EXPR, boolean_type_node, x,
4277 build_int_cst (TREE_TYPE (x), 0));
4278 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4279 gimplify_and_add (x, ilist);
4282 /* If any copyin variable is passed by reference, we must ensure the
4283 master thread doesn't modify it before it is copied over in all
4284 threads. Similarly for variables in both firstprivate and
4285 lastprivate clauses we need to ensure the lastprivate copying
4286 happens after firstprivate copying in all threads. And similarly
4287 for UDRs if initializer expression refers to omp_orig. */
4288 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4290 /* Don't add any barrier for #pragma omp simd or
4291 #pragma omp distribute. */
4292 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4293 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4294 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4297 /* If max_vf is non-zero, then we can use only a vectorization factor
4298 up to the max_vf we chose. So stick it into the safelen clause. */
4299 if (max_vf)
4301 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4302 OMP_CLAUSE_SAFELEN);
4303 if (c == NULL_TREE
4304 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4305 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4306 max_vf) == 1))
4308 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4309 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4310 max_vf);
4311 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4312 gimple_omp_for_set_clauses (ctx->stmt, c);
4318 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4319 both parallel and workshare constructs. PREDICATE may be NULL if it's
4320 always true. */
4322 static void
4323 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4324 omp_context *ctx)
4326 tree x, c, label = NULL, orig_clauses = clauses;
4327 bool par_clauses = false;
4328 tree simduid = NULL, lastlane = NULL;
4330 /* Early exit if there are no lastprivate or linear clauses. */
4331 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4332 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4333 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4334 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4335 break;
4336 if (clauses == NULL)
4338 /* If this was a workshare clause, see if it had been combined
4339 with its parallel. In that case, look for the clauses on the
4340 parallel statement itself. */
4341 if (is_parallel_ctx (ctx))
4342 return;
4344 ctx = ctx->outer;
4345 if (ctx == NULL || !is_parallel_ctx (ctx))
4346 return;
4348 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4349 OMP_CLAUSE_LASTPRIVATE);
4350 if (clauses == NULL)
4351 return;
4352 par_clauses = true;
4355 if (predicate)
4357 gcond *stmt;
4358 tree label_true, arm1, arm2;
4360 label = create_artificial_label (UNKNOWN_LOCATION);
4361 label_true = create_artificial_label (UNKNOWN_LOCATION);
4362 arm1 = TREE_OPERAND (predicate, 0);
4363 arm2 = TREE_OPERAND (predicate, 1);
4364 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4365 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4366 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4367 label_true, label);
4368 gimple_seq_add_stmt (stmt_list, stmt);
4369 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4372 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4373 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4375 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4376 if (simduid)
4377 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4380 for (c = clauses; c ;)
4382 tree var, new_var;
4383 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4385 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4386 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4387 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4389 var = OMP_CLAUSE_DECL (c);
4390 new_var = lookup_decl (var, ctx);
4392 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4394 tree val = DECL_VALUE_EXPR (new_var);
4395 if (TREE_CODE (val) == ARRAY_REF
4396 && VAR_P (TREE_OPERAND (val, 0))
4397 && lookup_attribute ("omp simd array",
4398 DECL_ATTRIBUTES (TREE_OPERAND (val,
4399 0))))
4401 if (lastlane == NULL)
4403 lastlane = create_tmp_var (unsigned_type_node);
4404 gcall *g
4405 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4406 2, simduid,
4407 TREE_OPERAND (val, 1));
4408 gimple_call_set_lhs (g, lastlane);
4409 gimple_seq_add_stmt (stmt_list, g);
4411 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4412 TREE_OPERAND (val, 0), lastlane,
4413 NULL_TREE, NULL_TREE);
4417 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4418 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4420 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4421 gimple_seq_add_seq (stmt_list,
4422 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4423 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4425 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4426 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4428 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4429 gimple_seq_add_seq (stmt_list,
4430 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4431 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4434 x = build_outer_var_ref (var, ctx);
4435 if (is_reference (var))
4436 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4437 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4438 gimplify_and_add (x, stmt_list);
4440 c = OMP_CLAUSE_CHAIN (c);
4441 if (c == NULL && !par_clauses)
4443 /* If this was a workshare clause, see if it had been combined
4444 with its parallel. In that case, continue looking for the
4445 clauses also on the parallel statement itself. */
4446 if (is_parallel_ctx (ctx))
4447 break;
4449 ctx = ctx->outer;
4450 if (ctx == NULL || !is_parallel_ctx (ctx))
4451 break;
4453 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4454 OMP_CLAUSE_LASTPRIVATE);
4455 par_clauses = true;
4459 if (label)
4460 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4463 static void
4464 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4465 tree tid, tree var, tree new_var)
4467 /* The atomic add at the end of the sum creates unnecessary
4468 write contention on accelerators. To work around this,
4469 create an array to store the partial reductions. Later, in
4470 lower_omp_for (for openacc), the values of array will be
4471 combined. */
4473 tree t = NULL_TREE, array, x;
4474 tree type = get_base_type (var);
4475 gimple stmt;
4477 /* Now insert the partial reductions into the array. */
4479 /* Find the reduction array. */
4481 tree ptype = build_pointer_type (type);
4483 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4484 t = build_receiver_ref (t, false, ctx->outer);
4486 array = create_tmp_var (ptype);
4487 gimplify_assign (array, t, stmt_seqp);
4489 tree ptr = create_tmp_var (TREE_TYPE (array));
4491 /* Find the reduction array. */
4493 /* testing a unary conversion. */
4494 tree offset = create_tmp_var (sizetype);
4495 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4496 stmt_seqp);
4497 t = create_tmp_var (sizetype);
4498 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4499 stmt_seqp);
4500 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4501 gimple_seq_add_stmt (stmt_seqp, stmt);
4503 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4504 of adding sizeof(var) to the array? */
4505 ptr = create_tmp_var (ptype);
4506 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4507 offset);
4508 gimple_seq_add_stmt (stmt_seqp, stmt);
4510 /* Move the local sum to gfc$sum[i]. */
4511 x = unshare_expr (build_simple_mem_ref (ptr));
4512 stmt = gimplify_assign (x, new_var, stmt_seqp);
4515 /* Generate code to implement the REDUCTION clauses. */
4517 static void
4518 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4520 gimple_seq sub_seq = NULL;
4521 gimple stmt;
4522 tree x, c, tid = NULL_TREE;
4523 int count = 0;
4525 /* SIMD reductions are handled in lower_rec_input_clauses. */
4526 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4527 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4528 return;
4530 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4531 update in that case, otherwise use a lock. */
4532 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4533 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4535 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4537 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4538 count = -1;
4539 break;
4541 count++;
4544 if (count == 0)
4545 return;
4547 /* Initialize thread info for OpenACC. */
4548 if (is_gimple_omp_oacc (ctx->stmt))
4550 /* Get the current thread id. */
4551 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4552 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4553 gimple stmt = gimple_build_call (call, 0);
4554 gimple_call_set_lhs (stmt, tid);
4555 gimple_seq_add_stmt (stmt_seqp, stmt);
4558 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4560 tree var, ref, new_var;
4561 enum tree_code code;
4562 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4564 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4565 continue;
4567 var = OMP_CLAUSE_DECL (c);
4568 new_var = lookup_decl (var, ctx);
4569 if (is_reference (var))
4570 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4571 ref = build_outer_var_ref (var, ctx);
4572 code = OMP_CLAUSE_REDUCTION_CODE (c);
4574 /* reduction(-:var) sums up the partial results, so it acts
4575 identically to reduction(+:var). */
4576 if (code == MINUS_EXPR)
4577 code = PLUS_EXPR;
4579 if (is_gimple_omp_oacc (ctx->stmt))
4581 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4583 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4585 else if (count == 1)
4587 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4589 addr = save_expr (addr);
4590 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4591 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4592 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4593 gimplify_and_add (x, stmt_seqp);
4594 return;
4596 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4598 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4600 if (is_reference (var)
4601 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4602 TREE_TYPE (ref)))
4603 ref = build_fold_addr_expr_loc (clause_loc, ref);
4604 SET_DECL_VALUE_EXPR (placeholder, ref);
4605 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4606 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4607 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4608 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4609 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4611 else
4613 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4614 ref = build_outer_var_ref (var, ctx);
4615 gimplify_assign (ref, x, &sub_seq);
4619 if (is_gimple_omp_oacc (ctx->stmt))
4620 return;
4622 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4624 gimple_seq_add_stmt (stmt_seqp, stmt);
4626 gimple_seq_add_seq (stmt_seqp, sub_seq);
4628 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4630 gimple_seq_add_stmt (stmt_seqp, stmt);
4634 /* Generate code to implement the COPYPRIVATE clauses. */
4636 static void
4637 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4638 omp_context *ctx)
4640 tree c;
4642 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4644 tree var, new_var, ref, x;
4645 bool by_ref;
4646 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4648 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4649 continue;
4651 var = OMP_CLAUSE_DECL (c);
4652 by_ref = use_pointer_for_field (var, NULL);
4654 ref = build_sender_ref (var, ctx);
4655 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4656 if (by_ref)
4658 x = build_fold_addr_expr_loc (clause_loc, new_var);
4659 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4661 gimplify_assign (ref, x, slist);
4663 ref = build_receiver_ref (var, false, ctx);
4664 if (by_ref)
4666 ref = fold_convert_loc (clause_loc,
4667 build_pointer_type (TREE_TYPE (new_var)),
4668 ref);
4669 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4671 if (is_reference (var))
4673 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4674 ref = build_simple_mem_ref_loc (clause_loc, ref);
4675 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4677 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4678 gimplify_and_add (x, rlist);
4683 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4684 and REDUCTION from the sender (aka parent) side. */
4686 static void
4687 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4688 omp_context *ctx)
4690 tree c;
4692 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4694 tree val, ref, x, var;
4695 bool by_ref, do_in = false, do_out = false;
4696 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4698 switch (OMP_CLAUSE_CODE (c))
4700 case OMP_CLAUSE_PRIVATE:
4701 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4702 break;
4703 continue;
4704 case OMP_CLAUSE_FIRSTPRIVATE:
4705 case OMP_CLAUSE_COPYIN:
4706 case OMP_CLAUSE_LASTPRIVATE:
4707 case OMP_CLAUSE_REDUCTION:
4708 case OMP_CLAUSE__LOOPTEMP_:
4709 break;
4710 default:
4711 continue;
4714 val = OMP_CLAUSE_DECL (c);
4715 var = lookup_decl_in_outer_ctx (val, ctx);
4717 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4718 && is_global_var (var))
4719 continue;
4720 if (is_variable_sized (val))
4721 continue;
4722 by_ref = use_pointer_for_field (val, NULL);
4724 switch (OMP_CLAUSE_CODE (c))
4726 case OMP_CLAUSE_PRIVATE:
4727 case OMP_CLAUSE_FIRSTPRIVATE:
4728 case OMP_CLAUSE_COPYIN:
4729 case OMP_CLAUSE__LOOPTEMP_:
4730 do_in = true;
4731 break;
4733 case OMP_CLAUSE_LASTPRIVATE:
4734 if (by_ref || is_reference (val))
4736 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4737 continue;
4738 do_in = true;
4740 else
4742 do_out = true;
4743 if (lang_hooks.decls.omp_private_outer_ref (val))
4744 do_in = true;
4746 break;
4748 case OMP_CLAUSE_REDUCTION:
4749 do_in = true;
4750 do_out = !(by_ref || is_reference (val));
4751 break;
4753 default:
4754 gcc_unreachable ();
4757 if (do_in)
4759 ref = build_sender_ref (val, ctx);
4760 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4761 gimplify_assign (ref, x, ilist);
4762 if (is_task_ctx (ctx))
4763 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4766 if (do_out)
4768 ref = build_sender_ref (val, ctx);
4769 gimplify_assign (var, ref, olist);
4774 /* Generate code to implement SHARED from the sender (aka parent)
4775 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4776 list things that got automatically shared. */
4778 static void
4779 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4781 tree var, ovar, nvar, f, x, record_type;
4783 if (ctx->record_type == NULL)
4784 return;
4786 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4787 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4789 ovar = DECL_ABSTRACT_ORIGIN (f);
4790 nvar = maybe_lookup_decl (ovar, ctx);
4791 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4792 continue;
4794 /* If CTX is a nested parallel directive. Find the immediately
4795 enclosing parallel or workshare construct that contains a
4796 mapping for OVAR. */
4797 var = lookup_decl_in_outer_ctx (ovar, ctx);
4799 if (use_pointer_for_field (ovar, ctx))
4801 x = build_sender_ref (ovar, ctx);
4802 var = build_fold_addr_expr (var);
4803 gimplify_assign (x, var, ilist);
4805 else
4807 x = build_sender_ref (ovar, ctx);
4808 gimplify_assign (x, var, ilist);
4810 if (!TREE_READONLY (var)
4811 /* We don't need to receive a new reference to a result
4812 or parm decl. In fact we may not store to it as we will
4813 invalidate any pending RSO and generate wrong gimple
4814 during inlining. */
4815 && !((TREE_CODE (var) == RESULT_DECL
4816 || TREE_CODE (var) == PARM_DECL)
4817 && DECL_BY_REFERENCE (var)))
4819 x = build_sender_ref (ovar, ctx);
4820 gimplify_assign (var, x, olist);
4827 /* A convenience function to build an empty GIMPLE_COND with just the
4828 condition. */
4830 static gcond *
4831 gimple_build_cond_empty (tree cond)
4833 enum tree_code pred_code;
4834 tree lhs, rhs;
4836 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4837 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4841 /* Build the function calls to GOMP_parallel_start etc to actually
4842 generate the parallel operation. REGION is the parallel region
4843 being expanded. BB is the block where to insert the code. WS_ARGS
4844 will be set if this is a call to a combined parallel+workshare
4845 construct, it contains the list of additional arguments needed by
4846 the workshare construct. */
4848 static void
4849 expand_parallel_call (struct omp_region *region, basic_block bb,
4850 gomp_parallel *entry_stmt,
4851 vec<tree, va_gc> *ws_args)
4853 tree t, t1, t2, val, cond, c, clauses, flags;
4854 gimple_stmt_iterator gsi;
4855 gimple stmt;
4856 enum built_in_function start_ix;
4857 int start_ix2;
4858 location_t clause_loc;
4859 vec<tree, va_gc> *args;
4861 clauses = gimple_omp_parallel_clauses (entry_stmt);
4863 /* Determine what flavor of GOMP_parallel we will be
4864 emitting. */
4865 start_ix = BUILT_IN_GOMP_PARALLEL;
4866 if (is_combined_parallel (region))
4868 switch (region->inner->type)
4870 case GIMPLE_OMP_FOR:
4871 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4872 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4873 + (region->inner->sched_kind
4874 == OMP_CLAUSE_SCHEDULE_RUNTIME
4875 ? 3 : region->inner->sched_kind));
4876 start_ix = (enum built_in_function)start_ix2;
4877 break;
4878 case GIMPLE_OMP_SECTIONS:
4879 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4880 break;
4881 default:
4882 gcc_unreachable ();
4886 /* By default, the value of NUM_THREADS is zero (selected at run time)
4887 and there is no conditional. */
4888 cond = NULL_TREE;
4889 val = build_int_cst (unsigned_type_node, 0);
4890 flags = build_int_cst (unsigned_type_node, 0);
4892 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4893 if (c)
4894 cond = OMP_CLAUSE_IF_EXPR (c);
4896 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4897 if (c)
4899 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4900 clause_loc = OMP_CLAUSE_LOCATION (c);
4902 else
4903 clause_loc = gimple_location (entry_stmt);
4905 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4906 if (c)
4907 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4909 /* Ensure 'val' is of the correct type. */
4910 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4912 /* If we found the clause 'if (cond)', build either
4913 (cond != 0) or (cond ? val : 1u). */
4914 if (cond)
4916 cond = gimple_boolify (cond);
4918 if (integer_zerop (val))
4919 val = fold_build2_loc (clause_loc,
4920 EQ_EXPR, unsigned_type_node, cond,
4921 build_int_cst (TREE_TYPE (cond), 0));
4922 else
4924 basic_block cond_bb, then_bb, else_bb;
4925 edge e, e_then, e_else;
4926 tree tmp_then, tmp_else, tmp_join, tmp_var;
4928 tmp_var = create_tmp_var (TREE_TYPE (val));
4929 if (gimple_in_ssa_p (cfun))
4931 tmp_then = make_ssa_name (tmp_var);
4932 tmp_else = make_ssa_name (tmp_var);
4933 tmp_join = make_ssa_name (tmp_var);
4935 else
4937 tmp_then = tmp_var;
4938 tmp_else = tmp_var;
4939 tmp_join = tmp_var;
4942 e = split_block_after_labels (bb);
4943 cond_bb = e->src;
4944 bb = e->dest;
4945 remove_edge (e);
4947 then_bb = create_empty_bb (cond_bb);
4948 else_bb = create_empty_bb (then_bb);
4949 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4950 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4952 stmt = gimple_build_cond_empty (cond);
4953 gsi = gsi_start_bb (cond_bb);
4954 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4956 gsi = gsi_start_bb (then_bb);
4957 stmt = gimple_build_assign (tmp_then, val);
4958 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4960 gsi = gsi_start_bb (else_bb);
4961 stmt = gimple_build_assign
4962 (tmp_else, build_int_cst (unsigned_type_node, 1));
4963 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4965 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4966 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4967 add_bb_to_loop (then_bb, cond_bb->loop_father);
4968 add_bb_to_loop (else_bb, cond_bb->loop_father);
4969 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4970 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4972 if (gimple_in_ssa_p (cfun))
4974 gphi *phi = create_phi_node (tmp_join, bb);
4975 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4976 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4979 val = tmp_join;
4982 gsi = gsi_start_bb (bb);
4983 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4984 false, GSI_CONTINUE_LINKING);
4987 gsi = gsi_last_bb (bb);
4988 t = gimple_omp_parallel_data_arg (entry_stmt);
4989 if (t == NULL)
4990 t1 = null_pointer_node;
4991 else
4992 t1 = build_fold_addr_expr (t);
4993 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4995 vec_alloc (args, 4 + vec_safe_length (ws_args));
4996 args->quick_push (t2);
4997 args->quick_push (t1);
4998 args->quick_push (val);
4999 if (ws_args)
5000 args->splice (*ws_args);
5001 args->quick_push (flags);
5003 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
5004 builtin_decl_explicit (start_ix), args);
5006 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5007 false, GSI_CONTINUE_LINKING);
5010 /* Insert a function call whose name is FUNC_NAME with the information from
5011 ENTRY_STMT into the basic_block BB. */
5013 static void
5014 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
5015 vec <tree, va_gc> *ws_args)
5017 tree t, t1, t2;
5018 gimple_stmt_iterator gsi;
5019 vec <tree, va_gc> *args;
5021 gcc_assert (vec_safe_length (ws_args) == 2);
5022 tree func_name = (*ws_args)[0];
5023 tree grain = (*ws_args)[1];
5025 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5026 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5027 gcc_assert (count != NULL_TREE);
5028 count = OMP_CLAUSE_OPERAND (count, 0);
5030 gsi = gsi_last_bb (bb);
5031 t = gimple_omp_parallel_data_arg (entry_stmt);
5032 if (t == NULL)
5033 t1 = null_pointer_node;
5034 else
5035 t1 = build_fold_addr_expr (t);
5036 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5038 vec_alloc (args, 4);
5039 args->quick_push (t2);
5040 args->quick_push (t1);
5041 args->quick_push (count);
5042 args->quick_push (grain);
5043 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5045 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5046 GSI_CONTINUE_LINKING);
5049 /* Build the function call to GOMP_task to actually
5050 generate the task operation. BB is the block where to insert the code. */
5052 static void
5053 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5055 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5056 gimple_stmt_iterator gsi;
5057 location_t loc = gimple_location (entry_stmt);
5059 clauses = gimple_omp_task_clauses (entry_stmt);
5061 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5062 if (c)
5063 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5064 else
5065 cond = boolean_true_node;
5067 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5068 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5069 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5070 flags = build_int_cst (unsigned_type_node,
5071 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5073 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5074 if (c)
5076 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5077 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5078 build_int_cst (unsigned_type_node, 2),
5079 build_int_cst (unsigned_type_node, 0));
5080 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5082 if (depend)
5083 depend = OMP_CLAUSE_DECL (depend);
5084 else
5085 depend = build_int_cst (ptr_type_node, 0);
5087 gsi = gsi_last_bb (bb);
5088 t = gimple_omp_task_data_arg (entry_stmt);
5089 if (t == NULL)
5090 t2 = null_pointer_node;
5091 else
5092 t2 = build_fold_addr_expr_loc (loc, t);
5093 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5094 t = gimple_omp_task_copy_fn (entry_stmt);
5095 if (t == NULL)
5096 t3 = null_pointer_node;
5097 else
5098 t3 = build_fold_addr_expr_loc (loc, t);
5100 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5101 8, t1, t2, t3,
5102 gimple_omp_task_arg_size (entry_stmt),
5103 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5104 depend);
5106 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5107 false, GSI_CONTINUE_LINKING);
5111 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5112 catch handler and return it. This prevents programs from violating the
5113 structured block semantics with throws. */
5115 static gimple_seq
5116 maybe_catch_exception (gimple_seq body)
5118 gimple g;
5119 tree decl;
5121 if (!flag_exceptions)
5122 return body;
5124 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5125 decl = lang_hooks.eh_protect_cleanup_actions ();
5126 else
5127 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5129 g = gimple_build_eh_must_not_throw (decl);
5130 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5131 GIMPLE_TRY_CATCH);
5133 return gimple_seq_alloc_with_stmt (g);
5136 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5138 static tree
5139 vec2chain (vec<tree, va_gc> *v)
5141 tree chain = NULL_TREE, t;
5142 unsigned ix;
5144 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5146 DECL_CHAIN (t) = chain;
5147 chain = t;
5150 return chain;
5154 /* Remove barriers in REGION->EXIT's block. Note that this is only
5155 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5156 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5157 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5158 removed. */
5160 static void
5161 remove_exit_barrier (struct omp_region *region)
5163 gimple_stmt_iterator gsi;
5164 basic_block exit_bb;
5165 edge_iterator ei;
5166 edge e;
5167 gimple stmt;
5168 int any_addressable_vars = -1;
5170 exit_bb = region->exit;
5172 /* If the parallel region doesn't return, we don't have REGION->EXIT
5173 block at all. */
5174 if (! exit_bb)
5175 return;
5177 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5178 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5179 statements that can appear in between are extremely limited -- no
5180 memory operations at all. Here, we allow nothing at all, so the
5181 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5182 gsi = gsi_last_bb (exit_bb);
5183 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5184 gsi_prev (&gsi);
5185 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5186 return;
5188 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5190 gsi = gsi_last_bb (e->src);
5191 if (gsi_end_p (gsi))
5192 continue;
5193 stmt = gsi_stmt (gsi);
5194 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5195 && !gimple_omp_return_nowait_p (stmt))
5197 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5198 in many cases. If there could be tasks queued, the barrier
5199 might be needed to let the tasks run before some local
5200 variable of the parallel that the task uses as shared
5201 runs out of scope. The task can be spawned either
5202 from within current function (this would be easy to check)
5203 or from some function it calls and gets passed an address
5204 of such a variable. */
5205 if (any_addressable_vars < 0)
5207 gomp_parallel *parallel_stmt
5208 = as_a <gomp_parallel *> (last_stmt (region->entry));
5209 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5210 tree local_decls, block, decl;
5211 unsigned ix;
5213 any_addressable_vars = 0;
5214 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5215 if (TREE_ADDRESSABLE (decl))
5217 any_addressable_vars = 1;
5218 break;
5220 for (block = gimple_block (stmt);
5221 !any_addressable_vars
5222 && block
5223 && TREE_CODE (block) == BLOCK;
5224 block = BLOCK_SUPERCONTEXT (block))
5226 for (local_decls = BLOCK_VARS (block);
5227 local_decls;
5228 local_decls = DECL_CHAIN (local_decls))
5229 if (TREE_ADDRESSABLE (local_decls))
5231 any_addressable_vars = 1;
5232 break;
5234 if (block == gimple_block (parallel_stmt))
5235 break;
5238 if (!any_addressable_vars)
5239 gimple_omp_return_set_nowait (stmt);
5244 static void
5245 remove_exit_barriers (struct omp_region *region)
5247 if (region->type == GIMPLE_OMP_PARALLEL)
5248 remove_exit_barrier (region);
5250 if (region->inner)
5252 region = region->inner;
5253 remove_exit_barriers (region);
5254 while (region->next)
5256 region = region->next;
5257 remove_exit_barriers (region);
5262 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5263 calls. These can't be declared as const functions, but
5264 within one parallel body they are constant, so they can be
5265 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5266 which are declared const. Similarly for task body, except
5267 that in untied task omp_get_thread_num () can change at any task
5268 scheduling point. */
5270 static void
5271 optimize_omp_library_calls (gimple entry_stmt)
5273 basic_block bb;
5274 gimple_stmt_iterator gsi;
5275 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5276 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5277 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5278 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5279 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5280 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5281 OMP_CLAUSE_UNTIED) != NULL);
5283 FOR_EACH_BB_FN (bb, cfun)
5284 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5286 gimple call = gsi_stmt (gsi);
5287 tree decl;
5289 if (is_gimple_call (call)
5290 && (decl = gimple_call_fndecl (call))
5291 && DECL_EXTERNAL (decl)
5292 && TREE_PUBLIC (decl)
5293 && DECL_INITIAL (decl) == NULL)
5295 tree built_in;
5297 if (DECL_NAME (decl) == thr_num_id)
5299 /* In #pragma omp task untied omp_get_thread_num () can change
5300 during the execution of the task region. */
5301 if (untied_task)
5302 continue;
5303 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5305 else if (DECL_NAME (decl) == num_thr_id)
5306 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5307 else
5308 continue;
5310 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5311 || gimple_call_num_args (call) != 0)
5312 continue;
5314 if (flag_exceptions && !TREE_NOTHROW (decl))
5315 continue;
5317 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5318 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5319 TREE_TYPE (TREE_TYPE (built_in))))
5320 continue;
5322 gimple_call_set_fndecl (call, built_in);
5327 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5328 regimplified. */
5330 static tree
5331 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5333 tree t = *tp;
5335 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5336 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5337 return t;
5339 if (TREE_CODE (t) == ADDR_EXPR)
5340 recompute_tree_invariant_for_addr_expr (t);
5342 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5343 return NULL_TREE;
5346 /* Prepend TO = FROM assignment before *GSI_P. */
5348 static void
5349 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5351 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5352 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5353 true, GSI_SAME_STMT);
5354 gimple stmt = gimple_build_assign (to, from);
5355 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5356 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5357 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5359 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5360 gimple_regimplify_operands (stmt, &gsi);
5364 /* Expand the OpenMP parallel or task directive starting at REGION. */
5366 static void
5367 expand_omp_taskreg (struct omp_region *region)
5369 basic_block entry_bb, exit_bb, new_bb;
5370 struct function *child_cfun;
5371 tree child_fn, block, t;
5372 gimple_stmt_iterator gsi;
5373 gimple entry_stmt, stmt;
5374 edge e;
5375 vec<tree, va_gc> *ws_args;
5377 entry_stmt = last_stmt (region->entry);
5378 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5379 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5381 entry_bb = region->entry;
5382 exit_bb = region->exit;
5384 bool is_cilk_for
5385 = (flag_cilkplus
5386 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5387 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5388 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5390 if (is_cilk_for)
5391 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5392 and the inner statement contains the name of the built-in function
5393 and grain. */
5394 ws_args = region->inner->ws_args;
5395 else if (is_combined_parallel (region))
5396 ws_args = region->ws_args;
5397 else
5398 ws_args = NULL;
5400 if (child_cfun->cfg)
5402 /* Due to inlining, it may happen that we have already outlined
5403 the region, in which case all we need to do is make the
5404 sub-graph unreachable and emit the parallel call. */
5405 edge entry_succ_e, exit_succ_e;
5407 entry_succ_e = single_succ_edge (entry_bb);
5409 gsi = gsi_last_bb (entry_bb);
5410 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5411 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5412 gsi_remove (&gsi, true);
5414 new_bb = entry_bb;
5415 if (exit_bb)
5417 exit_succ_e = single_succ_edge (exit_bb);
5418 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5420 remove_edge_and_dominated_blocks (entry_succ_e);
5422 else
5424 unsigned srcidx, dstidx, num;
5426 /* If the parallel region needs data sent from the parent
5427 function, then the very first statement (except possible
5428 tree profile counter updates) of the parallel body
5429 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5430 &.OMP_DATA_O is passed as an argument to the child function,
5431 we need to replace it with the argument as seen by the child
5432 function.
5434 In most cases, this will end up being the identity assignment
5435 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5436 a function call that has been inlined, the original PARM_DECL
5437 .OMP_DATA_I may have been converted into a different local
5438 variable. In which case, we need to keep the assignment. */
5439 if (gimple_omp_taskreg_data_arg (entry_stmt))
5441 basic_block entry_succ_bb = single_succ (entry_bb);
5442 tree arg, narg;
5443 gimple parcopy_stmt = NULL;
5445 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5447 gimple stmt;
5449 gcc_assert (!gsi_end_p (gsi));
5450 stmt = gsi_stmt (gsi);
5451 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5452 continue;
5454 if (gimple_num_ops (stmt) == 2)
5456 tree arg = gimple_assign_rhs1 (stmt);
5458 /* We're ignore the subcode because we're
5459 effectively doing a STRIP_NOPS. */
5461 if (TREE_CODE (arg) == ADDR_EXPR
5462 && TREE_OPERAND (arg, 0)
5463 == gimple_omp_taskreg_data_arg (entry_stmt))
5465 parcopy_stmt = stmt;
5466 break;
5471 gcc_assert (parcopy_stmt != NULL);
5472 arg = DECL_ARGUMENTS (child_fn);
5474 if (!gimple_in_ssa_p (cfun))
5476 if (gimple_assign_lhs (parcopy_stmt) == arg)
5477 gsi_remove (&gsi, true);
5478 else
5480 /* ?? Is setting the subcode really necessary ?? */
5481 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5482 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5485 else
5487 /* If we are in ssa form, we must load the value from the default
5488 definition of the argument. That should not be defined now,
5489 since the argument is not used uninitialized. */
5490 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5491 narg = make_ssa_name (arg, gimple_build_nop ());
5492 set_ssa_default_def (cfun, arg, narg);
5493 /* ?? Is setting the subcode really necessary ?? */
5494 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5495 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5496 update_stmt (parcopy_stmt);
5500 /* Declare local variables needed in CHILD_CFUN. */
5501 block = DECL_INITIAL (child_fn);
5502 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5503 /* The gimplifier could record temporaries in parallel/task block
5504 rather than in containing function's local_decls chain,
5505 which would mean cgraph missed finalizing them. Do it now. */
5506 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5507 if (TREE_CODE (t) == VAR_DECL
5508 && TREE_STATIC (t)
5509 && !DECL_EXTERNAL (t))
5510 varpool_node::finalize_decl (t);
5511 DECL_SAVED_TREE (child_fn) = NULL;
5512 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5513 gimple_set_body (child_fn, NULL);
5514 TREE_USED (block) = 1;
5516 /* Reset DECL_CONTEXT on function arguments. */
5517 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5518 DECL_CONTEXT (t) = child_fn;
5520 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5521 so that it can be moved to the child function. */
5522 gsi = gsi_last_bb (entry_bb);
5523 stmt = gsi_stmt (gsi);
5524 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5525 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5526 e = split_block (entry_bb, stmt);
5527 gsi_remove (&gsi, true);
5528 entry_bb = e->dest;
5529 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5531 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5532 if (exit_bb)
5534 gsi = gsi_last_bb (exit_bb);
5535 gcc_assert (!gsi_end_p (gsi)
5536 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5537 stmt = gimple_build_return (NULL);
5538 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5539 gsi_remove (&gsi, true);
5542 /* Move the parallel region into CHILD_CFUN. */
5544 if (gimple_in_ssa_p (cfun))
5546 init_tree_ssa (child_cfun);
5547 init_ssa_operands (child_cfun);
5548 child_cfun->gimple_df->in_ssa_p = true;
5549 block = NULL_TREE;
5551 else
5552 block = gimple_block (entry_stmt);
5554 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5555 if (exit_bb)
5556 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5557 /* When the OMP expansion process cannot guarantee an up-to-date
5558 loop tree arrange for the child function to fixup loops. */
5559 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5560 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5562 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5563 num = vec_safe_length (child_cfun->local_decls);
5564 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5566 t = (*child_cfun->local_decls)[srcidx];
5567 if (DECL_CONTEXT (t) == cfun->decl)
5568 continue;
5569 if (srcidx != dstidx)
5570 (*child_cfun->local_decls)[dstidx] = t;
5571 dstidx++;
5573 if (dstidx != num)
5574 vec_safe_truncate (child_cfun->local_decls, dstidx);
5576 /* Inform the callgraph about the new function. */
5577 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5578 cgraph_node::add_new_function (child_fn, true);
5579 cgraph_node::get (child_fn)->parallelized_function = 1;
5581 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5582 fixed in a following pass. */
5583 push_cfun (child_cfun);
5584 if (optimize)
5585 optimize_omp_library_calls (entry_stmt);
5586 cgraph_edge::rebuild_edges ();
5588 /* Some EH regions might become dead, see PR34608. If
5589 pass_cleanup_cfg isn't the first pass to happen with the
5590 new child, these dead EH edges might cause problems.
5591 Clean them up now. */
5592 if (flag_exceptions)
5594 basic_block bb;
5595 bool changed = false;
5597 FOR_EACH_BB_FN (bb, cfun)
5598 changed |= gimple_purge_dead_eh_edges (bb);
5599 if (changed)
5600 cleanup_tree_cfg ();
5602 if (gimple_in_ssa_p (cfun))
5603 update_ssa (TODO_update_ssa);
5604 pop_cfun ();
5607 /* Emit a library call to launch the children threads. */
5608 if (is_cilk_for)
5609 expand_cilk_for_call (new_bb,
5610 as_a <gomp_parallel *> (entry_stmt), ws_args);
5611 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5612 expand_parallel_call (region, new_bb,
5613 as_a <gomp_parallel *> (entry_stmt), ws_args);
5614 else
5615 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5616 if (gimple_in_ssa_p (cfun))
5617 update_ssa (TODO_update_ssa_only_virtuals);
5621 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5622 of the combined collapse > 1 loop constructs, generate code like:
5623 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5624 if (cond3 is <)
5625 adj = STEP3 - 1;
5626 else
5627 adj = STEP3 + 1;
5628 count3 = (adj + N32 - N31) / STEP3;
5629 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5630 if (cond2 is <)
5631 adj = STEP2 - 1;
5632 else
5633 adj = STEP2 + 1;
5634 count2 = (adj + N22 - N21) / STEP2;
5635 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5636 if (cond1 is <)
5637 adj = STEP1 - 1;
5638 else
5639 adj = STEP1 + 1;
5640 count1 = (adj + N12 - N11) / STEP1;
5641 count = count1 * count2 * count3;
5642 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5643 count = 0;
5644 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5645 of the combined loop constructs, just initialize COUNTS array
5646 from the _looptemp_ clauses. */
5648 /* NOTE: It *could* be better to moosh all of the BBs together,
5649 creating one larger BB with all the computation and the unexpected
5650 jump at the end. I.e.
5652 bool zero3, zero2, zero1, zero;
5654 zero3 = N32 c3 N31;
5655 count3 = (N32 - N31) /[cl] STEP3;
5656 zero2 = N22 c2 N21;
5657 count2 = (N22 - N21) /[cl] STEP2;
5658 zero1 = N12 c1 N11;
5659 count1 = (N12 - N11) /[cl] STEP1;
5660 zero = zero3 || zero2 || zero1;
5661 count = count1 * count2 * count3;
5662 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5664 After all, we expect the zero=false, and thus we expect to have to
5665 evaluate all of the comparison expressions, so short-circuiting
5666 oughtn't be a win. Since the condition isn't protecting a
5667 denominator, we're not concerned about divide-by-zero, so we can
5668 fully evaluate count even if a numerator turned out to be wrong.
5670 It seems like putting this all together would create much better
5671 scheduling opportunities, and less pressure on the chip's branch
5672 predictor. */
5674 static void
5675 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5676 basic_block &entry_bb, tree *counts,
5677 basic_block &zero_iter_bb, int &first_zero_iter,
5678 basic_block &l2_dom_bb)
5680 tree t, type = TREE_TYPE (fd->loop.v);
5681 edge e, ne;
5682 int i;
5684 /* Collapsed loops need work for expansion into SSA form. */
5685 gcc_assert (!gimple_in_ssa_p (cfun));
5687 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5688 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5690 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5691 isn't supposed to be handled, as the inner loop doesn't
5692 use it. */
5693 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5694 OMP_CLAUSE__LOOPTEMP_);
5695 gcc_assert (innerc);
5696 for (i = 0; i < fd->collapse; i++)
5698 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5699 OMP_CLAUSE__LOOPTEMP_);
5700 gcc_assert (innerc);
5701 if (i)
5702 counts[i] = OMP_CLAUSE_DECL (innerc);
5703 else
5704 counts[0] = NULL_TREE;
5706 return;
5709 for (i = 0; i < fd->collapse; i++)
5711 tree itype = TREE_TYPE (fd->loops[i].v);
5713 if (SSA_VAR_P (fd->loop.n2)
5714 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5715 fold_convert (itype, fd->loops[i].n1),
5716 fold_convert (itype, fd->loops[i].n2)))
5717 == NULL_TREE || !integer_onep (t)))
5719 gcond *cond_stmt;
5720 tree n1, n2;
5721 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5722 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5723 true, GSI_SAME_STMT);
5724 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5725 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5726 true, GSI_SAME_STMT);
5727 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5728 NULL_TREE, NULL_TREE);
5729 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5730 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5731 expand_omp_regimplify_p, NULL, NULL)
5732 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5733 expand_omp_regimplify_p, NULL, NULL))
5735 *gsi = gsi_for_stmt (cond_stmt);
5736 gimple_regimplify_operands (cond_stmt, gsi);
5738 e = split_block (entry_bb, cond_stmt);
5739 if (zero_iter_bb == NULL)
5741 gassign *assign_stmt;
5742 first_zero_iter = i;
5743 zero_iter_bb = create_empty_bb (entry_bb);
5744 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5745 *gsi = gsi_after_labels (zero_iter_bb);
5746 assign_stmt = gimple_build_assign (fd->loop.n2,
5747 build_zero_cst (type));
5748 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5749 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5750 entry_bb);
5752 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5753 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5754 e->flags = EDGE_TRUE_VALUE;
5755 e->probability = REG_BR_PROB_BASE - ne->probability;
5756 if (l2_dom_bb == NULL)
5757 l2_dom_bb = entry_bb;
5758 entry_bb = e->dest;
5759 *gsi = gsi_last_bb (entry_bb);
5762 if (POINTER_TYPE_P (itype))
5763 itype = signed_type_for (itype);
5764 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5765 ? -1 : 1));
5766 t = fold_build2 (PLUS_EXPR, itype,
5767 fold_convert (itype, fd->loops[i].step), t);
5768 t = fold_build2 (PLUS_EXPR, itype, t,
5769 fold_convert (itype, fd->loops[i].n2));
5770 t = fold_build2 (MINUS_EXPR, itype, t,
5771 fold_convert (itype, fd->loops[i].n1));
5772 /* ?? We could probably use CEIL_DIV_EXPR instead of
5773 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5774 generate the same code in the end because generically we
5775 don't know that the values involved must be negative for
5776 GT?? */
5777 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5778 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5779 fold_build1 (NEGATE_EXPR, itype, t),
5780 fold_build1 (NEGATE_EXPR, itype,
5781 fold_convert (itype,
5782 fd->loops[i].step)));
5783 else
5784 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5785 fold_convert (itype, fd->loops[i].step));
5786 t = fold_convert (type, t);
5787 if (TREE_CODE (t) == INTEGER_CST)
5788 counts[i] = t;
5789 else
5791 counts[i] = create_tmp_reg (type, ".count");
5792 expand_omp_build_assign (gsi, counts[i], t);
5794 if (SSA_VAR_P (fd->loop.n2))
5796 if (i == 0)
5797 t = counts[0];
5798 else
5799 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5800 expand_omp_build_assign (gsi, fd->loop.n2, t);
5806 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5807 T = V;
5808 V3 = N31 + (T % count3) * STEP3;
5809 T = T / count3;
5810 V2 = N21 + (T % count2) * STEP2;
5811 T = T / count2;
5812 V1 = N11 + T * STEP1;
5813 if this loop doesn't have an inner loop construct combined with it.
5814 If it does have an inner loop construct combined with it and the
5815 iteration count isn't known constant, store values from counts array
5816 into its _looptemp_ temporaries instead. */
5818 static void
5819 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5820 tree *counts, gimple inner_stmt, tree startvar)
5822 int i;
5823 if (gimple_omp_for_combined_p (fd->for_stmt))
5825 /* If fd->loop.n2 is constant, then no propagation of the counts
5826 is needed, they are constant. */
5827 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5828 return;
5830 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5831 ? gimple_omp_parallel_clauses (inner_stmt)
5832 : gimple_omp_for_clauses (inner_stmt);
5833 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5834 isn't supposed to be handled, as the inner loop doesn't
5835 use it. */
5836 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5837 gcc_assert (innerc);
5838 for (i = 0; i < fd->collapse; i++)
5840 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5841 OMP_CLAUSE__LOOPTEMP_);
5842 gcc_assert (innerc);
5843 if (i)
5845 tree tem = OMP_CLAUSE_DECL (innerc);
5846 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5847 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5848 false, GSI_CONTINUE_LINKING);
5849 gassign *stmt = gimple_build_assign (tem, t);
5850 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5853 return;
5856 tree type = TREE_TYPE (fd->loop.v);
5857 tree tem = create_tmp_reg (type, ".tem");
5858 gassign *stmt = gimple_build_assign (tem, startvar);
5859 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5861 for (i = fd->collapse - 1; i >= 0; i--)
5863 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5864 itype = vtype;
5865 if (POINTER_TYPE_P (vtype))
5866 itype = signed_type_for (vtype);
5867 if (i != 0)
5868 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5869 else
5870 t = tem;
5871 t = fold_convert (itype, t);
5872 t = fold_build2 (MULT_EXPR, itype, t,
5873 fold_convert (itype, fd->loops[i].step));
5874 if (POINTER_TYPE_P (vtype))
5875 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5876 else
5877 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5878 t = force_gimple_operand_gsi (gsi, t,
5879 DECL_P (fd->loops[i].v)
5880 && TREE_ADDRESSABLE (fd->loops[i].v),
5881 NULL_TREE, false,
5882 GSI_CONTINUE_LINKING);
5883 stmt = gimple_build_assign (fd->loops[i].v, t);
5884 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5885 if (i != 0)
5887 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5888 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5889 false, GSI_CONTINUE_LINKING);
5890 stmt = gimple_build_assign (tem, t);
5891 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5897 /* Helper function for expand_omp_for_*. Generate code like:
5898 L10:
5899 V3 += STEP3;
5900 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5901 L11:
5902 V3 = N31;
5903 V2 += STEP2;
5904 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5905 L12:
5906 V2 = N21;
5907 V1 += STEP1;
5908 goto BODY_BB; */
5910 static basic_block
5911 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5912 basic_block body_bb)
5914 basic_block last_bb, bb, collapse_bb = NULL;
5915 int i;
5916 gimple_stmt_iterator gsi;
5917 edge e;
5918 tree t;
5919 gimple stmt;
5921 last_bb = cont_bb;
5922 for (i = fd->collapse - 1; i >= 0; i--)
5924 tree vtype = TREE_TYPE (fd->loops[i].v);
5926 bb = create_empty_bb (last_bb);
5927 add_bb_to_loop (bb, last_bb->loop_father);
5928 gsi = gsi_start_bb (bb);
5930 if (i < fd->collapse - 1)
5932 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5933 e->probability = REG_BR_PROB_BASE / 8;
5935 t = fd->loops[i + 1].n1;
5936 t = force_gimple_operand_gsi (&gsi, t,
5937 DECL_P (fd->loops[i + 1].v)
5938 && TREE_ADDRESSABLE (fd->loops[i
5939 + 1].v),
5940 NULL_TREE, false,
5941 GSI_CONTINUE_LINKING);
5942 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5943 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5945 else
5946 collapse_bb = bb;
5948 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5950 if (POINTER_TYPE_P (vtype))
5951 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5952 else
5953 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5954 t = force_gimple_operand_gsi (&gsi, t,
5955 DECL_P (fd->loops[i].v)
5956 && TREE_ADDRESSABLE (fd->loops[i].v),
5957 NULL_TREE, false, GSI_CONTINUE_LINKING);
5958 stmt = gimple_build_assign (fd->loops[i].v, t);
5959 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5961 if (i > 0)
5963 t = fd->loops[i].n2;
5964 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5965 false, GSI_CONTINUE_LINKING);
5966 tree v = fd->loops[i].v;
5967 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5968 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5969 false, GSI_CONTINUE_LINKING);
5970 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5971 stmt = gimple_build_cond_empty (t);
5972 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5973 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5974 e->probability = REG_BR_PROB_BASE * 7 / 8;
5976 else
5977 make_edge (bb, body_bb, EDGE_FALLTHRU);
5978 last_bb = bb;
5981 return collapse_bb;
5985 /* A subroutine of expand_omp_for. Generate code for a parallel
5986 loop with any schedule. Given parameters:
5988 for (V = N1; V cond N2; V += STEP) BODY;
5990 where COND is "<" or ">", we generate pseudocode
5992 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5993 if (more) goto L0; else goto L3;
5995 V = istart0;
5996 iend = iend0;
5998 BODY;
5999 V += STEP;
6000 if (V cond iend) goto L1; else goto L2;
6002 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6005 If this is a combined omp parallel loop, instead of the call to
6006 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6007 If this is gimple_omp_for_combined_p loop, then instead of assigning
6008 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6009 inner GIMPLE_OMP_FOR and V += STEP; and
6010 if (V cond iend) goto L1; else goto L2; are removed.
6012 For collapsed loops, given parameters:
6013 collapse(3)
6014 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6015 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6016 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6017 BODY;
6019 we generate pseudocode
6021 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6022 if (cond3 is <)
6023 adj = STEP3 - 1;
6024 else
6025 adj = STEP3 + 1;
6026 count3 = (adj + N32 - N31) / STEP3;
6027 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6028 if (cond2 is <)
6029 adj = STEP2 - 1;
6030 else
6031 adj = STEP2 + 1;
6032 count2 = (adj + N22 - N21) / STEP2;
6033 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6034 if (cond1 is <)
6035 adj = STEP1 - 1;
6036 else
6037 adj = STEP1 + 1;
6038 count1 = (adj + N12 - N11) / STEP1;
6039 count = count1 * count2 * count3;
6040 goto Z1;
6042 count = 0;
6044 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6045 if (more) goto L0; else goto L3;
6047 V = istart0;
6048 T = V;
6049 V3 = N31 + (T % count3) * STEP3;
6050 T = T / count3;
6051 V2 = N21 + (T % count2) * STEP2;
6052 T = T / count2;
6053 V1 = N11 + T * STEP1;
6054 iend = iend0;
6056 BODY;
6057 V += 1;
6058 if (V < iend) goto L10; else goto L2;
6059 L10:
6060 V3 += STEP3;
6061 if (V3 cond3 N32) goto L1; else goto L11;
6062 L11:
6063 V3 = N31;
6064 V2 += STEP2;
6065 if (V2 cond2 N22) goto L1; else goto L12;
6066 L12:
6067 V2 = N21;
6068 V1 += STEP1;
6069 goto L1;
6071 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6076 static void
6077 expand_omp_for_generic (struct omp_region *region,
6078 struct omp_for_data *fd,
6079 enum built_in_function start_fn,
6080 enum built_in_function next_fn,
6081 gimple inner_stmt)
6083 tree type, istart0, iend0, iend;
6084 tree t, vmain, vback, bias = NULL_TREE;
6085 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6086 basic_block l2_bb = NULL, l3_bb = NULL;
6087 gimple_stmt_iterator gsi;
6088 gassign *assign_stmt;
6089 bool in_combined_parallel = is_combined_parallel (region);
6090 bool broken_loop = region->cont == NULL;
6091 edge e, ne;
6092 tree *counts = NULL;
6093 int i;
6095 gcc_assert (!broken_loop || !in_combined_parallel);
6096 gcc_assert (fd->iter_type == long_integer_type_node
6097 || !in_combined_parallel);
6099 type = TREE_TYPE (fd->loop.v);
6100 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6101 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6102 TREE_ADDRESSABLE (istart0) = 1;
6103 TREE_ADDRESSABLE (iend0) = 1;
6105 /* See if we need to bias by LLONG_MIN. */
6106 if (fd->iter_type == long_long_unsigned_type_node
6107 && TREE_CODE (type) == INTEGER_TYPE
6108 && !TYPE_UNSIGNED (type))
6110 tree n1, n2;
6112 if (fd->loop.cond_code == LT_EXPR)
6114 n1 = fd->loop.n1;
6115 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6117 else
6119 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6120 n2 = fd->loop.n1;
6122 if (TREE_CODE (n1) != INTEGER_CST
6123 || TREE_CODE (n2) != INTEGER_CST
6124 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6125 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6128 entry_bb = region->entry;
6129 cont_bb = region->cont;
6130 collapse_bb = NULL;
6131 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6132 gcc_assert (broken_loop
6133 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6134 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6135 l1_bb = single_succ (l0_bb);
6136 if (!broken_loop)
6138 l2_bb = create_empty_bb (cont_bb);
6139 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6140 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6142 else
6143 l2_bb = NULL;
6144 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6145 exit_bb = region->exit;
6147 gsi = gsi_last_bb (entry_bb);
6149 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6150 if (fd->collapse > 1)
6152 int first_zero_iter = -1;
6153 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6155 counts = XALLOCAVEC (tree, fd->collapse);
6156 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6157 zero_iter_bb, first_zero_iter,
6158 l2_dom_bb);
6160 if (zero_iter_bb)
6162 /* Some counts[i] vars might be uninitialized if
6163 some loop has zero iterations. But the body shouldn't
6164 be executed in that case, so just avoid uninit warnings. */
6165 for (i = first_zero_iter; i < fd->collapse; i++)
6166 if (SSA_VAR_P (counts[i]))
6167 TREE_NO_WARNING (counts[i]) = 1;
6168 gsi_prev (&gsi);
6169 e = split_block (entry_bb, gsi_stmt (gsi));
6170 entry_bb = e->dest;
6171 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6172 gsi = gsi_last_bb (entry_bb);
6173 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6174 get_immediate_dominator (CDI_DOMINATORS,
6175 zero_iter_bb));
6178 if (in_combined_parallel)
6180 /* In a combined parallel loop, emit a call to
6181 GOMP_loop_foo_next. */
6182 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6183 build_fold_addr_expr (istart0),
6184 build_fold_addr_expr (iend0));
6186 else
6188 tree t0, t1, t2, t3, t4;
6189 /* If this is not a combined parallel loop, emit a call to
6190 GOMP_loop_foo_start in ENTRY_BB. */
6191 t4 = build_fold_addr_expr (iend0);
6192 t3 = build_fold_addr_expr (istart0);
6193 t2 = fold_convert (fd->iter_type, fd->loop.step);
6194 t1 = fd->loop.n2;
6195 t0 = fd->loop.n1;
6196 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6198 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6199 OMP_CLAUSE__LOOPTEMP_);
6200 gcc_assert (innerc);
6201 t0 = OMP_CLAUSE_DECL (innerc);
6202 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6203 OMP_CLAUSE__LOOPTEMP_);
6204 gcc_assert (innerc);
6205 t1 = OMP_CLAUSE_DECL (innerc);
6207 if (POINTER_TYPE_P (TREE_TYPE (t0))
6208 && TYPE_PRECISION (TREE_TYPE (t0))
6209 != TYPE_PRECISION (fd->iter_type))
6211 /* Avoid casting pointers to integer of a different size. */
6212 tree itype = signed_type_for (type);
6213 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6214 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6216 else
6218 t1 = fold_convert (fd->iter_type, t1);
6219 t0 = fold_convert (fd->iter_type, t0);
6221 if (bias)
6223 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6224 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6226 if (fd->iter_type == long_integer_type_node)
6228 if (fd->chunk_size)
6230 t = fold_convert (fd->iter_type, fd->chunk_size);
6231 t = build_call_expr (builtin_decl_explicit (start_fn),
6232 6, t0, t1, t2, t, t3, t4);
6234 else
6235 t = build_call_expr (builtin_decl_explicit (start_fn),
6236 5, t0, t1, t2, t3, t4);
6238 else
6240 tree t5;
6241 tree c_bool_type;
6242 tree bfn_decl;
6244 /* The GOMP_loop_ull_*start functions have additional boolean
6245 argument, true for < loops and false for > loops.
6246 In Fortran, the C bool type can be different from
6247 boolean_type_node. */
6248 bfn_decl = builtin_decl_explicit (start_fn);
6249 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6250 t5 = build_int_cst (c_bool_type,
6251 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6252 if (fd->chunk_size)
6254 tree bfn_decl = builtin_decl_explicit (start_fn);
6255 t = fold_convert (fd->iter_type, fd->chunk_size);
6256 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6258 else
6259 t = build_call_expr (builtin_decl_explicit (start_fn),
6260 6, t5, t0, t1, t2, t3, t4);
6263 if (TREE_TYPE (t) != boolean_type_node)
6264 t = fold_build2 (NE_EXPR, boolean_type_node,
6265 t, build_int_cst (TREE_TYPE (t), 0));
6266 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6267 true, GSI_SAME_STMT);
6268 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6270 /* Remove the GIMPLE_OMP_FOR statement. */
6271 gsi_remove (&gsi, true);
6273 /* Iteration setup for sequential loop goes in L0_BB. */
6274 tree startvar = fd->loop.v;
6275 tree endvar = NULL_TREE;
6277 if (gimple_omp_for_combined_p (fd->for_stmt))
6279 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6280 && gimple_omp_for_kind (inner_stmt)
6281 == GF_OMP_FOR_KIND_SIMD);
6282 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6283 OMP_CLAUSE__LOOPTEMP_);
6284 gcc_assert (innerc);
6285 startvar = OMP_CLAUSE_DECL (innerc);
6286 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6287 OMP_CLAUSE__LOOPTEMP_);
6288 gcc_assert (innerc);
6289 endvar = OMP_CLAUSE_DECL (innerc);
6292 gsi = gsi_start_bb (l0_bb);
6293 t = istart0;
6294 if (bias)
6295 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6296 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6297 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6298 t = fold_convert (TREE_TYPE (startvar), t);
6299 t = force_gimple_operand_gsi (&gsi, t,
6300 DECL_P (startvar)
6301 && TREE_ADDRESSABLE (startvar),
6302 NULL_TREE, false, GSI_CONTINUE_LINKING);
6303 assign_stmt = gimple_build_assign (startvar, t);
6304 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6306 t = iend0;
6307 if (bias)
6308 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6309 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6310 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6311 t = fold_convert (TREE_TYPE (startvar), t);
6312 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6313 false, GSI_CONTINUE_LINKING);
6314 if (endvar)
6316 assign_stmt = gimple_build_assign (endvar, iend);
6317 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6318 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6319 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6320 else
6321 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6322 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6324 if (fd->collapse > 1)
6325 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6327 if (!broken_loop)
6329 /* Code to control the increment and predicate for the sequential
6330 loop goes in the CONT_BB. */
6331 gsi = gsi_last_bb (cont_bb);
6332 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6333 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6334 vmain = gimple_omp_continue_control_use (cont_stmt);
6335 vback = gimple_omp_continue_control_def (cont_stmt);
6337 if (!gimple_omp_for_combined_p (fd->for_stmt))
6339 if (POINTER_TYPE_P (type))
6340 t = fold_build_pointer_plus (vmain, fd->loop.step);
6341 else
6342 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6343 t = force_gimple_operand_gsi (&gsi, t,
6344 DECL_P (vback)
6345 && TREE_ADDRESSABLE (vback),
6346 NULL_TREE, true, GSI_SAME_STMT);
6347 assign_stmt = gimple_build_assign (vback, t);
6348 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6350 t = build2 (fd->loop.cond_code, boolean_type_node,
6351 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6352 iend);
6353 gcond *cond_stmt = gimple_build_cond_empty (t);
6354 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6357 /* Remove GIMPLE_OMP_CONTINUE. */
6358 gsi_remove (&gsi, true);
6360 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6361 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6363 /* Emit code to get the next parallel iteration in L2_BB. */
6364 gsi = gsi_start_bb (l2_bb);
6366 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6367 build_fold_addr_expr (istart0),
6368 build_fold_addr_expr (iend0));
6369 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6370 false, GSI_CONTINUE_LINKING);
6371 if (TREE_TYPE (t) != boolean_type_node)
6372 t = fold_build2 (NE_EXPR, boolean_type_node,
6373 t, build_int_cst (TREE_TYPE (t), 0));
6374 gcond *cond_stmt = gimple_build_cond_empty (t);
6375 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6378 /* Add the loop cleanup function. */
6379 gsi = gsi_last_bb (exit_bb);
6380 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6381 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6382 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6383 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6384 else
6385 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6386 gcall *call_stmt = gimple_build_call (t, 0);
6387 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6388 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6389 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6390 gsi_remove (&gsi, true);
6392 /* Connect the new blocks. */
6393 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6394 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6396 if (!broken_loop)
6398 gimple_seq phis;
6400 e = find_edge (cont_bb, l3_bb);
6401 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6403 phis = phi_nodes (l3_bb);
6404 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6406 gimple phi = gsi_stmt (gsi);
6407 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6408 PHI_ARG_DEF_FROM_EDGE (phi, e));
6410 remove_edge (e);
6412 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6413 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6414 e = find_edge (cont_bb, l1_bb);
6415 if (gimple_omp_for_combined_p (fd->for_stmt))
6417 remove_edge (e);
6418 e = NULL;
6420 else if (fd->collapse > 1)
6422 remove_edge (e);
6423 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6425 else
6426 e->flags = EDGE_TRUE_VALUE;
6427 if (e)
6429 e->probability = REG_BR_PROB_BASE * 7 / 8;
6430 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6432 else
6434 e = find_edge (cont_bb, l2_bb);
6435 e->flags = EDGE_FALLTHRU;
6437 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6439 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6440 recompute_dominator (CDI_DOMINATORS, l2_bb));
6441 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6442 recompute_dominator (CDI_DOMINATORS, l3_bb));
6443 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6444 recompute_dominator (CDI_DOMINATORS, l0_bb));
6445 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6446 recompute_dominator (CDI_DOMINATORS, l1_bb));
6448 struct loop *outer_loop = alloc_loop ();
6449 outer_loop->header = l0_bb;
6450 outer_loop->latch = l2_bb;
6451 add_loop (outer_loop, l0_bb->loop_father);
6453 if (!gimple_omp_for_combined_p (fd->for_stmt))
6455 struct loop *loop = alloc_loop ();
6456 loop->header = l1_bb;
6457 /* The loop may have multiple latches. */
6458 add_loop (loop, outer_loop);
6464 /* A subroutine of expand_omp_for. Generate code for a parallel
6465 loop with static schedule and no specified chunk size. Given
6466 parameters:
6468 for (V = N1; V cond N2; V += STEP) BODY;
6470 where COND is "<" or ">", we generate pseudocode
6472 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6473 if (cond is <)
6474 adj = STEP - 1;
6475 else
6476 adj = STEP + 1;
6477 if ((__typeof (V)) -1 > 0 && cond is >)
6478 n = -(adj + N2 - N1) / -STEP;
6479 else
6480 n = (adj + N2 - N1) / STEP;
6481 q = n / nthreads;
6482 tt = n % nthreads;
6483 if (threadid < tt) goto L3; else goto L4;
6485 tt = 0;
6486 q = q + 1;
6488 s0 = q * threadid + tt;
6489 e0 = s0 + q;
6490 V = s0 * STEP + N1;
6491 if (s0 >= e0) goto L2; else goto L0;
6493 e = e0 * STEP + N1;
6495 BODY;
6496 V += STEP;
6497 if (V cond e) goto L1;
6501 static void
6502 expand_omp_for_static_nochunk (struct omp_region *region,
6503 struct omp_for_data *fd,
6504 gimple inner_stmt)
6506 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6507 tree type, itype, vmain, vback;
6508 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6509 basic_block body_bb, cont_bb, collapse_bb = NULL;
6510 basic_block fin_bb;
6511 gimple_stmt_iterator gsi;
6512 edge ep;
6513 bool broken_loop = region->cont == NULL;
6514 tree *counts = NULL;
6515 tree n1, n2, step;
6517 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6518 != GF_OMP_FOR_KIND_OACC_LOOP)
6519 || !inner_stmt);
6521 itype = type = TREE_TYPE (fd->loop.v);
6522 if (POINTER_TYPE_P (type))
6523 itype = signed_type_for (type);
6525 entry_bb = region->entry;
6526 cont_bb = region->cont;
6527 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6528 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6529 gcc_assert (broken_loop
6530 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6531 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6532 body_bb = single_succ (seq_start_bb);
6533 if (!broken_loop)
6535 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6536 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6538 exit_bb = region->exit;
6540 /* Iteration space partitioning goes in ENTRY_BB. */
6541 gsi = gsi_last_bb (entry_bb);
6542 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6544 if (fd->collapse > 1)
6546 int first_zero_iter = -1;
6547 basic_block l2_dom_bb = NULL;
6549 counts = XALLOCAVEC (tree, fd->collapse);
6550 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6551 fin_bb, first_zero_iter,
6552 l2_dom_bb);
6553 t = NULL_TREE;
6555 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6556 t = integer_one_node;
6557 else
6558 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6559 fold_convert (type, fd->loop.n1),
6560 fold_convert (type, fd->loop.n2));
6561 if (fd->collapse == 1
6562 && TYPE_UNSIGNED (type)
6563 && (t == NULL_TREE || !integer_onep (t)))
6565 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6566 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6567 true, GSI_SAME_STMT);
6568 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6569 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6570 true, GSI_SAME_STMT);
6571 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6572 NULL_TREE, NULL_TREE);
6573 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6574 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6575 expand_omp_regimplify_p, NULL, NULL)
6576 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6577 expand_omp_regimplify_p, NULL, NULL))
6579 gsi = gsi_for_stmt (cond_stmt);
6580 gimple_regimplify_operands (cond_stmt, &gsi);
6582 ep = split_block (entry_bb, cond_stmt);
6583 ep->flags = EDGE_TRUE_VALUE;
6584 entry_bb = ep->dest;
6585 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6586 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6587 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6588 if (gimple_in_ssa_p (cfun))
6590 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6591 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6592 !gsi_end_p (gpi); gsi_next (&gpi))
6594 gphi *phi = gpi.phi ();
6595 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6596 ep, UNKNOWN_LOCATION);
6599 gsi = gsi_last_bb (entry_bb);
6602 switch (gimple_omp_for_kind (fd->for_stmt))
6604 case GF_OMP_FOR_KIND_FOR:
6605 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6606 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6607 break;
6608 case GF_OMP_FOR_KIND_DISTRIBUTE:
6609 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6610 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6611 break;
6612 case GF_OMP_FOR_KIND_OACC_LOOP:
6613 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6614 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6615 break;
6616 default:
6617 gcc_unreachable ();
6619 nthreads = build_call_expr (nthreads, 0);
6620 nthreads = fold_convert (itype, nthreads);
6621 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6622 true, GSI_SAME_STMT);
6623 threadid = build_call_expr (threadid, 0);
6624 threadid = fold_convert (itype, threadid);
6625 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6626 true, GSI_SAME_STMT);
6628 n1 = fd->loop.n1;
6629 n2 = fd->loop.n2;
6630 step = fd->loop.step;
6631 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6633 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6634 OMP_CLAUSE__LOOPTEMP_);
6635 gcc_assert (innerc);
6636 n1 = OMP_CLAUSE_DECL (innerc);
6637 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6638 OMP_CLAUSE__LOOPTEMP_);
6639 gcc_assert (innerc);
6640 n2 = OMP_CLAUSE_DECL (innerc);
6642 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6643 true, NULL_TREE, true, GSI_SAME_STMT);
6644 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6645 true, NULL_TREE, true, GSI_SAME_STMT);
6646 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6647 true, NULL_TREE, true, GSI_SAME_STMT);
6649 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6650 t = fold_build2 (PLUS_EXPR, itype, step, t);
6651 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6652 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6653 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6654 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6655 fold_build1 (NEGATE_EXPR, itype, t),
6656 fold_build1 (NEGATE_EXPR, itype, step));
6657 else
6658 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6659 t = fold_convert (itype, t);
6660 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6662 q = create_tmp_reg (itype, "q");
6663 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6664 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6665 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6667 tt = create_tmp_reg (itype, "tt");
6668 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6669 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6670 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6672 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6673 gcond *cond_stmt = gimple_build_cond_empty (t);
6674 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6676 second_bb = split_block (entry_bb, cond_stmt)->dest;
6677 gsi = gsi_last_bb (second_bb);
6678 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6680 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6681 GSI_SAME_STMT);
6682 gassign *assign_stmt
6683 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6684 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6686 third_bb = split_block (second_bb, assign_stmt)->dest;
6687 gsi = gsi_last_bb (third_bb);
6688 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6690 t = build2 (MULT_EXPR, itype, q, threadid);
6691 t = build2 (PLUS_EXPR, itype, t, tt);
6692 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6694 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6695 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6697 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6698 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6700 /* Remove the GIMPLE_OMP_FOR statement. */
6701 gsi_remove (&gsi, true);
6703 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6704 gsi = gsi_start_bb (seq_start_bb);
6706 tree startvar = fd->loop.v;
6707 tree endvar = NULL_TREE;
6709 if (gimple_omp_for_combined_p (fd->for_stmt))
6711 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6712 ? gimple_omp_parallel_clauses (inner_stmt)
6713 : gimple_omp_for_clauses (inner_stmt);
6714 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6715 gcc_assert (innerc);
6716 startvar = OMP_CLAUSE_DECL (innerc);
6717 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6718 OMP_CLAUSE__LOOPTEMP_);
6719 gcc_assert (innerc);
6720 endvar = OMP_CLAUSE_DECL (innerc);
6722 t = fold_convert (itype, s0);
6723 t = fold_build2 (MULT_EXPR, itype, t, step);
6724 if (POINTER_TYPE_P (type))
6725 t = fold_build_pointer_plus (n1, t);
6726 else
6727 t = fold_build2 (PLUS_EXPR, type, t, n1);
6728 t = fold_convert (TREE_TYPE (startvar), t);
6729 t = force_gimple_operand_gsi (&gsi, t,
6730 DECL_P (startvar)
6731 && TREE_ADDRESSABLE (startvar),
6732 NULL_TREE, false, GSI_CONTINUE_LINKING);
6733 assign_stmt = gimple_build_assign (startvar, t);
6734 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6736 t = fold_convert (itype, e0);
6737 t = fold_build2 (MULT_EXPR, itype, t, step);
6738 if (POINTER_TYPE_P (type))
6739 t = fold_build_pointer_plus (n1, t);
6740 else
6741 t = fold_build2 (PLUS_EXPR, type, t, n1);
6742 t = fold_convert (TREE_TYPE (startvar), t);
6743 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6744 false, GSI_CONTINUE_LINKING);
6745 if (endvar)
6747 assign_stmt = gimple_build_assign (endvar, e);
6748 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6749 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6750 assign_stmt = gimple_build_assign (fd->loop.v, e);
6751 else
6752 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6753 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6755 if (fd->collapse > 1)
6756 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6758 if (!broken_loop)
6760 /* The code controlling the sequential loop replaces the
6761 GIMPLE_OMP_CONTINUE. */
6762 gsi = gsi_last_bb (cont_bb);
6763 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6764 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6765 vmain = gimple_omp_continue_control_use (cont_stmt);
6766 vback = gimple_omp_continue_control_def (cont_stmt);
6768 if (!gimple_omp_for_combined_p (fd->for_stmt))
6770 if (POINTER_TYPE_P (type))
6771 t = fold_build_pointer_plus (vmain, step);
6772 else
6773 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6774 t = force_gimple_operand_gsi (&gsi, t,
6775 DECL_P (vback)
6776 && TREE_ADDRESSABLE (vback),
6777 NULL_TREE, true, GSI_SAME_STMT);
6778 assign_stmt = gimple_build_assign (vback, t);
6779 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6781 t = build2 (fd->loop.cond_code, boolean_type_node,
6782 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6783 ? t : vback, e);
6784 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6787 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6788 gsi_remove (&gsi, true);
6790 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6791 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6794 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6795 gsi = gsi_last_bb (exit_bb);
6796 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6798 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6799 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6800 gcc_checking_assert (t == NULL_TREE);
6801 else
6802 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6804 gsi_remove (&gsi, true);
6806 /* Connect all the blocks. */
6807 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6808 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6809 ep = find_edge (entry_bb, second_bb);
6810 ep->flags = EDGE_TRUE_VALUE;
6811 ep->probability = REG_BR_PROB_BASE / 4;
6812 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6813 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6815 if (!broken_loop)
6817 ep = find_edge (cont_bb, body_bb);
6818 if (gimple_omp_for_combined_p (fd->for_stmt))
6820 remove_edge (ep);
6821 ep = NULL;
6823 else if (fd->collapse > 1)
6825 remove_edge (ep);
6826 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6828 else
6829 ep->flags = EDGE_TRUE_VALUE;
6830 find_edge (cont_bb, fin_bb)->flags
6831 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6834 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6835 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6836 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6838 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6839 recompute_dominator (CDI_DOMINATORS, body_bb));
6840 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6841 recompute_dominator (CDI_DOMINATORS, fin_bb));
6843 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6845 struct loop *loop = alloc_loop ();
6846 loop->header = body_bb;
6847 if (collapse_bb == NULL)
6848 loop->latch = cont_bb;
6849 add_loop (loop, body_bb->loop_father);
6854 /* A subroutine of expand_omp_for. Generate code for a parallel
6855 loop with static schedule and a specified chunk size. Given
6856 parameters:
6858 for (V = N1; V cond N2; V += STEP) BODY;
6860 where COND is "<" or ">", we generate pseudocode
6862 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6863 if (cond is <)
6864 adj = STEP - 1;
6865 else
6866 adj = STEP + 1;
6867 if ((__typeof (V)) -1 > 0 && cond is >)
6868 n = -(adj + N2 - N1) / -STEP;
6869 else
6870 n = (adj + N2 - N1) / STEP;
6871 trip = 0;
6872 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6873 here so that V is defined
6874 if the loop is not entered
6876 s0 = (trip * nthreads + threadid) * CHUNK;
6877 e0 = min(s0 + CHUNK, n);
6878 if (s0 < n) goto L1; else goto L4;
6880 V = s0 * STEP + N1;
6881 e = e0 * STEP + N1;
6883 BODY;
6884 V += STEP;
6885 if (V cond e) goto L2; else goto L3;
6887 trip += 1;
6888 goto L0;
6892 static void
6893 expand_omp_for_static_chunk (struct omp_region *region,
6894 struct omp_for_data *fd, gimple inner_stmt)
6896 tree n, s0, e0, e, t;
6897 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6898 tree type, itype, vmain, vback, vextra;
6899 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6900 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6901 gimple_stmt_iterator gsi;
6902 edge se;
6903 bool broken_loop = region->cont == NULL;
6904 tree *counts = NULL;
6905 tree n1, n2, step;
6907 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6908 != GF_OMP_FOR_KIND_OACC_LOOP)
6909 || !inner_stmt);
6911 itype = type = TREE_TYPE (fd->loop.v);
6912 if (POINTER_TYPE_P (type))
6913 itype = signed_type_for (type);
6915 entry_bb = region->entry;
6916 se = split_block (entry_bb, last_stmt (entry_bb));
6917 entry_bb = se->src;
6918 iter_part_bb = se->dest;
6919 cont_bb = region->cont;
6920 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6921 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6922 gcc_assert (broken_loop
6923 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6924 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6925 body_bb = single_succ (seq_start_bb);
6926 if (!broken_loop)
6928 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6929 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6930 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6932 exit_bb = region->exit;
6934 /* Trip and adjustment setup goes in ENTRY_BB. */
6935 gsi = gsi_last_bb (entry_bb);
6936 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6938 if (fd->collapse > 1)
6940 int first_zero_iter = -1;
6941 basic_block l2_dom_bb = NULL;
6943 counts = XALLOCAVEC (tree, fd->collapse);
6944 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6945 fin_bb, first_zero_iter,
6946 l2_dom_bb);
6947 t = NULL_TREE;
6949 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6950 t = integer_one_node;
6951 else
6952 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6953 fold_convert (type, fd->loop.n1),
6954 fold_convert (type, fd->loop.n2));
6955 if (fd->collapse == 1
6956 && TYPE_UNSIGNED (type)
6957 && (t == NULL_TREE || !integer_onep (t)))
6959 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6960 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6961 true, GSI_SAME_STMT);
6962 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6963 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6964 true, GSI_SAME_STMT);
6965 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6966 NULL_TREE, NULL_TREE);
6967 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6968 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6969 expand_omp_regimplify_p, NULL, NULL)
6970 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6971 expand_omp_regimplify_p, NULL, NULL))
6973 gsi = gsi_for_stmt (cond_stmt);
6974 gimple_regimplify_operands (cond_stmt, &gsi);
6976 se = split_block (entry_bb, cond_stmt);
6977 se->flags = EDGE_TRUE_VALUE;
6978 entry_bb = se->dest;
6979 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6980 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6981 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6982 if (gimple_in_ssa_p (cfun))
6984 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6985 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6986 !gsi_end_p (gpi); gsi_next (&gpi))
6988 gphi *phi = gpi.phi ();
6989 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6990 se, UNKNOWN_LOCATION);
6993 gsi = gsi_last_bb (entry_bb);
6996 switch (gimple_omp_for_kind (fd->for_stmt))
6998 case GF_OMP_FOR_KIND_FOR:
6999 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7000 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7001 break;
7002 case GF_OMP_FOR_KIND_DISTRIBUTE:
7003 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7004 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7005 break;
7006 case GF_OMP_FOR_KIND_OACC_LOOP:
7007 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7008 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7009 break;
7010 default:
7011 gcc_unreachable ();
7013 nthreads = build_call_expr (nthreads, 0);
7014 nthreads = fold_convert (itype, nthreads);
7015 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7016 true, GSI_SAME_STMT);
7017 threadid = build_call_expr (threadid, 0);
7018 threadid = fold_convert (itype, threadid);
7019 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7020 true, GSI_SAME_STMT);
7022 n1 = fd->loop.n1;
7023 n2 = fd->loop.n2;
7024 step = fd->loop.step;
7025 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7027 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7028 OMP_CLAUSE__LOOPTEMP_);
7029 gcc_assert (innerc);
7030 n1 = OMP_CLAUSE_DECL (innerc);
7031 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7032 OMP_CLAUSE__LOOPTEMP_);
7033 gcc_assert (innerc);
7034 n2 = OMP_CLAUSE_DECL (innerc);
7036 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7037 true, NULL_TREE, true, GSI_SAME_STMT);
7038 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7039 true, NULL_TREE, true, GSI_SAME_STMT);
7040 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7041 true, NULL_TREE, true, GSI_SAME_STMT);
7042 fd->chunk_size
7043 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7044 true, NULL_TREE, true, GSI_SAME_STMT);
7046 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7047 t = fold_build2 (PLUS_EXPR, itype, step, t);
7048 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7049 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7050 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7051 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7052 fold_build1 (NEGATE_EXPR, itype, t),
7053 fold_build1 (NEGATE_EXPR, itype, step));
7054 else
7055 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7056 t = fold_convert (itype, t);
7057 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7058 true, GSI_SAME_STMT);
7060 trip_var = create_tmp_reg (itype, ".trip");
7061 if (gimple_in_ssa_p (cfun))
7063 trip_init = make_ssa_name (trip_var);
7064 trip_main = make_ssa_name (trip_var);
7065 trip_back = make_ssa_name (trip_var);
7067 else
7069 trip_init = trip_var;
7070 trip_main = trip_var;
7071 trip_back = trip_var;
7074 gassign *assign_stmt
7075 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7076 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7078 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7079 t = fold_build2 (MULT_EXPR, itype, t, step);
7080 if (POINTER_TYPE_P (type))
7081 t = fold_build_pointer_plus (n1, t);
7082 else
7083 t = fold_build2 (PLUS_EXPR, type, t, n1);
7084 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7085 true, GSI_SAME_STMT);
7087 /* Remove the GIMPLE_OMP_FOR. */
7088 gsi_remove (&gsi, true);
7090 /* Iteration space partitioning goes in ITER_PART_BB. */
7091 gsi = gsi_last_bb (iter_part_bb);
7093 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7094 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7095 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7096 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7097 false, GSI_CONTINUE_LINKING);
7099 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7100 t = fold_build2 (MIN_EXPR, itype, t, n);
7101 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7102 false, GSI_CONTINUE_LINKING);
7104 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7105 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7107 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7108 gsi = gsi_start_bb (seq_start_bb);
7110 tree startvar = fd->loop.v;
7111 tree endvar = NULL_TREE;
7113 if (gimple_omp_for_combined_p (fd->for_stmt))
7115 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7116 ? gimple_omp_parallel_clauses (inner_stmt)
7117 : gimple_omp_for_clauses (inner_stmt);
7118 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7119 gcc_assert (innerc);
7120 startvar = OMP_CLAUSE_DECL (innerc);
7121 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7122 OMP_CLAUSE__LOOPTEMP_);
7123 gcc_assert (innerc);
7124 endvar = OMP_CLAUSE_DECL (innerc);
7127 t = fold_convert (itype, s0);
7128 t = fold_build2 (MULT_EXPR, itype, t, step);
7129 if (POINTER_TYPE_P (type))
7130 t = fold_build_pointer_plus (n1, t);
7131 else
7132 t = fold_build2 (PLUS_EXPR, type, t, n1);
7133 t = fold_convert (TREE_TYPE (startvar), t);
7134 t = force_gimple_operand_gsi (&gsi, t,
7135 DECL_P (startvar)
7136 && TREE_ADDRESSABLE (startvar),
7137 NULL_TREE, false, GSI_CONTINUE_LINKING);
7138 assign_stmt = gimple_build_assign (startvar, t);
7139 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7141 t = fold_convert (itype, e0);
7142 t = fold_build2 (MULT_EXPR, itype, t, step);
7143 if (POINTER_TYPE_P (type))
7144 t = fold_build_pointer_plus (n1, t);
7145 else
7146 t = fold_build2 (PLUS_EXPR, type, t, n1);
7147 t = fold_convert (TREE_TYPE (startvar), t);
7148 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7149 false, GSI_CONTINUE_LINKING);
7150 if (endvar)
7152 assign_stmt = gimple_build_assign (endvar, e);
7153 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7154 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7155 assign_stmt = gimple_build_assign (fd->loop.v, e);
7156 else
7157 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7158 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7160 if (fd->collapse > 1)
7161 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7163 if (!broken_loop)
7165 /* The code controlling the sequential loop goes in CONT_BB,
7166 replacing the GIMPLE_OMP_CONTINUE. */
7167 gsi = gsi_last_bb (cont_bb);
7168 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7169 vmain = gimple_omp_continue_control_use (cont_stmt);
7170 vback = gimple_omp_continue_control_def (cont_stmt);
7172 if (!gimple_omp_for_combined_p (fd->for_stmt))
7174 if (POINTER_TYPE_P (type))
7175 t = fold_build_pointer_plus (vmain, step);
7176 else
7177 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7178 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7179 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7180 true, GSI_SAME_STMT);
7181 assign_stmt = gimple_build_assign (vback, t);
7182 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7184 t = build2 (fd->loop.cond_code, boolean_type_node,
7185 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7186 ? t : vback, e);
7187 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7190 /* Remove GIMPLE_OMP_CONTINUE. */
7191 gsi_remove (&gsi, true);
7193 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7194 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7196 /* Trip update code goes into TRIP_UPDATE_BB. */
7197 gsi = gsi_start_bb (trip_update_bb);
7199 t = build_int_cst (itype, 1);
7200 t = build2 (PLUS_EXPR, itype, trip_main, t);
7201 assign_stmt = gimple_build_assign (trip_back, t);
7202 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7205 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7206 gsi = gsi_last_bb (exit_bb);
7207 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7209 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7210 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7211 gcc_checking_assert (t == NULL_TREE);
7212 else
7213 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7215 gsi_remove (&gsi, true);
7217 /* Connect the new blocks. */
7218 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7219 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7221 if (!broken_loop)
7223 se = find_edge (cont_bb, body_bb);
7224 if (gimple_omp_for_combined_p (fd->for_stmt))
7226 remove_edge (se);
7227 se = NULL;
7229 else if (fd->collapse > 1)
7231 remove_edge (se);
7232 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7234 else
7235 se->flags = EDGE_TRUE_VALUE;
7236 find_edge (cont_bb, trip_update_bb)->flags
7237 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7239 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7242 if (gimple_in_ssa_p (cfun))
7244 gphi_iterator psi;
7245 gphi *phi;
7246 edge re, ene;
7247 edge_var_map *vm;
7248 size_t i;
7250 gcc_assert (fd->collapse == 1 && !broken_loop);
7252 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7253 remove arguments of the phi nodes in fin_bb. We need to create
7254 appropriate phi nodes in iter_part_bb instead. */
7255 se = single_pred_edge (fin_bb);
7256 re = single_succ_edge (trip_update_bb);
7257 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7258 ene = single_succ_edge (entry_bb);
7260 psi = gsi_start_phis (fin_bb);
7261 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7262 gsi_next (&psi), ++i)
7264 gphi *nphi;
7265 source_location locus;
7267 phi = psi.phi ();
7268 t = gimple_phi_result (phi);
7269 gcc_assert (t == redirect_edge_var_map_result (vm));
7270 nphi = create_phi_node (t, iter_part_bb);
7272 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7273 locus = gimple_phi_arg_location_from_edge (phi, se);
7275 /* A special case -- fd->loop.v is not yet computed in
7276 iter_part_bb, we need to use vextra instead. */
7277 if (t == fd->loop.v)
7278 t = vextra;
7279 add_phi_arg (nphi, t, ene, locus);
7280 locus = redirect_edge_var_map_location (vm);
7281 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7283 gcc_assert (gsi_end_p (psi) && i == head->length ());
7284 redirect_edge_var_map_clear (re);
7285 while (1)
7287 psi = gsi_start_phis (fin_bb);
7288 if (gsi_end_p (psi))
7289 break;
7290 remove_phi_node (&psi, false);
7293 /* Make phi node for trip. */
7294 phi = create_phi_node (trip_main, iter_part_bb);
7295 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7296 UNKNOWN_LOCATION);
7297 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7298 UNKNOWN_LOCATION);
7301 if (!broken_loop)
7302 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7303 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7304 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7305 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7306 recompute_dominator (CDI_DOMINATORS, fin_bb));
7307 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7308 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7309 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7310 recompute_dominator (CDI_DOMINATORS, body_bb));
7312 if (!broken_loop)
7314 struct loop *trip_loop = alloc_loop ();
7315 trip_loop->header = iter_part_bb;
7316 trip_loop->latch = trip_update_bb;
7317 add_loop (trip_loop, iter_part_bb->loop_father);
7319 if (!gimple_omp_for_combined_p (fd->for_stmt))
7321 struct loop *loop = alloc_loop ();
7322 loop->header = body_bb;
7323 if (collapse_bb == NULL)
7324 loop->latch = cont_bb;
7325 add_loop (loop, trip_loop);
7330 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7331 Given parameters:
7332 for (V = N1; V cond N2; V += STEP) BODY;
7334 where COND is "<" or ">" or "!=", we generate pseudocode
7336 for (ind_var = low; ind_var < high; ind_var++)
7338 V = n1 + (ind_var * STEP)
7340 <BODY>
7343 In the above pseudocode, low and high are function parameters of the
7344 child function. In the function below, we are inserting a temp.
7345 variable that will be making a call to two OMP functions that will not be
7346 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7347 with _Cilk_for). These functions are replaced with low and high
7348 by the function that handles taskreg. */
7351 static void
7352 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7354 bool broken_loop = region->cont == NULL;
7355 basic_block entry_bb = region->entry;
7356 basic_block cont_bb = region->cont;
7358 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7359 gcc_assert (broken_loop
7360 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7361 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7362 basic_block l1_bb, l2_bb;
7364 if (!broken_loop)
7366 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7367 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7368 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7369 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7371 else
7373 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7374 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7375 l2_bb = single_succ (l1_bb);
7377 basic_block exit_bb = region->exit;
7378 basic_block l2_dom_bb = NULL;
7380 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7382 /* Below statements until the "tree high_val = ..." are pseudo statements
7383 used to pass information to be used by expand_omp_taskreg.
7384 low_val and high_val will be replaced by the __low and __high
7385 parameter from the child function.
7387 The call_exprs part is a place-holder, it is mainly used
7388 to distinctly identify to the top-level part that this is
7389 where we should put low and high (reasoning given in header
7390 comment). */
7392 tree child_fndecl
7393 = gimple_omp_parallel_child_fn (
7394 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7395 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7396 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7398 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7399 high_val = t;
7400 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7401 low_val = t;
7403 gcc_assert (low_val && high_val);
7405 tree type = TREE_TYPE (low_val);
7406 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7407 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7409 /* Not needed in SSA form right now. */
7410 gcc_assert (!gimple_in_ssa_p (cfun));
7411 if (l2_dom_bb == NULL)
7412 l2_dom_bb = l1_bb;
7414 tree n1 = low_val;
7415 tree n2 = high_val;
7417 gimple stmt = gimple_build_assign (ind_var, n1);
7419 /* Replace the GIMPLE_OMP_FOR statement. */
7420 gsi_replace (&gsi, stmt, true);
7422 if (!broken_loop)
7424 /* Code to control the increment goes in the CONT_BB. */
7425 gsi = gsi_last_bb (cont_bb);
7426 stmt = gsi_stmt (gsi);
7427 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7428 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7429 build_one_cst (type));
7431 /* Replace GIMPLE_OMP_CONTINUE. */
7432 gsi_replace (&gsi, stmt, true);
7435 /* Emit the condition in L1_BB. */
7436 gsi = gsi_after_labels (l1_bb);
7437 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7438 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7439 fd->loop.step);
7440 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7441 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7442 fd->loop.n1, fold_convert (sizetype, t));
7443 else
7444 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7445 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7446 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7447 expand_omp_build_assign (&gsi, fd->loop.v, t);
7449 /* The condition is always '<' since the runtime will fill in the low
7450 and high values. */
7451 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7452 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7454 /* Remove GIMPLE_OMP_RETURN. */
7455 gsi = gsi_last_bb (exit_bb);
7456 gsi_remove (&gsi, true);
7458 /* Connect the new blocks. */
7459 remove_edge (FALLTHRU_EDGE (entry_bb));
7461 edge e, ne;
7462 if (!broken_loop)
7464 remove_edge (BRANCH_EDGE (entry_bb));
7465 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7467 e = BRANCH_EDGE (l1_bb);
7468 ne = FALLTHRU_EDGE (l1_bb);
7469 e->flags = EDGE_TRUE_VALUE;
7471 else
7473 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7475 ne = single_succ_edge (l1_bb);
7476 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7479 ne->flags = EDGE_FALSE_VALUE;
7480 e->probability = REG_BR_PROB_BASE * 7 / 8;
7481 ne->probability = REG_BR_PROB_BASE / 8;
7483 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7484 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7485 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7487 if (!broken_loop)
7489 struct loop *loop = alloc_loop ();
7490 loop->header = l1_bb;
7491 loop->latch = cont_bb;
7492 add_loop (loop, l1_bb->loop_father);
7493 loop->safelen = INT_MAX;
7496 /* Pick the correct library function based on the precision of the
7497 induction variable type. */
7498 tree lib_fun = NULL_TREE;
7499 if (TYPE_PRECISION (type) == 32)
7500 lib_fun = cilk_for_32_fndecl;
7501 else if (TYPE_PRECISION (type) == 64)
7502 lib_fun = cilk_for_64_fndecl;
7503 else
7504 gcc_unreachable ();
7506 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7508 /* WS_ARGS contains the library function flavor to call:
7509 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7510 user-defined grain value. If the user does not define one, then zero
7511 is passed in by the parser. */
7512 vec_alloc (region->ws_args, 2);
7513 region->ws_args->quick_push (lib_fun);
7514 region->ws_args->quick_push (fd->chunk_size);
7517 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7518 loop. Given parameters:
7520 for (V = N1; V cond N2; V += STEP) BODY;
7522 where COND is "<" or ">", we generate pseudocode
7524 V = N1;
7525 goto L1;
7527 BODY;
7528 V += STEP;
7530 if (V cond N2) goto L0; else goto L2;
7533 For collapsed loops, given parameters:
7534 collapse(3)
7535 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7536 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7537 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7538 BODY;
7540 we generate pseudocode
7542 if (cond3 is <)
7543 adj = STEP3 - 1;
7544 else
7545 adj = STEP3 + 1;
7546 count3 = (adj + N32 - N31) / STEP3;
7547 if (cond2 is <)
7548 adj = STEP2 - 1;
7549 else
7550 adj = STEP2 + 1;
7551 count2 = (adj + N22 - N21) / STEP2;
7552 if (cond1 is <)
7553 adj = STEP1 - 1;
7554 else
7555 adj = STEP1 + 1;
7556 count1 = (adj + N12 - N11) / STEP1;
7557 count = count1 * count2 * count3;
7558 V = 0;
7559 V1 = N11;
7560 V2 = N21;
7561 V3 = N31;
7562 goto L1;
7564 BODY;
7565 V += 1;
7566 V3 += STEP3;
7567 V2 += (V3 cond3 N32) ? 0 : STEP2;
7568 V3 = (V3 cond3 N32) ? V3 : N31;
7569 V1 += (V2 cond2 N22) ? 0 : STEP1;
7570 V2 = (V2 cond2 N22) ? V2 : N21;
7572 if (V < count) goto L0; else goto L2;
7577 static void
7578 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7580 tree type, t;
7581 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7582 gimple_stmt_iterator gsi;
7583 gimple stmt;
7584 gcond *cond_stmt;
7585 bool broken_loop = region->cont == NULL;
7586 edge e, ne;
7587 tree *counts = NULL;
7588 int i;
7589 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7590 OMP_CLAUSE_SAFELEN);
7591 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7592 OMP_CLAUSE__SIMDUID_);
7593 tree n1, n2;
7595 type = TREE_TYPE (fd->loop.v);
7596 entry_bb = region->entry;
7597 cont_bb = region->cont;
7598 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7599 gcc_assert (broken_loop
7600 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7601 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7602 if (!broken_loop)
7604 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7605 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7606 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7607 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7609 else
7611 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7612 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7613 l2_bb = single_succ (l1_bb);
7615 exit_bb = region->exit;
7616 l2_dom_bb = NULL;
7618 gsi = gsi_last_bb (entry_bb);
7620 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7621 /* Not needed in SSA form right now. */
7622 gcc_assert (!gimple_in_ssa_p (cfun));
7623 if (fd->collapse > 1)
7625 int first_zero_iter = -1;
7626 basic_block zero_iter_bb = l2_bb;
7628 counts = XALLOCAVEC (tree, fd->collapse);
7629 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7630 zero_iter_bb, first_zero_iter,
7631 l2_dom_bb);
7633 if (l2_dom_bb == NULL)
7634 l2_dom_bb = l1_bb;
7636 n1 = fd->loop.n1;
7637 n2 = fd->loop.n2;
7638 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7640 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7641 OMP_CLAUSE__LOOPTEMP_);
7642 gcc_assert (innerc);
7643 n1 = OMP_CLAUSE_DECL (innerc);
7644 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7645 OMP_CLAUSE__LOOPTEMP_);
7646 gcc_assert (innerc);
7647 n2 = OMP_CLAUSE_DECL (innerc);
7648 expand_omp_build_assign (&gsi, fd->loop.v,
7649 fold_convert (type, n1));
7650 if (fd->collapse > 1)
7652 gsi_prev (&gsi);
7653 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7654 gsi_next (&gsi);
7657 else
7659 expand_omp_build_assign (&gsi, fd->loop.v,
7660 fold_convert (type, fd->loop.n1));
7661 if (fd->collapse > 1)
7662 for (i = 0; i < fd->collapse; i++)
7664 tree itype = TREE_TYPE (fd->loops[i].v);
7665 if (POINTER_TYPE_P (itype))
7666 itype = signed_type_for (itype);
7667 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7668 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7672 /* Remove the GIMPLE_OMP_FOR statement. */
7673 gsi_remove (&gsi, true);
7675 if (!broken_loop)
7677 /* Code to control the increment goes in the CONT_BB. */
7678 gsi = gsi_last_bb (cont_bb);
7679 stmt = gsi_stmt (gsi);
7680 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7682 if (POINTER_TYPE_P (type))
7683 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7684 else
7685 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7686 expand_omp_build_assign (&gsi, fd->loop.v, t);
7688 if (fd->collapse > 1)
7690 i = fd->collapse - 1;
7691 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7693 t = fold_convert (sizetype, fd->loops[i].step);
7694 t = fold_build_pointer_plus (fd->loops[i].v, t);
7696 else
7698 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7699 fd->loops[i].step);
7700 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7701 fd->loops[i].v, t);
7703 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7705 for (i = fd->collapse - 1; i > 0; i--)
7707 tree itype = TREE_TYPE (fd->loops[i].v);
7708 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7709 if (POINTER_TYPE_P (itype2))
7710 itype2 = signed_type_for (itype2);
7711 t = build3 (COND_EXPR, itype2,
7712 build2 (fd->loops[i].cond_code, boolean_type_node,
7713 fd->loops[i].v,
7714 fold_convert (itype, fd->loops[i].n2)),
7715 build_int_cst (itype2, 0),
7716 fold_convert (itype2, fd->loops[i - 1].step));
7717 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7718 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7719 else
7720 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7721 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7723 t = build3 (COND_EXPR, itype,
7724 build2 (fd->loops[i].cond_code, boolean_type_node,
7725 fd->loops[i].v,
7726 fold_convert (itype, fd->loops[i].n2)),
7727 fd->loops[i].v,
7728 fold_convert (itype, fd->loops[i].n1));
7729 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7733 /* Remove GIMPLE_OMP_CONTINUE. */
7734 gsi_remove (&gsi, true);
7737 /* Emit the condition in L1_BB. */
7738 gsi = gsi_start_bb (l1_bb);
7740 t = fold_convert (type, n2);
7741 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7742 false, GSI_CONTINUE_LINKING);
7743 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7744 cond_stmt = gimple_build_cond_empty (t);
7745 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7746 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7747 NULL, NULL)
7748 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7749 NULL, NULL))
7751 gsi = gsi_for_stmt (cond_stmt);
7752 gimple_regimplify_operands (cond_stmt, &gsi);
7755 /* Remove GIMPLE_OMP_RETURN. */
7756 gsi = gsi_last_bb (exit_bb);
7757 gsi_remove (&gsi, true);
7759 /* Connect the new blocks. */
7760 remove_edge (FALLTHRU_EDGE (entry_bb));
7762 if (!broken_loop)
7764 remove_edge (BRANCH_EDGE (entry_bb));
7765 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7767 e = BRANCH_EDGE (l1_bb);
7768 ne = FALLTHRU_EDGE (l1_bb);
7769 e->flags = EDGE_TRUE_VALUE;
7771 else
7773 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7775 ne = single_succ_edge (l1_bb);
7776 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7779 ne->flags = EDGE_FALSE_VALUE;
7780 e->probability = REG_BR_PROB_BASE * 7 / 8;
7781 ne->probability = REG_BR_PROB_BASE / 8;
7783 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7784 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7785 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7787 if (!broken_loop)
7789 struct loop *loop = alloc_loop ();
7790 loop->header = l1_bb;
7791 loop->latch = cont_bb;
7792 add_loop (loop, l1_bb->loop_father);
7793 if (safelen == NULL_TREE)
7794 loop->safelen = INT_MAX;
7795 else
7797 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7798 if (TREE_CODE (safelen) != INTEGER_CST)
7799 loop->safelen = 0;
7800 else if (!tree_fits_uhwi_p (safelen)
7801 || tree_to_uhwi (safelen) > INT_MAX)
7802 loop->safelen = INT_MAX;
7803 else
7804 loop->safelen = tree_to_uhwi (safelen);
7805 if (loop->safelen == 1)
7806 loop->safelen = 0;
7808 if (simduid)
7810 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7811 cfun->has_simduid_loops = true;
7813 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7814 the loop. */
7815 if ((flag_tree_loop_vectorize
7816 || (!global_options_set.x_flag_tree_loop_vectorize
7817 && !global_options_set.x_flag_tree_vectorize))
7818 && flag_tree_loop_optimize
7819 && loop->safelen > 1)
7821 loop->force_vectorize = true;
7822 cfun->has_force_vectorize_loops = true;
7828 /* Expand the OMP loop defined by REGION. */
7830 static void
7831 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7833 struct omp_for_data fd;
7834 struct omp_for_data_loop *loops;
7836 loops
7837 = (struct omp_for_data_loop *)
7838 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7839 * sizeof (struct omp_for_data_loop));
7840 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7841 &fd, loops);
7842 region->sched_kind = fd.sched_kind;
7844 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7845 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7846 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7847 if (region->cont)
7849 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7850 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7851 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7853 else
7854 /* If there isn't a continue then this is a degerate case where
7855 the introduction of abnormal edges during lowering will prevent
7856 original loops from being detected. Fix that up. */
7857 loops_state_set (LOOPS_NEED_FIXUP);
7859 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7860 expand_omp_simd (region, &fd);
7861 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7862 expand_cilk_for (region, &fd);
7863 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7864 && !fd.have_ordered)
7866 if (fd.chunk_size == NULL)
7867 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7868 else
7869 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7871 else
7873 int fn_index, start_ix, next_ix;
7875 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7876 == GF_OMP_FOR_KIND_FOR);
7877 if (fd.chunk_size == NULL
7878 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7879 fd.chunk_size = integer_zero_node;
7880 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7881 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7882 ? 3 : fd.sched_kind;
7883 fn_index += fd.have_ordered * 4;
7884 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7885 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7886 if (fd.iter_type == long_long_unsigned_type_node)
7888 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7889 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7890 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7891 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7893 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7894 (enum built_in_function) next_ix, inner_stmt);
7897 if (gimple_in_ssa_p (cfun))
7898 update_ssa (TODO_update_ssa_only_virtuals);
7902 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7904 v = GOMP_sections_start (n);
7906 switch (v)
7908 case 0:
7909 goto L2;
7910 case 1:
7911 section 1;
7912 goto L1;
7913 case 2:
7915 case n:
7917 default:
7918 abort ();
7921 v = GOMP_sections_next ();
7922 goto L0;
7924 reduction;
7926 If this is a combined parallel sections, replace the call to
7927 GOMP_sections_start with call to GOMP_sections_next. */
7929 static void
7930 expand_omp_sections (struct omp_region *region)
7932 tree t, u, vin = NULL, vmain, vnext, l2;
7933 unsigned len;
7934 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7935 gimple_stmt_iterator si, switch_si;
7936 gomp_sections *sections_stmt;
7937 gimple stmt;
7938 gomp_continue *cont;
7939 edge_iterator ei;
7940 edge e;
7941 struct omp_region *inner;
7942 unsigned i, casei;
7943 bool exit_reachable = region->cont != NULL;
7945 gcc_assert (region->exit != NULL);
7946 entry_bb = region->entry;
7947 l0_bb = single_succ (entry_bb);
7948 l1_bb = region->cont;
7949 l2_bb = region->exit;
7950 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7951 l2 = gimple_block_label (l2_bb);
7952 else
7954 /* This can happen if there are reductions. */
7955 len = EDGE_COUNT (l0_bb->succs);
7956 gcc_assert (len > 0);
7957 e = EDGE_SUCC (l0_bb, len - 1);
7958 si = gsi_last_bb (e->dest);
7959 l2 = NULL_TREE;
7960 if (gsi_end_p (si)
7961 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7962 l2 = gimple_block_label (e->dest);
7963 else
7964 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7966 si = gsi_last_bb (e->dest);
7967 if (gsi_end_p (si)
7968 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7970 l2 = gimple_block_label (e->dest);
7971 break;
7975 if (exit_reachable)
7976 default_bb = create_empty_bb (l1_bb->prev_bb);
7977 else
7978 default_bb = create_empty_bb (l0_bb);
7980 /* We will build a switch() with enough cases for all the
7981 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7982 and a default case to abort if something goes wrong. */
7983 len = EDGE_COUNT (l0_bb->succs);
7985 /* Use vec::quick_push on label_vec throughout, since we know the size
7986 in advance. */
7987 auto_vec<tree> label_vec (len);
7989 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7990 GIMPLE_OMP_SECTIONS statement. */
7991 si = gsi_last_bb (entry_bb);
7992 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
7993 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
7994 vin = gimple_omp_sections_control (sections_stmt);
7995 if (!is_combined_parallel (region))
7997 /* If we are not inside a combined parallel+sections region,
7998 call GOMP_sections_start. */
7999 t = build_int_cst (unsigned_type_node, len - 1);
8000 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
8001 stmt = gimple_build_call (u, 1, t);
8003 else
8005 /* Otherwise, call GOMP_sections_next. */
8006 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8007 stmt = gimple_build_call (u, 0);
8009 gimple_call_set_lhs (stmt, vin);
8010 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8011 gsi_remove (&si, true);
8013 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8014 L0_BB. */
8015 switch_si = gsi_last_bb (l0_bb);
8016 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8017 if (exit_reachable)
8019 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8020 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8021 vmain = gimple_omp_continue_control_use (cont);
8022 vnext = gimple_omp_continue_control_def (cont);
8024 else
8026 vmain = vin;
8027 vnext = NULL_TREE;
8030 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8031 label_vec.quick_push (t);
8032 i = 1;
8034 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8035 for (inner = region->inner, casei = 1;
8036 inner;
8037 inner = inner->next, i++, casei++)
8039 basic_block s_entry_bb, s_exit_bb;
8041 /* Skip optional reduction region. */
8042 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8044 --i;
8045 --casei;
8046 continue;
8049 s_entry_bb = inner->entry;
8050 s_exit_bb = inner->exit;
8052 t = gimple_block_label (s_entry_bb);
8053 u = build_int_cst (unsigned_type_node, casei);
8054 u = build_case_label (u, NULL, t);
8055 label_vec.quick_push (u);
8057 si = gsi_last_bb (s_entry_bb);
8058 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8059 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8060 gsi_remove (&si, true);
8061 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8063 if (s_exit_bb == NULL)
8064 continue;
8066 si = gsi_last_bb (s_exit_bb);
8067 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8068 gsi_remove (&si, true);
8070 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8073 /* Error handling code goes in DEFAULT_BB. */
8074 t = gimple_block_label (default_bb);
8075 u = build_case_label (NULL, NULL, t);
8076 make_edge (l0_bb, default_bb, 0);
8077 add_bb_to_loop (default_bb, current_loops->tree_root);
8079 stmt = gimple_build_switch (vmain, u, label_vec);
8080 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8081 gsi_remove (&switch_si, true);
8083 si = gsi_start_bb (default_bb);
8084 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8085 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8087 if (exit_reachable)
8089 tree bfn_decl;
8091 /* Code to get the next section goes in L1_BB. */
8092 si = gsi_last_bb (l1_bb);
8093 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8095 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8096 stmt = gimple_build_call (bfn_decl, 0);
8097 gimple_call_set_lhs (stmt, vnext);
8098 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8099 gsi_remove (&si, true);
8101 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8104 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8105 si = gsi_last_bb (l2_bb);
8106 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8107 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8108 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8109 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8110 else
8111 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8112 stmt = gimple_build_call (t, 0);
8113 if (gimple_omp_return_lhs (gsi_stmt (si)))
8114 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8115 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8116 gsi_remove (&si, true);
8118 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8122 /* Expand code for an OpenMP single directive. We've already expanded
8123 much of the code, here we simply place the GOMP_barrier call. */
8125 static void
8126 expand_omp_single (struct omp_region *region)
8128 basic_block entry_bb, exit_bb;
8129 gimple_stmt_iterator si;
8131 entry_bb = region->entry;
8132 exit_bb = region->exit;
8134 si = gsi_last_bb (entry_bb);
8135 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8136 gsi_remove (&si, true);
8137 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8139 si = gsi_last_bb (exit_bb);
8140 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8142 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8143 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8145 gsi_remove (&si, true);
8146 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8150 /* Generic expansion for OpenMP synchronization directives: master,
8151 ordered and critical. All we need to do here is remove the entry
8152 and exit markers for REGION. */
8154 static void
8155 expand_omp_synch (struct omp_region *region)
8157 basic_block entry_bb, exit_bb;
8158 gimple_stmt_iterator si;
8160 entry_bb = region->entry;
8161 exit_bb = region->exit;
8163 si = gsi_last_bb (entry_bb);
8164 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8165 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8166 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8167 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8168 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8169 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8170 gsi_remove (&si, true);
8171 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8173 if (exit_bb)
8175 si = gsi_last_bb (exit_bb);
8176 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8177 gsi_remove (&si, true);
8178 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8182 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8183 operation as a normal volatile load. */
8185 static bool
8186 expand_omp_atomic_load (basic_block load_bb, tree addr,
8187 tree loaded_val, int index)
8189 enum built_in_function tmpbase;
8190 gimple_stmt_iterator gsi;
8191 basic_block store_bb;
8192 location_t loc;
8193 gimple stmt;
8194 tree decl, call, type, itype;
8196 gsi = gsi_last_bb (load_bb);
8197 stmt = gsi_stmt (gsi);
8198 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8199 loc = gimple_location (stmt);
8201 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8202 is smaller than word size, then expand_atomic_load assumes that the load
8203 is atomic. We could avoid the builtin entirely in this case. */
8205 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8206 decl = builtin_decl_explicit (tmpbase);
8207 if (decl == NULL_TREE)
8208 return false;
8210 type = TREE_TYPE (loaded_val);
8211 itype = TREE_TYPE (TREE_TYPE (decl));
8213 call = build_call_expr_loc (loc, decl, 2, addr,
8214 build_int_cst (NULL,
8215 gimple_omp_atomic_seq_cst_p (stmt)
8216 ? MEMMODEL_SEQ_CST
8217 : MEMMODEL_RELAXED));
8218 if (!useless_type_conversion_p (type, itype))
8219 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8220 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8222 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8223 gsi_remove (&gsi, true);
8225 store_bb = single_succ (load_bb);
8226 gsi = gsi_last_bb (store_bb);
8227 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8228 gsi_remove (&gsi, true);
8230 if (gimple_in_ssa_p (cfun))
8231 update_ssa (TODO_update_ssa_no_phi);
8233 return true;
8236 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8237 operation as a normal volatile store. */
8239 static bool
8240 expand_omp_atomic_store (basic_block load_bb, tree addr,
8241 tree loaded_val, tree stored_val, int index)
8243 enum built_in_function tmpbase;
8244 gimple_stmt_iterator gsi;
8245 basic_block store_bb = single_succ (load_bb);
8246 location_t loc;
8247 gimple stmt;
8248 tree decl, call, type, itype;
8249 machine_mode imode;
8250 bool exchange;
8252 gsi = gsi_last_bb (load_bb);
8253 stmt = gsi_stmt (gsi);
8254 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8256 /* If the load value is needed, then this isn't a store but an exchange. */
8257 exchange = gimple_omp_atomic_need_value_p (stmt);
8259 gsi = gsi_last_bb (store_bb);
8260 stmt = gsi_stmt (gsi);
8261 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8262 loc = gimple_location (stmt);
8264 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8265 is smaller than word size, then expand_atomic_store assumes that the store
8266 is atomic. We could avoid the builtin entirely in this case. */
8268 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8269 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8270 decl = builtin_decl_explicit (tmpbase);
8271 if (decl == NULL_TREE)
8272 return false;
8274 type = TREE_TYPE (stored_val);
8276 /* Dig out the type of the function's second argument. */
8277 itype = TREE_TYPE (decl);
8278 itype = TYPE_ARG_TYPES (itype);
8279 itype = TREE_CHAIN (itype);
8280 itype = TREE_VALUE (itype);
8281 imode = TYPE_MODE (itype);
8283 if (exchange && !can_atomic_exchange_p (imode, true))
8284 return false;
8286 if (!useless_type_conversion_p (itype, type))
8287 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8288 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8289 build_int_cst (NULL,
8290 gimple_omp_atomic_seq_cst_p (stmt)
8291 ? MEMMODEL_SEQ_CST
8292 : MEMMODEL_RELAXED));
8293 if (exchange)
8295 if (!useless_type_conversion_p (type, itype))
8296 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8297 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8300 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8301 gsi_remove (&gsi, true);
8303 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8304 gsi = gsi_last_bb (load_bb);
8305 gsi_remove (&gsi, true);
8307 if (gimple_in_ssa_p (cfun))
8308 update_ssa (TODO_update_ssa_no_phi);
8310 return true;
8313 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8314 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8315 size of the data type, and thus usable to find the index of the builtin
8316 decl. Returns false if the expression is not of the proper form. */
8318 static bool
8319 expand_omp_atomic_fetch_op (basic_block load_bb,
8320 tree addr, tree loaded_val,
8321 tree stored_val, int index)
8323 enum built_in_function oldbase, newbase, tmpbase;
8324 tree decl, itype, call;
8325 tree lhs, rhs;
8326 basic_block store_bb = single_succ (load_bb);
8327 gimple_stmt_iterator gsi;
8328 gimple stmt;
8329 location_t loc;
8330 enum tree_code code;
8331 bool need_old, need_new;
8332 machine_mode imode;
8333 bool seq_cst;
8335 /* We expect to find the following sequences:
8337 load_bb:
8338 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8340 store_bb:
8341 val = tmp OP something; (or: something OP tmp)
8342 GIMPLE_OMP_STORE (val)
8344 ???FIXME: Allow a more flexible sequence.
8345 Perhaps use data flow to pick the statements.
8349 gsi = gsi_after_labels (store_bb);
8350 stmt = gsi_stmt (gsi);
8351 loc = gimple_location (stmt);
8352 if (!is_gimple_assign (stmt))
8353 return false;
8354 gsi_next (&gsi);
8355 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8356 return false;
8357 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8358 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8359 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8360 gcc_checking_assert (!need_old || !need_new);
8362 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8363 return false;
8365 /* Check for one of the supported fetch-op operations. */
8366 code = gimple_assign_rhs_code (stmt);
8367 switch (code)
8369 case PLUS_EXPR:
8370 case POINTER_PLUS_EXPR:
8371 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8372 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8373 break;
8374 case MINUS_EXPR:
8375 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8376 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8377 break;
8378 case BIT_AND_EXPR:
8379 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8380 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8381 break;
8382 case BIT_IOR_EXPR:
8383 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8384 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8385 break;
8386 case BIT_XOR_EXPR:
8387 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8388 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8389 break;
8390 default:
8391 return false;
8394 /* Make sure the expression is of the proper form. */
8395 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8396 rhs = gimple_assign_rhs2 (stmt);
8397 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8398 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8399 rhs = gimple_assign_rhs1 (stmt);
8400 else
8401 return false;
8403 tmpbase = ((enum built_in_function)
8404 ((need_new ? newbase : oldbase) + index + 1));
8405 decl = builtin_decl_explicit (tmpbase);
8406 if (decl == NULL_TREE)
8407 return false;
8408 itype = TREE_TYPE (TREE_TYPE (decl));
8409 imode = TYPE_MODE (itype);
8411 /* We could test all of the various optabs involved, but the fact of the
8412 matter is that (with the exception of i486 vs i586 and xadd) all targets
8413 that support any atomic operaton optab also implements compare-and-swap.
8414 Let optabs.c take care of expanding any compare-and-swap loop. */
8415 if (!can_compare_and_swap_p (imode, true))
8416 return false;
8418 gsi = gsi_last_bb (load_bb);
8419 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8421 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8422 It only requires that the operation happen atomically. Thus we can
8423 use the RELAXED memory model. */
8424 call = build_call_expr_loc (loc, decl, 3, addr,
8425 fold_convert_loc (loc, itype, rhs),
8426 build_int_cst (NULL,
8427 seq_cst ? MEMMODEL_SEQ_CST
8428 : MEMMODEL_RELAXED));
8430 if (need_old || need_new)
8432 lhs = need_old ? loaded_val : stored_val;
8433 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8434 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8436 else
8437 call = fold_convert_loc (loc, void_type_node, call);
8438 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8439 gsi_remove (&gsi, true);
8441 gsi = gsi_last_bb (store_bb);
8442 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8443 gsi_remove (&gsi, true);
8444 gsi = gsi_last_bb (store_bb);
8445 gsi_remove (&gsi, true);
8447 if (gimple_in_ssa_p (cfun))
8448 update_ssa (TODO_update_ssa_no_phi);
8450 return true;
8453 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8455 oldval = *addr;
8456 repeat:
8457 newval = rhs; // with oldval replacing *addr in rhs
8458 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8459 if (oldval != newval)
8460 goto repeat;
8462 INDEX is log2 of the size of the data type, and thus usable to find the
8463 index of the builtin decl. */
8465 static bool
8466 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8467 tree addr, tree loaded_val, tree stored_val,
8468 int index)
8470 tree loadedi, storedi, initial, new_storedi, old_vali;
8471 tree type, itype, cmpxchg, iaddr;
8472 gimple_stmt_iterator si;
8473 basic_block loop_header = single_succ (load_bb);
8474 gimple phi, stmt;
8475 edge e;
8476 enum built_in_function fncode;
8478 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8479 order to use the RELAXED memory model effectively. */
8480 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8481 + index + 1);
8482 cmpxchg = builtin_decl_explicit (fncode);
8483 if (cmpxchg == NULL_TREE)
8484 return false;
8485 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8486 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8488 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8489 return false;
8491 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8492 si = gsi_last_bb (load_bb);
8493 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8495 /* For floating-point values, we'll need to view-convert them to integers
8496 so that we can perform the atomic compare and swap. Simplify the
8497 following code by always setting up the "i"ntegral variables. */
8498 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8500 tree iaddr_val;
8502 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8503 true));
8504 iaddr_val
8505 = force_gimple_operand_gsi (&si,
8506 fold_convert (TREE_TYPE (iaddr), addr),
8507 false, NULL_TREE, true, GSI_SAME_STMT);
8508 stmt = gimple_build_assign (iaddr, iaddr_val);
8509 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8510 loadedi = create_tmp_var (itype);
8511 if (gimple_in_ssa_p (cfun))
8512 loadedi = make_ssa_name (loadedi);
8514 else
8516 iaddr = addr;
8517 loadedi = loaded_val;
8520 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8521 tree loaddecl = builtin_decl_explicit (fncode);
8522 if (loaddecl)
8523 initial
8524 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8525 build_call_expr (loaddecl, 2, iaddr,
8526 build_int_cst (NULL_TREE,
8527 MEMMODEL_RELAXED)));
8528 else
8529 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8530 build_int_cst (TREE_TYPE (iaddr), 0));
8532 initial
8533 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8534 GSI_SAME_STMT);
8536 /* Move the value to the LOADEDI temporary. */
8537 if (gimple_in_ssa_p (cfun))
8539 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8540 phi = create_phi_node (loadedi, loop_header);
8541 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8542 initial);
8544 else
8545 gsi_insert_before (&si,
8546 gimple_build_assign (loadedi, initial),
8547 GSI_SAME_STMT);
8548 if (loadedi != loaded_val)
8550 gimple_stmt_iterator gsi2;
8551 tree x;
8553 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8554 gsi2 = gsi_start_bb (loop_header);
8555 if (gimple_in_ssa_p (cfun))
8557 gassign *stmt;
8558 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8559 true, GSI_SAME_STMT);
8560 stmt = gimple_build_assign (loaded_val, x);
8561 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8563 else
8565 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8566 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8567 true, GSI_SAME_STMT);
8570 gsi_remove (&si, true);
8572 si = gsi_last_bb (store_bb);
8573 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8575 if (iaddr == addr)
8576 storedi = stored_val;
8577 else
8578 storedi =
8579 force_gimple_operand_gsi (&si,
8580 build1 (VIEW_CONVERT_EXPR, itype,
8581 stored_val), true, NULL_TREE, true,
8582 GSI_SAME_STMT);
8584 /* Build the compare&swap statement. */
8585 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8586 new_storedi = force_gimple_operand_gsi (&si,
8587 fold_convert (TREE_TYPE (loadedi),
8588 new_storedi),
8589 true, NULL_TREE,
8590 true, GSI_SAME_STMT);
8592 if (gimple_in_ssa_p (cfun))
8593 old_vali = loadedi;
8594 else
8596 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8597 stmt = gimple_build_assign (old_vali, loadedi);
8598 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8600 stmt = gimple_build_assign (loadedi, new_storedi);
8601 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8604 /* Note that we always perform the comparison as an integer, even for
8605 floating point. This allows the atomic operation to properly
8606 succeed even with NaNs and -0.0. */
8607 stmt = gimple_build_cond_empty
8608 (build2 (NE_EXPR, boolean_type_node,
8609 new_storedi, old_vali));
8610 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8612 /* Update cfg. */
8613 e = single_succ_edge (store_bb);
8614 e->flags &= ~EDGE_FALLTHRU;
8615 e->flags |= EDGE_FALSE_VALUE;
8617 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8619 /* Copy the new value to loadedi (we already did that before the condition
8620 if we are not in SSA). */
8621 if (gimple_in_ssa_p (cfun))
8623 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8624 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8627 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8628 gsi_remove (&si, true);
8630 struct loop *loop = alloc_loop ();
8631 loop->header = loop_header;
8632 loop->latch = store_bb;
8633 add_loop (loop, loop_header->loop_father);
8635 if (gimple_in_ssa_p (cfun))
8636 update_ssa (TODO_update_ssa_no_phi);
8638 return true;
8641 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8643 GOMP_atomic_start ();
8644 *addr = rhs;
8645 GOMP_atomic_end ();
8647 The result is not globally atomic, but works so long as all parallel
8648 references are within #pragma omp atomic directives. According to
8649 responses received from omp@openmp.org, appears to be within spec.
8650 Which makes sense, since that's how several other compilers handle
8651 this situation as well.
8652 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8653 expanding. STORED_VAL is the operand of the matching
8654 GIMPLE_OMP_ATOMIC_STORE.
8656 We replace
8657 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8658 loaded_val = *addr;
8660 and replace
8661 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8662 *addr = stored_val;
8665 static bool
8666 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8667 tree addr, tree loaded_val, tree stored_val)
8669 gimple_stmt_iterator si;
8670 gassign *stmt;
8671 tree t;
8673 si = gsi_last_bb (load_bb);
8674 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8676 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8677 t = build_call_expr (t, 0);
8678 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8680 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8681 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8682 gsi_remove (&si, true);
8684 si = gsi_last_bb (store_bb);
8685 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8687 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8688 stored_val);
8689 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8691 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8692 t = build_call_expr (t, 0);
8693 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8694 gsi_remove (&si, true);
8696 if (gimple_in_ssa_p (cfun))
8697 update_ssa (TODO_update_ssa_no_phi);
8698 return true;
8701 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8702 using expand_omp_atomic_fetch_op. If it failed, we try to
8703 call expand_omp_atomic_pipeline, and if it fails too, the
8704 ultimate fallback is wrapping the operation in a mutex
8705 (expand_omp_atomic_mutex). REGION is the atomic region built
8706 by build_omp_regions_1(). */
8708 static void
8709 expand_omp_atomic (struct omp_region *region)
8711 basic_block load_bb = region->entry, store_bb = region->exit;
8712 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8713 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8714 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8715 tree addr = gimple_omp_atomic_load_rhs (load);
8716 tree stored_val = gimple_omp_atomic_store_val (store);
8717 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8718 HOST_WIDE_INT index;
8720 /* Make sure the type is one of the supported sizes. */
8721 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8722 index = exact_log2 (index);
8723 if (index >= 0 && index <= 4)
8725 unsigned int align = TYPE_ALIGN_UNIT (type);
8727 /* __sync builtins require strict data alignment. */
8728 if (exact_log2 (align) >= index)
8730 /* Atomic load. */
8731 if (loaded_val == stored_val
8732 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8733 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8734 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8735 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8736 return;
8738 /* Atomic store. */
8739 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8740 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8741 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8742 && store_bb == single_succ (load_bb)
8743 && first_stmt (store_bb) == store
8744 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8745 stored_val, index))
8746 return;
8748 /* When possible, use specialized atomic update functions. */
8749 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8750 && store_bb == single_succ (load_bb)
8751 && expand_omp_atomic_fetch_op (load_bb, addr,
8752 loaded_val, stored_val, index))
8753 return;
8755 /* If we don't have specialized __sync builtins, try and implement
8756 as a compare and swap loop. */
8757 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8758 loaded_val, stored_val, index))
8759 return;
8763 /* The ultimate fallback is wrapping the operation in a mutex. */
8764 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8768 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8770 static void
8771 expand_omp_target (struct omp_region *region)
8773 basic_block entry_bb, exit_bb, new_bb;
8774 struct function *child_cfun;
8775 tree child_fn, block, t;
8776 gimple_stmt_iterator gsi;
8777 gomp_target *entry_stmt;
8778 gimple stmt;
8779 edge e;
8780 bool offloaded, data_region;
8782 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8783 new_bb = region->entry;
8785 offloaded = is_gimple_omp_offloaded (entry_stmt);
8786 switch (gimple_omp_target_kind (entry_stmt))
8788 case GF_OMP_TARGET_KIND_REGION:
8789 case GF_OMP_TARGET_KIND_UPDATE:
8790 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8791 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8792 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8793 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8794 data_region = false;
8795 break;
8796 case GF_OMP_TARGET_KIND_DATA:
8797 case GF_OMP_TARGET_KIND_OACC_DATA:
8798 data_region = true;
8799 break;
8800 default:
8801 gcc_unreachable ();
8804 child_fn = NULL_TREE;
8805 child_cfun = NULL;
8806 if (offloaded)
8808 child_fn = gimple_omp_target_child_fn (entry_stmt);
8809 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8812 /* Supported by expand_omp_taskreg, but not here. */
8813 if (child_cfun != NULL)
8814 gcc_checking_assert (!child_cfun->cfg);
8815 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8817 entry_bb = region->entry;
8818 exit_bb = region->exit;
8820 if (offloaded)
8822 unsigned srcidx, dstidx, num;
8824 /* If the offloading region needs data sent from the parent
8825 function, then the very first statement (except possible
8826 tree profile counter updates) of the offloading body
8827 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8828 &.OMP_DATA_O is passed as an argument to the child function,
8829 we need to replace it with the argument as seen by the child
8830 function.
8832 In most cases, this will end up being the identity assignment
8833 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8834 a function call that has been inlined, the original PARM_DECL
8835 .OMP_DATA_I may have been converted into a different local
8836 variable. In which case, we need to keep the assignment. */
8837 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8838 if (data_arg)
8840 basic_block entry_succ_bb = single_succ (entry_bb);
8841 gimple_stmt_iterator gsi;
8842 tree arg;
8843 gimple tgtcopy_stmt = NULL;
8844 tree sender = TREE_VEC_ELT (data_arg, 0);
8846 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8848 gcc_assert (!gsi_end_p (gsi));
8849 stmt = gsi_stmt (gsi);
8850 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8851 continue;
8853 if (gimple_num_ops (stmt) == 2)
8855 tree arg = gimple_assign_rhs1 (stmt);
8857 /* We're ignoring the subcode because we're
8858 effectively doing a STRIP_NOPS. */
8860 if (TREE_CODE (arg) == ADDR_EXPR
8861 && TREE_OPERAND (arg, 0) == sender)
8863 tgtcopy_stmt = stmt;
8864 break;
8869 gcc_assert (tgtcopy_stmt != NULL);
8870 arg = DECL_ARGUMENTS (child_fn);
8872 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8873 gsi_remove (&gsi, true);
8876 /* Declare local variables needed in CHILD_CFUN. */
8877 block = DECL_INITIAL (child_fn);
8878 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8879 /* The gimplifier could record temporaries in the offloading block
8880 rather than in containing function's local_decls chain,
8881 which would mean cgraph missed finalizing them. Do it now. */
8882 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8883 if (TREE_CODE (t) == VAR_DECL
8884 && TREE_STATIC (t)
8885 && !DECL_EXTERNAL (t))
8886 varpool_node::finalize_decl (t);
8887 DECL_SAVED_TREE (child_fn) = NULL;
8888 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8889 gimple_set_body (child_fn, NULL);
8890 TREE_USED (block) = 1;
8892 /* Reset DECL_CONTEXT on function arguments. */
8893 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8894 DECL_CONTEXT (t) = child_fn;
8896 /* Split ENTRY_BB at GIMPLE_*,
8897 so that it can be moved to the child function. */
8898 gsi = gsi_last_bb (entry_bb);
8899 stmt = gsi_stmt (gsi);
8900 gcc_assert (stmt
8901 && gimple_code (stmt) == gimple_code (entry_stmt));
8902 e = split_block (entry_bb, stmt);
8903 gsi_remove (&gsi, true);
8904 entry_bb = e->dest;
8905 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8907 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8908 if (exit_bb)
8910 gsi = gsi_last_bb (exit_bb);
8911 gcc_assert (!gsi_end_p (gsi)
8912 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8913 stmt = gimple_build_return (NULL);
8914 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8915 gsi_remove (&gsi, true);
8918 /* Move the offloading region into CHILD_CFUN. */
8920 block = gimple_block (entry_stmt);
8922 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8923 if (exit_bb)
8924 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8925 /* When the OMP expansion process cannot guarantee an up-to-date
8926 loop tree arrange for the child function to fixup loops. */
8927 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8928 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8930 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8931 num = vec_safe_length (child_cfun->local_decls);
8932 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8934 t = (*child_cfun->local_decls)[srcidx];
8935 if (DECL_CONTEXT (t) == cfun->decl)
8936 continue;
8937 if (srcidx != dstidx)
8938 (*child_cfun->local_decls)[dstidx] = t;
8939 dstidx++;
8941 if (dstidx != num)
8942 vec_safe_truncate (child_cfun->local_decls, dstidx);
8944 /* Inform the callgraph about the new function. */
8945 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8946 cgraph_node::add_new_function (child_fn, true);
8948 #ifdef ENABLE_OFFLOADING
8949 /* Add the new function to the offload table. */
8950 vec_safe_push (offload_funcs, child_fn);
8951 #endif
8953 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8954 fixed in a following pass. */
8955 push_cfun (child_cfun);
8956 cgraph_edge::rebuild_edges ();
8958 #ifdef ENABLE_OFFLOADING
8959 /* Prevent IPA from removing child_fn as unreachable, since there are no
8960 refs from the parent function to child_fn in offload LTO mode. */
8961 struct cgraph_node *node = cgraph_node::get (child_fn);
8962 node->mark_force_output ();
8963 #endif
8965 /* Some EH regions might become dead, see PR34608. If
8966 pass_cleanup_cfg isn't the first pass to happen with the
8967 new child, these dead EH edges might cause problems.
8968 Clean them up now. */
8969 if (flag_exceptions)
8971 basic_block bb;
8972 bool changed = false;
8974 FOR_EACH_BB_FN (bb, cfun)
8975 changed |= gimple_purge_dead_eh_edges (bb);
8976 if (changed)
8977 cleanup_tree_cfg ();
8979 pop_cfun ();
8982 /* Emit a library call to launch the offloading region, or do data
8983 transfers. */
8984 tree t1, t2, t3, t4, device, cond, c, clauses;
8985 enum built_in_function start_ix;
8986 location_t clause_loc;
8988 switch (gimple_omp_target_kind (entry_stmt))
8990 case GF_OMP_TARGET_KIND_REGION:
8991 start_ix = BUILT_IN_GOMP_TARGET;
8992 break;
8993 case GF_OMP_TARGET_KIND_DATA:
8994 start_ix = BUILT_IN_GOMP_TARGET_DATA;
8995 break;
8996 case GF_OMP_TARGET_KIND_UPDATE:
8997 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
8998 break;
8999 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9000 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9001 start_ix = BUILT_IN_GOACC_PARALLEL;
9002 break;
9003 case GF_OMP_TARGET_KIND_OACC_DATA:
9004 start_ix = BUILT_IN_GOACC_DATA_START;
9005 break;
9006 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9007 start_ix = BUILT_IN_GOACC_UPDATE;
9008 break;
9009 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9010 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9011 break;
9012 default:
9013 gcc_unreachable ();
9016 clauses = gimple_omp_target_clauses (entry_stmt);
9018 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9019 library choose) and there is no conditional. */
9020 cond = NULL_TREE;
9021 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
9023 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9024 if (c)
9025 cond = OMP_CLAUSE_IF_EXPR (c);
9027 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9028 if (c)
9030 /* Even if we pass it to all library function calls, it is currently only
9031 defined/used for the OpenMP target ones. */
9032 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9033 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9034 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9036 device = OMP_CLAUSE_DEVICE_ID (c);
9037 clause_loc = OMP_CLAUSE_LOCATION (c);
9039 else
9040 clause_loc = gimple_location (entry_stmt);
9042 /* Ensure 'device' is of the correct type. */
9043 device = fold_convert_loc (clause_loc, integer_type_node, device);
9045 /* If we found the clause 'if (cond)', build
9046 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9047 if (cond)
9049 cond = gimple_boolify (cond);
9051 basic_block cond_bb, then_bb, else_bb;
9052 edge e;
9053 tree tmp_var;
9055 tmp_var = create_tmp_var (TREE_TYPE (device));
9056 if (offloaded)
9057 e = split_block_after_labels (new_bb);
9058 else
9060 gsi = gsi_last_bb (new_bb);
9061 gsi_prev (&gsi);
9062 e = split_block (new_bb, gsi_stmt (gsi));
9064 cond_bb = e->src;
9065 new_bb = e->dest;
9066 remove_edge (e);
9068 then_bb = create_empty_bb (cond_bb);
9069 else_bb = create_empty_bb (then_bb);
9070 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9071 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9073 stmt = gimple_build_cond_empty (cond);
9074 gsi = gsi_last_bb (cond_bb);
9075 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9077 gsi = gsi_start_bb (then_bb);
9078 stmt = gimple_build_assign (tmp_var, device);
9079 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9081 gsi = gsi_start_bb (else_bb);
9082 stmt = gimple_build_assign (tmp_var,
9083 build_int_cst (integer_type_node,
9084 GOMP_DEVICE_HOST_FALLBACK));
9085 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9087 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9088 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9089 add_bb_to_loop (then_bb, cond_bb->loop_father);
9090 add_bb_to_loop (else_bb, cond_bb->loop_father);
9091 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9092 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9094 device = tmp_var;
9097 gsi = gsi_last_bb (new_bb);
9098 t = gimple_omp_target_data_arg (entry_stmt);
9099 if (t == NULL)
9101 t1 = size_zero_node;
9102 t2 = build_zero_cst (ptr_type_node);
9103 t3 = t2;
9104 t4 = t2;
9106 else
9108 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9109 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9110 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9111 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9112 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9115 gimple g;
9116 /* The maximum number used by any start_ix, without varargs. */
9117 auto_vec<tree, 11> args;
9118 args.quick_push (device);
9119 if (offloaded)
9120 args.quick_push (build_fold_addr_expr (child_fn));
9121 switch (start_ix)
9123 case BUILT_IN_GOMP_TARGET:
9124 case BUILT_IN_GOMP_TARGET_DATA:
9125 case BUILT_IN_GOMP_TARGET_UPDATE:
9126 /* This const void * is part of the current ABI, but we're not actually
9127 using it. */
9128 args.quick_push (build_zero_cst (ptr_type_node));
9129 break;
9130 case BUILT_IN_GOACC_DATA_START:
9131 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9132 case BUILT_IN_GOACC_PARALLEL:
9133 case BUILT_IN_GOACC_UPDATE:
9134 break;
9135 default:
9136 gcc_unreachable ();
9138 args.quick_push (t1);
9139 args.quick_push (t2);
9140 args.quick_push (t3);
9141 args.quick_push (t4);
9142 switch (start_ix)
9144 case BUILT_IN_GOACC_DATA_START:
9145 case BUILT_IN_GOMP_TARGET:
9146 case BUILT_IN_GOMP_TARGET_DATA:
9147 case BUILT_IN_GOMP_TARGET_UPDATE:
9148 break;
9149 case BUILT_IN_GOACC_PARALLEL:
9151 tree t_num_gangs, t_num_workers, t_vector_length;
9153 /* Default values for num_gangs, num_workers, and vector_length. */
9154 t_num_gangs = t_num_workers = t_vector_length
9155 = fold_convert_loc (gimple_location (entry_stmt),
9156 integer_type_node, integer_one_node);
9157 /* ..., but if present, use the value specified by the respective
9158 clause, making sure that are of the correct type. */
9159 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9160 if (c)
9161 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9162 integer_type_node,
9163 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9164 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9165 if (c)
9166 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9167 integer_type_node,
9168 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9169 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9170 if (c)
9171 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9172 integer_type_node,
9173 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9174 args.quick_push (t_num_gangs);
9175 args.quick_push (t_num_workers);
9176 args.quick_push (t_vector_length);
9178 /* FALLTHRU */
9179 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9180 case BUILT_IN_GOACC_UPDATE:
9182 tree t_async;
9183 int t_wait_idx;
9185 /* Default values for t_async. */
9186 t_async = fold_convert_loc (gimple_location (entry_stmt),
9187 integer_type_node,
9188 build_int_cst (integer_type_node,
9189 GOMP_ASYNC_SYNC));
9190 /* ..., but if present, use the value specified by the respective
9191 clause, making sure that is of the correct type. */
9192 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9193 if (c)
9194 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9195 integer_type_node,
9196 OMP_CLAUSE_ASYNC_EXPR (c));
9198 args.quick_push (t_async);
9199 /* Save the index, and... */
9200 t_wait_idx = args.length ();
9201 /* ... push a default value. */
9202 args.quick_push (fold_convert_loc (gimple_location (entry_stmt),
9203 integer_type_node,
9204 integer_zero_node));
9205 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9206 if (c)
9208 int n = 0;
9210 for (; c; c = OMP_CLAUSE_CHAIN (c))
9212 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9214 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9215 integer_type_node,
9216 OMP_CLAUSE_WAIT_EXPR (c)));
9217 n++;
9221 /* Now that we know the number, replace the default value. */
9222 args.ordered_remove (t_wait_idx);
9223 args.quick_insert (t_wait_idx,
9224 fold_convert_loc (gimple_location (entry_stmt),
9225 integer_type_node,
9226 build_int_cst (integer_type_node, n)));
9229 break;
9230 default:
9231 gcc_unreachable ();
9234 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
9235 gimple_set_location (g, gimple_location (entry_stmt));
9236 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9237 if (!offloaded)
9239 g = gsi_stmt (gsi);
9240 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9241 gsi_remove (&gsi, true);
9243 if (data_region
9244 && region->exit)
9246 gsi = gsi_last_bb (region->exit);
9247 g = gsi_stmt (gsi);
9248 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9249 gsi_remove (&gsi, true);
9254 /* Expand the parallel region tree rooted at REGION. Expansion
9255 proceeds in depth-first order. Innermost regions are expanded
9256 first. This way, parallel regions that require a new function to
9257 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9258 internal dependencies in their body. */
9260 static void
9261 expand_omp (struct omp_region *region)
9263 while (region)
9265 location_t saved_location;
9266 gimple inner_stmt = NULL;
9268 /* First, determine whether this is a combined parallel+workshare
9269 region. */
9270 if (region->type == GIMPLE_OMP_PARALLEL)
9271 determine_parallel_type (region);
9273 if (region->type == GIMPLE_OMP_FOR
9274 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9275 inner_stmt = last_stmt (region->inner->entry);
9277 if (region->inner)
9278 expand_omp (region->inner);
9280 saved_location = input_location;
9281 if (gimple_has_location (last_stmt (region->entry)))
9282 input_location = gimple_location (last_stmt (region->entry));
9284 switch (region->type)
9286 case GIMPLE_OMP_PARALLEL:
9287 case GIMPLE_OMP_TASK:
9288 expand_omp_taskreg (region);
9289 break;
9291 case GIMPLE_OMP_FOR:
9292 expand_omp_for (region, inner_stmt);
9293 break;
9295 case GIMPLE_OMP_SECTIONS:
9296 expand_omp_sections (region);
9297 break;
9299 case GIMPLE_OMP_SECTION:
9300 /* Individual omp sections are handled together with their
9301 parent GIMPLE_OMP_SECTIONS region. */
9302 break;
9304 case GIMPLE_OMP_SINGLE:
9305 expand_omp_single (region);
9306 break;
9308 case GIMPLE_OMP_MASTER:
9309 case GIMPLE_OMP_TASKGROUP:
9310 case GIMPLE_OMP_ORDERED:
9311 case GIMPLE_OMP_CRITICAL:
9312 case GIMPLE_OMP_TEAMS:
9313 expand_omp_synch (region);
9314 break;
9316 case GIMPLE_OMP_ATOMIC_LOAD:
9317 expand_omp_atomic (region);
9318 break;
9320 case GIMPLE_OMP_TARGET:
9321 expand_omp_target (region);
9322 break;
9324 default:
9325 gcc_unreachable ();
9328 input_location = saved_location;
9329 region = region->next;
9334 /* Helper for build_omp_regions. Scan the dominator tree starting at
9335 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9336 true, the function ends once a single tree is built (otherwise, whole
9337 forest of OMP constructs may be built). */
9339 static void
9340 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9341 bool single_tree)
9343 gimple_stmt_iterator gsi;
9344 gimple stmt;
9345 basic_block son;
9347 gsi = gsi_last_bb (bb);
9348 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9350 struct omp_region *region;
9351 enum gimple_code code;
9353 stmt = gsi_stmt (gsi);
9354 code = gimple_code (stmt);
9355 if (code == GIMPLE_OMP_RETURN)
9357 /* STMT is the return point out of region PARENT. Mark it
9358 as the exit point and make PARENT the immediately
9359 enclosing region. */
9360 gcc_assert (parent);
9361 region = parent;
9362 region->exit = bb;
9363 parent = parent->outer;
9365 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9367 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9368 GIMPLE_OMP_RETURN, but matches with
9369 GIMPLE_OMP_ATOMIC_LOAD. */
9370 gcc_assert (parent);
9371 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9372 region = parent;
9373 region->exit = bb;
9374 parent = parent->outer;
9376 else if (code == GIMPLE_OMP_CONTINUE)
9378 gcc_assert (parent);
9379 parent->cont = bb;
9381 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9383 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9384 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9386 else
9388 region = new_omp_region (bb, code, parent);
9389 /* Otherwise... */
9390 if (code == GIMPLE_OMP_TARGET)
9392 switch (gimple_omp_target_kind (stmt))
9394 case GF_OMP_TARGET_KIND_REGION:
9395 case GF_OMP_TARGET_KIND_DATA:
9396 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9397 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9398 case GF_OMP_TARGET_KIND_OACC_DATA:
9399 break;
9400 case GF_OMP_TARGET_KIND_UPDATE:
9401 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9402 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9403 /* ..., other than for those stand-alone directives... */
9404 region = NULL;
9405 break;
9406 default:
9407 gcc_unreachable ();
9410 /* ..., this directive becomes the parent for a new region. */
9411 if (region)
9412 parent = region;
9416 if (single_tree && !parent)
9417 return;
9419 for (son = first_dom_son (CDI_DOMINATORS, bb);
9420 son;
9421 son = next_dom_son (CDI_DOMINATORS, son))
9422 build_omp_regions_1 (son, parent, single_tree);
9425 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9426 root_omp_region. */
9428 static void
9429 build_omp_regions_root (basic_block root)
9431 gcc_assert (root_omp_region == NULL);
9432 build_omp_regions_1 (root, NULL, true);
9433 gcc_assert (root_omp_region != NULL);
9436 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9438 void
9439 omp_expand_local (basic_block head)
9441 build_omp_regions_root (head);
9442 if (dump_file && (dump_flags & TDF_DETAILS))
9444 fprintf (dump_file, "\nOMP region tree\n\n");
9445 dump_omp_region (dump_file, root_omp_region, 0);
9446 fprintf (dump_file, "\n");
9449 remove_exit_barriers (root_omp_region);
9450 expand_omp (root_omp_region);
9452 free_omp_regions ();
9455 /* Scan the CFG and build a tree of OMP regions. Return the root of
9456 the OMP region tree. */
9458 static void
9459 build_omp_regions (void)
9461 gcc_assert (root_omp_region == NULL);
9462 calculate_dominance_info (CDI_DOMINATORS);
9463 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9466 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9468 static unsigned int
9469 execute_expand_omp (void)
9471 build_omp_regions ();
9473 if (!root_omp_region)
9474 return 0;
9476 if (dump_file)
9478 fprintf (dump_file, "\nOMP region tree\n\n");
9479 dump_omp_region (dump_file, root_omp_region, 0);
9480 fprintf (dump_file, "\n");
9483 remove_exit_barriers (root_omp_region);
9485 expand_omp (root_omp_region);
9487 cleanup_tree_cfg ();
9489 free_omp_regions ();
9491 return 0;
9494 /* OMP expansion -- the default pass, run before creation of SSA form. */
9496 namespace {
9498 const pass_data pass_data_expand_omp =
9500 GIMPLE_PASS, /* type */
9501 "ompexp", /* name */
9502 OPTGROUP_NONE, /* optinfo_flags */
9503 TV_NONE, /* tv_id */
9504 PROP_gimple_any, /* properties_required */
9505 PROP_gimple_eomp, /* properties_provided */
9506 0, /* properties_destroyed */
9507 0, /* todo_flags_start */
9508 0, /* todo_flags_finish */
9511 class pass_expand_omp : public gimple_opt_pass
9513 public:
9514 pass_expand_omp (gcc::context *ctxt)
9515 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9518 /* opt_pass methods: */
9519 virtual unsigned int execute (function *)
9521 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9522 || flag_openmp_simd != 0)
9523 && !seen_error ());
9525 /* This pass always runs, to provide PROP_gimple_eomp.
9526 But often, there is nothing to do. */
9527 if (!gate)
9528 return 0;
9530 return execute_expand_omp ();
9533 }; // class pass_expand_omp
9535 } // anon namespace
9537 gimple_opt_pass *
9538 make_pass_expand_omp (gcc::context *ctxt)
9540 return new pass_expand_omp (ctxt);
9543 namespace {
9545 const pass_data pass_data_expand_omp_ssa =
9547 GIMPLE_PASS, /* type */
9548 "ompexpssa", /* name */
9549 OPTGROUP_NONE, /* optinfo_flags */
9550 TV_NONE, /* tv_id */
9551 PROP_cfg | PROP_ssa, /* properties_required */
9552 PROP_gimple_eomp, /* properties_provided */
9553 0, /* properties_destroyed */
9554 0, /* todo_flags_start */
9555 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9558 class pass_expand_omp_ssa : public gimple_opt_pass
9560 public:
9561 pass_expand_omp_ssa (gcc::context *ctxt)
9562 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9565 /* opt_pass methods: */
9566 virtual bool gate (function *fun)
9568 return !(fun->curr_properties & PROP_gimple_eomp);
9570 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9572 }; // class pass_expand_omp_ssa
9574 } // anon namespace
9576 gimple_opt_pass *
9577 make_pass_expand_omp_ssa (gcc::context *ctxt)
9579 return new pass_expand_omp_ssa (ctxt);
9582 /* Routines to lower OMP directives into OMP-GIMPLE. */
9584 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9585 convert it to gimple. */
9586 static void
9587 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9589 gimple stmt;
9591 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9593 stmt = gimple_build_assign (dest, op, dest, src);
9594 gimple_seq_add_stmt (seq, stmt);
9595 return;
9598 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9599 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9600 gimplify_assign (t, rdest, seq);
9601 rdest = t;
9603 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9604 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9605 gimplify_assign (t, idest, seq);
9606 idest = t;
9608 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9609 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9610 gimplify_assign (t, rsrc, seq);
9611 rsrc = t;
9613 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9614 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9615 gimplify_assign (t, isrc, seq);
9616 isrc = t;
9618 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9619 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9620 tree result;
9622 if (op == PLUS_EXPR)
9624 stmt = gimple_build_assign (r, op, rdest, rsrc);
9625 gimple_seq_add_stmt (seq, stmt);
9627 stmt = gimple_build_assign (i, op, idest, isrc);
9628 gimple_seq_add_stmt (seq, stmt);
9630 else if (op == MULT_EXPR)
9632 /* Let x = a + ib = dest, y = c + id = src.
9633 x * y = (ac - bd) + i(ad + bc) */
9634 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9635 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9636 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9637 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9639 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9640 gimple_seq_add_stmt (seq, stmt);
9642 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9643 gimple_seq_add_stmt (seq, stmt);
9645 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9646 gimple_seq_add_stmt (seq, stmt);
9648 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9649 gimple_seq_add_stmt (seq, stmt);
9651 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9652 gimple_seq_add_stmt (seq, stmt);
9654 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9655 gimple_seq_add_stmt (seq, stmt);
9657 else
9658 gcc_unreachable ();
9660 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9661 gimplify_assign (dest, result, seq);
9664 /* Helper function to initialize local data for the reduction arrays.
9665 The reduction arrays need to be placed inside the calling function
9666 for accelerators, or else the host won't be able to preform the final
9667 reduction. */
9669 static void
9670 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9671 gimple_seq *stmt_seqp, omp_context *ctx)
9673 tree c, t, oc;
9674 gimple stmt;
9675 omp_context *octx;
9677 /* Find the innermost OpenACC parallel context. */
9678 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9679 && (gimple_omp_target_kind (ctx->stmt)
9680 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9681 octx = ctx;
9682 else
9683 octx = ctx->outer;
9684 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9685 && (gimple_omp_target_kind (octx->stmt)
9686 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9688 /* Extract the clauses. */
9689 oc = gimple_omp_target_clauses (octx->stmt);
9691 /* Find the last outer clause. */
9692 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9695 /* Allocate arrays for each reduction variable. */
9696 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9698 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9699 continue;
9701 tree var = OMP_CLAUSE_DECL (c);
9702 tree type = get_base_type (var);
9703 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9704 ctx);
9705 tree size, call;
9707 /* Calculate size of the reduction array. */
9708 t = create_tmp_var (TREE_TYPE (nthreads));
9709 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9710 fold_convert (TREE_TYPE (nthreads),
9711 TYPE_SIZE_UNIT (type)));
9712 gimple_seq_add_stmt (stmt_seqp, stmt);
9714 size = create_tmp_var (sizetype);
9715 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9717 /* Now allocate memory for it. */
9718 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9719 stmt = gimple_build_call (call, 1, size);
9720 gimple_call_set_lhs (stmt, array);
9721 gimple_seq_add_stmt (stmt_seqp, stmt);
9723 /* Map this array into the accelerator. */
9725 /* Add the reduction array to the list of clauses. */
9726 tree x = array;
9727 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9728 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9729 OMP_CLAUSE_DECL (t) = x;
9730 OMP_CLAUSE_CHAIN (t) = NULL;
9731 if (oc)
9732 OMP_CLAUSE_CHAIN (oc) = t;
9733 else
9734 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9735 OMP_CLAUSE_SIZE (t) = size;
9736 oc = t;
9740 /* Helper function to process the array of partial reductions. Nthreads
9741 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9742 cannot be used here, because nthreads on the host may be different than
9743 on the accelerator. */
9745 static void
9746 oacc_finalize_reduction_data (tree clauses, tree nthreads,
9747 gimple_seq *stmt_seqp, omp_context *ctx)
9749 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9750 gimple stmt;
9752 /* Create for loop.
9754 let var = the original reduction variable
9755 let array = reduction variable array
9757 for (i = 0; i < nthreads; i++)
9758 var op= array[i]
9761 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9762 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9763 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9765 /* Create and initialize an index variable. */
9766 tree ix = create_tmp_var (sizetype);
9767 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9768 stmt_seqp);
9770 /* Insert the loop header label here. */
9771 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9773 /* Exit loop if ix >= nthreads. */
9774 x = create_tmp_var (sizetype);
9775 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9776 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9777 gimple_seq_add_stmt (stmt_seqp, stmt);
9779 /* Insert the loop body label here. */
9780 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9782 /* Collapse each reduction array, one element at a time. */
9783 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9785 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9786 continue;
9788 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9790 /* reduction(-:var) sums up the partial results, so it acts
9791 identically to reduction(+:var). */
9792 if (reduction_code == MINUS_EXPR)
9793 reduction_code = PLUS_EXPR;
9795 /* Set up reduction variable var. */
9796 var = OMP_CLAUSE_DECL (c);
9797 type = get_base_type (var);
9798 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9799 (OMP_CLAUSE_DECL (c)), ctx);
9801 /* Calculate the array offset. */
9802 tree offset = create_tmp_var (sizetype);
9803 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9804 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9805 gimple_seq_add_stmt (stmt_seqp, stmt);
9807 tree ptr = create_tmp_var (TREE_TYPE (array));
9808 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9809 gimple_seq_add_stmt (stmt_seqp, stmt);
9811 /* Extract array[ix] into mem. */
9812 tree mem = create_tmp_var (type);
9813 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9815 /* Find the original reduction variable. */
9816 if (is_reference (var))
9817 var = build_simple_mem_ref (var);
9819 tree t = create_tmp_var (type);
9821 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9822 gimplify_and_add (unshare_expr(x), stmt_seqp);
9824 /* var = var op mem */
9825 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9827 case TRUTH_ANDIF_EXPR:
9828 case TRUTH_ORIF_EXPR:
9829 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9830 t, mem);
9831 gimplify_and_add (t, stmt_seqp);
9832 break;
9833 default:
9834 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9835 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9836 stmt_seqp);
9839 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9840 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9841 gimplify_and_add (unshare_expr(x), stmt_seqp);
9844 /* Increment the induction variable. */
9845 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9846 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9847 gimple_seq_add_stmt (stmt_seqp, stmt);
9849 /* Go back to the top of the loop. */
9850 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9852 /* Place the loop exit label here. */
9853 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9856 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9857 scan that for reductions. */
9859 static void
9860 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9861 gimple_seq *out_stmt_seqp, omp_context *ctx)
9863 gimple_stmt_iterator gsi;
9864 gimple_seq inner = NULL;
9866 /* A collapse clause may have inserted a new bind block. */
9867 gsi = gsi_start (*body);
9868 while (!gsi_end_p (gsi))
9870 gimple stmt = gsi_stmt (gsi);
9871 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9873 inner = gimple_bind_body (bind_stmt);
9874 body = &inner;
9875 gsi = gsi_start (*body);
9877 else if (dyn_cast <gomp_for *> (stmt))
9878 break;
9879 else
9880 gsi_next (&gsi);
9883 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9885 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9886 enter, exit;
9887 bool reduction_found = false;
9889 gimple stmt = gsi_stmt (gsi);
9891 switch (gimple_code (stmt))
9893 case GIMPLE_OMP_FOR:
9894 clauses = gimple_omp_for_clauses (stmt);
9896 /* Search for a reduction clause. */
9897 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9898 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9900 reduction_found = true;
9901 break;
9904 if (!reduction_found)
9905 break;
9907 ctx = maybe_lookup_ctx (stmt);
9908 t = NULL_TREE;
9910 /* Extract the number of threads. */
9911 nthreads = create_tmp_var (sizetype);
9912 t = oacc_max_threads (ctx);
9913 gimplify_assign (nthreads, t, in_stmt_seqp);
9915 /* Determine if this is kernel will be executed on the host. */
9916 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9917 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9918 stmt = gimple_build_call (call, 0);
9919 gimple_call_set_lhs (stmt, acc_device);
9920 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9922 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9923 acc_device_host = create_tmp_var (integer_type_node,
9924 ".acc_device_host");
9925 gimplify_assign (acc_device_host,
9926 build_int_cst (integer_type_node,
9927 GOMP_DEVICE_HOST),
9928 in_stmt_seqp);
9930 enter = create_artificial_label (UNKNOWN_LOCATION);
9931 exit = create_artificial_label (UNKNOWN_LOCATION);
9933 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9934 enter, exit);
9935 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9936 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9937 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9938 integer_one_node),
9939 in_stmt_seqp);
9940 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9942 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9943 gimplify_assign (acc_device_host,
9944 build_int_cst (integer_type_node,
9945 GOMP_DEVICE_HOST_NONSHM),
9946 in_stmt_seqp);
9948 enter = create_artificial_label (UNKNOWN_LOCATION);
9949 exit = create_artificial_label (UNKNOWN_LOCATION);
9951 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9952 enter, exit);
9953 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9954 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9955 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9956 integer_one_node),
9957 in_stmt_seqp);
9958 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9960 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9961 ctx);
9962 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9963 break;
9964 default:
9965 // Scan for other directives which support reduction here.
9966 break;
9971 /* If ctx is a worksharing context inside of a cancellable parallel
9972 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9973 and conditional branch to parallel's cancel_label to handle
9974 cancellation in the implicit barrier. */
9976 static void
9977 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9979 gimple omp_return = gimple_seq_last_stmt (*body);
9980 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
9981 if (gimple_omp_return_nowait_p (omp_return))
9982 return;
9983 if (ctx->outer
9984 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
9985 && ctx->outer->cancellable)
9987 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
9988 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
9989 tree lhs = create_tmp_var (c_bool_type);
9990 gimple_omp_return_set_lhs (omp_return, lhs);
9991 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
9992 gimple g = gimple_build_cond (NE_EXPR, lhs,
9993 fold_convert (c_bool_type,
9994 boolean_false_node),
9995 ctx->outer->cancel_label, fallthru_label);
9996 gimple_seq_add_stmt (body, g);
9997 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10001 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10002 CTX is the enclosing OMP context for the current statement. */
10004 static void
10005 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10007 tree block, control;
10008 gimple_stmt_iterator tgsi;
10009 gomp_sections *stmt;
10010 gimple t;
10011 gbind *new_stmt, *bind;
10012 gimple_seq ilist, dlist, olist, new_body;
10014 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
10016 push_gimplify_context ();
10018 dlist = NULL;
10019 ilist = NULL;
10020 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10021 &ilist, &dlist, ctx, NULL);
10023 new_body = gimple_omp_body (stmt);
10024 gimple_omp_set_body (stmt, NULL);
10025 tgsi = gsi_start (new_body);
10026 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10028 omp_context *sctx;
10029 gimple sec_start;
10031 sec_start = gsi_stmt (tgsi);
10032 sctx = maybe_lookup_ctx (sec_start);
10033 gcc_assert (sctx);
10035 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10036 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10037 GSI_CONTINUE_LINKING);
10038 gimple_omp_set_body (sec_start, NULL);
10040 if (gsi_one_before_end_p (tgsi))
10042 gimple_seq l = NULL;
10043 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10044 &l, ctx);
10045 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10046 gimple_omp_section_set_last (sec_start);
10049 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10050 GSI_CONTINUE_LINKING);
10053 block = make_node (BLOCK);
10054 bind = gimple_build_bind (NULL, new_body, block);
10056 olist = NULL;
10057 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10059 block = make_node (BLOCK);
10060 new_stmt = gimple_build_bind (NULL, NULL, block);
10061 gsi_replace (gsi_p, new_stmt, true);
10063 pop_gimplify_context (new_stmt);
10064 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10065 BLOCK_VARS (block) = gimple_bind_vars (bind);
10066 if (BLOCK_VARS (block))
10067 TREE_USED (block) = 1;
10069 new_body = NULL;
10070 gimple_seq_add_seq (&new_body, ilist);
10071 gimple_seq_add_stmt (&new_body, stmt);
10072 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10073 gimple_seq_add_stmt (&new_body, bind);
10075 control = create_tmp_var (unsigned_type_node, ".section");
10076 t = gimple_build_omp_continue (control, control);
10077 gimple_omp_sections_set_control (stmt, control);
10078 gimple_seq_add_stmt (&new_body, t);
10080 gimple_seq_add_seq (&new_body, olist);
10081 if (ctx->cancellable)
10082 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10083 gimple_seq_add_seq (&new_body, dlist);
10085 new_body = maybe_catch_exception (new_body);
10087 t = gimple_build_omp_return
10088 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10089 OMP_CLAUSE_NOWAIT));
10090 gimple_seq_add_stmt (&new_body, t);
10091 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10093 gimple_bind_set_body (new_stmt, new_body);
10097 /* A subroutine of lower_omp_single. Expand the simple form of
10098 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10100 if (GOMP_single_start ())
10101 BODY;
10102 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10104 FIXME. It may be better to delay expanding the logic of this until
10105 pass_expand_omp. The expanded logic may make the job more difficult
10106 to a synchronization analysis pass. */
10108 static void
10109 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10111 location_t loc = gimple_location (single_stmt);
10112 tree tlabel = create_artificial_label (loc);
10113 tree flabel = create_artificial_label (loc);
10114 gimple call, cond;
10115 tree lhs, decl;
10117 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10118 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10119 call = gimple_build_call (decl, 0);
10120 gimple_call_set_lhs (call, lhs);
10121 gimple_seq_add_stmt (pre_p, call);
10123 cond = gimple_build_cond (EQ_EXPR, lhs,
10124 fold_convert_loc (loc, TREE_TYPE (lhs),
10125 boolean_true_node),
10126 tlabel, flabel);
10127 gimple_seq_add_stmt (pre_p, cond);
10128 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10129 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10130 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10134 /* A subroutine of lower_omp_single. Expand the simple form of
10135 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10137 #pragma omp single copyprivate (a, b, c)
10139 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10142 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10144 BODY;
10145 copyout.a = a;
10146 copyout.b = b;
10147 copyout.c = c;
10148 GOMP_single_copy_end (&copyout);
10150 else
10152 a = copyout_p->a;
10153 b = copyout_p->b;
10154 c = copyout_p->c;
10156 GOMP_barrier ();
10159 FIXME. It may be better to delay expanding the logic of this until
10160 pass_expand_omp. The expanded logic may make the job more difficult
10161 to a synchronization analysis pass. */
10163 static void
10164 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10165 omp_context *ctx)
10167 tree ptr_type, t, l0, l1, l2, bfn_decl;
10168 gimple_seq copyin_seq;
10169 location_t loc = gimple_location (single_stmt);
10171 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10173 ptr_type = build_pointer_type (ctx->record_type);
10174 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10176 l0 = create_artificial_label (loc);
10177 l1 = create_artificial_label (loc);
10178 l2 = create_artificial_label (loc);
10180 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10181 t = build_call_expr_loc (loc, bfn_decl, 0);
10182 t = fold_convert_loc (loc, ptr_type, t);
10183 gimplify_assign (ctx->receiver_decl, t, pre_p);
10185 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10186 build_int_cst (ptr_type, 0));
10187 t = build3 (COND_EXPR, void_type_node, t,
10188 build_and_jump (&l0), build_and_jump (&l1));
10189 gimplify_and_add (t, pre_p);
10191 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10193 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10195 copyin_seq = NULL;
10196 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10197 &copyin_seq, ctx);
10199 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10200 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10201 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10202 gimplify_and_add (t, pre_p);
10204 t = build_and_jump (&l2);
10205 gimplify_and_add (t, pre_p);
10207 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10209 gimple_seq_add_seq (pre_p, copyin_seq);
10211 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10215 /* Expand code for an OpenMP single directive. */
10217 static void
10218 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10220 tree block;
10221 gimple t;
10222 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10223 gbind *bind;
10224 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10226 push_gimplify_context ();
10228 block = make_node (BLOCK);
10229 bind = gimple_build_bind (NULL, NULL, block);
10230 gsi_replace (gsi_p, bind, true);
10231 bind_body = NULL;
10232 dlist = NULL;
10233 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10234 &bind_body, &dlist, ctx, NULL);
10235 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10237 gimple_seq_add_stmt (&bind_body, single_stmt);
10239 if (ctx->record_type)
10240 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10241 else
10242 lower_omp_single_simple (single_stmt, &bind_body);
10244 gimple_omp_set_body (single_stmt, NULL);
10246 gimple_seq_add_seq (&bind_body, dlist);
10248 bind_body = maybe_catch_exception (bind_body);
10250 t = gimple_build_omp_return
10251 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10252 OMP_CLAUSE_NOWAIT));
10253 gimple_seq_add_stmt (&bind_body_tail, t);
10254 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10255 if (ctx->record_type)
10257 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10258 tree clobber = build_constructor (ctx->record_type, NULL);
10259 TREE_THIS_VOLATILE (clobber) = 1;
10260 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10261 clobber), GSI_SAME_STMT);
10263 gimple_seq_add_seq (&bind_body, bind_body_tail);
10264 gimple_bind_set_body (bind, bind_body);
10266 pop_gimplify_context (bind);
10268 gimple_bind_append_vars (bind, ctx->block_vars);
10269 BLOCK_VARS (block) = ctx->block_vars;
10270 if (BLOCK_VARS (block))
10271 TREE_USED (block) = 1;
10275 /* Expand code for an OpenMP master directive. */
10277 static void
10278 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10280 tree block, lab = NULL, x, bfn_decl;
10281 gimple stmt = gsi_stmt (*gsi_p);
10282 gbind *bind;
10283 location_t loc = gimple_location (stmt);
10284 gimple_seq tseq;
10286 push_gimplify_context ();
10288 block = make_node (BLOCK);
10289 bind = gimple_build_bind (NULL, NULL, block);
10290 gsi_replace (gsi_p, bind, true);
10291 gimple_bind_add_stmt (bind, stmt);
10293 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10294 x = build_call_expr_loc (loc, bfn_decl, 0);
10295 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10296 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10297 tseq = NULL;
10298 gimplify_and_add (x, &tseq);
10299 gimple_bind_add_seq (bind, tseq);
10301 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10302 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10303 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10304 gimple_omp_set_body (stmt, NULL);
10306 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10308 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10310 pop_gimplify_context (bind);
10312 gimple_bind_append_vars (bind, ctx->block_vars);
10313 BLOCK_VARS (block) = ctx->block_vars;
10317 /* Expand code for an OpenMP taskgroup directive. */
10319 static void
10320 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10322 gimple stmt = gsi_stmt (*gsi_p);
10323 gcall *x;
10324 gbind *bind;
10325 tree block = make_node (BLOCK);
10327 bind = gimple_build_bind (NULL, NULL, block);
10328 gsi_replace (gsi_p, bind, true);
10329 gimple_bind_add_stmt (bind, stmt);
10331 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10333 gimple_bind_add_stmt (bind, x);
10335 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10336 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10337 gimple_omp_set_body (stmt, NULL);
10339 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10341 gimple_bind_append_vars (bind, ctx->block_vars);
10342 BLOCK_VARS (block) = ctx->block_vars;
10346 /* Expand code for an OpenMP ordered directive. */
10348 static void
10349 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10351 tree block;
10352 gimple stmt = gsi_stmt (*gsi_p);
10353 gcall *x;
10354 gbind *bind;
10356 push_gimplify_context ();
10358 block = make_node (BLOCK);
10359 bind = gimple_build_bind (NULL, NULL, block);
10360 gsi_replace (gsi_p, bind, true);
10361 gimple_bind_add_stmt (bind, stmt);
10363 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10365 gimple_bind_add_stmt (bind, x);
10367 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10368 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10369 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10370 gimple_omp_set_body (stmt, NULL);
10372 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10373 gimple_bind_add_stmt (bind, x);
10375 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10377 pop_gimplify_context (bind);
10379 gimple_bind_append_vars (bind, ctx->block_vars);
10380 BLOCK_VARS (block) = gimple_bind_vars (bind);
10384 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10385 substitution of a couple of function calls. But in the NAMED case,
10386 requires that languages coordinate a symbol name. It is therefore
10387 best put here in common code. */
10389 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10391 static void
10392 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10394 tree block;
10395 tree name, lock, unlock;
10396 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10397 gbind *bind;
10398 location_t loc = gimple_location (stmt);
10399 gimple_seq tbody;
10401 name = gimple_omp_critical_name (stmt);
10402 if (name)
10404 tree decl;
10406 if (!critical_name_mutexes)
10407 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10409 tree *n = critical_name_mutexes->get (name);
10410 if (n == NULL)
10412 char *new_str;
10414 decl = create_tmp_var_raw (ptr_type_node);
10416 new_str = ACONCAT ((".gomp_critical_user_",
10417 IDENTIFIER_POINTER (name), NULL));
10418 DECL_NAME (decl) = get_identifier (new_str);
10419 TREE_PUBLIC (decl) = 1;
10420 TREE_STATIC (decl) = 1;
10421 DECL_COMMON (decl) = 1;
10422 DECL_ARTIFICIAL (decl) = 1;
10423 DECL_IGNORED_P (decl) = 1;
10425 varpool_node::finalize_decl (decl);
10427 critical_name_mutexes->put (name, decl);
10429 else
10430 decl = *n;
10432 /* If '#pragma omp critical' is inside offloaded region or
10433 inside function marked as offloadable, the symbol must be
10434 marked as offloadable too. */
10435 omp_context *octx;
10436 if (cgraph_node::get (current_function_decl)->offloadable)
10437 varpool_node::get_create (decl)->offloadable = 1;
10438 else
10439 for (octx = ctx->outer; octx; octx = octx->outer)
10440 if (is_gimple_omp_offloaded (octx->stmt))
10442 varpool_node::get_create (decl)->offloadable = 1;
10443 break;
10446 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10447 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10449 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10450 unlock = build_call_expr_loc (loc, unlock, 1,
10451 build_fold_addr_expr_loc (loc, decl));
10453 else
10455 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10456 lock = build_call_expr_loc (loc, lock, 0);
10458 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10459 unlock = build_call_expr_loc (loc, unlock, 0);
10462 push_gimplify_context ();
10464 block = make_node (BLOCK);
10465 bind = gimple_build_bind (NULL, NULL, block);
10466 gsi_replace (gsi_p, bind, true);
10467 gimple_bind_add_stmt (bind, stmt);
10469 tbody = gimple_bind_body (bind);
10470 gimplify_and_add (lock, &tbody);
10471 gimple_bind_set_body (bind, tbody);
10473 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10474 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10475 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10476 gimple_omp_set_body (stmt, NULL);
10478 tbody = gimple_bind_body (bind);
10479 gimplify_and_add (unlock, &tbody);
10480 gimple_bind_set_body (bind, tbody);
10482 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10484 pop_gimplify_context (bind);
10485 gimple_bind_append_vars (bind, ctx->block_vars);
10486 BLOCK_VARS (block) = gimple_bind_vars (bind);
10490 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10491 for a lastprivate clause. Given a loop control predicate of (V
10492 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10493 is appended to *DLIST, iterator initialization is appended to
10494 *BODY_P. */
10496 static void
10497 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10498 gimple_seq *dlist, struct omp_context *ctx)
10500 tree clauses, cond, vinit;
10501 enum tree_code cond_code;
10502 gimple_seq stmts;
10504 cond_code = fd->loop.cond_code;
10505 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10507 /* When possible, use a strict equality expression. This can let VRP
10508 type optimizations deduce the value and remove a copy. */
10509 if (tree_fits_shwi_p (fd->loop.step))
10511 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10512 if (step == 1 || step == -1)
10513 cond_code = EQ_EXPR;
10516 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
10518 clauses = gimple_omp_for_clauses (fd->for_stmt);
10519 stmts = NULL;
10520 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10521 if (!gimple_seq_empty_p (stmts))
10523 gimple_seq_add_seq (&stmts, *dlist);
10524 *dlist = stmts;
10526 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10527 vinit = fd->loop.n1;
10528 if (cond_code == EQ_EXPR
10529 && tree_fits_shwi_p (fd->loop.n2)
10530 && ! integer_zerop (fd->loop.n2))
10531 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10532 else
10533 vinit = unshare_expr (vinit);
10535 /* Initialize the iterator variable, so that threads that don't execute
10536 any iterations don't execute the lastprivate clauses by accident. */
10537 gimplify_assign (fd->loop.v, vinit, body_p);
10542 /* Lower code for an OMP loop directive. */
10544 static void
10545 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10547 tree *rhs_p, block;
10548 struct omp_for_data fd, *fdp = NULL;
10549 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10550 gbind *new_stmt;
10551 gimple_seq omp_for_body, body, dlist;
10552 size_t i;
10554 push_gimplify_context ();
10556 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10558 block = make_node (BLOCK);
10559 new_stmt = gimple_build_bind (NULL, NULL, block);
10560 /* Replace at gsi right away, so that 'stmt' is no member
10561 of a sequence anymore as we're going to add to to a different
10562 one below. */
10563 gsi_replace (gsi_p, new_stmt, true);
10565 /* Move declaration of temporaries in the loop body before we make
10566 it go away. */
10567 omp_for_body = gimple_omp_body (stmt);
10568 if (!gimple_seq_empty_p (omp_for_body)
10569 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10571 gbind *inner_bind
10572 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10573 tree vars = gimple_bind_vars (inner_bind);
10574 gimple_bind_append_vars (new_stmt, vars);
10575 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10576 keep them on the inner_bind and it's block. */
10577 gimple_bind_set_vars (inner_bind, NULL_TREE);
10578 if (gimple_bind_block (inner_bind))
10579 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10582 if (gimple_omp_for_combined_into_p (stmt))
10584 extract_omp_for_data (stmt, &fd, NULL);
10585 fdp = &fd;
10587 /* We need two temporaries with fd.loop.v type (istart/iend)
10588 and then (fd.collapse - 1) temporaries with the same
10589 type for count2 ... countN-1 vars if not constant. */
10590 size_t count = 2;
10591 tree type = fd.iter_type;
10592 if (fd.collapse > 1
10593 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10594 count += fd.collapse - 1;
10595 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10596 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10597 tree clauses = *pc;
10598 if (parallel_for)
10599 outerc
10600 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10601 OMP_CLAUSE__LOOPTEMP_);
10602 for (i = 0; i < count; i++)
10604 tree temp;
10605 if (parallel_for)
10607 gcc_assert (outerc);
10608 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10609 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10610 OMP_CLAUSE__LOOPTEMP_);
10612 else
10614 temp = create_tmp_var (type);
10615 insert_decl_map (&ctx->outer->cb, temp, temp);
10617 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10618 OMP_CLAUSE_DECL (*pc) = temp;
10619 pc = &OMP_CLAUSE_CHAIN (*pc);
10621 *pc = clauses;
10624 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10625 dlist = NULL;
10626 body = NULL;
10627 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10628 fdp);
10629 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10631 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10633 /* Lower the header expressions. At this point, we can assume that
10634 the header is of the form:
10636 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10638 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10639 using the .omp_data_s mapping, if needed. */
10640 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10642 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10643 if (!is_gimple_min_invariant (*rhs_p))
10644 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10646 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10647 if (!is_gimple_min_invariant (*rhs_p))
10648 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10650 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10651 if (!is_gimple_min_invariant (*rhs_p))
10652 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10655 /* Once lowered, extract the bounds and clauses. */
10656 extract_omp_for_data (stmt, &fd, NULL);
10658 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10660 gimple_seq_add_stmt (&body, stmt);
10661 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10663 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10664 fd.loop.v));
10666 /* After the loop, add exit clauses. */
10667 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10669 if (ctx->cancellable)
10670 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10672 gimple_seq_add_seq (&body, dlist);
10674 body = maybe_catch_exception (body);
10676 /* Region exit marker goes at the end of the loop body. */
10677 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10678 maybe_add_implicit_barrier_cancel (ctx, &body);
10679 pop_gimplify_context (new_stmt);
10681 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10682 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10683 if (BLOCK_VARS (block))
10684 TREE_USED (block) = 1;
10686 gimple_bind_set_body (new_stmt, body);
10687 gimple_omp_set_body (stmt, NULL);
10688 gimple_omp_for_set_pre_body (stmt, NULL);
10691 /* Callback for walk_stmts. Check if the current statement only contains
10692 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10694 static tree
10695 check_combined_parallel (gimple_stmt_iterator *gsi_p,
10696 bool *handled_ops_p,
10697 struct walk_stmt_info *wi)
10699 int *info = (int *) wi->info;
10700 gimple stmt = gsi_stmt (*gsi_p);
10702 *handled_ops_p = true;
10703 switch (gimple_code (stmt))
10705 WALK_SUBSTMTS;
10707 case GIMPLE_OMP_FOR:
10708 case GIMPLE_OMP_SECTIONS:
10709 *info = *info == 0 ? 1 : -1;
10710 break;
10711 default:
10712 *info = -1;
10713 break;
10715 return NULL;
10718 struct omp_taskcopy_context
10720 /* This field must be at the beginning, as we do "inheritance": Some
10721 callback functions for tree-inline.c (e.g., omp_copy_decl)
10722 receive a copy_body_data pointer that is up-casted to an
10723 omp_context pointer. */
10724 copy_body_data cb;
10725 omp_context *ctx;
10728 static tree
10729 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10731 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10733 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10734 return create_tmp_var (TREE_TYPE (var));
10736 return var;
10739 static tree
10740 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10742 tree name, new_fields = NULL, type, f;
10744 type = lang_hooks.types.make_type (RECORD_TYPE);
10745 name = DECL_NAME (TYPE_NAME (orig_type));
10746 name = build_decl (gimple_location (tcctx->ctx->stmt),
10747 TYPE_DECL, name, type);
10748 TYPE_NAME (type) = name;
10750 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10752 tree new_f = copy_node (f);
10753 DECL_CONTEXT (new_f) = type;
10754 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10755 TREE_CHAIN (new_f) = new_fields;
10756 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10757 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10758 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10759 &tcctx->cb, NULL);
10760 new_fields = new_f;
10761 tcctx->cb.decl_map->put (f, new_f);
10763 TYPE_FIELDS (type) = nreverse (new_fields);
10764 layout_type (type);
10765 return type;
10768 /* Create task copyfn. */
10770 static void
10771 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
10773 struct function *child_cfun;
10774 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10775 tree record_type, srecord_type, bind, list;
10776 bool record_needs_remap = false, srecord_needs_remap = false;
10777 splay_tree_node n;
10778 struct omp_taskcopy_context tcctx;
10779 location_t loc = gimple_location (task_stmt);
10781 child_fn = gimple_omp_task_copy_fn (task_stmt);
10782 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10783 gcc_assert (child_cfun->cfg == NULL);
10784 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10786 /* Reset DECL_CONTEXT on function arguments. */
10787 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10788 DECL_CONTEXT (t) = child_fn;
10790 /* Populate the function. */
10791 push_gimplify_context ();
10792 push_cfun (child_cfun);
10794 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10795 TREE_SIDE_EFFECTS (bind) = 1;
10796 list = NULL;
10797 DECL_SAVED_TREE (child_fn) = bind;
10798 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10800 /* Remap src and dst argument types if needed. */
10801 record_type = ctx->record_type;
10802 srecord_type = ctx->srecord_type;
10803 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10804 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10806 record_needs_remap = true;
10807 break;
10809 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10810 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10812 srecord_needs_remap = true;
10813 break;
10816 if (record_needs_remap || srecord_needs_remap)
10818 memset (&tcctx, '\0', sizeof (tcctx));
10819 tcctx.cb.src_fn = ctx->cb.src_fn;
10820 tcctx.cb.dst_fn = child_fn;
10821 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
10822 gcc_checking_assert (tcctx.cb.src_node);
10823 tcctx.cb.dst_node = tcctx.cb.src_node;
10824 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10825 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10826 tcctx.cb.eh_lp_nr = 0;
10827 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10828 tcctx.cb.decl_map = new hash_map<tree, tree>;
10829 tcctx.ctx = ctx;
10831 if (record_needs_remap)
10832 record_type = task_copyfn_remap_type (&tcctx, record_type);
10833 if (srecord_needs_remap)
10834 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10836 else
10837 tcctx.cb.decl_map = NULL;
10839 arg = DECL_ARGUMENTS (child_fn);
10840 TREE_TYPE (arg) = build_pointer_type (record_type);
10841 sarg = DECL_CHAIN (arg);
10842 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10844 /* First pass: initialize temporaries used in record_type and srecord_type
10845 sizes and field offsets. */
10846 if (tcctx.cb.decl_map)
10847 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10848 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10850 tree *p;
10852 decl = OMP_CLAUSE_DECL (c);
10853 p = tcctx.cb.decl_map->get (decl);
10854 if (p == NULL)
10855 continue;
10856 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10857 sf = (tree) n->value;
10858 sf = *tcctx.cb.decl_map->get (sf);
10859 src = build_simple_mem_ref_loc (loc, sarg);
10860 src = omp_build_component_ref (src, sf);
10861 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10862 append_to_statement_list (t, &list);
10865 /* Second pass: copy shared var pointers and copy construct non-VLA
10866 firstprivate vars. */
10867 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10868 switch (OMP_CLAUSE_CODE (c))
10870 case OMP_CLAUSE_SHARED:
10871 decl = OMP_CLAUSE_DECL (c);
10872 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10873 if (n == NULL)
10874 break;
10875 f = (tree) n->value;
10876 if (tcctx.cb.decl_map)
10877 f = *tcctx.cb.decl_map->get (f);
10878 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10879 sf = (tree) n->value;
10880 if (tcctx.cb.decl_map)
10881 sf = *tcctx.cb.decl_map->get (sf);
10882 src = build_simple_mem_ref_loc (loc, sarg);
10883 src = omp_build_component_ref (src, sf);
10884 dst = build_simple_mem_ref_loc (loc, arg);
10885 dst = omp_build_component_ref (dst, f);
10886 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10887 append_to_statement_list (t, &list);
10888 break;
10889 case OMP_CLAUSE_FIRSTPRIVATE:
10890 decl = OMP_CLAUSE_DECL (c);
10891 if (is_variable_sized (decl))
10892 break;
10893 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10894 if (n == NULL)
10895 break;
10896 f = (tree) n->value;
10897 if (tcctx.cb.decl_map)
10898 f = *tcctx.cb.decl_map->get (f);
10899 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10900 if (n != NULL)
10902 sf = (tree) n->value;
10903 if (tcctx.cb.decl_map)
10904 sf = *tcctx.cb.decl_map->get (sf);
10905 src = build_simple_mem_ref_loc (loc, sarg);
10906 src = omp_build_component_ref (src, sf);
10907 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
10908 src = build_simple_mem_ref_loc (loc, src);
10910 else
10911 src = decl;
10912 dst = build_simple_mem_ref_loc (loc, arg);
10913 dst = omp_build_component_ref (dst, f);
10914 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10915 append_to_statement_list (t, &list);
10916 break;
10917 case OMP_CLAUSE_PRIVATE:
10918 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10919 break;
10920 decl = OMP_CLAUSE_DECL (c);
10921 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10922 f = (tree) n->value;
10923 if (tcctx.cb.decl_map)
10924 f = *tcctx.cb.decl_map->get (f);
10925 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10926 if (n != NULL)
10928 sf = (tree) n->value;
10929 if (tcctx.cb.decl_map)
10930 sf = *tcctx.cb.decl_map->get (sf);
10931 src = build_simple_mem_ref_loc (loc, sarg);
10932 src = omp_build_component_ref (src, sf);
10933 if (use_pointer_for_field (decl, NULL))
10934 src = build_simple_mem_ref_loc (loc, src);
10936 else
10937 src = decl;
10938 dst = build_simple_mem_ref_loc (loc, arg);
10939 dst = omp_build_component_ref (dst, f);
10940 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10941 append_to_statement_list (t, &list);
10942 break;
10943 default:
10944 break;
10947 /* Last pass: handle VLA firstprivates. */
10948 if (tcctx.cb.decl_map)
10949 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10950 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10952 tree ind, ptr, df;
10954 decl = OMP_CLAUSE_DECL (c);
10955 if (!is_variable_sized (decl))
10956 continue;
10957 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10958 if (n == NULL)
10959 continue;
10960 f = (tree) n->value;
10961 f = *tcctx.cb.decl_map->get (f);
10962 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10963 ind = DECL_VALUE_EXPR (decl);
10964 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10965 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10966 n = splay_tree_lookup (ctx->sfield_map,
10967 (splay_tree_key) TREE_OPERAND (ind, 0));
10968 sf = (tree) n->value;
10969 sf = *tcctx.cb.decl_map->get (sf);
10970 src = build_simple_mem_ref_loc (loc, sarg);
10971 src = omp_build_component_ref (src, sf);
10972 src = build_simple_mem_ref_loc (loc, src);
10973 dst = build_simple_mem_ref_loc (loc, arg);
10974 dst = omp_build_component_ref (dst, f);
10975 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10976 append_to_statement_list (t, &list);
10977 n = splay_tree_lookup (ctx->field_map,
10978 (splay_tree_key) TREE_OPERAND (ind, 0));
10979 df = (tree) n->value;
10980 df = *tcctx.cb.decl_map->get (df);
10981 ptr = build_simple_mem_ref_loc (loc, arg);
10982 ptr = omp_build_component_ref (ptr, df);
10983 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
10984 build_fold_addr_expr_loc (loc, dst));
10985 append_to_statement_list (t, &list);
10988 t = build1 (RETURN_EXPR, void_type_node, NULL);
10989 append_to_statement_list (t, &list);
10991 if (tcctx.cb.decl_map)
10992 delete tcctx.cb.decl_map;
10993 pop_gimplify_context (NULL);
10994 BIND_EXPR_BODY (bind) = list;
10995 pop_cfun ();
10998 static void
10999 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
11001 tree c, clauses;
11002 gimple g;
11003 size_t n_in = 0, n_out = 0, idx = 2, i;
11005 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11006 OMP_CLAUSE_DEPEND);
11007 gcc_assert (clauses);
11008 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11009 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11010 switch (OMP_CLAUSE_DEPEND_KIND (c))
11012 case OMP_CLAUSE_DEPEND_IN:
11013 n_in++;
11014 break;
11015 case OMP_CLAUSE_DEPEND_OUT:
11016 case OMP_CLAUSE_DEPEND_INOUT:
11017 n_out++;
11018 break;
11019 default:
11020 gcc_unreachable ();
11022 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11023 tree array = create_tmp_var (type);
11024 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11025 NULL_TREE);
11026 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11027 gimple_seq_add_stmt (iseq, g);
11028 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11029 NULL_TREE);
11030 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11031 gimple_seq_add_stmt (iseq, g);
11032 for (i = 0; i < 2; i++)
11034 if ((i ? n_in : n_out) == 0)
11035 continue;
11036 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11037 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11038 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11040 tree t = OMP_CLAUSE_DECL (c);
11041 t = fold_convert (ptr_type_node, t);
11042 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11043 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11044 NULL_TREE, NULL_TREE);
11045 g = gimple_build_assign (r, t);
11046 gimple_seq_add_stmt (iseq, g);
11049 tree *p = gimple_omp_task_clauses_ptr (stmt);
11050 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11051 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11052 OMP_CLAUSE_CHAIN (c) = *p;
11053 *p = c;
11054 tree clobber = build_constructor (type, NULL);
11055 TREE_THIS_VOLATILE (clobber) = 1;
11056 g = gimple_build_assign (array, clobber);
11057 gimple_seq_add_stmt (oseq, g);
11060 /* Lower the OpenMP parallel or task directive in the current statement
11061 in GSI_P. CTX holds context information for the directive. */
11063 static void
11064 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11066 tree clauses;
11067 tree child_fn, t;
11068 gimple stmt = gsi_stmt (*gsi_p);
11069 gbind *par_bind, *bind, *dep_bind = NULL;
11070 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11071 location_t loc = gimple_location (stmt);
11073 clauses = gimple_omp_taskreg_clauses (stmt);
11074 par_bind
11075 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11076 par_body = gimple_bind_body (par_bind);
11077 child_fn = ctx->cb.dst_fn;
11078 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11079 && !gimple_omp_parallel_combined_p (stmt))
11081 struct walk_stmt_info wi;
11082 int ws_num = 0;
11084 memset (&wi, 0, sizeof (wi));
11085 wi.info = &ws_num;
11086 wi.val_only = true;
11087 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11088 if (ws_num == 1)
11089 gimple_omp_parallel_set_combined_p (stmt, true);
11091 gimple_seq dep_ilist = NULL;
11092 gimple_seq dep_olist = NULL;
11093 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11094 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11096 push_gimplify_context ();
11097 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11098 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11101 if (ctx->srecord_type)
11102 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11104 push_gimplify_context ();
11106 par_olist = NULL;
11107 par_ilist = NULL;
11108 par_rlist = NULL;
11109 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11110 lower_omp (&par_body, ctx);
11111 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11112 lower_reduction_clauses (clauses, &par_rlist, ctx);
11114 /* Declare all the variables created by mapping and the variables
11115 declared in the scope of the parallel body. */
11116 record_vars_into (ctx->block_vars, child_fn);
11117 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11119 if (ctx->record_type)
11121 ctx->sender_decl
11122 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11123 : ctx->record_type, ".omp_data_o");
11124 DECL_NAMELESS (ctx->sender_decl) = 1;
11125 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11126 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11129 olist = NULL;
11130 ilist = NULL;
11131 lower_send_clauses (clauses, &ilist, &olist, ctx);
11132 lower_send_shared_vars (&ilist, &olist, ctx);
11134 if (ctx->record_type)
11136 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11137 TREE_THIS_VOLATILE (clobber) = 1;
11138 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11139 clobber));
11142 /* Once all the expansions are done, sequence all the different
11143 fragments inside gimple_omp_body. */
11145 new_body = NULL;
11147 if (ctx->record_type)
11149 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11150 /* fixup_child_record_type might have changed receiver_decl's type. */
11151 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11152 gimple_seq_add_stmt (&new_body,
11153 gimple_build_assign (ctx->receiver_decl, t));
11156 gimple_seq_add_seq (&new_body, par_ilist);
11157 gimple_seq_add_seq (&new_body, par_body);
11158 gimple_seq_add_seq (&new_body, par_rlist);
11159 if (ctx->cancellable)
11160 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11161 gimple_seq_add_seq (&new_body, par_olist);
11162 new_body = maybe_catch_exception (new_body);
11163 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11164 gimple_omp_set_body (stmt, new_body);
11166 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11167 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11168 gimple_bind_add_seq (bind, ilist);
11169 gimple_bind_add_stmt (bind, stmt);
11170 gimple_bind_add_seq (bind, olist);
11172 pop_gimplify_context (NULL);
11174 if (dep_bind)
11176 gimple_bind_add_seq (dep_bind, dep_ilist);
11177 gimple_bind_add_stmt (dep_bind, bind);
11178 gimple_bind_add_seq (dep_bind, dep_olist);
11179 pop_gimplify_context (dep_bind);
11183 /* Lower the GIMPLE_OMP_TARGET in the current statement
11184 in GSI_P. CTX holds context information for the directive. */
11186 static void
11187 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11189 tree clauses;
11190 tree child_fn, t, c;
11191 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11192 gbind *tgt_bind, *bind;
11193 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11194 location_t loc = gimple_location (stmt);
11195 bool offloaded, data_region;
11196 unsigned int map_cnt = 0;
11198 offloaded = is_gimple_omp_offloaded (stmt);
11199 switch (gimple_omp_target_kind (stmt))
11201 case GF_OMP_TARGET_KIND_REGION:
11202 case GF_OMP_TARGET_KIND_UPDATE:
11203 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11204 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11205 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11206 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11207 data_region = false;
11208 break;
11209 case GF_OMP_TARGET_KIND_DATA:
11210 case GF_OMP_TARGET_KIND_OACC_DATA:
11211 data_region = true;
11212 break;
11213 default:
11214 gcc_unreachable ();
11217 clauses = gimple_omp_target_clauses (stmt);
11219 tgt_bind = NULL;
11220 tgt_body = NULL;
11221 if (offloaded)
11223 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11224 tgt_body = gimple_bind_body (tgt_bind);
11226 else if (data_region)
11227 tgt_body = gimple_omp_body (stmt);
11228 child_fn = ctx->cb.dst_fn;
11230 push_gimplify_context ();
11232 irlist = NULL;
11233 orlist = NULL;
11234 if (offloaded
11235 && is_gimple_omp_oacc (stmt))
11236 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11238 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11239 switch (OMP_CLAUSE_CODE (c))
11241 tree var, x;
11243 default:
11244 break;
11245 case OMP_CLAUSE_MAP:
11246 #ifdef ENABLE_CHECKING
11247 /* First check what we're prepared to handle in the following. */
11248 switch (OMP_CLAUSE_MAP_KIND (c))
11250 case GOMP_MAP_ALLOC:
11251 case GOMP_MAP_TO:
11252 case GOMP_MAP_FROM:
11253 case GOMP_MAP_TOFROM:
11254 case GOMP_MAP_POINTER:
11255 case GOMP_MAP_TO_PSET:
11256 break;
11257 case GOMP_MAP_FORCE_ALLOC:
11258 case GOMP_MAP_FORCE_TO:
11259 case GOMP_MAP_FORCE_FROM:
11260 case GOMP_MAP_FORCE_TOFROM:
11261 case GOMP_MAP_FORCE_PRESENT:
11262 case GOMP_MAP_FORCE_DEALLOC:
11263 case GOMP_MAP_FORCE_DEVICEPTR:
11264 gcc_assert (is_gimple_omp_oacc (stmt));
11265 break;
11266 default:
11267 gcc_unreachable ();
11269 #endif
11270 /* FALLTHRU */
11271 case OMP_CLAUSE_TO:
11272 case OMP_CLAUSE_FROM:
11273 var = OMP_CLAUSE_DECL (c);
11274 if (!DECL_P (var))
11276 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11277 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11278 map_cnt++;
11279 continue;
11282 if (DECL_SIZE (var)
11283 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11285 tree var2 = DECL_VALUE_EXPR (var);
11286 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11287 var2 = TREE_OPERAND (var2, 0);
11288 gcc_assert (DECL_P (var2));
11289 var = var2;
11292 if (!maybe_lookup_field (var, ctx))
11293 continue;
11295 if (offloaded)
11297 x = build_receiver_ref (var, true, ctx);
11298 tree new_var = lookup_decl (var, ctx);
11299 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11300 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11301 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11302 x = build_simple_mem_ref (x);
11303 SET_DECL_VALUE_EXPR (new_var, x);
11304 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11306 map_cnt++;
11309 if (offloaded)
11311 target_nesting_level++;
11312 lower_omp (&tgt_body, ctx);
11313 target_nesting_level--;
11315 else if (data_region)
11316 lower_omp (&tgt_body, ctx);
11318 if (offloaded)
11320 /* Declare all the variables created by mapping and the variables
11321 declared in the scope of the target body. */
11322 record_vars_into (ctx->block_vars, child_fn);
11323 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11326 olist = NULL;
11327 ilist = NULL;
11328 if (ctx->record_type)
11330 ctx->sender_decl
11331 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11332 DECL_NAMELESS (ctx->sender_decl) = 1;
11333 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11334 t = make_tree_vec (3);
11335 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11336 TREE_VEC_ELT (t, 1)
11337 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11338 ".omp_data_sizes");
11339 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11340 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11341 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11342 tree tkind_type;
11343 int talign_shift;
11344 if (is_gimple_omp_oacc (stmt))
11346 tkind_type = short_unsigned_type_node;
11347 talign_shift = 8;
11349 else
11351 tkind_type = unsigned_char_type_node;
11352 talign_shift = 3;
11354 TREE_VEC_ELT (t, 2)
11355 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11356 ".omp_data_kinds");
11357 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11358 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11359 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11360 gimple_omp_target_set_data_arg (stmt, t);
11362 vec<constructor_elt, va_gc> *vsize;
11363 vec<constructor_elt, va_gc> *vkind;
11364 vec_alloc (vsize, map_cnt);
11365 vec_alloc (vkind, map_cnt);
11366 unsigned int map_idx = 0;
11368 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11369 switch (OMP_CLAUSE_CODE (c))
11371 tree ovar, nc;
11373 default:
11374 break;
11375 case OMP_CLAUSE_MAP:
11376 case OMP_CLAUSE_TO:
11377 case OMP_CLAUSE_FROM:
11378 nc = c;
11379 ovar = OMP_CLAUSE_DECL (c);
11380 if (!DECL_P (ovar))
11382 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11383 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11385 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11386 == get_base_address (ovar));
11387 nc = OMP_CLAUSE_CHAIN (c);
11388 ovar = OMP_CLAUSE_DECL (nc);
11390 else
11392 tree x = build_sender_ref (ovar, ctx);
11393 tree v
11394 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11395 gimplify_assign (x, v, &ilist);
11396 nc = NULL_TREE;
11399 else
11401 if (DECL_SIZE (ovar)
11402 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11404 tree ovar2 = DECL_VALUE_EXPR (ovar);
11405 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11406 ovar2 = TREE_OPERAND (ovar2, 0);
11407 gcc_assert (DECL_P (ovar2));
11408 ovar = ovar2;
11410 if (!maybe_lookup_field (ovar, ctx))
11411 continue;
11414 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11415 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11416 talign = DECL_ALIGN_UNIT (ovar);
11417 if (nc)
11419 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11420 tree x = build_sender_ref (ovar, ctx);
11421 if (maybe_lookup_oacc_reduction (var, ctx))
11423 gcc_checking_assert (offloaded
11424 && is_gimple_omp_oacc (stmt));
11425 gimplify_assign (x, var, &ilist);
11427 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11428 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11429 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11430 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11432 gcc_assert (offloaded);
11433 tree avar
11434 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11435 mark_addressable (avar);
11436 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11437 talign = DECL_ALIGN_UNIT (avar);
11438 avar = build_fold_addr_expr (avar);
11439 gimplify_assign (x, avar, &ilist);
11441 else if (is_gimple_reg (var))
11443 gcc_assert (offloaded);
11444 tree avar = create_tmp_var (TREE_TYPE (var));
11445 mark_addressable (avar);
11446 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11447 if (GOMP_MAP_COPY_TO_P (map_kind)
11448 || map_kind == GOMP_MAP_POINTER
11449 || map_kind == GOMP_MAP_TO_PSET
11450 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11451 gimplify_assign (avar, var, &ilist);
11452 avar = build_fold_addr_expr (avar);
11453 gimplify_assign (x, avar, &ilist);
11454 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11455 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11456 && !TYPE_READONLY (TREE_TYPE (var)))
11458 x = build_sender_ref (ovar, ctx);
11459 x = build_simple_mem_ref (x);
11460 gimplify_assign (var, x, &olist);
11463 else
11465 var = build_fold_addr_expr (var);
11466 gimplify_assign (x, var, &ilist);
11469 tree s = OMP_CLAUSE_SIZE (c);
11470 if (s == NULL_TREE)
11471 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11472 s = fold_convert (size_type_node, s);
11473 tree purpose = size_int (map_idx++);
11474 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11475 if (TREE_CODE (s) != INTEGER_CST)
11476 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11478 unsigned HOST_WIDE_INT tkind;
11479 switch (OMP_CLAUSE_CODE (c))
11481 case OMP_CLAUSE_MAP:
11482 tkind = OMP_CLAUSE_MAP_KIND (c);
11483 break;
11484 case OMP_CLAUSE_TO:
11485 tkind = GOMP_MAP_TO;
11486 break;
11487 case OMP_CLAUSE_FROM:
11488 tkind = GOMP_MAP_FROM;
11489 break;
11490 default:
11491 gcc_unreachable ();
11493 gcc_checking_assert (tkind
11494 < (HOST_WIDE_INT_C (1U) << talign_shift));
11495 talign = ceil_log2 (talign);
11496 tkind |= talign << talign_shift;
11497 gcc_checking_assert (tkind
11498 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11499 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11500 build_int_cstu (tkind_type, tkind));
11501 if (nc && nc != c)
11502 c = nc;
11505 gcc_assert (map_idx == map_cnt);
11507 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11508 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11509 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11510 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11511 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11513 gimple_seq initlist = NULL;
11514 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11515 TREE_VEC_ELT (t, 1)),
11516 &initlist, true, NULL_TREE);
11517 gimple_seq_add_seq (&ilist, initlist);
11519 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11520 NULL);
11521 TREE_THIS_VOLATILE (clobber) = 1;
11522 gimple_seq_add_stmt (&olist,
11523 gimple_build_assign (TREE_VEC_ELT (t, 1),
11524 clobber));
11527 tree clobber = build_constructor (ctx->record_type, NULL);
11528 TREE_THIS_VOLATILE (clobber) = 1;
11529 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11530 clobber));
11533 /* Once all the expansions are done, sequence all the different
11534 fragments inside gimple_omp_body. */
11536 new_body = NULL;
11538 if (offloaded
11539 && ctx->record_type)
11541 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11542 /* fixup_child_record_type might have changed receiver_decl's type. */
11543 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11544 gimple_seq_add_stmt (&new_body,
11545 gimple_build_assign (ctx->receiver_decl, t));
11548 if (offloaded)
11550 gimple_seq_add_seq (&new_body, tgt_body);
11551 new_body = maybe_catch_exception (new_body);
11553 else if (data_region)
11554 new_body = tgt_body;
11555 if (offloaded || data_region)
11557 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11558 gimple_omp_set_body (stmt, new_body);
11561 bind = gimple_build_bind (NULL, NULL,
11562 tgt_bind ? gimple_bind_block (tgt_bind)
11563 : NULL_TREE);
11564 gsi_replace (gsi_p, bind, true);
11565 gimple_bind_add_seq (bind, irlist);
11566 gimple_bind_add_seq (bind, ilist);
11567 gimple_bind_add_stmt (bind, stmt);
11568 gimple_bind_add_seq (bind, olist);
11569 gimple_bind_add_seq (bind, orlist);
11571 pop_gimplify_context (NULL);
11574 /* Expand code for an OpenMP teams directive. */
11576 static void
11577 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11579 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11580 push_gimplify_context ();
11582 tree block = make_node (BLOCK);
11583 gbind *bind = gimple_build_bind (NULL, NULL, block);
11584 gsi_replace (gsi_p, bind, true);
11585 gimple_seq bind_body = NULL;
11586 gimple_seq dlist = NULL;
11587 gimple_seq olist = NULL;
11589 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11590 OMP_CLAUSE_NUM_TEAMS);
11591 if (num_teams == NULL_TREE)
11592 num_teams = build_int_cst (unsigned_type_node, 0);
11593 else
11595 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11596 num_teams = fold_convert (unsigned_type_node, num_teams);
11597 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11599 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11600 OMP_CLAUSE_THREAD_LIMIT);
11601 if (thread_limit == NULL_TREE)
11602 thread_limit = build_int_cst (unsigned_type_node, 0);
11603 else
11605 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11606 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11607 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11608 fb_rvalue);
11611 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11612 &bind_body, &dlist, ctx, NULL);
11613 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11614 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11615 gimple_seq_add_stmt (&bind_body, teams_stmt);
11617 location_t loc = gimple_location (teams_stmt);
11618 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11619 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11620 gimple_set_location (call, loc);
11621 gimple_seq_add_stmt (&bind_body, call);
11623 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11624 gimple_omp_set_body (teams_stmt, NULL);
11625 gimple_seq_add_seq (&bind_body, olist);
11626 gimple_seq_add_seq (&bind_body, dlist);
11627 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11628 gimple_bind_set_body (bind, bind_body);
11630 pop_gimplify_context (bind);
11632 gimple_bind_append_vars (bind, ctx->block_vars);
11633 BLOCK_VARS (block) = ctx->block_vars;
11634 if (BLOCK_VARS (block))
11635 TREE_USED (block) = 1;
11639 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11640 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11641 of OMP context, but with task_shared_vars set. */
11643 static tree
11644 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11645 void *data)
11647 tree t = *tp;
11649 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11650 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11651 return t;
11653 if (task_shared_vars
11654 && DECL_P (t)
11655 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11656 return t;
11658 /* If a global variable has been privatized, TREE_CONSTANT on
11659 ADDR_EXPR might be wrong. */
11660 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11661 recompute_tree_invariant_for_addr_expr (t);
11663 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11664 return NULL_TREE;
11667 static void
11668 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11670 gimple stmt = gsi_stmt (*gsi_p);
11671 struct walk_stmt_info wi;
11672 gcall *call_stmt;
11674 if (gimple_has_location (stmt))
11675 input_location = gimple_location (stmt);
11677 if (task_shared_vars)
11678 memset (&wi, '\0', sizeof (wi));
11680 /* If we have issued syntax errors, avoid doing any heavy lifting.
11681 Just replace the OMP directives with a NOP to avoid
11682 confusing RTL expansion. */
11683 if (seen_error () && is_gimple_omp (stmt))
11685 gsi_replace (gsi_p, gimple_build_nop (), true);
11686 return;
11689 switch (gimple_code (stmt))
11691 case GIMPLE_COND:
11693 gcond *cond_stmt = as_a <gcond *> (stmt);
11694 if ((ctx || task_shared_vars)
11695 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11696 lower_omp_regimplify_p,
11697 ctx ? NULL : &wi, NULL)
11698 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11699 lower_omp_regimplify_p,
11700 ctx ? NULL : &wi, NULL)))
11701 gimple_regimplify_operands (cond_stmt, gsi_p);
11703 break;
11704 case GIMPLE_CATCH:
11705 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
11706 break;
11707 case GIMPLE_EH_FILTER:
11708 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
11709 break;
11710 case GIMPLE_TRY:
11711 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11712 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
11713 break;
11714 case GIMPLE_TRANSACTION:
11715 lower_omp (gimple_transaction_body_ptr (
11716 as_a <gtransaction *> (stmt)),
11717 ctx);
11718 break;
11719 case GIMPLE_BIND:
11720 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
11721 break;
11722 case GIMPLE_OMP_PARALLEL:
11723 case GIMPLE_OMP_TASK:
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_taskreg (gsi_p, ctx);
11729 break;
11730 case GIMPLE_OMP_FOR:
11731 ctx = maybe_lookup_ctx (stmt);
11732 gcc_assert (ctx);
11733 if (ctx->cancellable)
11734 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11735 lower_omp_for (gsi_p, ctx);
11736 break;
11737 case GIMPLE_OMP_SECTIONS:
11738 ctx = maybe_lookup_ctx (stmt);
11739 gcc_assert (ctx);
11740 if (ctx->cancellable)
11741 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11742 lower_omp_sections (gsi_p, ctx);
11743 break;
11744 case GIMPLE_OMP_SINGLE:
11745 ctx = maybe_lookup_ctx (stmt);
11746 gcc_assert (ctx);
11747 lower_omp_single (gsi_p, ctx);
11748 break;
11749 case GIMPLE_OMP_MASTER:
11750 ctx = maybe_lookup_ctx (stmt);
11751 gcc_assert (ctx);
11752 lower_omp_master (gsi_p, ctx);
11753 break;
11754 case GIMPLE_OMP_TASKGROUP:
11755 ctx = maybe_lookup_ctx (stmt);
11756 gcc_assert (ctx);
11757 lower_omp_taskgroup (gsi_p, ctx);
11758 break;
11759 case GIMPLE_OMP_ORDERED:
11760 ctx = maybe_lookup_ctx (stmt);
11761 gcc_assert (ctx);
11762 lower_omp_ordered (gsi_p, ctx);
11763 break;
11764 case GIMPLE_OMP_CRITICAL:
11765 ctx = maybe_lookup_ctx (stmt);
11766 gcc_assert (ctx);
11767 lower_omp_critical (gsi_p, ctx);
11768 break;
11769 case GIMPLE_OMP_ATOMIC_LOAD:
11770 if ((ctx || task_shared_vars)
11771 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11772 as_a <gomp_atomic_load *> (stmt)),
11773 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11774 gimple_regimplify_operands (stmt, gsi_p);
11775 break;
11776 case GIMPLE_OMP_TARGET:
11777 ctx = maybe_lookup_ctx (stmt);
11778 gcc_assert (ctx);
11779 lower_omp_target (gsi_p, ctx);
11780 break;
11781 case GIMPLE_OMP_TEAMS:
11782 ctx = maybe_lookup_ctx (stmt);
11783 gcc_assert (ctx);
11784 lower_omp_teams (gsi_p, ctx);
11785 break;
11786 case GIMPLE_CALL:
11787 tree fndecl;
11788 call_stmt = as_a <gcall *> (stmt);
11789 fndecl = gimple_call_fndecl (call_stmt);
11790 if (fndecl
11791 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11792 switch (DECL_FUNCTION_CODE (fndecl))
11794 case BUILT_IN_GOMP_BARRIER:
11795 if (ctx == NULL)
11796 break;
11797 /* FALLTHRU */
11798 case BUILT_IN_GOMP_CANCEL:
11799 case BUILT_IN_GOMP_CANCELLATION_POINT:
11800 omp_context *cctx;
11801 cctx = ctx;
11802 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11803 cctx = cctx->outer;
11804 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
11805 if (!cctx->cancellable)
11807 if (DECL_FUNCTION_CODE (fndecl)
11808 == BUILT_IN_GOMP_CANCELLATION_POINT)
11810 stmt = gimple_build_nop ();
11811 gsi_replace (gsi_p, stmt, false);
11813 break;
11815 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11817 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
11818 gimple_call_set_fndecl (call_stmt, fndecl);
11819 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
11821 tree lhs;
11822 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
11823 gimple_call_set_lhs (call_stmt, lhs);
11824 tree fallthru_label;
11825 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11826 gimple g;
11827 g = gimple_build_label (fallthru_label);
11828 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11829 g = gimple_build_cond (NE_EXPR, lhs,
11830 fold_convert (TREE_TYPE (lhs),
11831 boolean_false_node),
11832 cctx->cancel_label, fallthru_label);
11833 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11834 break;
11835 default:
11836 break;
11838 /* FALLTHRU */
11839 default:
11840 if ((ctx || task_shared_vars)
11841 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11842 ctx ? NULL : &wi))
11844 /* Just remove clobbers, this should happen only if we have
11845 "privatized" local addressable variables in SIMD regions,
11846 the clobber isn't needed in that case and gimplifying address
11847 of the ARRAY_REF into a pointer and creating MEM_REF based
11848 clobber would create worse code than we get with the clobber
11849 dropped. */
11850 if (gimple_clobber_p (stmt))
11852 gsi_replace (gsi_p, gimple_build_nop (), true);
11853 break;
11855 gimple_regimplify_operands (stmt, gsi_p);
11857 break;
11861 static void
11862 lower_omp (gimple_seq *body, omp_context *ctx)
11864 location_t saved_location = input_location;
11865 gimple_stmt_iterator gsi;
11866 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11867 lower_omp_1 (&gsi, ctx);
11868 /* During gimplification, we haven't folded statments inside offloading
11869 regions (gimplify.c:maybe_fold_stmt); do that now. */
11870 if (target_nesting_level)
11871 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11872 fold_stmt (&gsi);
11873 input_location = saved_location;
11876 /* Main entry point. */
11878 static unsigned int
11879 execute_lower_omp (void)
11881 gimple_seq body;
11882 int i;
11883 omp_context *ctx;
11885 /* This pass always runs, to provide PROP_gimple_lomp.
11886 But often, there is nothing to do. */
11887 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11888 && flag_openmp_simd == 0)
11889 return 0;
11891 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11892 delete_omp_context);
11894 body = gimple_body (current_function_decl);
11895 scan_omp (&body, NULL);
11896 gcc_assert (taskreg_nesting_level == 0);
11897 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11898 finish_taskreg_scan (ctx);
11899 taskreg_contexts.release ();
11901 if (all_contexts->root)
11903 if (task_shared_vars)
11904 push_gimplify_context ();
11905 lower_omp (&body, NULL);
11906 if (task_shared_vars)
11907 pop_gimplify_context (NULL);
11910 if (all_contexts)
11912 splay_tree_delete (all_contexts);
11913 all_contexts = NULL;
11915 BITMAP_FREE (task_shared_vars);
11916 return 0;
11919 namespace {
11921 const pass_data pass_data_lower_omp =
11923 GIMPLE_PASS, /* type */
11924 "omplower", /* name */
11925 OPTGROUP_NONE, /* optinfo_flags */
11926 TV_NONE, /* tv_id */
11927 PROP_gimple_any, /* properties_required */
11928 PROP_gimple_lomp, /* properties_provided */
11929 0, /* properties_destroyed */
11930 0, /* todo_flags_start */
11931 0, /* todo_flags_finish */
11934 class pass_lower_omp : public gimple_opt_pass
11936 public:
11937 pass_lower_omp (gcc::context *ctxt)
11938 : gimple_opt_pass (pass_data_lower_omp, ctxt)
11941 /* opt_pass methods: */
11942 virtual unsigned int execute (function *) { return execute_lower_omp (); }
11944 }; // class pass_lower_omp
11946 } // anon namespace
11948 gimple_opt_pass *
11949 make_pass_lower_omp (gcc::context *ctxt)
11951 return new pass_lower_omp (ctxt);
11954 /* The following is a utility to diagnose structured block violations.
11955 It is not part of the "omplower" pass, as that's invoked too late. It
11956 should be invoked by the respective front ends after gimplification. */
11958 static splay_tree all_labels;
11960 /* Check for mismatched contexts and generate an error if needed. Return
11961 true if an error is detected. */
11963 static bool
11964 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
11965 gimple branch_ctx, gimple label_ctx)
11967 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
11968 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
11970 if (label_ctx == branch_ctx)
11971 return false;
11973 const char* kind = NULL;
11975 if (flag_cilkplus)
11977 if ((branch_ctx
11978 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
11979 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
11980 || (label_ctx
11981 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
11982 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
11983 kind = "Cilk Plus";
11985 if (flag_openacc)
11987 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
11988 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
11990 gcc_checking_assert (kind == NULL);
11991 kind = "OpenACC";
11994 if (kind == NULL)
11996 gcc_checking_assert (flag_openmp);
11997 kind = "OpenMP";
12001 Previously we kept track of the label's entire context in diagnose_sb_[12]
12002 so we could traverse it and issue a correct "exit" or "enter" error
12003 message upon a structured block violation.
12005 We built the context by building a list with tree_cons'ing, but there is
12006 no easy counterpart in gimple tuples. It seems like far too much work
12007 for issuing exit/enter error messages. If someone really misses the
12008 distinct error message... patches welcome.
12011 #if 0
12012 /* Try to avoid confusing the user by producing and error message
12013 with correct "exit" or "enter" verbiage. We prefer "exit"
12014 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12015 if (branch_ctx == NULL)
12016 exit_p = false;
12017 else
12019 while (label_ctx)
12021 if (TREE_VALUE (label_ctx) == branch_ctx)
12023 exit_p = false;
12024 break;
12026 label_ctx = TREE_CHAIN (label_ctx);
12030 if (exit_p)
12031 error ("invalid exit from %s structured block", kind);
12032 else
12033 error ("invalid entry to %s structured block", kind);
12034 #endif
12036 /* If it's obvious we have an invalid entry, be specific about the error. */
12037 if (branch_ctx == NULL)
12038 error ("invalid entry to %s structured block", kind);
12039 else
12041 /* Otherwise, be vague and lazy, but efficient. */
12042 error ("invalid branch to/from %s structured block", kind);
12045 gsi_replace (gsi_p, gimple_build_nop (), false);
12046 return true;
12049 /* Pass 1: Create a minimal tree of structured blocks, and record
12050 where each label is found. */
12052 static tree
12053 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12054 struct walk_stmt_info *wi)
12056 gimple context = (gimple) wi->info;
12057 gimple inner_context;
12058 gimple stmt = gsi_stmt (*gsi_p);
12060 *handled_ops_p = true;
12062 switch (gimple_code (stmt))
12064 WALK_SUBSTMTS;
12066 case GIMPLE_OMP_PARALLEL:
12067 case GIMPLE_OMP_TASK:
12068 case GIMPLE_OMP_SECTIONS:
12069 case GIMPLE_OMP_SINGLE:
12070 case GIMPLE_OMP_SECTION:
12071 case GIMPLE_OMP_MASTER:
12072 case GIMPLE_OMP_ORDERED:
12073 case GIMPLE_OMP_CRITICAL:
12074 case GIMPLE_OMP_TARGET:
12075 case GIMPLE_OMP_TEAMS:
12076 case GIMPLE_OMP_TASKGROUP:
12077 /* The minimal context here is just the current OMP construct. */
12078 inner_context = stmt;
12079 wi->info = inner_context;
12080 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12081 wi->info = context;
12082 break;
12084 case GIMPLE_OMP_FOR:
12085 inner_context = stmt;
12086 wi->info = inner_context;
12087 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12088 walk them. */
12089 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12090 diagnose_sb_1, NULL, wi);
12091 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12092 wi->info = context;
12093 break;
12095 case GIMPLE_LABEL:
12096 splay_tree_insert (all_labels,
12097 (splay_tree_key) gimple_label_label (
12098 as_a <glabel *> (stmt)),
12099 (splay_tree_value) context);
12100 break;
12102 default:
12103 break;
12106 return NULL_TREE;
12109 /* Pass 2: Check each branch and see if its context differs from that of
12110 the destination label's context. */
12112 static tree
12113 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12114 struct walk_stmt_info *wi)
12116 gimple context = (gimple) wi->info;
12117 splay_tree_node n;
12118 gimple stmt = gsi_stmt (*gsi_p);
12120 *handled_ops_p = true;
12122 switch (gimple_code (stmt))
12124 WALK_SUBSTMTS;
12126 case GIMPLE_OMP_PARALLEL:
12127 case GIMPLE_OMP_TASK:
12128 case GIMPLE_OMP_SECTIONS:
12129 case GIMPLE_OMP_SINGLE:
12130 case GIMPLE_OMP_SECTION:
12131 case GIMPLE_OMP_MASTER:
12132 case GIMPLE_OMP_ORDERED:
12133 case GIMPLE_OMP_CRITICAL:
12134 case GIMPLE_OMP_TARGET:
12135 case GIMPLE_OMP_TEAMS:
12136 case GIMPLE_OMP_TASKGROUP:
12137 wi->info = stmt;
12138 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12139 wi->info = context;
12140 break;
12142 case GIMPLE_OMP_FOR:
12143 wi->info = stmt;
12144 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12145 walk them. */
12146 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12147 diagnose_sb_2, NULL, wi);
12148 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12149 wi->info = context;
12150 break;
12152 case GIMPLE_COND:
12154 gcond *cond_stmt = as_a <gcond *> (stmt);
12155 tree lab = gimple_cond_true_label (cond_stmt);
12156 if (lab)
12158 n = splay_tree_lookup (all_labels,
12159 (splay_tree_key) lab);
12160 diagnose_sb_0 (gsi_p, context,
12161 n ? (gimple) n->value : NULL);
12163 lab = gimple_cond_false_label (cond_stmt);
12164 if (lab)
12166 n = splay_tree_lookup (all_labels,
12167 (splay_tree_key) lab);
12168 diagnose_sb_0 (gsi_p, context,
12169 n ? (gimple) n->value : NULL);
12172 break;
12174 case GIMPLE_GOTO:
12176 tree lab = gimple_goto_dest (stmt);
12177 if (TREE_CODE (lab) != LABEL_DECL)
12178 break;
12180 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12181 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
12183 break;
12185 case GIMPLE_SWITCH:
12187 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12188 unsigned int i;
12189 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12191 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12192 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12193 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
12194 break;
12197 break;
12199 case GIMPLE_RETURN:
12200 diagnose_sb_0 (gsi_p, context, NULL);
12201 break;
12203 default:
12204 break;
12207 return NULL_TREE;
12210 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12211 GIMPLE_* codes. */
12212 bool
12213 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12214 int *region_idx)
12216 gimple last = last_stmt (bb);
12217 enum gimple_code code = gimple_code (last);
12218 struct omp_region *cur_region = *region;
12219 bool fallthru = false;
12221 switch (code)
12223 case GIMPLE_OMP_PARALLEL:
12224 case GIMPLE_OMP_TASK:
12225 case GIMPLE_OMP_FOR:
12226 case GIMPLE_OMP_SINGLE:
12227 case GIMPLE_OMP_TEAMS:
12228 case GIMPLE_OMP_MASTER:
12229 case GIMPLE_OMP_TASKGROUP:
12230 case GIMPLE_OMP_ORDERED:
12231 case GIMPLE_OMP_CRITICAL:
12232 case GIMPLE_OMP_SECTION:
12233 cur_region = new_omp_region (bb, code, cur_region);
12234 fallthru = true;
12235 break;
12237 case GIMPLE_OMP_TARGET:
12238 cur_region = new_omp_region (bb, code, cur_region);
12239 fallthru = true;
12240 switch (gimple_omp_target_kind (last))
12242 case GF_OMP_TARGET_KIND_REGION:
12243 case GF_OMP_TARGET_KIND_DATA:
12244 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12245 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12246 case GF_OMP_TARGET_KIND_OACC_DATA:
12247 break;
12248 case GF_OMP_TARGET_KIND_UPDATE:
12249 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12250 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12251 cur_region = cur_region->outer;
12252 break;
12253 default:
12254 gcc_unreachable ();
12256 break;
12258 case GIMPLE_OMP_SECTIONS:
12259 cur_region = new_omp_region (bb, code, cur_region);
12260 fallthru = true;
12261 break;
12263 case GIMPLE_OMP_SECTIONS_SWITCH:
12264 fallthru = false;
12265 break;
12267 case GIMPLE_OMP_ATOMIC_LOAD:
12268 case GIMPLE_OMP_ATOMIC_STORE:
12269 fallthru = true;
12270 break;
12272 case GIMPLE_OMP_RETURN:
12273 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12274 somewhere other than the next block. This will be
12275 created later. */
12276 cur_region->exit = bb;
12277 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12278 cur_region = cur_region->outer;
12279 break;
12281 case GIMPLE_OMP_CONTINUE:
12282 cur_region->cont = bb;
12283 switch (cur_region->type)
12285 case GIMPLE_OMP_FOR:
12286 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12287 succs edges as abnormal to prevent splitting
12288 them. */
12289 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12290 /* Make the loopback edge. */
12291 make_edge (bb, single_succ (cur_region->entry),
12292 EDGE_ABNORMAL);
12294 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12295 corresponds to the case that the body of the loop
12296 is not executed at all. */
12297 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12298 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12299 fallthru = false;
12300 break;
12302 case GIMPLE_OMP_SECTIONS:
12303 /* Wire up the edges into and out of the nested sections. */
12305 basic_block switch_bb = single_succ (cur_region->entry);
12307 struct omp_region *i;
12308 for (i = cur_region->inner; i ; i = i->next)
12310 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12311 make_edge (switch_bb, i->entry, 0);
12312 make_edge (i->exit, bb, EDGE_FALLTHRU);
12315 /* Make the loopback edge to the block with
12316 GIMPLE_OMP_SECTIONS_SWITCH. */
12317 make_edge (bb, switch_bb, 0);
12319 /* Make the edge from the switch to exit. */
12320 make_edge (switch_bb, bb->next_bb, 0);
12321 fallthru = false;
12323 break;
12325 default:
12326 gcc_unreachable ();
12328 break;
12330 default:
12331 gcc_unreachable ();
12334 if (*region != cur_region)
12336 *region = cur_region;
12337 if (cur_region)
12338 *region_idx = cur_region->entry->index;
12339 else
12340 *region_idx = 0;
12343 return fallthru;
12346 static unsigned int
12347 diagnose_omp_structured_block_errors (void)
12349 struct walk_stmt_info wi;
12350 gimple_seq body = gimple_body (current_function_decl);
12352 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12354 memset (&wi, 0, sizeof (wi));
12355 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12357 memset (&wi, 0, sizeof (wi));
12358 wi.want_locations = true;
12359 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12361 gimple_set_body (current_function_decl, body);
12363 splay_tree_delete (all_labels);
12364 all_labels = NULL;
12366 return 0;
12369 namespace {
12371 const pass_data pass_data_diagnose_omp_blocks =
12373 GIMPLE_PASS, /* type */
12374 "*diagnose_omp_blocks", /* name */
12375 OPTGROUP_NONE, /* optinfo_flags */
12376 TV_NONE, /* tv_id */
12377 PROP_gimple_any, /* properties_required */
12378 0, /* properties_provided */
12379 0, /* properties_destroyed */
12380 0, /* todo_flags_start */
12381 0, /* todo_flags_finish */
12384 class pass_diagnose_omp_blocks : public gimple_opt_pass
12386 public:
12387 pass_diagnose_omp_blocks (gcc::context *ctxt)
12388 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12391 /* opt_pass methods: */
12392 virtual bool gate (function *)
12394 return flag_cilkplus || flag_openacc || flag_openmp;
12396 virtual unsigned int execute (function *)
12398 return diagnose_omp_structured_block_errors ();
12401 }; // class pass_diagnose_omp_blocks
12403 } // anon namespace
12405 gimple_opt_pass *
12406 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12408 return new pass_diagnose_omp_blocks (ctxt);
12411 /* SIMD clone supporting code. */
12413 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12414 of arguments to reserve space for. */
12416 static struct cgraph_simd_clone *
12417 simd_clone_struct_alloc (int nargs)
12419 struct cgraph_simd_clone *clone_info;
12420 size_t len = (sizeof (struct cgraph_simd_clone)
12421 + nargs * sizeof (struct cgraph_simd_clone_arg));
12422 clone_info = (struct cgraph_simd_clone *)
12423 ggc_internal_cleared_alloc (len);
12424 return clone_info;
12427 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12429 static inline void
12430 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12431 struct cgraph_simd_clone *from)
12433 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12434 + ((from->nargs - from->inbranch)
12435 * sizeof (struct cgraph_simd_clone_arg))));
12438 /* Return vector of parameter types of function FNDECL. This uses
12439 TYPE_ARG_TYPES if available, otherwise falls back to types of
12440 DECL_ARGUMENTS types. */
12442 vec<tree>
12443 simd_clone_vector_of_formal_parm_types (tree fndecl)
12445 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12446 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12447 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12448 unsigned int i;
12449 tree arg;
12450 FOR_EACH_VEC_ELT (args, i, arg)
12451 args[i] = TREE_TYPE (args[i]);
12452 return args;
12455 /* Given a simd function in NODE, extract the simd specific
12456 information from the OMP clauses passed in CLAUSES, and return
12457 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12458 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12459 otherwise set to FALSE. */
12461 static struct cgraph_simd_clone *
12462 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12463 bool *inbranch_specified)
12465 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12466 tree t;
12467 int n;
12468 *inbranch_specified = false;
12470 n = args.length ();
12471 if (n > 0 && args.last () == void_type_node)
12472 n--;
12474 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12475 be cloned have a distinctive artificial label in addition to "omp
12476 declare simd". */
12477 bool cilk_clone
12478 = (flag_cilkplus
12479 && lookup_attribute ("cilk simd function",
12480 DECL_ATTRIBUTES (node->decl)));
12482 /* Allocate one more than needed just in case this is an in-branch
12483 clone which will require a mask argument. */
12484 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12485 clone_info->nargs = n;
12486 clone_info->cilk_elemental = cilk_clone;
12488 if (!clauses)
12490 args.release ();
12491 return clone_info;
12493 clauses = TREE_VALUE (clauses);
12494 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12495 return clone_info;
12497 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12499 switch (OMP_CLAUSE_CODE (t))
12501 case OMP_CLAUSE_INBRANCH:
12502 clone_info->inbranch = 1;
12503 *inbranch_specified = true;
12504 break;
12505 case OMP_CLAUSE_NOTINBRANCH:
12506 clone_info->inbranch = 0;
12507 *inbranch_specified = true;
12508 break;
12509 case OMP_CLAUSE_SIMDLEN:
12510 clone_info->simdlen
12511 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12512 break;
12513 case OMP_CLAUSE_LINEAR:
12515 tree decl = OMP_CLAUSE_DECL (t);
12516 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12517 int argno = TREE_INT_CST_LOW (decl);
12518 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12520 clone_info->args[argno].arg_type
12521 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12522 clone_info->args[argno].linear_step = tree_to_shwi (step);
12523 gcc_assert (clone_info->args[argno].linear_step >= 0
12524 && clone_info->args[argno].linear_step < n);
12526 else
12528 if (POINTER_TYPE_P (args[argno]))
12529 step = fold_convert (ssizetype, step);
12530 if (!tree_fits_shwi_p (step))
12532 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12533 "ignoring large linear step");
12534 args.release ();
12535 return NULL;
12537 else if (integer_zerop (step))
12539 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12540 "ignoring zero linear step");
12541 args.release ();
12542 return NULL;
12544 else
12546 clone_info->args[argno].arg_type
12547 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12548 clone_info->args[argno].linear_step = tree_to_shwi (step);
12551 break;
12553 case OMP_CLAUSE_UNIFORM:
12555 tree decl = OMP_CLAUSE_DECL (t);
12556 int argno = tree_to_uhwi (decl);
12557 clone_info->args[argno].arg_type
12558 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12559 break;
12561 case OMP_CLAUSE_ALIGNED:
12563 tree decl = OMP_CLAUSE_DECL (t);
12564 int argno = tree_to_uhwi (decl);
12565 clone_info->args[argno].alignment
12566 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12567 break;
12569 default:
12570 break;
12573 args.release ();
12574 return clone_info;
12577 /* Given a SIMD clone in NODE, calculate the characteristic data
12578 type and return the coresponding type. The characteristic data
12579 type is computed as described in the Intel Vector ABI. */
12581 static tree
12582 simd_clone_compute_base_data_type (struct cgraph_node *node,
12583 struct cgraph_simd_clone *clone_info)
12585 tree type = integer_type_node;
12586 tree fndecl = node->decl;
12588 /* a) For non-void function, the characteristic data type is the
12589 return type. */
12590 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12591 type = TREE_TYPE (TREE_TYPE (fndecl));
12593 /* b) If the function has any non-uniform, non-linear parameters,
12594 then the characteristic data type is the type of the first
12595 such parameter. */
12596 else
12598 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12599 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12600 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12602 type = map[i];
12603 break;
12605 map.release ();
12608 /* c) If the characteristic data type determined by a) or b) above
12609 is struct, union, or class type which is pass-by-value (except
12610 for the type that maps to the built-in complex data type), the
12611 characteristic data type is int. */
12612 if (RECORD_OR_UNION_TYPE_P (type)
12613 && !aggregate_value_p (type, NULL)
12614 && TREE_CODE (type) != COMPLEX_TYPE)
12615 return integer_type_node;
12617 /* d) If none of the above three classes is applicable, the
12618 characteristic data type is int. */
12620 return type;
12622 /* e) For Intel Xeon Phi native and offload compilation, if the
12623 resulting characteristic data type is 8-bit or 16-bit integer
12624 data type, the characteristic data type is int. */
12625 /* Well, we don't handle Xeon Phi yet. */
12628 static tree
12629 simd_clone_mangle (struct cgraph_node *node,
12630 struct cgraph_simd_clone *clone_info)
12632 char vecsize_mangle = clone_info->vecsize_mangle;
12633 char mask = clone_info->inbranch ? 'M' : 'N';
12634 unsigned int simdlen = clone_info->simdlen;
12635 unsigned int n;
12636 pretty_printer pp;
12638 gcc_assert (vecsize_mangle && simdlen);
12640 pp_string (&pp, "_ZGV");
12641 pp_character (&pp, vecsize_mangle);
12642 pp_character (&pp, mask);
12643 pp_decimal_int (&pp, simdlen);
12645 for (n = 0; n < clone_info->nargs; ++n)
12647 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12649 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12650 pp_character (&pp, 'u');
12651 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12653 gcc_assert (arg.linear_step != 0);
12654 pp_character (&pp, 'l');
12655 if (arg.linear_step > 1)
12656 pp_unsigned_wide_integer (&pp, arg.linear_step);
12657 else if (arg.linear_step < 0)
12659 pp_character (&pp, 'n');
12660 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12661 arg.linear_step));
12664 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12666 pp_character (&pp, 's');
12667 pp_unsigned_wide_integer (&pp, arg.linear_step);
12669 else
12670 pp_character (&pp, 'v');
12671 if (arg.alignment)
12673 pp_character (&pp, 'a');
12674 pp_decimal_int (&pp, arg.alignment);
12678 pp_underscore (&pp);
12679 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
12680 if (*str == '*')
12681 ++str;
12682 pp_string (&pp, str);
12683 str = pp_formatted_text (&pp);
12685 /* If there already is a SIMD clone with the same mangled name, don't
12686 add another one. This can happen e.g. for
12687 #pragma omp declare simd
12688 #pragma omp declare simd simdlen(8)
12689 int foo (int, int);
12690 if the simdlen is assumed to be 8 for the first one, etc. */
12691 for (struct cgraph_node *clone = node->simd_clones; clone;
12692 clone = clone->simdclone->next_clone)
12693 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12694 str) == 0)
12695 return NULL_TREE;
12697 return get_identifier (str);
12700 /* Create a simd clone of OLD_NODE and return it. */
12702 static struct cgraph_node *
12703 simd_clone_create (struct cgraph_node *old_node)
12705 struct cgraph_node *new_node;
12706 if (old_node->definition)
12708 if (!old_node->has_gimple_body_p ())
12709 return NULL;
12710 old_node->get_body ();
12711 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12712 false, NULL, NULL,
12713 "simdclone");
12715 else
12717 tree old_decl = old_node->decl;
12718 tree new_decl = copy_node (old_node->decl);
12719 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12720 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12721 SET_DECL_RTL (new_decl, NULL);
12722 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12723 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
12724 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
12725 symtab->call_cgraph_insertion_hooks (new_node);
12727 if (new_node == NULL)
12728 return new_node;
12730 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12732 /* The function cgraph_function_versioning () will force the new
12733 symbol local. Undo this, and inherit external visability from
12734 the old node. */
12735 new_node->local.local = old_node->local.local;
12736 new_node->externally_visible = old_node->externally_visible;
12738 return new_node;
12741 /* Adjust the return type of the given function to its appropriate
12742 vector counterpart. Returns a simd array to be used throughout the
12743 function as a return value. */
12745 static tree
12746 simd_clone_adjust_return_type (struct cgraph_node *node)
12748 tree fndecl = node->decl;
12749 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12750 unsigned int veclen;
12751 tree t;
12753 /* Adjust the function return type. */
12754 if (orig_rettype == void_type_node)
12755 return NULL_TREE;
12756 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
12757 t = TREE_TYPE (TREE_TYPE (fndecl));
12758 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
12759 veclen = node->simdclone->vecsize_int;
12760 else
12761 veclen = node->simdclone->vecsize_float;
12762 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
12763 if (veclen > node->simdclone->simdlen)
12764 veclen = node->simdclone->simdlen;
12765 if (POINTER_TYPE_P (t))
12766 t = pointer_sized_int_node;
12767 if (veclen == node->simdclone->simdlen)
12768 t = build_vector_type (t, node->simdclone->simdlen);
12769 else
12771 t = build_vector_type (t, veclen);
12772 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
12774 TREE_TYPE (TREE_TYPE (fndecl)) = t;
12775 if (!node->definition)
12776 return NULL_TREE;
12778 t = DECL_RESULT (fndecl);
12779 /* Adjust the DECL_RESULT. */
12780 gcc_assert (TREE_TYPE (t) != void_type_node);
12781 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12782 relayout_decl (t);
12784 tree atype = build_array_type_nelts (orig_rettype,
12785 node->simdclone->simdlen);
12786 if (veclen != node->simdclone->simdlen)
12787 return build1 (VIEW_CONVERT_EXPR, atype, t);
12789 /* Set up a SIMD array to use as the return value. */
12790 tree retval = create_tmp_var_raw (atype, "retval");
12791 gimple_add_tmp_var (retval);
12792 return retval;
12795 /* Each vector argument has a corresponding array to be used locally
12796 as part of the eventual loop. Create such temporary array and
12797 return it.
12799 PREFIX is the prefix to be used for the temporary.
12801 TYPE is the inner element type.
12803 SIMDLEN is the number of elements. */
12805 static tree
12806 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12808 tree atype = build_array_type_nelts (type, simdlen);
12809 tree avar = create_tmp_var_raw (atype, prefix);
12810 gimple_add_tmp_var (avar);
12811 return avar;
12814 /* Modify the function argument types to their corresponding vector
12815 counterparts if appropriate. Also, create one array for each simd
12816 argument to be used locally when using the function arguments as
12817 part of the loop.
12819 NODE is the function whose arguments are to be adjusted.
12821 Returns an adjustment vector that will be filled describing how the
12822 argument types will be adjusted. */
12824 static ipa_parm_adjustment_vec
12825 simd_clone_adjust_argument_types (struct cgraph_node *node)
12827 vec<tree> args;
12828 ipa_parm_adjustment_vec adjustments;
12830 if (node->definition)
12831 args = ipa_get_vector_of_formal_parms (node->decl);
12832 else
12833 args = simd_clone_vector_of_formal_parm_types (node->decl);
12834 adjustments.create (args.length ());
12835 unsigned i, j, veclen;
12836 struct ipa_parm_adjustment adj;
12837 for (i = 0; i < node->simdclone->nargs; ++i)
12839 memset (&adj, 0, sizeof (adj));
12840 tree parm = args[i];
12841 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12842 adj.base_index = i;
12843 adj.base = parm;
12845 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12846 node->simdclone->args[i].orig_type = parm_type;
12848 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12850 /* No adjustment necessary for scalar arguments. */
12851 adj.op = IPA_PARM_OP_COPY;
12853 else
12855 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12856 veclen = node->simdclone->vecsize_int;
12857 else
12858 veclen = node->simdclone->vecsize_float;
12859 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12860 if (veclen > node->simdclone->simdlen)
12861 veclen = node->simdclone->simdlen;
12862 adj.arg_prefix = "simd";
12863 if (POINTER_TYPE_P (parm_type))
12864 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12865 else
12866 adj.type = build_vector_type (parm_type, veclen);
12867 node->simdclone->args[i].vector_type = adj.type;
12868 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12870 adjustments.safe_push (adj);
12871 if (j == veclen)
12873 memset (&adj, 0, sizeof (adj));
12874 adj.op = IPA_PARM_OP_NEW;
12875 adj.arg_prefix = "simd";
12876 adj.base_index = i;
12877 adj.type = node->simdclone->args[i].vector_type;
12881 if (node->definition)
12882 node->simdclone->args[i].simd_array
12883 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12884 parm_type, node->simdclone->simdlen);
12886 adjustments.safe_push (adj);
12889 if (node->simdclone->inbranch)
12891 tree base_type
12892 = simd_clone_compute_base_data_type (node->simdclone->origin,
12893 node->simdclone);
12895 memset (&adj, 0, sizeof (adj));
12896 adj.op = IPA_PARM_OP_NEW;
12897 adj.arg_prefix = "mask";
12899 adj.base_index = i;
12900 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12901 veclen = node->simdclone->vecsize_int;
12902 else
12903 veclen = node->simdclone->vecsize_float;
12904 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12905 if (veclen > node->simdclone->simdlen)
12906 veclen = node->simdclone->simdlen;
12907 if (POINTER_TYPE_P (base_type))
12908 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12909 else
12910 adj.type = build_vector_type (base_type, veclen);
12911 adjustments.safe_push (adj);
12913 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12914 adjustments.safe_push (adj);
12916 /* We have previously allocated one extra entry for the mask. Use
12917 it and fill it. */
12918 struct cgraph_simd_clone *sc = node->simdclone;
12919 sc->nargs++;
12920 if (node->definition)
12922 sc->args[i].orig_arg
12923 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12924 sc->args[i].simd_array
12925 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12927 sc->args[i].orig_type = base_type;
12928 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12931 if (node->definition)
12932 ipa_modify_formal_parameters (node->decl, adjustments);
12933 else
12935 tree new_arg_types = NULL_TREE, new_reversed;
12936 bool last_parm_void = false;
12937 if (args.length () > 0 && args.last () == void_type_node)
12938 last_parm_void = true;
12940 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12941 j = adjustments.length ();
12942 for (i = 0; i < j; i++)
12944 struct ipa_parm_adjustment *adj = &adjustments[i];
12945 tree ptype;
12946 if (adj->op == IPA_PARM_OP_COPY)
12947 ptype = args[adj->base_index];
12948 else
12949 ptype = adj->type;
12950 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12952 new_reversed = nreverse (new_arg_types);
12953 if (last_parm_void)
12955 if (new_reversed)
12956 TREE_CHAIN (new_arg_types) = void_list_node;
12957 else
12958 new_reversed = void_list_node;
12961 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
12962 TYPE_ARG_TYPES (new_type) = new_reversed;
12963 TREE_TYPE (node->decl) = new_type;
12965 adjustments.release ();
12967 args.release ();
12968 return adjustments;
12971 /* Initialize and copy the function arguments in NODE to their
12972 corresponding local simd arrays. Returns a fresh gimple_seq with
12973 the instruction sequence generated. */
12975 static gimple_seq
12976 simd_clone_init_simd_arrays (struct cgraph_node *node,
12977 ipa_parm_adjustment_vec adjustments)
12979 gimple_seq seq = NULL;
12980 unsigned i = 0, j = 0, k;
12982 for (tree arg = DECL_ARGUMENTS (node->decl);
12983 arg;
12984 arg = DECL_CHAIN (arg), i++, j++)
12986 if (adjustments[j].op == IPA_PARM_OP_COPY)
12987 continue;
12989 node->simdclone->args[i].vector_arg = arg;
12991 tree array = node->simdclone->args[i].simd_array;
12992 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
12994 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
12995 tree ptr = build_fold_addr_expr (array);
12996 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
12997 build_int_cst (ptype, 0));
12998 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
12999 gimplify_and_add (t, &seq);
13001 else
13003 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13004 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13005 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13007 tree ptr = build_fold_addr_expr (array);
13008 int elemsize;
13009 if (k)
13011 arg = DECL_CHAIN (arg);
13012 j++;
13014 elemsize
13015 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13016 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13017 build_int_cst (ptype, k * elemsize));
13018 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13019 gimplify_and_add (t, &seq);
13023 return seq;
13026 /* Callback info for ipa_simd_modify_stmt_ops below. */
13028 struct modify_stmt_info {
13029 ipa_parm_adjustment_vec adjustments;
13030 gimple stmt;
13031 /* True if the parent statement was modified by
13032 ipa_simd_modify_stmt_ops. */
13033 bool modified;
13036 /* Callback for walk_gimple_op.
13038 Adjust operands from a given statement as specified in the
13039 adjustments vector in the callback data. */
13041 static tree
13042 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13044 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13045 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13046 tree *orig_tp = tp;
13047 if (TREE_CODE (*tp) == ADDR_EXPR)
13048 tp = &TREE_OPERAND (*tp, 0);
13049 struct ipa_parm_adjustment *cand = NULL;
13050 if (TREE_CODE (*tp) == PARM_DECL)
13051 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13052 else
13054 if (TYPE_P (*tp))
13055 *walk_subtrees = 0;
13058 tree repl = NULL_TREE;
13059 if (cand)
13060 repl = unshare_expr (cand->new_decl);
13061 else
13063 if (tp != orig_tp)
13065 *walk_subtrees = 0;
13066 bool modified = info->modified;
13067 info->modified = false;
13068 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13069 if (!info->modified)
13071 info->modified = modified;
13072 return NULL_TREE;
13074 info->modified = modified;
13075 repl = *tp;
13077 else
13078 return NULL_TREE;
13081 if (tp != orig_tp)
13083 repl = build_fold_addr_expr (repl);
13084 gimple stmt;
13085 if (is_gimple_debug (info->stmt))
13087 tree vexpr = make_node (DEBUG_EXPR_DECL);
13088 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13089 DECL_ARTIFICIAL (vexpr) = 1;
13090 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13091 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13092 repl = vexpr;
13094 else
13096 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13097 repl = gimple_assign_lhs (stmt);
13099 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13100 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13101 *orig_tp = repl;
13103 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13105 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13106 *tp = vce;
13108 else
13109 *tp = repl;
13111 info->modified = true;
13112 return NULL_TREE;
13115 /* Traverse the function body and perform all modifications as
13116 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13117 modified such that the replacement/reduction value will now be an
13118 offset into the corresponding simd_array.
13120 This function will replace all function argument uses with their
13121 corresponding simd array elements, and ajust the return values
13122 accordingly. */
13124 static void
13125 ipa_simd_modify_function_body (struct cgraph_node *node,
13126 ipa_parm_adjustment_vec adjustments,
13127 tree retval_array, tree iter)
13129 basic_block bb;
13130 unsigned int i, j, l;
13132 /* Re-use the adjustments array, but this time use it to replace
13133 every function argument use to an offset into the corresponding
13134 simd_array. */
13135 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13137 if (!node->simdclone->args[i].vector_arg)
13138 continue;
13140 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13141 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13142 adjustments[j].new_decl
13143 = build4 (ARRAY_REF,
13144 basetype,
13145 node->simdclone->args[i].simd_array,
13146 iter,
13147 NULL_TREE, NULL_TREE);
13148 if (adjustments[j].op == IPA_PARM_OP_NONE
13149 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13150 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13153 l = adjustments.length ();
13154 for (i = 1; i < num_ssa_names; i++)
13156 tree name = ssa_name (i);
13157 if (name
13158 && SSA_NAME_VAR (name)
13159 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13161 for (j = 0; j < l; j++)
13162 if (SSA_NAME_VAR (name) == adjustments[j].base
13163 && adjustments[j].new_decl)
13165 tree base_var;
13166 if (adjustments[j].new_ssa_base == NULL_TREE)
13168 base_var
13169 = copy_var_decl (adjustments[j].base,
13170 DECL_NAME (adjustments[j].base),
13171 TREE_TYPE (adjustments[j].base));
13172 adjustments[j].new_ssa_base = base_var;
13174 else
13175 base_var = adjustments[j].new_ssa_base;
13176 if (SSA_NAME_IS_DEFAULT_DEF (name))
13178 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13179 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13180 tree new_decl = unshare_expr (adjustments[j].new_decl);
13181 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13182 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13183 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13184 gimple stmt = gimple_build_assign (name, new_decl);
13185 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13187 else
13188 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13193 struct modify_stmt_info info;
13194 info.adjustments = adjustments;
13196 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13198 gimple_stmt_iterator gsi;
13200 gsi = gsi_start_bb (bb);
13201 while (!gsi_end_p (gsi))
13203 gimple stmt = gsi_stmt (gsi);
13204 info.stmt = stmt;
13205 struct walk_stmt_info wi;
13207 memset (&wi, 0, sizeof (wi));
13208 info.modified = false;
13209 wi.info = &info;
13210 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13212 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13214 tree retval = gimple_return_retval (return_stmt);
13215 if (!retval)
13217 gsi_remove (&gsi, true);
13218 continue;
13221 /* Replace `return foo' with `retval_array[iter] = foo'. */
13222 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13223 retval_array, iter, NULL, NULL);
13224 stmt = gimple_build_assign (ref, retval);
13225 gsi_replace (&gsi, stmt, true);
13226 info.modified = true;
13229 if (info.modified)
13231 update_stmt (stmt);
13232 if (maybe_clean_eh_stmt (stmt))
13233 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13235 gsi_next (&gsi);
13240 /* Adjust the argument types in NODE to their appropriate vector
13241 counterparts. */
13243 static void
13244 simd_clone_adjust (struct cgraph_node *node)
13246 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13248 targetm.simd_clone.adjust (node);
13250 tree retval = simd_clone_adjust_return_type (node);
13251 ipa_parm_adjustment_vec adjustments
13252 = simd_clone_adjust_argument_types (node);
13254 push_gimplify_context ();
13256 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13258 /* Adjust all uses of vector arguments accordingly. Adjust all
13259 return values accordingly. */
13260 tree iter = create_tmp_var (unsigned_type_node, "iter");
13261 tree iter1 = make_ssa_name (iter);
13262 tree iter2 = make_ssa_name (iter);
13263 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13265 /* Initialize the iteration variable. */
13266 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13267 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13268 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13269 /* Insert the SIMD array and iv initialization at function
13270 entry. */
13271 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13273 pop_gimplify_context (NULL);
13275 /* Create a new BB right before the original exit BB, to hold the
13276 iteration increment and the condition/branch. */
13277 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13278 basic_block incr_bb = create_empty_bb (orig_exit);
13279 add_bb_to_loop (incr_bb, body_bb->loop_father);
13280 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13281 flag. Set it now to be a FALLTHRU_EDGE. */
13282 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13283 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13284 for (unsigned i = 0;
13285 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13287 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13288 redirect_edge_succ (e, incr_bb);
13290 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13291 e->probability = REG_BR_PROB_BASE;
13292 gsi = gsi_last_bb (incr_bb);
13293 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13294 build_int_cst (unsigned_type_node, 1));
13295 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13297 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13298 struct loop *loop = alloc_loop ();
13299 cfun->has_force_vectorize_loops = true;
13300 loop->safelen = node->simdclone->simdlen;
13301 loop->force_vectorize = true;
13302 loop->header = body_bb;
13304 /* Branch around the body if the mask applies. */
13305 if (node->simdclone->inbranch)
13307 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13308 tree mask_array
13309 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13310 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13311 tree aref = build4 (ARRAY_REF,
13312 TREE_TYPE (TREE_TYPE (mask_array)),
13313 mask_array, iter1,
13314 NULL, NULL);
13315 g = gimple_build_assign (mask, aref);
13316 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13317 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13318 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13320 aref = build1 (VIEW_CONVERT_EXPR,
13321 build_nonstandard_integer_type (bitsize, 0), mask);
13322 mask = make_ssa_name (TREE_TYPE (aref));
13323 g = gimple_build_assign (mask, aref);
13324 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13327 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13328 NULL, NULL);
13329 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13330 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13331 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13334 /* Generate the condition. */
13335 g = gimple_build_cond (LT_EXPR,
13336 iter2,
13337 build_int_cst (unsigned_type_node,
13338 node->simdclone->simdlen),
13339 NULL, NULL);
13340 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13341 e = split_block (incr_bb, gsi_stmt (gsi));
13342 basic_block latch_bb = e->dest;
13343 basic_block new_exit_bb;
13344 new_exit_bb = split_block_after_labels (latch_bb)->dest;
13345 loop->latch = latch_bb;
13347 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13349 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13350 /* The successor of incr_bb is already pointing to latch_bb; just
13351 change the flags.
13352 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13353 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13355 gphi *phi = create_phi_node (iter1, body_bb);
13356 edge preheader_edge = find_edge (entry_bb, body_bb);
13357 edge latch_edge = single_succ_edge (latch_bb);
13358 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13359 UNKNOWN_LOCATION);
13360 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13362 /* Generate the new return. */
13363 gsi = gsi_last_bb (new_exit_bb);
13364 if (retval
13365 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13366 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13367 retval = TREE_OPERAND (retval, 0);
13368 else if (retval)
13370 retval = build1 (VIEW_CONVERT_EXPR,
13371 TREE_TYPE (TREE_TYPE (node->decl)),
13372 retval);
13373 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13374 false, GSI_CONTINUE_LINKING);
13376 g = gimple_build_return (retval);
13377 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13379 /* Handle aligned clauses by replacing default defs of the aligned
13380 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13381 lhs. Handle linear by adding PHIs. */
13382 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13383 if (node->simdclone->args[i].alignment
13384 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13385 && (node->simdclone->args[i].alignment
13386 & (node->simdclone->args[i].alignment - 1)) == 0
13387 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13388 == POINTER_TYPE)
13390 unsigned int alignment = node->simdclone->args[i].alignment;
13391 tree orig_arg = node->simdclone->args[i].orig_arg;
13392 tree def = ssa_default_def (cfun, orig_arg);
13393 if (def && !has_zero_uses (def))
13395 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13396 gimple_seq seq = NULL;
13397 bool need_cvt = false;
13398 gcall *call
13399 = gimple_build_call (fn, 2, def, size_int (alignment));
13400 g = call;
13401 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13402 ptr_type_node))
13403 need_cvt = true;
13404 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13405 gimple_call_set_lhs (g, t);
13406 gimple_seq_add_stmt_without_update (&seq, g);
13407 if (need_cvt)
13409 t = make_ssa_name (orig_arg);
13410 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13411 gimple_seq_add_stmt_without_update (&seq, g);
13413 gsi_insert_seq_on_edge_immediate
13414 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13416 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13417 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13418 entry_bb);
13419 node->create_edge (cgraph_node::get_create (fn),
13420 call, entry_bb->count, freq);
13422 imm_use_iterator iter;
13423 use_operand_p use_p;
13424 gimple use_stmt;
13425 tree repl = gimple_get_lhs (g);
13426 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13427 if (is_gimple_debug (use_stmt) || use_stmt == call)
13428 continue;
13429 else
13430 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13431 SET_USE (use_p, repl);
13434 else if (node->simdclone->args[i].arg_type
13435 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13437 tree orig_arg = node->simdclone->args[i].orig_arg;
13438 tree def = ssa_default_def (cfun, orig_arg);
13439 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13440 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13441 if (def && !has_zero_uses (def))
13443 iter1 = make_ssa_name (orig_arg);
13444 iter2 = make_ssa_name (orig_arg);
13445 phi = create_phi_node (iter1, body_bb);
13446 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13447 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13448 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13449 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13450 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13451 ? TREE_TYPE (orig_arg) : sizetype;
13452 tree addcst
13453 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13454 g = gimple_build_assign (iter2, code, iter1, addcst);
13455 gsi = gsi_last_bb (incr_bb);
13456 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13458 imm_use_iterator iter;
13459 use_operand_p use_p;
13460 gimple use_stmt;
13461 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13462 if (use_stmt == phi)
13463 continue;
13464 else
13465 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13466 SET_USE (use_p, iter1);
13470 calculate_dominance_info (CDI_DOMINATORS);
13471 add_loop (loop, loop->header->loop_father);
13472 update_ssa (TODO_update_ssa);
13474 pop_cfun ();
13477 /* If the function in NODE is tagged as an elemental SIMD function,
13478 create the appropriate SIMD clones. */
13480 static void
13481 expand_simd_clones (struct cgraph_node *node)
13483 tree attr = lookup_attribute ("omp declare simd",
13484 DECL_ATTRIBUTES (node->decl));
13485 if (attr == NULL_TREE
13486 || node->global.inlined_to
13487 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13488 return;
13490 /* Ignore
13491 #pragma omp declare simd
13492 extern int foo ();
13493 in C, there we don't know the argument types at all. */
13494 if (!node->definition
13495 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13496 return;
13500 /* Start with parsing the "omp declare simd" attribute(s). */
13501 bool inbranch_clause_specified;
13502 struct cgraph_simd_clone *clone_info
13503 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13504 &inbranch_clause_specified);
13505 if (clone_info == NULL)
13506 continue;
13508 int orig_simdlen = clone_info->simdlen;
13509 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13510 /* The target can return 0 (no simd clones should be created),
13511 1 (just one ISA of simd clones should be created) or higher
13512 count of ISA variants. In that case, clone_info is initialized
13513 for the first ISA variant. */
13514 int count
13515 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13516 base_type, 0);
13517 if (count == 0)
13518 continue;
13520 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13521 also create one inbranch and one !inbranch clone of it. */
13522 for (int i = 0; i < count * 2; i++)
13524 struct cgraph_simd_clone *clone = clone_info;
13525 if (inbranch_clause_specified && (i & 1) != 0)
13526 continue;
13528 if (i != 0)
13530 clone = simd_clone_struct_alloc (clone_info->nargs
13531 + ((i & 1) != 0));
13532 simd_clone_struct_copy (clone, clone_info);
13533 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13534 and simd_clone_adjust_argument_types did to the first
13535 clone's info. */
13536 clone->nargs -= clone_info->inbranch;
13537 clone->simdlen = orig_simdlen;
13538 /* And call the target hook again to get the right ISA. */
13539 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13540 base_type,
13541 i / 2);
13542 if ((i & 1) != 0)
13543 clone->inbranch = 1;
13546 /* simd_clone_mangle might fail if such a clone has been created
13547 already. */
13548 tree id = simd_clone_mangle (node, clone);
13549 if (id == NULL_TREE)
13550 continue;
13552 /* Only when we are sure we want to create the clone actually
13553 clone the function (or definitions) or create another
13554 extern FUNCTION_DECL (for prototypes without definitions). */
13555 struct cgraph_node *n = simd_clone_create (node);
13556 if (n == NULL)
13557 continue;
13559 n->simdclone = clone;
13560 clone->origin = node;
13561 clone->next_clone = NULL;
13562 if (node->simd_clones == NULL)
13564 clone->prev_clone = n;
13565 node->simd_clones = n;
13567 else
13569 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13570 clone->prev_clone->simdclone->next_clone = n;
13571 node->simd_clones->simdclone->prev_clone = n;
13573 symtab->change_decl_assembler_name (n->decl, id);
13574 /* And finally adjust the return type, parameters and for
13575 definitions also function body. */
13576 if (node->definition)
13577 simd_clone_adjust (n);
13578 else
13580 simd_clone_adjust_return_type (n);
13581 simd_clone_adjust_argument_types (n);
13585 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13588 /* Entry point for IPA simd clone creation pass. */
13590 static unsigned int
13591 ipa_omp_simd_clone (void)
13593 struct cgraph_node *node;
13594 FOR_EACH_FUNCTION (node)
13595 expand_simd_clones (node);
13596 return 0;
13599 namespace {
13601 const pass_data pass_data_omp_simd_clone =
13603 SIMPLE_IPA_PASS, /* type */
13604 "simdclone", /* name */
13605 OPTGROUP_NONE, /* optinfo_flags */
13606 TV_NONE, /* tv_id */
13607 ( PROP_ssa | PROP_cfg ), /* properties_required */
13608 0, /* properties_provided */
13609 0, /* properties_destroyed */
13610 0, /* todo_flags_start */
13611 0, /* todo_flags_finish */
13614 class pass_omp_simd_clone : public simple_ipa_opt_pass
13616 public:
13617 pass_omp_simd_clone(gcc::context *ctxt)
13618 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13621 /* opt_pass methods: */
13622 virtual bool gate (function *);
13623 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
13626 bool
13627 pass_omp_simd_clone::gate (function *)
13629 return ((flag_openmp || flag_openmp_simd
13630 || flag_cilkplus
13631 || (in_lto_p && !flag_wpa))
13632 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13635 } // anon namespace
13637 simple_ipa_opt_pass *
13638 make_pass_omp_simd_clone (gcc::context *ctxt)
13640 return new pass_omp_simd_clone (ctxt);
13643 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13644 adds their addresses and sizes to constructor-vector V_CTOR. */
13645 static void
13646 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13647 vec<constructor_elt, va_gc> *v_ctor)
13649 unsigned len = vec_safe_length (v_decls);
13650 for (unsigned i = 0; i < len; i++)
13652 tree it = (*v_decls)[i];
13653 bool is_function = TREE_CODE (it) != VAR_DECL;
13655 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13656 if (!is_function)
13657 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13658 fold_convert (const_ptr_type_node,
13659 DECL_SIZE_UNIT (it)));
13663 /* Create new symbols containing (address, size) pairs for global variables,
13664 marked with "omp declare target" attribute, as well as addresses for the
13665 functions, which are outlined offloading regions. */
13666 void
13667 omp_finish_file (void)
13669 unsigned num_funcs = vec_safe_length (offload_funcs);
13670 unsigned num_vars = vec_safe_length (offload_vars);
13672 if (num_funcs == 0 && num_vars == 0)
13673 return;
13675 if (targetm_common.have_named_sections)
13677 vec<constructor_elt, va_gc> *v_f, *v_v;
13678 vec_alloc (v_f, num_funcs);
13679 vec_alloc (v_v, num_vars * 2);
13681 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13682 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13684 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13685 num_vars * 2);
13686 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13687 num_funcs);
13688 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13689 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13690 tree ctor_v = build_constructor (vars_decl_type, v_v);
13691 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13692 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13693 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13694 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13695 get_identifier (".offload_func_table"),
13696 funcs_decl_type);
13697 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13698 get_identifier (".offload_var_table"),
13699 vars_decl_type);
13700 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13701 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13702 otherwise a joint table in a binary will contain padding between
13703 tables from multiple object files. */
13704 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13705 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13706 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13707 DECL_INITIAL (funcs_decl) = ctor_f;
13708 DECL_INITIAL (vars_decl) = ctor_v;
13709 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13710 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13712 varpool_node::finalize_decl (vars_decl);
13713 varpool_node::finalize_decl (funcs_decl);
13715 else
13717 for (unsigned i = 0; i < num_funcs; i++)
13719 tree it = (*offload_funcs)[i];
13720 targetm.record_offload_symbol (it);
13722 for (unsigned i = 0; i < num_vars; i++)
13724 tree it = (*offload_vars)[i];
13725 targetm.record_offload_symbol (it);
13730 #include "gt-omp-low.h"