Merged trunk revision 225993 into the hsa branch.
[official-gcc.git] / gcc / omp-low.c
blobd7e53a62190e6c78b9f1f77afa365b36375cf556
1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "cfghooks.h"
30 #include "tree.h"
31 #include "gimple.h"
32 #include "rtl.h"
33 #include "ssa.h"
34 #include "alias.h"
35 #include "fold-const.h"
36 #include "stor-layout.h"
37 #include "cfganal.h"
38 #include "internal-fn.h"
39 #include "gimple-fold.h"
40 #include "gimplify.h"
41 #include "gimple-iterator.h"
42 #include "gimplify-me.h"
43 #include "gimple-walk.h"
44 #include "tree-iterator.h"
45 #include "tree-inline.h"
46 #include "langhooks.h"
47 #include "diagnostic-core.h"
48 #include "cgraph.h"
49 #include "tree-cfg.h"
50 #include "tree-into-ssa.h"
51 #include "flags.h"
52 #include "insn-config.h"
53 #include "expmed.h"
54 #include "dojump.h"
55 #include "explow.h"
56 #include "calls.h"
57 #include "emit-rtl.h"
58 #include "varasm.h"
59 #include "stmt.h"
60 #include "expr.h"
61 #include "tree-dfa.h"
62 #include "tree-ssa.h"
63 #include "tree-pass.h"
64 #include "except.h"
65 #include "splay-tree.h"
66 #include "insn-codes.h"
67 #include "optabs.h"
68 #include "cfgloop.h"
69 #include "target.h"
70 #include "common/common-target.h"
71 #include "omp-low.h"
72 #include "gimple-low.h"
73 #include "tree-cfgcleanup.h"
74 #include "pretty-print.h"
75 #include "alloc-pool.h"
76 #include "symbol-summary.h"
77 #include "ipa-prop.h"
78 #include "tree-nested.h"
79 #include "tree-eh.h"
80 #include "cilk.h"
81 #include "context.h"
82 #include "lto-section-names.h"
83 #include "gomp-constants.h"
86 /* Lowering of OMP parallel and workshare constructs proceeds in two
87 phases. The first phase scans the function looking for OMP statements
88 and then for variables that must be replaced to satisfy data sharing
89 clauses. The second phase expands code for the constructs, as well as
90 re-gimplifying things when variables have been replaced with complex
91 expressions.
93 Final code generation is done by pass_expand_omp. The flowgraph is
94 scanned for regions which are then moved to a new
95 function, to be invoked by the thread library, or offloaded. */
97 /* OMP region information. Every parallel and workshare
98 directive is enclosed between two markers, the OMP_* directive
99 and a corresponding OMP_RETURN statement. */
101 struct omp_region
103 /* The enclosing region. */
104 struct omp_region *outer;
106 /* First child region. */
107 struct omp_region *inner;
109 /* Next peer region. */
110 struct omp_region *next;
112 /* Block containing the omp directive as its last stmt. */
113 basic_block entry;
115 /* Block containing the OMP_RETURN as its last stmt. */
116 basic_block exit;
118 /* Block containing the OMP_CONTINUE as its last stmt. */
119 basic_block cont;
121 /* If this is a combined parallel+workshare region, this is a list
122 of additional arguments needed by the combined parallel+workshare
123 library call. */
124 vec<tree, va_gc> *ws_args;
126 /* The code for the omp directive of this region. */
127 enum gimple_code type;
129 /* Schedule kind, only used for OMP_FOR type regions. */
130 enum omp_clause_schedule_kind sched_kind;
132 /* True if this is a combined parallel+workshare region. */
133 bool is_combined_parallel;
135 /* True if this region is or is a part of kernelized parallel block. */
136 bool kernelize;
138 /* Requested group size or kernelized loops. */
139 tree req_group_size;
141 /* For kernelized for loops, the original iteration information. */
142 struct gimple_omp_for_iter *orig_first_iter;
145 /* Levels of parallelism as defined by OpenACC. Increasing numbers
146 correspond to deeper loop nesting levels. */
147 #define MASK_GANG 1
148 #define MASK_WORKER 2
149 #define MASK_VECTOR 4
151 /* Context structure. Used to store information about each parallel
152 directive in the code. */
154 typedef struct omp_context
156 /* This field must be at the beginning, as we do "inheritance": Some
157 callback functions for tree-inline.c (e.g., omp_copy_decl)
158 receive a copy_body_data pointer that is up-casted to an
159 omp_context pointer. */
160 copy_body_data cb;
162 /* The tree of contexts corresponding to the encountered constructs. */
163 struct omp_context *outer;
164 gimple stmt;
166 /* Map variables to fields in a structure that allows communication
167 between sending and receiving threads. */
168 splay_tree field_map;
169 tree record_type;
170 tree sender_decl;
171 tree receiver_decl;
173 /* These are used just by task contexts, if task firstprivate fn is
174 needed. srecord_type is used to communicate from the thread
175 that encountered the task construct to task firstprivate fn,
176 record_type is allocated by GOMP_task, initialized by task firstprivate
177 fn and passed to the task body fn. */
178 splay_tree sfield_map;
179 tree srecord_type;
181 /* A chain of variables to add to the top-level block surrounding the
182 construct. In the case of a parallel, this is in the child function. */
183 tree block_vars;
185 /* A map of reduction pointer variables. For accelerators, each
186 reduction variable is replaced with an array. Each thread, in turn,
187 is assigned to a slot on that array. */
188 splay_tree reduction_map;
190 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
191 barriers should jump to during omplower pass. */
192 tree cancel_label;
194 /* What to do with variables with implicitly determined sharing
195 attributes. */
196 enum omp_clause_default_kind default_kind;
198 /* Nesting depth of this context. Used to beautify error messages re
199 invalid gotos. The outermost ctx is depth 1, with depth 0 being
200 reserved for the main body of the function. */
201 int depth;
203 /* True if this parallel directive is nested within another. */
204 bool is_nested;
206 /* True if this construct can be cancelled. */
207 bool cancellable;
209 /* For OpenACC loops, a mask of gang, worker and vector used at
210 levels below this one. */
211 int gwv_below;
212 /* For OpenACC loops, a mask of gang, worker and vector used at
213 this level and above. For parallel and kernels clauses, a mask
214 indicating which of num_gangs/num_workers/num_vectors was used. */
215 int gwv_this;
216 } omp_context;
218 /* A structure holding the elements of:
219 for (V = N1; V cond N2; V += STEP) [...] */
221 struct omp_for_data_loop
223 tree v, n1, n2, step;
224 enum tree_code cond_code;
227 /* A structure describing the main elements of a parallel loop. */
229 struct omp_for_data
231 struct omp_for_data_loop loop;
232 tree chunk_size;
233 gomp_for *for_stmt;
234 tree pre, iter_type;
235 int collapse;
236 bool have_nowait, have_ordered;
237 enum omp_clause_schedule_kind sched_kind;
238 struct omp_for_data_loop *loops;
242 static splay_tree all_contexts;
243 static int taskreg_nesting_level;
244 static int target_nesting_level;
245 static struct omp_region *root_omp_region;
246 static bitmap task_shared_vars;
247 static vec<omp_context *> taskreg_contexts;
249 static void scan_omp (gimple_seq *, omp_context *);
250 static tree scan_omp_1_op (tree *, int *, void *);
252 #define WALK_SUBSTMTS \
253 case GIMPLE_BIND: \
254 case GIMPLE_TRY: \
255 case GIMPLE_CATCH: \
256 case GIMPLE_EH_FILTER: \
257 case GIMPLE_TRANSACTION: \
258 /* The sub-statements for these should be walked. */ \
259 *handled_ops_p = false; \
260 break;
262 /* Helper function to get the name of the array containing the partial
263 reductions for OpenACC reductions. */
264 static const char *
265 oacc_get_reduction_array_id (tree node)
267 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
268 int len = strlen ("OACC") + strlen (id);
269 char *temp_name = XALLOCAVEC (char, len + 1);
270 snprintf (temp_name, len + 1, "OACC%s", id);
271 return IDENTIFIER_POINTER (get_identifier (temp_name));
274 /* Determine the number of threads OpenACC threads used to determine the
275 size of the array of partial reductions. Currently, this is num_gangs
276 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
277 because it is independed of the device used. */
279 static tree
280 oacc_max_threads (omp_context *ctx)
282 tree nthreads, vector_length, gangs, clauses;
284 gangs = fold_convert (sizetype, integer_one_node);
285 vector_length = gangs;
287 /* The reduction clause may be nested inside a loop directive.
288 Scan for the innermost vector_length clause. */
289 for (omp_context *oc = ctx; oc; oc = oc->outer)
291 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
292 || (gimple_omp_target_kind (oc->stmt)
293 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
294 continue;
296 clauses = gimple_omp_target_clauses (oc->stmt);
298 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
299 if (vector_length)
300 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
301 sizetype,
302 OMP_CLAUSE_VECTOR_LENGTH_EXPR
303 (vector_length));
304 else
305 vector_length = fold_convert (sizetype, integer_one_node);
307 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
308 if (gangs)
309 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
310 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
311 else
312 gangs = fold_convert (sizetype, integer_one_node);
314 break;
317 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
319 return nthreads;
322 /* Holds offload tables with decls. */
323 vec<tree, va_gc> *offload_funcs, *offload_vars;
325 /* Convenience function for calling scan_omp_1_op on tree operands. */
327 static inline tree
328 scan_omp_op (tree *tp, omp_context *ctx)
330 struct walk_stmt_info wi;
332 memset (&wi, 0, sizeof (wi));
333 wi.info = ctx;
334 wi.want_locations = true;
336 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
339 static void lower_omp (gimple_seq *, omp_context *);
340 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
341 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
343 /* Find an OMP clause of type KIND within CLAUSES. */
345 tree
346 find_omp_clause (tree clauses, enum omp_clause_code kind)
348 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
349 if (OMP_CLAUSE_CODE (clauses) == kind)
350 return clauses;
352 return NULL_TREE;
355 /* Return true if CTX is for an omp parallel. */
357 static inline bool
358 is_parallel_ctx (omp_context *ctx)
360 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
364 /* Return true if CTX is for an omp task. */
366 static inline bool
367 is_task_ctx (omp_context *ctx)
369 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
373 /* Return true if CTX is for an omp parallel or omp task. */
375 static inline bool
376 is_taskreg_ctx (omp_context *ctx)
378 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
379 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
383 /* Return true if REGION is a combined parallel+workshare region. */
385 static inline bool
386 is_combined_parallel (struct omp_region *region)
388 return region->is_combined_parallel;
391 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or
392 GT_EXPR. */
394 static void
395 adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2)
397 switch (*cond_code)
399 case LT_EXPR:
400 case GT_EXPR:
401 case NE_EXPR:
402 break;
403 case LE_EXPR:
404 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
405 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
406 else
407 *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
408 build_int_cst (TREE_TYPE (*n2), 1));
409 *cond_code = LT_EXPR;
410 break;
411 case GE_EXPR:
412 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
413 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
414 else
415 *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
416 build_int_cst (TREE_TYPE (*n2), 1));
417 *cond_code = GT_EXPR;
418 break;
419 default:
420 gcc_unreachable ();
424 /* Return the looping step from INCR, extracted from the gimple omp
425 statement. */
427 static tree
428 get_omp_for_step_from_incr (location_t loc, tree incr)
430 tree step;
431 switch (TREE_CODE (incr))
433 case PLUS_EXPR:
434 step = TREE_OPERAND (incr, 1);
435 break;
436 case POINTER_PLUS_EXPR:
437 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
438 break;
439 case MINUS_EXPR:
440 step = TREE_OPERAND (incr, 1);
441 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
442 break;
443 default:
444 gcc_unreachable ();
446 return step;
449 /* Extract the header elements of parallel loop FOR_STMT and store
450 them into *FD. */
452 static void
453 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
454 struct omp_for_data_loop *loops)
456 tree t, var, *collapse_iter, *collapse_count;
457 tree count = NULL_TREE, iter_type = long_integer_type_node;
458 struct omp_for_data_loop *loop;
459 int i;
460 struct omp_for_data_loop dummy_loop;
461 location_t loc = gimple_location (for_stmt);
462 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
463 bool distribute = gimple_omp_for_kind (for_stmt)
464 == GF_OMP_FOR_KIND_DISTRIBUTE;
466 fd->for_stmt = for_stmt;
467 fd->pre = NULL;
468 fd->collapse = gimple_omp_for_collapse (for_stmt);
469 if (fd->collapse > 1)
470 fd->loops = loops;
471 else
472 fd->loops = &fd->loop;
474 fd->have_nowait = distribute || simd;
475 fd->have_ordered = false;
476 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
477 fd->chunk_size = NULL_TREE;
478 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
479 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
480 collapse_iter = NULL;
481 collapse_count = NULL;
483 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
484 switch (OMP_CLAUSE_CODE (t))
486 case OMP_CLAUSE_NOWAIT:
487 fd->have_nowait = true;
488 break;
489 case OMP_CLAUSE_ORDERED:
490 fd->have_ordered = true;
491 break;
492 case OMP_CLAUSE_SCHEDULE:
493 gcc_assert (!distribute);
494 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
495 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
496 break;
497 case OMP_CLAUSE_DIST_SCHEDULE:
498 gcc_assert (distribute);
499 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
500 break;
501 case OMP_CLAUSE_COLLAPSE:
502 if (fd->collapse > 1)
504 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
505 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
507 break;
508 default:
509 break;
512 /* FIXME: for now map schedule(auto) to schedule(static).
513 There should be analysis to determine whether all iterations
514 are approximately the same amount of work (then schedule(static)
515 is best) or if it varies (then schedule(dynamic,N) is better). */
516 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
518 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
519 gcc_assert (fd->chunk_size == NULL);
521 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
522 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
523 gcc_assert (fd->chunk_size == NULL);
524 else if (fd->chunk_size == NULL)
526 /* We only need to compute a default chunk size for ordered
527 static loops and dynamic loops. */
528 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
529 || fd->have_ordered)
530 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
531 ? integer_zero_node : integer_one_node;
534 for (i = 0; i < fd->collapse; i++)
536 if (fd->collapse == 1)
537 loop = &fd->loop;
538 else if (loops != NULL)
539 loop = loops + i;
540 else
541 loop = &dummy_loop;
543 loop->v = gimple_omp_for_index (for_stmt, i);
544 gcc_assert (SSA_VAR_P (loop->v));
545 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
546 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
547 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
548 loop->n1 = gimple_omp_for_initial (for_stmt, i);
550 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
551 loop->n2 = gimple_omp_for_final (for_stmt, i);
552 gcc_assert (loop->cond_code != NE_EXPR
553 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKSIMD
554 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKFOR);
555 adjust_for_condition (loc, &loop->cond_code, &loop->n2);
557 t = gimple_omp_for_incr (for_stmt, i);
558 gcc_assert (TREE_OPERAND (t, 0) == var);
559 loop->step = get_omp_for_step_from_incr (loc, t);
561 if (simd
562 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
563 && !fd->have_ordered))
565 if (fd->collapse == 1)
566 iter_type = TREE_TYPE (loop->v);
567 else if (i == 0
568 || TYPE_PRECISION (iter_type)
569 < TYPE_PRECISION (TREE_TYPE (loop->v)))
570 iter_type
571 = build_nonstandard_integer_type
572 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
574 else if (iter_type != long_long_unsigned_type_node)
576 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
577 iter_type = long_long_unsigned_type_node;
578 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
579 && TYPE_PRECISION (TREE_TYPE (loop->v))
580 >= TYPE_PRECISION (iter_type))
582 tree n;
584 if (loop->cond_code == LT_EXPR)
585 n = fold_build2_loc (loc,
586 PLUS_EXPR, TREE_TYPE (loop->v),
587 loop->n2, loop->step);
588 else
589 n = loop->n1;
590 if (TREE_CODE (n) != INTEGER_CST
591 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
592 iter_type = long_long_unsigned_type_node;
594 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
595 > TYPE_PRECISION (iter_type))
597 tree n1, n2;
599 if (loop->cond_code == LT_EXPR)
601 n1 = loop->n1;
602 n2 = fold_build2_loc (loc,
603 PLUS_EXPR, TREE_TYPE (loop->v),
604 loop->n2, loop->step);
606 else
608 n1 = fold_build2_loc (loc,
609 MINUS_EXPR, TREE_TYPE (loop->v),
610 loop->n2, loop->step);
611 n2 = loop->n1;
613 if (TREE_CODE (n1) != INTEGER_CST
614 || TREE_CODE (n2) != INTEGER_CST
615 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
616 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
617 iter_type = long_long_unsigned_type_node;
621 if (collapse_count && *collapse_count == NULL)
623 t = fold_binary (loop->cond_code, boolean_type_node,
624 fold_convert (TREE_TYPE (loop->v), loop->n1),
625 fold_convert (TREE_TYPE (loop->v), loop->n2));
626 if (t && integer_zerop (t))
627 count = build_zero_cst (long_long_unsigned_type_node);
628 else if ((i == 0 || count != NULL_TREE)
629 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
630 && TREE_CONSTANT (loop->n1)
631 && TREE_CONSTANT (loop->n2)
632 && TREE_CODE (loop->step) == INTEGER_CST)
634 tree itype = TREE_TYPE (loop->v);
636 if (POINTER_TYPE_P (itype))
637 itype = signed_type_for (itype);
638 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
639 t = fold_build2_loc (loc,
640 PLUS_EXPR, itype,
641 fold_convert_loc (loc, itype, loop->step), t);
642 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
643 fold_convert_loc (loc, itype, loop->n2));
644 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
645 fold_convert_loc (loc, itype, loop->n1));
646 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
647 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
648 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
649 fold_build1_loc (loc, NEGATE_EXPR, itype,
650 fold_convert_loc (loc, itype,
651 loop->step)));
652 else
653 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
654 fold_convert_loc (loc, itype, loop->step));
655 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
656 if (count != NULL_TREE)
657 count = fold_build2_loc (loc,
658 MULT_EXPR, long_long_unsigned_type_node,
659 count, t);
660 else
661 count = t;
662 if (TREE_CODE (count) != INTEGER_CST)
663 count = NULL_TREE;
665 else if (count && !integer_zerop (count))
666 count = NULL_TREE;
670 if (count
671 && !simd
672 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
673 || fd->have_ordered))
675 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
676 iter_type = long_long_unsigned_type_node;
677 else
678 iter_type = long_integer_type_node;
680 else if (collapse_iter && *collapse_iter != NULL)
681 iter_type = TREE_TYPE (*collapse_iter);
682 fd->iter_type = iter_type;
683 if (collapse_iter && *collapse_iter == NULL)
684 *collapse_iter = create_tmp_var (iter_type, ".iter");
685 if (collapse_count && *collapse_count == NULL)
687 if (count)
688 *collapse_count = fold_convert_loc (loc, iter_type, count);
689 else
690 *collapse_count = create_tmp_var (iter_type, ".count");
693 if (fd->collapse > 1)
695 fd->loop.v = *collapse_iter;
696 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
697 fd->loop.n2 = *collapse_count;
698 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
699 fd->loop.cond_code = LT_EXPR;
702 /* For OpenACC loops, force a chunk size of one, as this avoids the default
703 scheduling where several subsequent iterations are being executed by the
704 same thread. */
705 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
707 gcc_assert (fd->chunk_size == NULL_TREE);
708 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
713 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
714 is the immediate dominator of PAR_ENTRY_BB, return true if there
715 are no data dependencies that would prevent expanding the parallel
716 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
718 When expanding a combined parallel+workshare region, the call to
719 the child function may need additional arguments in the case of
720 GIMPLE_OMP_FOR regions. In some cases, these arguments are
721 computed out of variables passed in from the parent to the child
722 via 'struct .omp_data_s'. For instance:
724 #pragma omp parallel for schedule (guided, i * 4)
725 for (j ...)
727 Is lowered into:
729 # BLOCK 2 (PAR_ENTRY_BB)
730 .omp_data_o.i = i;
731 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
733 # BLOCK 3 (WS_ENTRY_BB)
734 .omp_data_i = &.omp_data_o;
735 D.1667 = .omp_data_i->i;
736 D.1598 = D.1667 * 4;
737 #pragma omp for schedule (guided, D.1598)
739 When we outline the parallel region, the call to the child function
740 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
741 that value is computed *after* the call site. So, in principle we
742 cannot do the transformation.
744 To see whether the code in WS_ENTRY_BB blocks the combined
745 parallel+workshare call, we collect all the variables used in the
746 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
747 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
748 call.
750 FIXME. If we had the SSA form built at this point, we could merely
751 hoist the code in block 3 into block 2 and be done with it. But at
752 this point we don't have dataflow information and though we could
753 hack something up here, it is really not worth the aggravation. */
755 static bool
756 workshare_safe_to_combine_p (basic_block ws_entry_bb)
758 struct omp_for_data fd;
759 gimple ws_stmt = last_stmt (ws_entry_bb);
761 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
762 return true;
764 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
766 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
768 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
769 return false;
770 if (fd.iter_type != long_integer_type_node)
771 return false;
773 /* FIXME. We give up too easily here. If any of these arguments
774 are not constants, they will likely involve variables that have
775 been mapped into fields of .omp_data_s for sharing with the child
776 function. With appropriate data flow, it would be possible to
777 see through this. */
778 if (!is_gimple_min_invariant (fd.loop.n1)
779 || !is_gimple_min_invariant (fd.loop.n2)
780 || !is_gimple_min_invariant (fd.loop.step)
781 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
782 return false;
784 return true;
788 /* Collect additional arguments needed to emit a combined
789 parallel+workshare call. WS_STMT is the workshare directive being
790 expanded. */
792 static vec<tree, va_gc> *
793 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
795 tree t;
796 location_t loc = gimple_location (ws_stmt);
797 vec<tree, va_gc> *ws_args;
799 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
801 struct omp_for_data fd;
802 tree n1, n2;
804 extract_omp_for_data (for_stmt, &fd, NULL);
805 n1 = fd.loop.n1;
806 n2 = fd.loop.n2;
808 if (gimple_omp_for_combined_into_p (for_stmt))
810 tree innerc
811 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
812 OMP_CLAUSE__LOOPTEMP_);
813 gcc_assert (innerc);
814 n1 = OMP_CLAUSE_DECL (innerc);
815 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
816 OMP_CLAUSE__LOOPTEMP_);
817 gcc_assert (innerc);
818 n2 = OMP_CLAUSE_DECL (innerc);
821 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
823 t = fold_convert_loc (loc, long_integer_type_node, n1);
824 ws_args->quick_push (t);
826 t = fold_convert_loc (loc, long_integer_type_node, n2);
827 ws_args->quick_push (t);
829 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
830 ws_args->quick_push (t);
832 if (fd.chunk_size)
834 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
835 ws_args->quick_push (t);
838 return ws_args;
840 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
842 /* Number of sections is equal to the number of edges from the
843 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
844 the exit of the sections region. */
845 basic_block bb = single_succ (gimple_bb (ws_stmt));
846 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
847 vec_alloc (ws_args, 1);
848 ws_args->quick_push (t);
849 return ws_args;
852 gcc_unreachable ();
856 /* Discover whether REGION is a combined parallel+workshare region. */
858 static void
859 determine_parallel_type (struct omp_region *region)
861 basic_block par_entry_bb, par_exit_bb;
862 basic_block ws_entry_bb, ws_exit_bb;
864 if (region == NULL || region->inner == NULL
865 || region->exit == NULL || region->inner->exit == NULL
866 || region->inner->cont == NULL)
867 return;
869 /* We only support parallel+for and parallel+sections. */
870 if (region->type != GIMPLE_OMP_PARALLEL
871 || (region->inner->type != GIMPLE_OMP_FOR
872 && region->inner->type != GIMPLE_OMP_SECTIONS))
873 return;
875 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
876 WS_EXIT_BB -> PAR_EXIT_BB. */
877 par_entry_bb = region->entry;
878 par_exit_bb = region->exit;
879 ws_entry_bb = region->inner->entry;
880 ws_exit_bb = region->inner->exit;
882 if (single_succ (par_entry_bb) == ws_entry_bb
883 && single_succ (ws_exit_bb) == par_exit_bb
884 && workshare_safe_to_combine_p (ws_entry_bb)
885 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
886 || (last_and_only_stmt (ws_entry_bb)
887 && last_and_only_stmt (par_exit_bb))))
889 gimple par_stmt = last_stmt (par_entry_bb);
890 gimple ws_stmt = last_stmt (ws_entry_bb);
892 if (region->inner->type == GIMPLE_OMP_FOR)
894 /* If this is a combined parallel loop, we need to determine
895 whether or not to use the combined library calls. There
896 are two cases where we do not apply the transformation:
897 static loops and any kind of ordered loop. In the first
898 case, we already open code the loop so there is no need
899 to do anything else. In the latter case, the combined
900 parallel loop call would still need extra synchronization
901 to implement ordered semantics, so there would not be any
902 gain in using the combined call. */
903 tree clauses = gimple_omp_for_clauses (ws_stmt);
904 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
905 if (c == NULL
906 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
907 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
909 region->is_combined_parallel = false;
910 region->inner->is_combined_parallel = false;
911 return;
915 region->is_combined_parallel = true;
916 region->inner->is_combined_parallel = true;
917 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
922 /* Return true if EXPR is variable sized. */
924 static inline bool
925 is_variable_sized (const_tree expr)
927 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
930 /* Return true if DECL is a reference type. */
932 static inline bool
933 is_reference (tree decl)
935 return lang_hooks.decls.omp_privatize_by_reference (decl);
938 /* Return the type of a decl. If the decl is reference type,
939 return its base type. */
940 static inline tree
941 get_base_type (tree decl)
943 tree type = TREE_TYPE (decl);
944 if (is_reference (decl))
945 type = TREE_TYPE (type);
946 return type;
949 /* Lookup variables. The "maybe" form
950 allows for the variable form to not have been entered, otherwise we
951 assert that the variable must have been entered. */
953 static inline tree
954 lookup_decl (tree var, omp_context *ctx)
956 tree *n = ctx->cb.decl_map->get (var);
957 return *n;
960 static inline tree
961 maybe_lookup_decl (const_tree var, omp_context *ctx)
963 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
964 return n ? *n : NULL_TREE;
967 static inline tree
968 lookup_field (tree var, omp_context *ctx)
970 splay_tree_node n;
971 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
972 return (tree) n->value;
975 static inline tree
976 lookup_sfield (tree var, omp_context *ctx)
978 splay_tree_node n;
979 n = splay_tree_lookup (ctx->sfield_map
980 ? ctx->sfield_map : ctx->field_map,
981 (splay_tree_key) var);
982 return (tree) n->value;
985 static inline tree
986 maybe_lookup_field (tree var, omp_context *ctx)
988 splay_tree_node n;
989 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
990 return n ? (tree) n->value : NULL_TREE;
993 static inline tree
994 lookup_oacc_reduction (const char *id, omp_context *ctx)
996 splay_tree_node n;
997 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
998 return (tree) n->value;
1001 static inline tree
1002 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
1004 splay_tree_node n = NULL;
1005 if (ctx->reduction_map)
1006 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
1007 return n ? (tree) n->value : NULL_TREE;
1010 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1011 the parallel context if DECL is to be shared. */
1013 static bool
1014 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1016 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1017 return true;
1019 /* We can only use copy-in/copy-out semantics for shared variables
1020 when we know the value is not accessible from an outer scope. */
1021 if (shared_ctx)
1023 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1025 /* ??? Trivially accessible from anywhere. But why would we even
1026 be passing an address in this case? Should we simply assert
1027 this to be false, or should we have a cleanup pass that removes
1028 these from the list of mappings? */
1029 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1030 return true;
1032 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1033 without analyzing the expression whether or not its location
1034 is accessible to anyone else. In the case of nested parallel
1035 regions it certainly may be. */
1036 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1037 return true;
1039 /* Do not use copy-in/copy-out for variables that have their
1040 address taken. */
1041 if (TREE_ADDRESSABLE (decl))
1042 return true;
1044 /* lower_send_shared_vars only uses copy-in, but not copy-out
1045 for these. */
1046 if (TREE_READONLY (decl)
1047 || ((TREE_CODE (decl) == RESULT_DECL
1048 || TREE_CODE (decl) == PARM_DECL)
1049 && DECL_BY_REFERENCE (decl)))
1050 return false;
1052 /* Disallow copy-in/out in nested parallel if
1053 decl is shared in outer parallel, otherwise
1054 each thread could store the shared variable
1055 in its own copy-in location, making the
1056 variable no longer really shared. */
1057 if (shared_ctx->is_nested)
1059 omp_context *up;
1061 for (up = shared_ctx->outer; up; up = up->outer)
1062 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1063 break;
1065 if (up)
1067 tree c;
1069 for (c = gimple_omp_taskreg_clauses (up->stmt);
1070 c; c = OMP_CLAUSE_CHAIN (c))
1071 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1072 && OMP_CLAUSE_DECL (c) == decl)
1073 break;
1075 if (c)
1076 goto maybe_mark_addressable_and_ret;
1080 /* For tasks avoid using copy-in/out. As tasks can be
1081 deferred or executed in different thread, when GOMP_task
1082 returns, the task hasn't necessarily terminated. */
1083 if (is_task_ctx (shared_ctx))
1085 tree outer;
1086 maybe_mark_addressable_and_ret:
1087 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1088 if (is_gimple_reg (outer))
1090 /* Taking address of OUTER in lower_send_shared_vars
1091 might need regimplification of everything that uses the
1092 variable. */
1093 if (!task_shared_vars)
1094 task_shared_vars = BITMAP_ALLOC (NULL);
1095 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1096 TREE_ADDRESSABLE (outer) = 1;
1098 return true;
1102 return false;
1105 /* Construct a new automatic decl similar to VAR. */
1107 static tree
1108 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1110 tree copy = copy_var_decl (var, name, type);
1112 DECL_CONTEXT (copy) = current_function_decl;
1113 DECL_CHAIN (copy) = ctx->block_vars;
1114 ctx->block_vars = copy;
1116 return copy;
1119 static tree
1120 omp_copy_decl_1 (tree var, omp_context *ctx)
1122 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1125 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1126 as appropriate. */
1127 static tree
1128 omp_build_component_ref (tree obj, tree field)
1130 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1131 if (TREE_THIS_VOLATILE (field))
1132 TREE_THIS_VOLATILE (ret) |= 1;
1133 if (TREE_READONLY (field))
1134 TREE_READONLY (ret) |= 1;
1135 return ret;
1138 /* Build tree nodes to access the field for VAR on the receiver side. */
1140 static tree
1141 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1143 tree x, field = lookup_field (var, ctx);
1145 /* If the receiver record type was remapped in the child function,
1146 remap the field into the new record type. */
1147 x = maybe_lookup_field (field, ctx);
1148 if (x != NULL)
1149 field = x;
1151 x = build_simple_mem_ref (ctx->receiver_decl);
1152 TREE_THIS_NOTRAP (x) = 1;
1153 x = omp_build_component_ref (x, field);
1154 if (by_ref)
1155 x = build_simple_mem_ref (x);
1157 return x;
1160 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1161 of a parallel, this is a component reference; for workshare constructs
1162 this is some variable. */
1164 static tree
1165 build_outer_var_ref (tree var, omp_context *ctx)
1167 tree x;
1169 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1170 x = var;
1171 else if (is_variable_sized (var))
1173 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1174 x = build_outer_var_ref (x, ctx);
1175 x = build_simple_mem_ref (x);
1177 else if (is_taskreg_ctx (ctx))
1179 bool by_ref = use_pointer_for_field (var, NULL);
1180 x = build_receiver_ref (var, by_ref, ctx);
1182 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1183 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1185 /* #pragma omp simd isn't a worksharing construct, and can reference even
1186 private vars in its linear etc. clauses. */
1187 x = NULL_TREE;
1188 if (ctx->outer && is_taskreg_ctx (ctx))
1189 x = lookup_decl (var, ctx->outer);
1190 else if (ctx->outer)
1191 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1192 if (x == NULL_TREE)
1193 x = var;
1195 else if (ctx->outer)
1196 x = lookup_decl (var, ctx->outer);
1197 else if (is_reference (var))
1198 /* This can happen with orphaned constructs. If var is reference, it is
1199 possible it is shared and as such valid. */
1200 x = var;
1201 else
1202 gcc_unreachable ();
1204 if (is_reference (var))
1205 x = build_simple_mem_ref (x);
1207 return x;
1210 /* Build tree nodes to access the field for VAR on the sender side. */
1212 static tree
1213 build_sender_ref (tree var, omp_context *ctx)
1215 tree field = lookup_sfield (var, ctx);
1216 return omp_build_component_ref (ctx->sender_decl, field);
1219 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1221 static void
1222 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1224 tree field, type, sfield = NULL_TREE;
1226 gcc_assert ((mask & 1) == 0
1227 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1228 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1229 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1230 gcc_assert ((mask & 3) == 3
1231 || !is_gimple_omp_oacc (ctx->stmt));
1233 type = TREE_TYPE (var);
1234 if (mask & 4)
1236 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1237 type = build_pointer_type (build_pointer_type (type));
1239 else if (by_ref)
1240 type = build_pointer_type (type);
1241 else if ((mask & 3) == 1 && is_reference (var))
1242 type = TREE_TYPE (type);
1244 field = build_decl (DECL_SOURCE_LOCATION (var),
1245 FIELD_DECL, DECL_NAME (var), type);
1247 /* Remember what variable this field was created for. This does have a
1248 side effect of making dwarf2out ignore this member, so for helpful
1249 debugging we clear it later in delete_omp_context. */
1250 DECL_ABSTRACT_ORIGIN (field) = var;
1251 if (type == TREE_TYPE (var))
1253 DECL_ALIGN (field) = DECL_ALIGN (var);
1254 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1255 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1257 else
1258 DECL_ALIGN (field) = TYPE_ALIGN (type);
1260 if ((mask & 3) == 3)
1262 insert_field_into_struct (ctx->record_type, field);
1263 if (ctx->srecord_type)
1265 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1266 FIELD_DECL, DECL_NAME (var), type);
1267 DECL_ABSTRACT_ORIGIN (sfield) = var;
1268 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1269 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1270 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1271 insert_field_into_struct (ctx->srecord_type, sfield);
1274 else
1276 if (ctx->srecord_type == NULL_TREE)
1278 tree t;
1280 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1281 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1282 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1284 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1285 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1286 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1287 insert_field_into_struct (ctx->srecord_type, sfield);
1288 splay_tree_insert (ctx->sfield_map,
1289 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1290 (splay_tree_value) sfield);
1293 sfield = field;
1294 insert_field_into_struct ((mask & 1) ? ctx->record_type
1295 : ctx->srecord_type, field);
1298 if (mask & 1)
1299 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1300 (splay_tree_value) field);
1301 if ((mask & 2) && ctx->sfield_map)
1302 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1303 (splay_tree_value) sfield);
1306 static tree
1307 install_var_local (tree var, omp_context *ctx)
1309 tree new_var = omp_copy_decl_1 (var, ctx);
1310 insert_decl_map (&ctx->cb, var, new_var);
1311 return new_var;
1314 /* Adjust the replacement for DECL in CTX for the new context. This means
1315 copying the DECL_VALUE_EXPR, and fixing up the type. */
1317 static void
1318 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1320 tree new_decl, size;
1322 new_decl = lookup_decl (decl, ctx);
1324 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1326 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1327 && DECL_HAS_VALUE_EXPR_P (decl))
1329 tree ve = DECL_VALUE_EXPR (decl);
1330 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1331 SET_DECL_VALUE_EXPR (new_decl, ve);
1332 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1335 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1337 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1338 if (size == error_mark_node)
1339 size = TYPE_SIZE (TREE_TYPE (new_decl));
1340 DECL_SIZE (new_decl) = size;
1342 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1343 if (size == error_mark_node)
1344 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1345 DECL_SIZE_UNIT (new_decl) = size;
1349 /* The callback for remap_decl. Search all containing contexts for a
1350 mapping of the variable; this avoids having to duplicate the splay
1351 tree ahead of time. We know a mapping doesn't already exist in the
1352 given context. Create new mappings to implement default semantics. */
1354 static tree
1355 omp_copy_decl (tree var, copy_body_data *cb)
1357 omp_context *ctx = (omp_context *) cb;
1358 tree new_var;
1360 if (TREE_CODE (var) == LABEL_DECL)
1362 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1363 DECL_CONTEXT (new_var) = current_function_decl;
1364 insert_decl_map (&ctx->cb, var, new_var);
1365 return new_var;
1368 while (!is_taskreg_ctx (ctx))
1370 ctx = ctx->outer;
1371 if (ctx == NULL)
1372 return var;
1373 new_var = maybe_lookup_decl (var, ctx);
1374 if (new_var)
1375 return new_var;
1378 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1379 return var;
1381 return error_mark_node;
1385 /* Debugging dumps for parallel regions. */
1386 void dump_omp_region (FILE *, struct omp_region *, int);
1387 void debug_omp_region (struct omp_region *);
1388 void debug_all_omp_regions (void);
1390 /* Dump the parallel region tree rooted at REGION. */
1392 void
1393 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1395 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1396 gimple_code_name[region->type]);
1398 if (region->inner)
1399 dump_omp_region (file, region->inner, indent + 4);
1401 if (region->cont)
1403 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1404 region->cont->index);
1407 if (region->exit)
1408 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1409 region->exit->index);
1410 else
1411 fprintf (file, "%*s[no exit marker]\n", indent, "");
1413 if (region->next)
1414 dump_omp_region (file, region->next, indent);
1417 DEBUG_FUNCTION void
1418 debug_omp_region (struct omp_region *region)
1420 dump_omp_region (stderr, region, 0);
1423 DEBUG_FUNCTION void
1424 debug_all_omp_regions (void)
1426 dump_omp_region (stderr, root_omp_region, 0);
1430 /* Create a new parallel region starting at STMT inside region PARENT. */
1432 static struct omp_region *
1433 new_omp_region (basic_block bb, enum gimple_code type,
1434 struct omp_region *parent)
1436 struct omp_region *region = XCNEW (struct omp_region);
1438 region->outer = parent;
1439 region->entry = bb;
1440 region->type = type;
1442 if (parent)
1444 /* This is a nested region. Add it to the list of inner
1445 regions in PARENT. */
1446 region->next = parent->inner;
1447 parent->inner = region;
1449 else
1451 /* This is a toplevel region. Add it to the list of toplevel
1452 regions in ROOT_OMP_REGION. */
1453 region->next = root_omp_region;
1454 root_omp_region = region;
1457 return region;
1460 /* Release the memory associated with the region tree rooted at REGION. */
1462 static void
1463 free_omp_region_1 (struct omp_region *region)
1465 struct omp_region *i, *n;
1467 for (i = region->inner; i ; i = n)
1469 n = i->next;
1470 free_omp_region_1 (i);
1473 free (region);
1476 /* Release the memory for the entire omp region tree. */
1478 void
1479 free_omp_regions (void)
1481 struct omp_region *r, *n;
1482 for (r = root_omp_region; r ; r = n)
1484 n = r->next;
1485 free_omp_region_1 (r);
1487 root_omp_region = NULL;
1491 /* Create a new context, with OUTER_CTX being the surrounding context. */
1493 static omp_context *
1494 new_omp_context (gimple stmt, omp_context *outer_ctx)
1496 omp_context *ctx = XCNEW (omp_context);
1498 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1499 (splay_tree_value) ctx);
1500 ctx->stmt = stmt;
1502 if (outer_ctx)
1504 ctx->outer = outer_ctx;
1505 ctx->cb = outer_ctx->cb;
1506 ctx->cb.block = NULL;
1507 ctx->depth = outer_ctx->depth + 1;
1508 ctx->reduction_map = outer_ctx->reduction_map;
1510 else
1512 ctx->cb.src_fn = current_function_decl;
1513 ctx->cb.dst_fn = current_function_decl;
1514 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1515 gcc_checking_assert (ctx->cb.src_node);
1516 ctx->cb.dst_node = ctx->cb.src_node;
1517 ctx->cb.src_cfun = cfun;
1518 ctx->cb.copy_decl = omp_copy_decl;
1519 ctx->cb.eh_lp_nr = 0;
1520 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1521 ctx->depth = 1;
1524 ctx->cb.decl_map = new hash_map<tree, tree>;
1526 return ctx;
1529 static gimple_seq maybe_catch_exception (gimple_seq);
1531 /* Finalize task copyfn. */
1533 static void
1534 finalize_task_copyfn (gomp_task *task_stmt)
1536 struct function *child_cfun;
1537 tree child_fn;
1538 gimple_seq seq = NULL, new_seq;
1539 gbind *bind;
1541 child_fn = gimple_omp_task_copy_fn (task_stmt);
1542 if (child_fn == NULL_TREE)
1543 return;
1545 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1546 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1548 push_cfun (child_cfun);
1549 bind = gimplify_body (child_fn, false);
1550 gimple_seq_add_stmt (&seq, bind);
1551 new_seq = maybe_catch_exception (seq);
1552 if (new_seq != seq)
1554 bind = gimple_build_bind (NULL, new_seq, NULL);
1555 seq = NULL;
1556 gimple_seq_add_stmt (&seq, bind);
1558 gimple_set_body (child_fn, seq);
1559 pop_cfun ();
1561 /* Inform the callgraph about the new function. */
1562 cgraph_node *node = cgraph_node::get_create (child_fn);
1563 node->parallelized_function = 1;
1564 cgraph_node::add_new_function (child_fn, false);
1567 /* Destroy a omp_context data structures. Called through the splay tree
1568 value delete callback. */
1570 static void
1571 delete_omp_context (splay_tree_value value)
1573 omp_context *ctx = (omp_context *) value;
1575 delete ctx->cb.decl_map;
1577 if (ctx->field_map)
1578 splay_tree_delete (ctx->field_map);
1579 if (ctx->sfield_map)
1580 splay_tree_delete (ctx->sfield_map);
1581 /* Reduction map is copied to nested contexts, so only delete it in the
1582 owner. */
1583 if (ctx->reduction_map
1584 && gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
1585 && is_gimple_omp_offloaded (ctx->stmt)
1586 && is_gimple_omp_oacc (ctx->stmt))
1587 splay_tree_delete (ctx->reduction_map);
1589 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1590 it produces corrupt debug information. */
1591 if (ctx->record_type)
1593 tree t;
1594 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1595 DECL_ABSTRACT_ORIGIN (t) = NULL;
1597 if (ctx->srecord_type)
1599 tree t;
1600 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1601 DECL_ABSTRACT_ORIGIN (t) = NULL;
1604 if (is_task_ctx (ctx))
1605 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1607 XDELETE (ctx);
1610 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1611 context. */
1613 static void
1614 fixup_child_record_type (omp_context *ctx)
1616 tree f, type = ctx->record_type;
1618 /* ??? It isn't sufficient to just call remap_type here, because
1619 variably_modified_type_p doesn't work the way we expect for
1620 record types. Testing each field for whether it needs remapping
1621 and creating a new record by hand works, however. */
1622 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1623 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1624 break;
1625 if (f)
1627 tree name, new_fields = NULL;
1629 type = lang_hooks.types.make_type (RECORD_TYPE);
1630 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1631 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1632 TYPE_DECL, name, type);
1633 TYPE_NAME (type) = name;
1635 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1637 tree new_f = copy_node (f);
1638 DECL_CONTEXT (new_f) = type;
1639 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1640 DECL_CHAIN (new_f) = new_fields;
1641 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1642 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1643 &ctx->cb, NULL);
1644 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1645 &ctx->cb, NULL);
1646 new_fields = new_f;
1648 /* Arrange to be able to look up the receiver field
1649 given the sender field. */
1650 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1651 (splay_tree_value) new_f);
1653 TYPE_FIELDS (type) = nreverse (new_fields);
1654 layout_type (type);
1657 TREE_TYPE (ctx->receiver_decl)
1658 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1661 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1662 specified by CLAUSES. */
1664 static void
1665 scan_sharing_clauses (tree clauses, omp_context *ctx)
1667 tree c, decl;
1668 bool scan_array_reductions = false;
1670 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1672 bool by_ref;
1674 switch (OMP_CLAUSE_CODE (c))
1676 case OMP_CLAUSE_PRIVATE:
1677 decl = OMP_CLAUSE_DECL (c);
1678 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1679 goto do_private;
1680 else if (!is_variable_sized (decl))
1681 install_var_local (decl, ctx);
1682 break;
1684 case OMP_CLAUSE_SHARED:
1685 decl = OMP_CLAUSE_DECL (c);
1686 /* Ignore shared directives in teams construct. */
1687 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1689 /* Global variables don't need to be copied,
1690 the receiver side will use them directly. */
1691 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1692 if (is_global_var (odecl))
1693 break;
1694 insert_decl_map (&ctx->cb, decl, odecl);
1695 break;
1697 gcc_assert (is_taskreg_ctx (ctx));
1698 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1699 || !is_variable_sized (decl));
1700 /* Global variables don't need to be copied,
1701 the receiver side will use them directly. */
1702 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1703 break;
1704 by_ref = use_pointer_for_field (decl, ctx);
1705 if (! TREE_READONLY (decl)
1706 || TREE_ADDRESSABLE (decl)
1707 || by_ref
1708 || is_reference (decl))
1710 install_var_field (decl, by_ref, 3, ctx);
1711 install_var_local (decl, ctx);
1712 break;
1714 /* We don't need to copy const scalar vars back. */
1715 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1716 goto do_private;
1718 case OMP_CLAUSE_LASTPRIVATE:
1719 /* Let the corresponding firstprivate clause create
1720 the variable. */
1721 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1722 break;
1723 /* FALLTHRU */
1725 case OMP_CLAUSE_FIRSTPRIVATE:
1726 if (is_gimple_omp_oacc (ctx->stmt))
1728 sorry ("clause not supported yet");
1729 break;
1731 /* FALLTHRU */
1732 case OMP_CLAUSE_REDUCTION:
1733 case OMP_CLAUSE_LINEAR:
1734 decl = OMP_CLAUSE_DECL (c);
1735 do_private:
1736 if (is_variable_sized (decl))
1738 if (is_task_ctx (ctx))
1739 install_var_field (decl, false, 1, ctx);
1740 break;
1742 else if (is_taskreg_ctx (ctx))
1744 bool global
1745 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1746 by_ref = use_pointer_for_field (decl, NULL);
1748 if (is_task_ctx (ctx)
1749 && (global || by_ref || is_reference (decl)))
1751 install_var_field (decl, false, 1, ctx);
1752 if (!global)
1753 install_var_field (decl, by_ref, 2, ctx);
1755 else if (!global)
1756 install_var_field (decl, by_ref, 3, ctx);
1758 install_var_local (decl, ctx);
1759 if (is_gimple_omp_oacc (ctx->stmt)
1760 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1762 /* Create a decl for the reduction array. */
1763 tree var = OMP_CLAUSE_DECL (c);
1764 tree type = get_base_type (var);
1765 tree ptype = build_pointer_type (type);
1766 tree array = create_tmp_var (ptype,
1767 oacc_get_reduction_array_id (var));
1768 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1769 install_var_field (array, true, 3, c);
1770 install_var_local (array, c);
1772 /* Insert it into the current context. */
1773 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1774 oacc_get_reduction_array_id (var),
1775 (splay_tree_value) array);
1776 splay_tree_insert (ctx->reduction_map,
1777 (splay_tree_key) array,
1778 (splay_tree_value) array);
1780 break;
1782 case OMP_CLAUSE__LOOPTEMP_:
1783 gcc_assert (is_parallel_ctx (ctx));
1784 decl = OMP_CLAUSE_DECL (c);
1785 install_var_field (decl, false, 3, ctx);
1786 install_var_local (decl, ctx);
1787 break;
1789 case OMP_CLAUSE_COPYPRIVATE:
1790 case OMP_CLAUSE_COPYIN:
1791 decl = OMP_CLAUSE_DECL (c);
1792 by_ref = use_pointer_for_field (decl, NULL);
1793 install_var_field (decl, by_ref, 3, ctx);
1794 break;
1796 case OMP_CLAUSE_DEFAULT:
1797 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1798 break;
1800 case OMP_CLAUSE_FINAL:
1801 case OMP_CLAUSE_IF:
1802 case OMP_CLAUSE_NUM_THREADS:
1803 case OMP_CLAUSE_NUM_TEAMS:
1804 case OMP_CLAUSE_THREAD_LIMIT:
1805 case OMP_CLAUSE_DEVICE:
1806 case OMP_CLAUSE_SCHEDULE:
1807 case OMP_CLAUSE_DIST_SCHEDULE:
1808 case OMP_CLAUSE_DEPEND:
1809 case OMP_CLAUSE__CILK_FOR_COUNT_:
1810 case OMP_CLAUSE_NUM_GANGS:
1811 case OMP_CLAUSE_NUM_WORKERS:
1812 case OMP_CLAUSE_VECTOR_LENGTH:
1813 if (ctx->outer)
1814 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1815 break;
1817 case OMP_CLAUSE_TO:
1818 case OMP_CLAUSE_FROM:
1819 case OMP_CLAUSE_MAP:
1820 if (ctx->outer)
1821 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1822 decl = OMP_CLAUSE_DECL (c);
1823 /* Global variables with "omp declare target" attribute
1824 don't need to be copied, the receiver side will use them
1825 directly. */
1826 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1827 && DECL_P (decl)
1828 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1829 && varpool_node::get_create (decl)->offloadable)
1830 break;
1831 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1832 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
1834 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1835 not offloaded; there is nothing to map for those. */
1836 if (!is_gimple_omp_offloaded (ctx->stmt)
1837 && !POINTER_TYPE_P (TREE_TYPE (decl))
1838 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
1839 break;
1841 if (DECL_P (decl))
1843 if (DECL_SIZE (decl)
1844 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1846 tree decl2 = DECL_VALUE_EXPR (decl);
1847 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1848 decl2 = TREE_OPERAND (decl2, 0);
1849 gcc_assert (DECL_P (decl2));
1850 install_var_field (decl2, true, 3, ctx);
1851 install_var_local (decl2, ctx);
1852 install_var_local (decl, ctx);
1854 else
1856 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1857 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1858 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1859 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1860 install_var_field (decl, true, 7, ctx);
1861 else
1862 install_var_field (decl, true, 3, ctx);
1863 if (is_gimple_omp_offloaded (ctx->stmt))
1864 install_var_local (decl, ctx);
1867 else
1869 tree base = get_base_address (decl);
1870 tree nc = OMP_CLAUSE_CHAIN (c);
1871 if (DECL_P (base)
1872 && nc != NULL_TREE
1873 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1874 && OMP_CLAUSE_DECL (nc) == base
1875 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1876 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1878 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1879 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1881 else
1883 if (ctx->outer)
1885 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1886 decl = OMP_CLAUSE_DECL (c);
1888 gcc_assert (!splay_tree_lookup (ctx->field_map,
1889 (splay_tree_key) decl));
1890 tree field
1891 = build_decl (OMP_CLAUSE_LOCATION (c),
1892 FIELD_DECL, NULL_TREE, ptr_type_node);
1893 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1894 insert_field_into_struct (ctx->record_type, field);
1895 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1896 (splay_tree_value) field);
1899 break;
1901 case OMP_CLAUSE_NOWAIT:
1902 case OMP_CLAUSE_ORDERED:
1903 case OMP_CLAUSE_COLLAPSE:
1904 case OMP_CLAUSE_UNTIED:
1905 case OMP_CLAUSE_MERGEABLE:
1906 case OMP_CLAUSE_PROC_BIND:
1907 case OMP_CLAUSE_SAFELEN:
1908 case OMP_CLAUSE_ASYNC:
1909 case OMP_CLAUSE_WAIT:
1910 case OMP_CLAUSE_GANG:
1911 case OMP_CLAUSE_WORKER:
1912 case OMP_CLAUSE_VECTOR:
1913 break;
1915 case OMP_CLAUSE_ALIGNED:
1916 decl = OMP_CLAUSE_DECL (c);
1917 if (is_global_var (decl)
1918 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1919 install_var_local (decl, ctx);
1920 break;
1922 case OMP_CLAUSE_DEVICE_RESIDENT:
1923 case OMP_CLAUSE_USE_DEVICE:
1924 case OMP_CLAUSE__CACHE_:
1925 case OMP_CLAUSE_INDEPENDENT:
1926 case OMP_CLAUSE_AUTO:
1927 case OMP_CLAUSE_SEQ:
1928 sorry ("Clause not supported yet");
1929 break;
1931 default:
1932 gcc_unreachable ();
1936 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1938 switch (OMP_CLAUSE_CODE (c))
1940 case OMP_CLAUSE_LASTPRIVATE:
1941 /* Let the corresponding firstprivate clause create
1942 the variable. */
1943 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1944 scan_array_reductions = true;
1945 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1946 break;
1947 /* FALLTHRU */
1949 case OMP_CLAUSE_FIRSTPRIVATE:
1950 if (is_gimple_omp_oacc (ctx->stmt))
1952 sorry ("clause not supported yet");
1953 break;
1955 /* FALLTHRU */
1956 case OMP_CLAUSE_PRIVATE:
1957 case OMP_CLAUSE_REDUCTION:
1958 case OMP_CLAUSE_LINEAR:
1959 decl = OMP_CLAUSE_DECL (c);
1960 if (is_variable_sized (decl))
1961 install_var_local (decl, ctx);
1962 fixup_remapped_decl (decl, ctx,
1963 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1964 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1965 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1966 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1967 scan_array_reductions = true;
1968 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1969 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1970 scan_array_reductions = true;
1971 break;
1973 case OMP_CLAUSE_SHARED:
1974 /* Ignore shared directives in teams construct. */
1975 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1976 break;
1977 decl = OMP_CLAUSE_DECL (c);
1978 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1979 fixup_remapped_decl (decl, ctx, false);
1980 break;
1982 case OMP_CLAUSE_MAP:
1983 if (!is_gimple_omp_offloaded (ctx->stmt))
1984 break;
1985 decl = OMP_CLAUSE_DECL (c);
1986 if (DECL_P (decl)
1987 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1988 && varpool_node::get_create (decl)->offloadable)
1989 break;
1990 if (DECL_P (decl))
1992 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1993 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
1994 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
1996 tree new_decl = lookup_decl (decl, ctx);
1997 TREE_TYPE (new_decl)
1998 = remap_type (TREE_TYPE (decl), &ctx->cb);
2000 else if (DECL_SIZE (decl)
2001 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2003 tree decl2 = DECL_VALUE_EXPR (decl);
2004 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2005 decl2 = TREE_OPERAND (decl2, 0);
2006 gcc_assert (DECL_P (decl2));
2007 fixup_remapped_decl (decl2, ctx, false);
2008 fixup_remapped_decl (decl, ctx, true);
2010 else
2011 fixup_remapped_decl (decl, ctx, false);
2013 break;
2015 case OMP_CLAUSE_COPYPRIVATE:
2016 case OMP_CLAUSE_COPYIN:
2017 case OMP_CLAUSE_DEFAULT:
2018 case OMP_CLAUSE_IF:
2019 case OMP_CLAUSE_NUM_THREADS:
2020 case OMP_CLAUSE_NUM_TEAMS:
2021 case OMP_CLAUSE_THREAD_LIMIT:
2022 case OMP_CLAUSE_DEVICE:
2023 case OMP_CLAUSE_SCHEDULE:
2024 case OMP_CLAUSE_DIST_SCHEDULE:
2025 case OMP_CLAUSE_NOWAIT:
2026 case OMP_CLAUSE_ORDERED:
2027 case OMP_CLAUSE_COLLAPSE:
2028 case OMP_CLAUSE_UNTIED:
2029 case OMP_CLAUSE_FINAL:
2030 case OMP_CLAUSE_MERGEABLE:
2031 case OMP_CLAUSE_PROC_BIND:
2032 case OMP_CLAUSE_SAFELEN:
2033 case OMP_CLAUSE_ALIGNED:
2034 case OMP_CLAUSE_DEPEND:
2035 case OMP_CLAUSE__LOOPTEMP_:
2036 case OMP_CLAUSE_TO:
2037 case OMP_CLAUSE_FROM:
2038 case OMP_CLAUSE__CILK_FOR_COUNT_:
2039 case OMP_CLAUSE_ASYNC:
2040 case OMP_CLAUSE_WAIT:
2041 case OMP_CLAUSE_NUM_GANGS:
2042 case OMP_CLAUSE_NUM_WORKERS:
2043 case OMP_CLAUSE_VECTOR_LENGTH:
2044 case OMP_CLAUSE_GANG:
2045 case OMP_CLAUSE_WORKER:
2046 case OMP_CLAUSE_VECTOR:
2047 break;
2049 case OMP_CLAUSE_DEVICE_RESIDENT:
2050 case OMP_CLAUSE_USE_DEVICE:
2051 case OMP_CLAUSE__CACHE_:
2052 case OMP_CLAUSE_INDEPENDENT:
2053 case OMP_CLAUSE_AUTO:
2054 case OMP_CLAUSE_SEQ:
2055 sorry ("Clause not supported yet");
2056 break;
2058 default:
2059 gcc_unreachable ();
2063 gcc_checking_assert (!scan_array_reductions
2064 || !is_gimple_omp_oacc (ctx->stmt));
2065 if (scan_array_reductions)
2066 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2067 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2068 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2070 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2071 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2073 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2074 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2075 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2076 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2077 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2078 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2081 /* Create a new name for omp child function. Returns an identifier. If
2082 IS_CILK_FOR is true then the suffix for the child function is
2083 "_cilk_for_fn." */
2085 static tree
2086 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2088 if (is_cilk_for)
2089 return clone_function_name (current_function_decl, "_cilk_for_fn");
2090 return clone_function_name (current_function_decl,
2091 task_copy ? "_omp_cpyfn" : "_omp_fn");
2094 /* Returns the type of the induction variable for the child function for
2095 _Cilk_for and the types for _high and _low variables based on TYPE. */
2097 static tree
2098 cilk_for_check_loop_diff_type (tree type)
2100 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2102 if (TYPE_UNSIGNED (type))
2103 return uint32_type_node;
2104 else
2105 return integer_type_node;
2107 else
2109 if (TYPE_UNSIGNED (type))
2110 return uint64_type_node;
2111 else
2112 return long_long_integer_type_node;
2116 /* Build a decl for the omp child function. It'll not contain a body
2117 yet, just the bare decl. */
2119 static void
2120 create_omp_child_function (omp_context *ctx, bool task_copy)
2122 tree decl, type, name, t;
2124 tree cilk_for_count
2125 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2126 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2127 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2128 tree cilk_var_type = NULL_TREE;
2130 name = create_omp_child_function_name (task_copy,
2131 cilk_for_count != NULL_TREE);
2132 if (task_copy)
2133 type = build_function_type_list (void_type_node, ptr_type_node,
2134 ptr_type_node, NULL_TREE);
2135 else if (cilk_for_count)
2137 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2138 cilk_var_type = cilk_for_check_loop_diff_type (type);
2139 type = build_function_type_list (void_type_node, ptr_type_node,
2140 cilk_var_type, cilk_var_type, NULL_TREE);
2142 else
2143 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2145 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2147 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2148 || !task_copy);
2149 if (!task_copy)
2150 ctx->cb.dst_fn = decl;
2151 else
2152 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2154 TREE_STATIC (decl) = 1;
2155 TREE_USED (decl) = 1;
2156 DECL_ARTIFICIAL (decl) = 1;
2157 DECL_IGNORED_P (decl) = 0;
2158 TREE_PUBLIC (decl) = 0;
2159 DECL_UNINLINABLE (decl) = 1;
2160 DECL_EXTERNAL (decl) = 0;
2161 DECL_CONTEXT (decl) = NULL_TREE;
2162 DECL_INITIAL (decl) = make_node (BLOCK);
2163 if (cgraph_node::get (current_function_decl)->offloadable)
2164 cgraph_node::get_create (decl)->offloadable = 1;
2165 else
2167 omp_context *octx;
2168 for (octx = ctx; octx; octx = octx->outer)
2169 if (is_gimple_omp_offloaded (octx->stmt))
2171 cgraph_node::get_create (decl)->offloadable = 1;
2172 #ifdef ENABLE_OFFLOADING
2173 g->have_offload = true;
2174 #endif
2175 break;
2179 if (cgraph_node::get_create (decl)->offloadable
2180 && !lookup_attribute ("omp declare target",
2181 DECL_ATTRIBUTES (current_function_decl)))
2182 DECL_ATTRIBUTES (decl)
2183 = tree_cons (get_identifier ("omp target entrypoint"),
2184 NULL_TREE, DECL_ATTRIBUTES (decl));
2186 t = build_decl (DECL_SOURCE_LOCATION (decl),
2187 RESULT_DECL, NULL_TREE, void_type_node);
2188 DECL_ARTIFICIAL (t) = 1;
2189 DECL_IGNORED_P (t) = 1;
2190 DECL_CONTEXT (t) = decl;
2191 DECL_RESULT (decl) = t;
2193 /* _Cilk_for's child function requires two extra parameters called
2194 __low and __high that are set the by Cilk runtime when it calls this
2195 function. */
2196 if (cilk_for_count)
2198 t = build_decl (DECL_SOURCE_LOCATION (decl),
2199 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2200 DECL_ARTIFICIAL (t) = 1;
2201 DECL_NAMELESS (t) = 1;
2202 DECL_ARG_TYPE (t) = ptr_type_node;
2203 DECL_CONTEXT (t) = current_function_decl;
2204 TREE_USED (t) = 1;
2205 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2206 DECL_ARGUMENTS (decl) = t;
2208 t = build_decl (DECL_SOURCE_LOCATION (decl),
2209 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2210 DECL_ARTIFICIAL (t) = 1;
2211 DECL_NAMELESS (t) = 1;
2212 DECL_ARG_TYPE (t) = ptr_type_node;
2213 DECL_CONTEXT (t) = current_function_decl;
2214 TREE_USED (t) = 1;
2215 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2216 DECL_ARGUMENTS (decl) = t;
2219 tree data_name = get_identifier (".omp_data_i");
2220 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2221 ptr_type_node);
2222 DECL_ARTIFICIAL (t) = 1;
2223 DECL_NAMELESS (t) = 1;
2224 DECL_ARG_TYPE (t) = ptr_type_node;
2225 DECL_CONTEXT (t) = current_function_decl;
2226 TREE_USED (t) = 1;
2227 if (cilk_for_count)
2228 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2229 DECL_ARGUMENTS (decl) = t;
2230 if (!task_copy)
2231 ctx->receiver_decl = t;
2232 else
2234 t = build_decl (DECL_SOURCE_LOCATION (decl),
2235 PARM_DECL, get_identifier (".omp_data_o"),
2236 ptr_type_node);
2237 DECL_ARTIFICIAL (t) = 1;
2238 DECL_NAMELESS (t) = 1;
2239 DECL_ARG_TYPE (t) = ptr_type_node;
2240 DECL_CONTEXT (t) = current_function_decl;
2241 TREE_USED (t) = 1;
2242 TREE_ADDRESSABLE (t) = 1;
2243 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2244 DECL_ARGUMENTS (decl) = t;
2247 /* Allocate memory for the function structure. The call to
2248 allocate_struct_function clobbers CFUN, so we need to restore
2249 it afterward. */
2250 push_struct_function (decl);
2251 cfun->function_end_locus = gimple_location (ctx->stmt);
2252 pop_cfun ();
2255 /* Callback for walk_gimple_seq. Check if combined parallel
2256 contains gimple_omp_for_combined_into_p OMP_FOR. */
2258 static tree
2259 find_combined_for (gimple_stmt_iterator *gsi_p,
2260 bool *handled_ops_p,
2261 struct walk_stmt_info *wi)
2263 gimple stmt = gsi_stmt (*gsi_p);
2265 *handled_ops_p = true;
2266 switch (gimple_code (stmt))
2268 WALK_SUBSTMTS;
2270 case GIMPLE_OMP_FOR:
2271 if (gimple_omp_for_combined_into_p (stmt)
2272 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2274 wi->info = stmt;
2275 return integer_zero_node;
2277 break;
2278 default:
2279 break;
2281 return NULL;
2284 /* Scan an OpenMP parallel directive. */
2286 static void
2287 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2289 omp_context *ctx;
2290 tree name;
2291 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2293 /* Ignore parallel directives with empty bodies, unless there
2294 are copyin clauses. */
2295 if (optimize > 0
2296 && empty_body_p (gimple_omp_body (stmt))
2297 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2298 OMP_CLAUSE_COPYIN) == NULL)
2300 gsi_replace (gsi, gimple_build_nop (), false);
2301 return;
2304 if (gimple_omp_parallel_combined_p (stmt))
2306 struct walk_stmt_info wi;
2308 memset (&wi, 0, sizeof (wi));
2309 wi.val_only = true;
2310 walk_gimple_seq (gimple_omp_body (stmt),
2311 find_combined_for, NULL, &wi);
2312 if (wi.info)
2314 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2315 struct omp_for_data fd;
2316 extract_omp_for_data (for_stmt, &fd, NULL);
2317 /* We need two temporaries with fd.loop.v type (istart/iend)
2318 and then (fd.collapse - 1) temporaries with the same
2319 type for count2 ... countN-1 vars if not constant. */
2320 size_t count = 2, i;
2321 tree type = fd.iter_type;
2322 if (fd.collapse > 1
2323 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2324 count += fd.collapse - 1;
2325 for (i = 0; i < count; i++)
2327 tree temp = create_tmp_var (type);
2328 tree c = build_omp_clause (UNKNOWN_LOCATION,
2329 OMP_CLAUSE__LOOPTEMP_);
2330 insert_decl_map (&outer_ctx->cb, temp, temp);
2331 OMP_CLAUSE_DECL (c) = temp;
2332 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2333 gimple_omp_parallel_set_clauses (stmt, c);
2338 ctx = new_omp_context (stmt, outer_ctx);
2339 taskreg_contexts.safe_push (ctx);
2340 if (taskreg_nesting_level > 1)
2341 ctx->is_nested = true;
2342 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2343 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2344 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2345 name = create_tmp_var_name (".omp_data_s");
2346 name = build_decl (gimple_location (stmt),
2347 TYPE_DECL, name, ctx->record_type);
2348 DECL_ARTIFICIAL (name) = 1;
2349 DECL_NAMELESS (name) = 1;
2350 TYPE_NAME (ctx->record_type) = name;
2351 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2352 create_omp_child_function (ctx, false);
2353 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2355 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2356 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2358 if (TYPE_FIELDS (ctx->record_type) == NULL)
2359 ctx->record_type = ctx->receiver_decl = NULL;
2362 /* Scan an OpenMP task directive. */
2364 static void
2365 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2367 omp_context *ctx;
2368 tree name, t;
2369 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2371 /* Ignore task directives with empty bodies. */
2372 if (optimize > 0
2373 && empty_body_p (gimple_omp_body (stmt)))
2375 gsi_replace (gsi, gimple_build_nop (), false);
2376 return;
2379 ctx = new_omp_context (stmt, outer_ctx);
2380 taskreg_contexts.safe_push (ctx);
2381 if (taskreg_nesting_level > 1)
2382 ctx->is_nested = true;
2383 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2384 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2385 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2386 name = create_tmp_var_name (".omp_data_s");
2387 name = build_decl (gimple_location (stmt),
2388 TYPE_DECL, name, ctx->record_type);
2389 DECL_ARTIFICIAL (name) = 1;
2390 DECL_NAMELESS (name) = 1;
2391 TYPE_NAME (ctx->record_type) = name;
2392 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2393 create_omp_child_function (ctx, false);
2394 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2396 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2398 if (ctx->srecord_type)
2400 name = create_tmp_var_name (".omp_data_a");
2401 name = build_decl (gimple_location (stmt),
2402 TYPE_DECL, name, ctx->srecord_type);
2403 DECL_ARTIFICIAL (name) = 1;
2404 DECL_NAMELESS (name) = 1;
2405 TYPE_NAME (ctx->srecord_type) = name;
2406 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2407 create_omp_child_function (ctx, true);
2410 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2412 if (TYPE_FIELDS (ctx->record_type) == NULL)
2414 ctx->record_type = ctx->receiver_decl = NULL;
2415 t = build_int_cst (long_integer_type_node, 0);
2416 gimple_omp_task_set_arg_size (stmt, t);
2417 t = build_int_cst (long_integer_type_node, 1);
2418 gimple_omp_task_set_arg_align (stmt, t);
2423 /* If any decls have been made addressable during scan_omp,
2424 adjust their fields if needed, and layout record types
2425 of parallel/task constructs. */
2427 static void
2428 finish_taskreg_scan (omp_context *ctx)
2430 if (ctx->record_type == NULL_TREE)
2431 return;
2433 /* If any task_shared_vars were needed, verify all
2434 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2435 statements if use_pointer_for_field hasn't changed
2436 because of that. If it did, update field types now. */
2437 if (task_shared_vars)
2439 tree c;
2441 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2442 c; c = OMP_CLAUSE_CHAIN (c))
2443 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2445 tree decl = OMP_CLAUSE_DECL (c);
2447 /* Global variables don't need to be copied,
2448 the receiver side will use them directly. */
2449 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2450 continue;
2451 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2452 || !use_pointer_for_field (decl, ctx))
2453 continue;
2454 tree field = lookup_field (decl, ctx);
2455 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2456 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2457 continue;
2458 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2459 TREE_THIS_VOLATILE (field) = 0;
2460 DECL_USER_ALIGN (field) = 0;
2461 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2462 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2463 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2464 if (ctx->srecord_type)
2466 tree sfield = lookup_sfield (decl, ctx);
2467 TREE_TYPE (sfield) = TREE_TYPE (field);
2468 TREE_THIS_VOLATILE (sfield) = 0;
2469 DECL_USER_ALIGN (sfield) = 0;
2470 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2471 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2472 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2477 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2479 layout_type (ctx->record_type);
2480 fixup_child_record_type (ctx);
2482 else
2484 location_t loc = gimple_location (ctx->stmt);
2485 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2486 /* Move VLA fields to the end. */
2487 p = &TYPE_FIELDS (ctx->record_type);
2488 while (*p)
2489 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2490 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2492 *q = *p;
2493 *p = TREE_CHAIN (*p);
2494 TREE_CHAIN (*q) = NULL_TREE;
2495 q = &TREE_CHAIN (*q);
2497 else
2498 p = &DECL_CHAIN (*p);
2499 *p = vla_fields;
2500 layout_type (ctx->record_type);
2501 fixup_child_record_type (ctx);
2502 if (ctx->srecord_type)
2503 layout_type (ctx->srecord_type);
2504 tree t = fold_convert_loc (loc, long_integer_type_node,
2505 TYPE_SIZE_UNIT (ctx->record_type));
2506 gimple_omp_task_set_arg_size (ctx->stmt, t);
2507 t = build_int_cst (long_integer_type_node,
2508 TYPE_ALIGN_UNIT (ctx->record_type));
2509 gimple_omp_task_set_arg_align (ctx->stmt, t);
2514 static omp_context *
2515 enclosing_target_ctx (omp_context *ctx)
2517 while (ctx != NULL
2518 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2519 ctx = ctx->outer;
2520 gcc_assert (ctx != NULL);
2521 return ctx;
2524 static bool
2525 oacc_loop_or_target_p (gimple stmt)
2527 enum gimple_code outer_type = gimple_code (stmt);
2528 return ((outer_type == GIMPLE_OMP_TARGET
2529 && ((gimple_omp_target_kind (stmt)
2530 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2531 || (gimple_omp_target_kind (stmt)
2532 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2533 || (outer_type == GIMPLE_OMP_FOR
2534 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2537 /* Scan a GIMPLE_OMP_FOR. */
2539 static void
2540 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2542 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
2543 omp_context *ctx;
2544 size_t i;
2545 tree clauses = gimple_omp_for_clauses (stmt);
2547 if (outer_ctx)
2548 outer_type = gimple_code (outer_ctx->stmt);
2550 ctx = new_omp_context (stmt, outer_ctx);
2552 if (is_gimple_omp_oacc (stmt))
2554 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2555 ctx->gwv_this = outer_ctx->gwv_this;
2556 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2558 int val;
2559 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2560 val = MASK_GANG;
2561 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2562 val = MASK_WORKER;
2563 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2564 val = MASK_VECTOR;
2565 else
2566 continue;
2567 ctx->gwv_this |= val;
2568 if (!outer_ctx)
2570 /* Skip; not nested inside a region. */
2571 continue;
2573 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2575 /* Skip; not nested inside an OpenACC region. */
2576 continue;
2578 if (outer_type == GIMPLE_OMP_FOR)
2579 outer_ctx->gwv_below |= val;
2580 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2582 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2583 if (gimple_omp_target_kind (enclosing->stmt)
2584 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2585 error_at (gimple_location (stmt),
2586 "no arguments allowed to gang, worker and vector clauses inside parallel");
2591 scan_sharing_clauses (clauses, ctx);
2593 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2594 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2596 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2597 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2598 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2599 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2601 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2603 if (is_gimple_omp_oacc (stmt))
2605 if (ctx->gwv_this & ctx->gwv_below)
2606 error_at (gimple_location (stmt),
2607 "gang, worker and vector may occur only once in a loop nest");
2608 else if (ctx->gwv_below != 0
2609 && ctx->gwv_this > ctx->gwv_below)
2610 error_at (gimple_location (stmt),
2611 "gang, worker and vector must occur in this order in a loop nest");
2612 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2613 outer_ctx->gwv_below |= ctx->gwv_below;
2617 /* Scan an OpenMP sections directive. */
2619 static void
2620 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2622 omp_context *ctx;
2624 ctx = new_omp_context (stmt, outer_ctx);
2625 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2626 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2629 /* Scan an OpenMP single directive. */
2631 static void
2632 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2634 omp_context *ctx;
2635 tree name;
2637 ctx = new_omp_context (stmt, outer_ctx);
2638 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2639 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2640 name = create_tmp_var_name (".omp_copy_s");
2641 name = build_decl (gimple_location (stmt),
2642 TYPE_DECL, name, ctx->record_type);
2643 TYPE_NAME (ctx->record_type) = name;
2645 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2646 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2648 if (TYPE_FIELDS (ctx->record_type) == NULL)
2649 ctx->record_type = NULL;
2650 else
2651 layout_type (ctx->record_type);
2654 /* Scan a GIMPLE_OMP_TARGET. */
2656 static void
2657 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2659 omp_context *ctx;
2660 tree name;
2661 bool offloaded = is_gimple_omp_offloaded (stmt);
2662 tree clauses = gimple_omp_target_clauses (stmt);
2664 ctx = new_omp_context (stmt, outer_ctx);
2665 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2666 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2667 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2668 name = create_tmp_var_name (".omp_data_t");
2669 name = build_decl (gimple_location (stmt),
2670 TYPE_DECL, name, ctx->record_type);
2671 DECL_ARTIFICIAL (name) = 1;
2672 DECL_NAMELESS (name) = 1;
2673 TYPE_NAME (ctx->record_type) = name;
2674 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2675 if (offloaded)
2677 if (is_gimple_omp_oacc (stmt))
2678 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2679 0, 0);
2681 create_omp_child_function (ctx, false);
2682 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2685 if (is_gimple_omp_oacc (stmt))
2687 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2689 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2690 ctx->gwv_this |= MASK_GANG;
2691 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2692 ctx->gwv_this |= MASK_WORKER;
2693 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2694 ctx->gwv_this |= MASK_VECTOR;
2698 scan_sharing_clauses (clauses, ctx);
2699 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2701 if (TYPE_FIELDS (ctx->record_type) == NULL)
2702 ctx->record_type = ctx->receiver_decl = NULL;
2703 else
2705 TYPE_FIELDS (ctx->record_type)
2706 = nreverse (TYPE_FIELDS (ctx->record_type));
2707 #ifdef ENABLE_CHECKING
2708 tree field;
2709 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2710 for (field = TYPE_FIELDS (ctx->record_type);
2711 field;
2712 field = DECL_CHAIN (field))
2713 gcc_assert (DECL_ALIGN (field) == align);
2714 #endif
2715 layout_type (ctx->record_type);
2716 if (offloaded)
2717 fixup_child_record_type (ctx);
2721 /* Scan an OpenMP teams directive. */
2723 static void
2724 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2726 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2727 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2728 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2731 /* Check nesting restrictions. */
2732 static bool
2733 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2735 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2736 inside an OpenACC CTX. */
2737 if (!(is_gimple_omp (stmt)
2738 && is_gimple_omp_oacc (stmt)))
2740 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2741 if (is_gimple_omp (ctx_->stmt)
2742 && is_gimple_omp_oacc (ctx_->stmt))
2744 error_at (gimple_location (stmt),
2745 "non-OpenACC construct inside of OpenACC region");
2746 return false;
2750 if (ctx != NULL)
2752 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2753 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2755 error_at (gimple_location (stmt),
2756 "OpenMP constructs may not be nested inside simd region");
2757 return false;
2759 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2761 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2762 || (gimple_omp_for_kind (stmt)
2763 != GF_OMP_FOR_KIND_DISTRIBUTE))
2764 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2766 error_at (gimple_location (stmt),
2767 "only distribute or parallel constructs are allowed to "
2768 "be closely nested inside teams construct");
2769 return false;
2773 switch (gimple_code (stmt))
2775 case GIMPLE_OMP_FOR:
2776 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2777 return true;
2778 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2780 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2782 error_at (gimple_location (stmt),
2783 "distribute construct must be closely nested inside "
2784 "teams construct");
2785 return false;
2787 return true;
2789 /* FALLTHRU */
2790 case GIMPLE_CALL:
2791 if (is_gimple_call (stmt)
2792 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2793 == BUILT_IN_GOMP_CANCEL
2794 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2795 == BUILT_IN_GOMP_CANCELLATION_POINT))
2797 const char *bad = NULL;
2798 const char *kind = NULL;
2799 if (ctx == NULL)
2801 error_at (gimple_location (stmt), "orphaned %qs construct",
2802 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2803 == BUILT_IN_GOMP_CANCEL
2804 ? "#pragma omp cancel"
2805 : "#pragma omp cancellation point");
2806 return false;
2808 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2809 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2810 : 0)
2812 case 1:
2813 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2814 bad = "#pragma omp parallel";
2815 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2816 == BUILT_IN_GOMP_CANCEL
2817 && !integer_zerop (gimple_call_arg (stmt, 1)))
2818 ctx->cancellable = true;
2819 kind = "parallel";
2820 break;
2821 case 2:
2822 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2823 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2824 bad = "#pragma omp for";
2825 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2826 == BUILT_IN_GOMP_CANCEL
2827 && !integer_zerop (gimple_call_arg (stmt, 1)))
2829 ctx->cancellable = true;
2830 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2831 OMP_CLAUSE_NOWAIT))
2832 warning_at (gimple_location (stmt), 0,
2833 "%<#pragma omp cancel for%> inside "
2834 "%<nowait%> for construct");
2835 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2836 OMP_CLAUSE_ORDERED))
2837 warning_at (gimple_location (stmt), 0,
2838 "%<#pragma omp cancel for%> inside "
2839 "%<ordered%> for construct");
2841 kind = "for";
2842 break;
2843 case 4:
2844 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2845 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2846 bad = "#pragma omp sections";
2847 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2848 == BUILT_IN_GOMP_CANCEL
2849 && !integer_zerop (gimple_call_arg (stmt, 1)))
2851 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2853 ctx->cancellable = true;
2854 if (find_omp_clause (gimple_omp_sections_clauses
2855 (ctx->stmt),
2856 OMP_CLAUSE_NOWAIT))
2857 warning_at (gimple_location (stmt), 0,
2858 "%<#pragma omp cancel sections%> inside "
2859 "%<nowait%> sections construct");
2861 else
2863 gcc_assert (ctx->outer
2864 && gimple_code (ctx->outer->stmt)
2865 == GIMPLE_OMP_SECTIONS);
2866 ctx->outer->cancellable = true;
2867 if (find_omp_clause (gimple_omp_sections_clauses
2868 (ctx->outer->stmt),
2869 OMP_CLAUSE_NOWAIT))
2870 warning_at (gimple_location (stmt), 0,
2871 "%<#pragma omp cancel sections%> inside "
2872 "%<nowait%> sections construct");
2875 kind = "sections";
2876 break;
2877 case 8:
2878 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2879 bad = "#pragma omp task";
2880 else
2881 ctx->cancellable = true;
2882 kind = "taskgroup";
2883 break;
2884 default:
2885 error_at (gimple_location (stmt), "invalid arguments");
2886 return false;
2888 if (bad)
2890 error_at (gimple_location (stmt),
2891 "%<%s %s%> construct not closely nested inside of %qs",
2892 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2893 == BUILT_IN_GOMP_CANCEL
2894 ? "#pragma omp cancel"
2895 : "#pragma omp cancellation point", kind, bad);
2896 return false;
2899 /* FALLTHRU */
2900 case GIMPLE_OMP_SECTIONS:
2901 case GIMPLE_OMP_SINGLE:
2902 for (; ctx != NULL; ctx = ctx->outer)
2903 switch (gimple_code (ctx->stmt))
2905 case GIMPLE_OMP_FOR:
2906 case GIMPLE_OMP_SECTIONS:
2907 case GIMPLE_OMP_SINGLE:
2908 case GIMPLE_OMP_ORDERED:
2909 case GIMPLE_OMP_MASTER:
2910 case GIMPLE_OMP_TASK:
2911 case GIMPLE_OMP_CRITICAL:
2912 if (is_gimple_call (stmt))
2914 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2915 != BUILT_IN_GOMP_BARRIER)
2916 return true;
2917 error_at (gimple_location (stmt),
2918 "barrier region may not be closely nested inside "
2919 "of work-sharing, critical, ordered, master or "
2920 "explicit task region");
2921 return false;
2923 error_at (gimple_location (stmt),
2924 "work-sharing region may not be closely nested inside "
2925 "of work-sharing, critical, ordered, master or explicit "
2926 "task region");
2927 return false;
2928 case GIMPLE_OMP_PARALLEL:
2929 return true;
2930 default:
2931 break;
2933 break;
2934 case GIMPLE_OMP_MASTER:
2935 for (; ctx != NULL; ctx = ctx->outer)
2936 switch (gimple_code (ctx->stmt))
2938 case GIMPLE_OMP_FOR:
2939 case GIMPLE_OMP_SECTIONS:
2940 case GIMPLE_OMP_SINGLE:
2941 case GIMPLE_OMP_TASK:
2942 error_at (gimple_location (stmt),
2943 "master region may not be closely nested inside "
2944 "of work-sharing or explicit task region");
2945 return false;
2946 case GIMPLE_OMP_PARALLEL:
2947 return true;
2948 default:
2949 break;
2951 break;
2952 case GIMPLE_OMP_ORDERED:
2953 for (; ctx != NULL; ctx = ctx->outer)
2954 switch (gimple_code (ctx->stmt))
2956 case GIMPLE_OMP_CRITICAL:
2957 case GIMPLE_OMP_TASK:
2958 error_at (gimple_location (stmt),
2959 "ordered region may not be closely nested inside "
2960 "of critical or explicit task region");
2961 return false;
2962 case GIMPLE_OMP_FOR:
2963 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2964 OMP_CLAUSE_ORDERED) == NULL)
2966 error_at (gimple_location (stmt),
2967 "ordered region must be closely nested inside "
2968 "a loop region with an ordered clause");
2969 return false;
2971 return true;
2972 case GIMPLE_OMP_PARALLEL:
2973 error_at (gimple_location (stmt),
2974 "ordered region must be closely nested inside "
2975 "a loop region with an ordered clause");
2976 return false;
2977 default:
2978 break;
2980 break;
2981 case GIMPLE_OMP_CRITICAL:
2983 tree this_stmt_name
2984 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2985 for (; ctx != NULL; ctx = ctx->outer)
2986 if (gomp_critical *other_crit
2987 = dyn_cast <gomp_critical *> (ctx->stmt))
2988 if (this_stmt_name == gimple_omp_critical_name (other_crit))
2990 error_at (gimple_location (stmt),
2991 "critical region may not be nested inside a critical "
2992 "region with the same name");
2993 return false;
2996 break;
2997 case GIMPLE_OMP_TEAMS:
2998 if (ctx == NULL
2999 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3000 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3002 error_at (gimple_location (stmt),
3003 "teams construct not closely nested inside of target "
3004 "region");
3005 return false;
3007 break;
3008 case GIMPLE_OMP_TARGET:
3009 for (; ctx != NULL; ctx = ctx->outer)
3011 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3013 if (is_gimple_omp (stmt)
3014 && is_gimple_omp_oacc (stmt)
3015 && is_gimple_omp (ctx->stmt))
3017 error_at (gimple_location (stmt),
3018 "OpenACC construct inside of non-OpenACC region");
3019 return false;
3021 continue;
3024 const char *stmt_name, *ctx_stmt_name;
3025 switch (gimple_omp_target_kind (stmt))
3027 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3028 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3029 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3030 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3031 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3032 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3033 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3034 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3035 default: gcc_unreachable ();
3037 switch (gimple_omp_target_kind (ctx->stmt))
3039 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3040 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3041 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3042 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3043 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3044 default: gcc_unreachable ();
3047 /* OpenACC/OpenMP mismatch? */
3048 if (is_gimple_omp_oacc (stmt)
3049 != is_gimple_omp_oacc (ctx->stmt))
3051 error_at (gimple_location (stmt),
3052 "%s %s construct inside of %s %s region",
3053 (is_gimple_omp_oacc (stmt)
3054 ? "OpenACC" : "OpenMP"), stmt_name,
3055 (is_gimple_omp_oacc (ctx->stmt)
3056 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3057 return false;
3059 if (is_gimple_omp_offloaded (ctx->stmt))
3061 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3062 if (is_gimple_omp_oacc (ctx->stmt))
3064 error_at (gimple_location (stmt),
3065 "%s construct inside of %s region",
3066 stmt_name, ctx_stmt_name);
3067 return false;
3069 else
3071 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3072 warning_at (gimple_location (stmt), 0,
3073 "%s construct inside of %s region",
3074 stmt_name, ctx_stmt_name);
3078 break;
3079 default:
3080 break;
3082 return true;
3086 /* Helper function scan_omp.
3088 Callback for walk_tree or operators in walk_gimple_stmt used to
3089 scan for OMP directives in TP. */
3091 static tree
3092 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3094 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3095 omp_context *ctx = (omp_context *) wi->info;
3096 tree t = *tp;
3098 switch (TREE_CODE (t))
3100 case VAR_DECL:
3101 case PARM_DECL:
3102 case LABEL_DECL:
3103 case RESULT_DECL:
3104 if (ctx)
3105 *tp = remap_decl (t, &ctx->cb);
3106 break;
3108 default:
3109 if (ctx && TYPE_P (t))
3110 *tp = remap_type (t, &ctx->cb);
3111 else if (!DECL_P (t))
3113 *walk_subtrees = 1;
3114 if (ctx)
3116 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3117 if (tem != TREE_TYPE (t))
3119 if (TREE_CODE (t) == INTEGER_CST)
3120 *tp = wide_int_to_tree (tem, t);
3121 else
3122 TREE_TYPE (t) = tem;
3126 break;
3129 return NULL_TREE;
3132 /* Return true if FNDECL is a setjmp or a longjmp. */
3134 static bool
3135 setjmp_or_longjmp_p (const_tree fndecl)
3137 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3138 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3139 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3140 return true;
3142 tree declname = DECL_NAME (fndecl);
3143 if (!declname)
3144 return false;
3145 const char *name = IDENTIFIER_POINTER (declname);
3146 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3150 /* Helper function for scan_omp.
3152 Callback for walk_gimple_stmt used to scan for OMP directives in
3153 the current statement in GSI. */
3155 static tree
3156 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3157 struct walk_stmt_info *wi)
3159 gimple stmt = gsi_stmt (*gsi);
3160 omp_context *ctx = (omp_context *) wi->info;
3162 if (gimple_has_location (stmt))
3163 input_location = gimple_location (stmt);
3165 /* Check the nesting restrictions. */
3166 bool remove = false;
3167 if (is_gimple_omp (stmt))
3168 remove = !check_omp_nesting_restrictions (stmt, ctx);
3169 else if (is_gimple_call (stmt))
3171 tree fndecl = gimple_call_fndecl (stmt);
3172 if (fndecl)
3174 if (setjmp_or_longjmp_p (fndecl)
3175 && ctx
3176 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3177 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3179 remove = true;
3180 error_at (gimple_location (stmt),
3181 "setjmp/longjmp inside simd construct");
3183 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3184 switch (DECL_FUNCTION_CODE (fndecl))
3186 case BUILT_IN_GOMP_BARRIER:
3187 case BUILT_IN_GOMP_CANCEL:
3188 case BUILT_IN_GOMP_CANCELLATION_POINT:
3189 case BUILT_IN_GOMP_TASKYIELD:
3190 case BUILT_IN_GOMP_TASKWAIT:
3191 case BUILT_IN_GOMP_TASKGROUP_START:
3192 case BUILT_IN_GOMP_TASKGROUP_END:
3193 remove = !check_omp_nesting_restrictions (stmt, ctx);
3194 break;
3195 default:
3196 break;
3200 if (remove)
3202 stmt = gimple_build_nop ();
3203 gsi_replace (gsi, stmt, false);
3206 *handled_ops_p = true;
3208 switch (gimple_code (stmt))
3210 case GIMPLE_OMP_PARALLEL:
3211 taskreg_nesting_level++;
3212 scan_omp_parallel (gsi, ctx);
3213 taskreg_nesting_level--;
3214 break;
3216 case GIMPLE_OMP_TASK:
3217 taskreg_nesting_level++;
3218 scan_omp_task (gsi, ctx);
3219 taskreg_nesting_level--;
3220 break;
3222 case GIMPLE_OMP_FOR:
3223 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3224 break;
3226 case GIMPLE_OMP_SECTIONS:
3227 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3228 break;
3230 case GIMPLE_OMP_SINGLE:
3231 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3232 break;
3234 case GIMPLE_OMP_SECTION:
3235 case GIMPLE_OMP_MASTER:
3236 case GIMPLE_OMP_TASKGROUP:
3237 case GIMPLE_OMP_ORDERED:
3238 case GIMPLE_OMP_CRITICAL:
3239 ctx = new_omp_context (stmt, ctx);
3240 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3241 break;
3243 case GIMPLE_OMP_TARGET:
3244 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3245 break;
3247 case GIMPLE_OMP_TEAMS:
3248 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3249 break;
3251 case GIMPLE_BIND:
3253 tree var;
3255 *handled_ops_p = false;
3256 if (ctx)
3257 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3258 var ;
3259 var = DECL_CHAIN (var))
3260 insert_decl_map (&ctx->cb, var, var);
3262 break;
3263 default:
3264 *handled_ops_p = false;
3265 break;
3268 return NULL_TREE;
3272 /* Scan all the statements starting at the current statement. CTX
3273 contains context information about the OMP directives and
3274 clauses found during the scan. */
3276 static void
3277 scan_omp (gimple_seq *body_p, omp_context *ctx)
3279 location_t saved_location;
3280 struct walk_stmt_info wi;
3282 memset (&wi, 0, sizeof (wi));
3283 wi.info = ctx;
3284 wi.want_locations = true;
3286 saved_location = input_location;
3287 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3288 input_location = saved_location;
3291 /* Re-gimplification and code generation routines. */
3293 /* Build a call to GOMP_barrier. */
3295 static gimple
3296 build_omp_barrier (tree lhs)
3298 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3299 : BUILT_IN_GOMP_BARRIER);
3300 gcall *g = gimple_build_call (fndecl, 0);
3301 if (lhs)
3302 gimple_call_set_lhs (g, lhs);
3303 return g;
3306 /* If a context was created for STMT when it was scanned, return it. */
3308 static omp_context *
3309 maybe_lookup_ctx (gimple stmt)
3311 splay_tree_node n;
3312 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3313 return n ? (omp_context *) n->value : NULL;
3317 /* Find the mapping for DECL in CTX or the immediately enclosing
3318 context that has a mapping for DECL.
3320 If CTX is a nested parallel directive, we may have to use the decl
3321 mappings created in CTX's parent context. Suppose that we have the
3322 following parallel nesting (variable UIDs showed for clarity):
3324 iD.1562 = 0;
3325 #omp parallel shared(iD.1562) -> outer parallel
3326 iD.1562 = iD.1562 + 1;
3328 #omp parallel shared (iD.1562) -> inner parallel
3329 iD.1562 = iD.1562 - 1;
3331 Each parallel structure will create a distinct .omp_data_s structure
3332 for copying iD.1562 in/out of the directive:
3334 outer parallel .omp_data_s.1.i -> iD.1562
3335 inner parallel .omp_data_s.2.i -> iD.1562
3337 A shared variable mapping will produce a copy-out operation before
3338 the parallel directive and a copy-in operation after it. So, in
3339 this case we would have:
3341 iD.1562 = 0;
3342 .omp_data_o.1.i = iD.1562;
3343 #omp parallel shared(iD.1562) -> outer parallel
3344 .omp_data_i.1 = &.omp_data_o.1
3345 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3347 .omp_data_o.2.i = iD.1562; -> **
3348 #omp parallel shared(iD.1562) -> inner parallel
3349 .omp_data_i.2 = &.omp_data_o.2
3350 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3353 ** This is a problem. The symbol iD.1562 cannot be referenced
3354 inside the body of the outer parallel region. But since we are
3355 emitting this copy operation while expanding the inner parallel
3356 directive, we need to access the CTX structure of the outer
3357 parallel directive to get the correct mapping:
3359 .omp_data_o.2.i = .omp_data_i.1->i
3361 Since there may be other workshare or parallel directives enclosing
3362 the parallel directive, it may be necessary to walk up the context
3363 parent chain. This is not a problem in general because nested
3364 parallelism happens only rarely. */
3366 static tree
3367 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3369 tree t;
3370 omp_context *up;
3372 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3373 t = maybe_lookup_decl (decl, up);
3375 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3377 return t ? t : decl;
3381 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3382 in outer contexts. */
3384 static tree
3385 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3387 tree t = NULL;
3388 omp_context *up;
3390 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3391 t = maybe_lookup_decl (decl, up);
3393 return t ? t : decl;
3397 /* Construct the initialization value for reduction CLAUSE. */
3399 tree
3400 omp_reduction_init (tree clause, tree type)
3402 location_t loc = OMP_CLAUSE_LOCATION (clause);
3403 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3405 case PLUS_EXPR:
3406 case MINUS_EXPR:
3407 case BIT_IOR_EXPR:
3408 case BIT_XOR_EXPR:
3409 case TRUTH_OR_EXPR:
3410 case TRUTH_ORIF_EXPR:
3411 case TRUTH_XOR_EXPR:
3412 case NE_EXPR:
3413 return build_zero_cst (type);
3415 case MULT_EXPR:
3416 case TRUTH_AND_EXPR:
3417 case TRUTH_ANDIF_EXPR:
3418 case EQ_EXPR:
3419 return fold_convert_loc (loc, type, integer_one_node);
3421 case BIT_AND_EXPR:
3422 return fold_convert_loc (loc, type, integer_minus_one_node);
3424 case MAX_EXPR:
3425 if (SCALAR_FLOAT_TYPE_P (type))
3427 REAL_VALUE_TYPE max, min;
3428 if (HONOR_INFINITIES (type))
3430 real_inf (&max);
3431 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3433 else
3434 real_maxval (&min, 1, TYPE_MODE (type));
3435 return build_real (type, min);
3437 else
3439 gcc_assert (INTEGRAL_TYPE_P (type));
3440 return TYPE_MIN_VALUE (type);
3443 case MIN_EXPR:
3444 if (SCALAR_FLOAT_TYPE_P (type))
3446 REAL_VALUE_TYPE max;
3447 if (HONOR_INFINITIES (type))
3448 real_inf (&max);
3449 else
3450 real_maxval (&max, 0, TYPE_MODE (type));
3451 return build_real (type, max);
3453 else
3455 gcc_assert (INTEGRAL_TYPE_P (type));
3456 return TYPE_MAX_VALUE (type);
3459 default:
3460 gcc_unreachable ();
3464 /* Return alignment to be assumed for var in CLAUSE, which should be
3465 OMP_CLAUSE_ALIGNED. */
3467 static tree
3468 omp_clause_aligned_alignment (tree clause)
3470 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3471 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3473 /* Otherwise return implementation defined alignment. */
3474 unsigned int al = 1;
3475 machine_mode mode, vmode;
3476 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3477 if (vs)
3478 vs = 1 << floor_log2 (vs);
3479 static enum mode_class classes[]
3480 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3481 for (int i = 0; i < 4; i += 2)
3482 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3483 mode != VOIDmode;
3484 mode = GET_MODE_WIDER_MODE (mode))
3486 vmode = targetm.vectorize.preferred_simd_mode (mode);
3487 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3488 continue;
3489 while (vs
3490 && GET_MODE_SIZE (vmode) < vs
3491 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3492 vmode = GET_MODE_2XWIDER_MODE (vmode);
3494 tree type = lang_hooks.types.type_for_mode (mode, 1);
3495 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3496 continue;
3497 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3498 / GET_MODE_SIZE (mode));
3499 if (TYPE_MODE (type) != vmode)
3500 continue;
3501 if (TYPE_ALIGN_UNIT (type) > al)
3502 al = TYPE_ALIGN_UNIT (type);
3504 return build_int_cst (integer_type_node, al);
3507 /* Return maximum possible vectorization factor for the target. */
3509 static int
3510 omp_max_vf (void)
3512 if (!optimize
3513 || optimize_debug
3514 || !flag_tree_loop_optimize
3515 || (!flag_tree_loop_vectorize
3516 && (global_options_set.x_flag_tree_loop_vectorize
3517 || global_options_set.x_flag_tree_vectorize)))
3518 return 1;
3520 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3521 if (vs)
3523 vs = 1 << floor_log2 (vs);
3524 return vs;
3526 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3527 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3528 return GET_MODE_NUNITS (vqimode);
3529 return 1;
3532 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3533 privatization. */
3535 static bool
3536 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3537 tree &idx, tree &lane, tree &ivar, tree &lvar)
3539 if (max_vf == 0)
3541 max_vf = omp_max_vf ();
3542 if (max_vf > 1)
3544 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3545 OMP_CLAUSE_SAFELEN);
3546 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3547 max_vf = 1;
3548 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3549 max_vf) == -1)
3550 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3552 if (max_vf > 1)
3554 idx = create_tmp_var (unsigned_type_node);
3555 lane = create_tmp_var (unsigned_type_node);
3558 if (max_vf == 1)
3559 return false;
3561 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3562 tree avar = create_tmp_var_raw (atype);
3563 if (TREE_ADDRESSABLE (new_var))
3564 TREE_ADDRESSABLE (avar) = 1;
3565 DECL_ATTRIBUTES (avar)
3566 = tree_cons (get_identifier ("omp simd array"), NULL,
3567 DECL_ATTRIBUTES (avar));
3568 gimple_add_tmp_var (avar);
3569 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3570 NULL_TREE, NULL_TREE);
3571 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3572 NULL_TREE, NULL_TREE);
3573 if (DECL_P (new_var))
3575 SET_DECL_VALUE_EXPR (new_var, lvar);
3576 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3578 return true;
3581 /* Helper function of lower_rec_input_clauses. For a reference
3582 in simd reduction, add an underlying variable it will reference. */
3584 static void
3585 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3587 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3588 if (TREE_CONSTANT (z))
3590 const char *name = NULL;
3591 if (DECL_NAME (new_vard))
3592 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3594 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3595 gimple_add_tmp_var (z);
3596 TREE_ADDRESSABLE (z) = 1;
3597 z = build_fold_addr_expr_loc (loc, z);
3598 gimplify_assign (new_vard, z, ilist);
3602 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3603 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3604 private variables. Initialization statements go in ILIST, while calls
3605 to destructors go in DLIST. */
3607 static void
3608 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3609 omp_context *ctx, struct omp_for_data *fd)
3611 tree c, dtor, copyin_seq, x, ptr;
3612 bool copyin_by_ref = false;
3613 bool lastprivate_firstprivate = false;
3614 bool reduction_omp_orig_ref = false;
3615 int pass;
3616 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3617 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3618 int max_vf = 0;
3619 tree lane = NULL_TREE, idx = NULL_TREE;
3620 tree ivar = NULL_TREE, lvar = NULL_TREE;
3621 gimple_seq llist[2] = { NULL, NULL };
3623 copyin_seq = NULL;
3625 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3626 with data sharing clauses referencing variable sized vars. That
3627 is unnecessarily hard to support and very unlikely to result in
3628 vectorized code anyway. */
3629 if (is_simd)
3630 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3631 switch (OMP_CLAUSE_CODE (c))
3633 case OMP_CLAUSE_LINEAR:
3634 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3635 max_vf = 1;
3636 /* FALLTHRU */
3637 case OMP_CLAUSE_REDUCTION:
3638 case OMP_CLAUSE_PRIVATE:
3639 case OMP_CLAUSE_FIRSTPRIVATE:
3640 case OMP_CLAUSE_LASTPRIVATE:
3641 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3642 max_vf = 1;
3643 break;
3644 default:
3645 continue;
3648 /* Do all the fixed sized types in the first pass, and the variable sized
3649 types in the second pass. This makes sure that the scalar arguments to
3650 the variable sized types are processed before we use them in the
3651 variable sized operations. */
3652 for (pass = 0; pass < 2; ++pass)
3654 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3656 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3657 tree var, new_var;
3658 bool by_ref;
3659 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3661 switch (c_kind)
3663 case OMP_CLAUSE_PRIVATE:
3664 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3665 continue;
3666 break;
3667 case OMP_CLAUSE_SHARED:
3668 /* Ignore shared directives in teams construct. */
3669 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3670 continue;
3671 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3673 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3674 continue;
3676 case OMP_CLAUSE_FIRSTPRIVATE:
3677 case OMP_CLAUSE_COPYIN:
3678 case OMP_CLAUSE_LINEAR:
3679 break;
3680 case OMP_CLAUSE_REDUCTION:
3681 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3682 reduction_omp_orig_ref = true;
3683 break;
3684 case OMP_CLAUSE__LOOPTEMP_:
3685 /* Handle _looptemp_ clauses only on parallel. */
3686 if (fd)
3687 continue;
3688 break;
3689 case OMP_CLAUSE_LASTPRIVATE:
3690 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3692 lastprivate_firstprivate = true;
3693 if (pass != 0)
3694 continue;
3696 /* Even without corresponding firstprivate, if
3697 decl is Fortran allocatable, it needs outer var
3698 reference. */
3699 else if (pass == 0
3700 && lang_hooks.decls.omp_private_outer_ref
3701 (OMP_CLAUSE_DECL (c)))
3702 lastprivate_firstprivate = true;
3703 break;
3704 case OMP_CLAUSE_ALIGNED:
3705 if (pass == 0)
3706 continue;
3707 var = OMP_CLAUSE_DECL (c);
3708 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3709 && !is_global_var (var))
3711 new_var = maybe_lookup_decl (var, ctx);
3712 if (new_var == NULL_TREE)
3713 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3714 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3715 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3716 omp_clause_aligned_alignment (c));
3717 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3718 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3719 gimplify_and_add (x, ilist);
3721 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3722 && is_global_var (var))
3724 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3725 new_var = lookup_decl (var, ctx);
3726 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3727 t = build_fold_addr_expr_loc (clause_loc, t);
3728 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3729 t = build_call_expr_loc (clause_loc, t2, 2, t,
3730 omp_clause_aligned_alignment (c));
3731 t = fold_convert_loc (clause_loc, ptype, t);
3732 x = create_tmp_var (ptype);
3733 t = build2 (MODIFY_EXPR, ptype, x, t);
3734 gimplify_and_add (t, ilist);
3735 t = build_simple_mem_ref_loc (clause_loc, x);
3736 SET_DECL_VALUE_EXPR (new_var, t);
3737 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3739 continue;
3740 default:
3741 continue;
3744 new_var = var = OMP_CLAUSE_DECL (c);
3745 if (c_kind != OMP_CLAUSE_COPYIN)
3746 new_var = lookup_decl (var, ctx);
3748 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3750 if (pass != 0)
3751 continue;
3753 else if (is_variable_sized (var))
3755 /* For variable sized types, we need to allocate the
3756 actual storage here. Call alloca and store the
3757 result in the pointer decl that we created elsewhere. */
3758 if (pass == 0)
3759 continue;
3761 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3763 gcall *stmt;
3764 tree tmp, atmp;
3766 ptr = DECL_VALUE_EXPR (new_var);
3767 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3768 ptr = TREE_OPERAND (ptr, 0);
3769 gcc_assert (DECL_P (ptr));
3770 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3772 /* void *tmp = __builtin_alloca */
3773 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3774 stmt = gimple_build_call (atmp, 1, x);
3775 tmp = create_tmp_var_raw (ptr_type_node);
3776 gimple_add_tmp_var (tmp);
3777 gimple_call_set_lhs (stmt, tmp);
3779 gimple_seq_add_stmt (ilist, stmt);
3781 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3782 gimplify_assign (ptr, x, ilist);
3785 else if (is_reference (var))
3787 /* For references that are being privatized for Fortran,
3788 allocate new backing storage for the new pointer
3789 variable. This allows us to avoid changing all the
3790 code that expects a pointer to something that expects
3791 a direct variable. */
3792 if (pass == 0)
3793 continue;
3795 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3796 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3798 x = build_receiver_ref (var, false, ctx);
3799 x = build_fold_addr_expr_loc (clause_loc, x);
3801 else if (TREE_CONSTANT (x))
3803 /* For reduction in SIMD loop, defer adding the
3804 initialization of the reference, because if we decide
3805 to use SIMD array for it, the initilization could cause
3806 expansion ICE. */
3807 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3808 x = NULL_TREE;
3809 else
3811 const char *name = NULL;
3812 if (DECL_NAME (var))
3813 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3815 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3816 name);
3817 gimple_add_tmp_var (x);
3818 TREE_ADDRESSABLE (x) = 1;
3819 x = build_fold_addr_expr_loc (clause_loc, x);
3822 else
3824 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3825 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3828 if (x)
3830 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3831 gimplify_assign (new_var, x, ilist);
3834 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3836 else if (c_kind == OMP_CLAUSE_REDUCTION
3837 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3839 if (pass == 0)
3840 continue;
3842 else if (pass != 0)
3843 continue;
3845 switch (OMP_CLAUSE_CODE (c))
3847 case OMP_CLAUSE_SHARED:
3848 /* Ignore shared directives in teams construct. */
3849 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3850 continue;
3851 /* Shared global vars are just accessed directly. */
3852 if (is_global_var (new_var))
3853 break;
3854 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3855 needs to be delayed until after fixup_child_record_type so
3856 that we get the correct type during the dereference. */
3857 by_ref = use_pointer_for_field (var, ctx);
3858 x = build_receiver_ref (var, by_ref, ctx);
3859 SET_DECL_VALUE_EXPR (new_var, x);
3860 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3862 /* ??? If VAR is not passed by reference, and the variable
3863 hasn't been initialized yet, then we'll get a warning for
3864 the store into the omp_data_s structure. Ideally, we'd be
3865 able to notice this and not store anything at all, but
3866 we're generating code too early. Suppress the warning. */
3867 if (!by_ref)
3868 TREE_NO_WARNING (var) = 1;
3869 break;
3871 case OMP_CLAUSE_LASTPRIVATE:
3872 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3873 break;
3874 /* FALLTHRU */
3876 case OMP_CLAUSE_PRIVATE:
3877 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3878 x = build_outer_var_ref (var, ctx);
3879 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3881 if (is_task_ctx (ctx))
3882 x = build_receiver_ref (var, false, ctx);
3883 else
3884 x = build_outer_var_ref (var, ctx);
3886 else
3887 x = NULL;
3888 do_private:
3889 tree nx;
3890 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3891 if (is_simd)
3893 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3894 if ((TREE_ADDRESSABLE (new_var) || nx || y
3895 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3896 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3897 idx, lane, ivar, lvar))
3899 if (nx)
3900 x = lang_hooks.decls.omp_clause_default_ctor
3901 (c, unshare_expr (ivar), x);
3902 if (nx && x)
3903 gimplify_and_add (x, &llist[0]);
3904 if (y)
3906 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3907 if (y)
3909 gimple_seq tseq = NULL;
3911 dtor = y;
3912 gimplify_stmt (&dtor, &tseq);
3913 gimple_seq_add_seq (&llist[1], tseq);
3916 break;
3919 if (nx)
3920 gimplify_and_add (nx, ilist);
3921 /* FALLTHRU */
3923 do_dtor:
3924 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3925 if (x)
3927 gimple_seq tseq = NULL;
3929 dtor = x;
3930 gimplify_stmt (&dtor, &tseq);
3931 gimple_seq_add_seq (dlist, tseq);
3933 break;
3935 case OMP_CLAUSE_LINEAR:
3936 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3937 goto do_firstprivate;
3938 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3939 x = NULL;
3940 else
3941 x = build_outer_var_ref (var, ctx);
3942 goto do_private;
3944 case OMP_CLAUSE_FIRSTPRIVATE:
3945 if (is_task_ctx (ctx))
3947 if (is_reference (var) || is_variable_sized (var))
3948 goto do_dtor;
3949 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3950 ctx))
3951 || use_pointer_for_field (var, NULL))
3953 x = build_receiver_ref (var, false, ctx);
3954 SET_DECL_VALUE_EXPR (new_var, x);
3955 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3956 goto do_dtor;
3959 do_firstprivate:
3960 x = build_outer_var_ref (var, ctx);
3961 if (is_simd)
3963 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3964 && gimple_omp_for_combined_into_p (ctx->stmt))
3966 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3967 tree stept = TREE_TYPE (t);
3968 tree ct = find_omp_clause (clauses,
3969 OMP_CLAUSE__LOOPTEMP_);
3970 gcc_assert (ct);
3971 tree l = OMP_CLAUSE_DECL (ct);
3972 tree n1 = fd->loop.n1;
3973 tree step = fd->loop.step;
3974 tree itype = TREE_TYPE (l);
3975 if (POINTER_TYPE_P (itype))
3976 itype = signed_type_for (itype);
3977 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3978 if (TYPE_UNSIGNED (itype)
3979 && fd->loop.cond_code == GT_EXPR)
3980 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3981 fold_build1 (NEGATE_EXPR, itype, l),
3982 fold_build1 (NEGATE_EXPR,
3983 itype, step));
3984 else
3985 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3986 t = fold_build2 (MULT_EXPR, stept,
3987 fold_convert (stept, l), t);
3989 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3991 x = lang_hooks.decls.omp_clause_linear_ctor
3992 (c, new_var, x, t);
3993 gimplify_and_add (x, ilist);
3994 goto do_dtor;
3997 if (POINTER_TYPE_P (TREE_TYPE (x)))
3998 x = fold_build2 (POINTER_PLUS_EXPR,
3999 TREE_TYPE (x), x, t);
4000 else
4001 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4004 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4005 || TREE_ADDRESSABLE (new_var))
4006 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4007 idx, lane, ivar, lvar))
4009 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4011 tree iv = create_tmp_var (TREE_TYPE (new_var));
4012 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4013 gimplify_and_add (x, ilist);
4014 gimple_stmt_iterator gsi
4015 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4016 gassign *g
4017 = gimple_build_assign (unshare_expr (lvar), iv);
4018 gsi_insert_before_without_update (&gsi, g,
4019 GSI_SAME_STMT);
4020 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4021 enum tree_code code = PLUS_EXPR;
4022 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4023 code = POINTER_PLUS_EXPR;
4024 g = gimple_build_assign (iv, code, iv, t);
4025 gsi_insert_before_without_update (&gsi, g,
4026 GSI_SAME_STMT);
4027 break;
4029 x = lang_hooks.decls.omp_clause_copy_ctor
4030 (c, unshare_expr (ivar), x);
4031 gimplify_and_add (x, &llist[0]);
4032 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4033 if (x)
4035 gimple_seq tseq = NULL;
4037 dtor = x;
4038 gimplify_stmt (&dtor, &tseq);
4039 gimple_seq_add_seq (&llist[1], tseq);
4041 break;
4044 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4045 gimplify_and_add (x, ilist);
4046 goto do_dtor;
4048 case OMP_CLAUSE__LOOPTEMP_:
4049 gcc_assert (is_parallel_ctx (ctx));
4050 x = build_outer_var_ref (var, ctx);
4051 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4052 gimplify_and_add (x, ilist);
4053 break;
4055 case OMP_CLAUSE_COPYIN:
4056 by_ref = use_pointer_for_field (var, NULL);
4057 x = build_receiver_ref (var, by_ref, ctx);
4058 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4059 append_to_statement_list (x, &copyin_seq);
4060 copyin_by_ref |= by_ref;
4061 break;
4063 case OMP_CLAUSE_REDUCTION:
4064 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4066 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4067 gimple tseq;
4068 x = build_outer_var_ref (var, ctx);
4070 if (is_reference (var)
4071 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4072 TREE_TYPE (x)))
4073 x = build_fold_addr_expr_loc (clause_loc, x);
4074 SET_DECL_VALUE_EXPR (placeholder, x);
4075 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4076 tree new_vard = new_var;
4077 if (is_reference (var))
4079 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4080 new_vard = TREE_OPERAND (new_var, 0);
4081 gcc_assert (DECL_P (new_vard));
4083 if (is_simd
4084 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4085 idx, lane, ivar, lvar))
4087 if (new_vard == new_var)
4089 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4090 SET_DECL_VALUE_EXPR (new_var, ivar);
4092 else
4094 SET_DECL_VALUE_EXPR (new_vard,
4095 build_fold_addr_expr (ivar));
4096 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4098 x = lang_hooks.decls.omp_clause_default_ctor
4099 (c, unshare_expr (ivar),
4100 build_outer_var_ref (var, ctx));
4101 if (x)
4102 gimplify_and_add (x, &llist[0]);
4103 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4105 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4106 lower_omp (&tseq, ctx);
4107 gimple_seq_add_seq (&llist[0], tseq);
4109 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4110 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4111 lower_omp (&tseq, ctx);
4112 gimple_seq_add_seq (&llist[1], tseq);
4113 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4114 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4115 if (new_vard == new_var)
4116 SET_DECL_VALUE_EXPR (new_var, lvar);
4117 else
4118 SET_DECL_VALUE_EXPR (new_vard,
4119 build_fold_addr_expr (lvar));
4120 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4121 if (x)
4123 tseq = NULL;
4124 dtor = x;
4125 gimplify_stmt (&dtor, &tseq);
4126 gimple_seq_add_seq (&llist[1], tseq);
4128 break;
4130 /* If this is a reference to constant size reduction var
4131 with placeholder, we haven't emitted the initializer
4132 for it because it is undesirable if SIMD arrays are used.
4133 But if they aren't used, we need to emit the deferred
4134 initialization now. */
4135 else if (is_reference (var) && is_simd)
4136 handle_simd_reference (clause_loc, new_vard, ilist);
4137 x = lang_hooks.decls.omp_clause_default_ctor
4138 (c, unshare_expr (new_var),
4139 build_outer_var_ref (var, ctx));
4140 if (x)
4141 gimplify_and_add (x, ilist);
4142 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4144 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4145 lower_omp (&tseq, ctx);
4146 gimple_seq_add_seq (ilist, tseq);
4148 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4149 if (is_simd)
4151 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4152 lower_omp (&tseq, ctx);
4153 gimple_seq_add_seq (dlist, tseq);
4154 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4156 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4157 goto do_dtor;
4159 else
4161 x = omp_reduction_init (c, TREE_TYPE (new_var));
4162 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4163 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4165 /* reduction(-:var) sums up the partial results, so it
4166 acts identically to reduction(+:var). */
4167 if (code == MINUS_EXPR)
4168 code = PLUS_EXPR;
4170 tree new_vard = new_var;
4171 if (is_simd && is_reference (var))
4173 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4174 new_vard = TREE_OPERAND (new_var, 0);
4175 gcc_assert (DECL_P (new_vard));
4177 if (is_simd
4178 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4179 idx, lane, ivar, lvar))
4181 tree ref = build_outer_var_ref (var, ctx);
4183 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4185 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4186 ref = build_outer_var_ref (var, ctx);
4187 gimplify_assign (ref, x, &llist[1]);
4189 if (new_vard != new_var)
4191 SET_DECL_VALUE_EXPR (new_vard,
4192 build_fold_addr_expr (lvar));
4193 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4196 else
4198 if (is_reference (var) && is_simd)
4199 handle_simd_reference (clause_loc, new_vard, ilist);
4200 gimplify_assign (new_var, x, ilist);
4201 if (is_simd)
4203 tree ref = build_outer_var_ref (var, ctx);
4205 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4206 ref = build_outer_var_ref (var, ctx);
4207 gimplify_assign (ref, x, dlist);
4211 break;
4213 default:
4214 gcc_unreachable ();
4219 if (lane)
4221 tree uid = create_tmp_var (ptr_type_node, "simduid");
4222 /* Don't want uninit warnings on simduid, it is always uninitialized,
4223 but we use it not for the value, but for the DECL_UID only. */
4224 TREE_NO_WARNING (uid) = 1;
4225 gimple g
4226 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4227 gimple_call_set_lhs (g, lane);
4228 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4229 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4230 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4231 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4232 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4233 gimple_omp_for_set_clauses (ctx->stmt, c);
4234 g = gimple_build_assign (lane, INTEGER_CST,
4235 build_int_cst (unsigned_type_node, 0));
4236 gimple_seq_add_stmt (ilist, g);
4237 for (int i = 0; i < 2; i++)
4238 if (llist[i])
4240 tree vf = create_tmp_var (unsigned_type_node);
4241 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4242 gimple_call_set_lhs (g, vf);
4243 gimple_seq *seq = i == 0 ? ilist : dlist;
4244 gimple_seq_add_stmt (seq, g);
4245 tree t = build_int_cst (unsigned_type_node, 0);
4246 g = gimple_build_assign (idx, INTEGER_CST, t);
4247 gimple_seq_add_stmt (seq, g);
4248 tree body = create_artificial_label (UNKNOWN_LOCATION);
4249 tree header = create_artificial_label (UNKNOWN_LOCATION);
4250 tree end = create_artificial_label (UNKNOWN_LOCATION);
4251 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4252 gimple_seq_add_stmt (seq, gimple_build_label (body));
4253 gimple_seq_add_seq (seq, llist[i]);
4254 t = build_int_cst (unsigned_type_node, 1);
4255 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4256 gimple_seq_add_stmt (seq, g);
4257 gimple_seq_add_stmt (seq, gimple_build_label (header));
4258 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4259 gimple_seq_add_stmt (seq, g);
4260 gimple_seq_add_stmt (seq, gimple_build_label (end));
4264 /* The copyin sequence is not to be executed by the main thread, since
4265 that would result in self-copies. Perhaps not visible to scalars,
4266 but it certainly is to C++ operator=. */
4267 if (copyin_seq)
4269 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4271 x = build2 (NE_EXPR, boolean_type_node, x,
4272 build_int_cst (TREE_TYPE (x), 0));
4273 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4274 gimplify_and_add (x, ilist);
4277 /* If any copyin variable is passed by reference, we must ensure the
4278 master thread doesn't modify it before it is copied over in all
4279 threads. Similarly for variables in both firstprivate and
4280 lastprivate clauses we need to ensure the lastprivate copying
4281 happens after firstprivate copying in all threads. And similarly
4282 for UDRs if initializer expression refers to omp_orig. */
4283 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4285 /* Don't add any barrier for #pragma omp simd or
4286 #pragma omp distribute. */
4287 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4288 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4289 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4292 /* If max_vf is non-zero, then we can use only a vectorization factor
4293 up to the max_vf we chose. So stick it into the safelen clause. */
4294 if (max_vf)
4296 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4297 OMP_CLAUSE_SAFELEN);
4298 if (c == NULL_TREE
4299 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4300 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4301 max_vf) == 1))
4303 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4304 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4305 max_vf);
4306 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4307 gimple_omp_for_set_clauses (ctx->stmt, c);
4313 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4314 both parallel and workshare constructs. PREDICATE may be NULL if it's
4315 always true. */
4317 static void
4318 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4319 omp_context *ctx)
4321 tree x, c, label = NULL, orig_clauses = clauses;
4322 bool par_clauses = false;
4323 tree simduid = NULL, lastlane = NULL;
4325 /* Early exit if there are no lastprivate or linear clauses. */
4326 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4327 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4328 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4329 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4330 break;
4331 if (clauses == NULL)
4333 /* If this was a workshare clause, see if it had been combined
4334 with its parallel. In that case, look for the clauses on the
4335 parallel statement itself. */
4336 if (is_parallel_ctx (ctx))
4337 return;
4339 ctx = ctx->outer;
4340 if (ctx == NULL || !is_parallel_ctx (ctx))
4341 return;
4343 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4344 OMP_CLAUSE_LASTPRIVATE);
4345 if (clauses == NULL)
4346 return;
4347 par_clauses = true;
4350 if (predicate)
4352 gcond *stmt;
4353 tree label_true, arm1, arm2;
4355 label = create_artificial_label (UNKNOWN_LOCATION);
4356 label_true = create_artificial_label (UNKNOWN_LOCATION);
4357 arm1 = TREE_OPERAND (predicate, 0);
4358 arm2 = TREE_OPERAND (predicate, 1);
4359 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4360 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4361 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4362 label_true, label);
4363 gimple_seq_add_stmt (stmt_list, stmt);
4364 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4367 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4368 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4370 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4371 if (simduid)
4372 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4375 for (c = clauses; c ;)
4377 tree var, new_var;
4378 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4380 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4381 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4382 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4384 var = OMP_CLAUSE_DECL (c);
4385 new_var = lookup_decl (var, ctx);
4387 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4389 tree val = DECL_VALUE_EXPR (new_var);
4390 if (TREE_CODE (val) == ARRAY_REF
4391 && VAR_P (TREE_OPERAND (val, 0))
4392 && lookup_attribute ("omp simd array",
4393 DECL_ATTRIBUTES (TREE_OPERAND (val,
4394 0))))
4396 if (lastlane == NULL)
4398 lastlane = create_tmp_var (unsigned_type_node);
4399 gcall *g
4400 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4401 2, simduid,
4402 TREE_OPERAND (val, 1));
4403 gimple_call_set_lhs (g, lastlane);
4404 gimple_seq_add_stmt (stmt_list, g);
4406 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4407 TREE_OPERAND (val, 0), lastlane,
4408 NULL_TREE, NULL_TREE);
4412 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4413 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4415 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4416 gimple_seq_add_seq (stmt_list,
4417 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4418 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4420 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4421 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4423 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4424 gimple_seq_add_seq (stmt_list,
4425 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4426 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4429 x = build_outer_var_ref (var, ctx);
4430 if (is_reference (var))
4431 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4432 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4433 gimplify_and_add (x, stmt_list);
4435 c = OMP_CLAUSE_CHAIN (c);
4436 if (c == NULL && !par_clauses)
4438 /* If this was a workshare clause, see if it had been combined
4439 with its parallel. In that case, continue looking for the
4440 clauses also on the parallel statement itself. */
4441 if (is_parallel_ctx (ctx))
4442 break;
4444 ctx = ctx->outer;
4445 if (ctx == NULL || !is_parallel_ctx (ctx))
4446 break;
4448 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4449 OMP_CLAUSE_LASTPRIVATE);
4450 par_clauses = true;
4454 if (label)
4455 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4458 static void
4459 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4460 tree tid, tree var, tree new_var)
4462 /* The atomic add at the end of the sum creates unnecessary
4463 write contention on accelerators. To work around this,
4464 create an array to store the partial reductions. Later, in
4465 lower_omp_for (for openacc), the values of array will be
4466 combined. */
4468 tree t = NULL_TREE, array, x;
4469 tree type = get_base_type (var);
4470 gimple stmt;
4472 /* Now insert the partial reductions into the array. */
4474 /* Find the reduction array. */
4476 tree ptype = build_pointer_type (type);
4478 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4479 t = build_receiver_ref (t, false, ctx->outer);
4481 array = create_tmp_var (ptype);
4482 gimplify_assign (array, t, stmt_seqp);
4484 tree ptr = create_tmp_var (TREE_TYPE (array));
4486 /* Find the reduction array. */
4488 /* testing a unary conversion. */
4489 tree offset = create_tmp_var (sizetype);
4490 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4491 stmt_seqp);
4492 t = create_tmp_var (sizetype);
4493 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4494 stmt_seqp);
4495 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4496 gimple_seq_add_stmt (stmt_seqp, stmt);
4498 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4499 of adding sizeof(var) to the array? */
4500 ptr = create_tmp_var (ptype);
4501 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4502 offset);
4503 gimple_seq_add_stmt (stmt_seqp, stmt);
4505 /* Move the local sum to gfc$sum[i]. */
4506 x = unshare_expr (build_simple_mem_ref (ptr));
4507 stmt = gimplify_assign (x, new_var, stmt_seqp);
4510 /* Generate code to implement the REDUCTION clauses. */
4512 static void
4513 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4515 gimple_seq sub_seq = NULL;
4516 gimple stmt;
4517 tree x, c, tid = NULL_TREE;
4518 int count = 0;
4520 /* SIMD reductions are handled in lower_rec_input_clauses. */
4521 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4522 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4523 return;
4525 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4526 update in that case, otherwise use a lock. */
4527 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4528 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4530 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4532 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4533 count = -1;
4534 break;
4536 count++;
4539 if (count == 0)
4540 return;
4542 /* Initialize thread info for OpenACC. */
4543 if (is_gimple_omp_oacc (ctx->stmt))
4545 /* Get the current thread id. */
4546 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4547 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4548 gimple stmt = gimple_build_call (call, 0);
4549 gimple_call_set_lhs (stmt, tid);
4550 gimple_seq_add_stmt (stmt_seqp, stmt);
4553 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4555 tree var, ref, new_var;
4556 enum tree_code code;
4557 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4559 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4560 continue;
4562 var = OMP_CLAUSE_DECL (c);
4563 new_var = lookup_decl (var, ctx);
4564 if (is_reference (var))
4565 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4566 ref = build_outer_var_ref (var, ctx);
4567 code = OMP_CLAUSE_REDUCTION_CODE (c);
4569 /* reduction(-:var) sums up the partial results, so it acts
4570 identically to reduction(+:var). */
4571 if (code == MINUS_EXPR)
4572 code = PLUS_EXPR;
4574 if (is_gimple_omp_oacc (ctx->stmt))
4576 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4578 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4580 else if (count == 1)
4582 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4584 addr = save_expr (addr);
4585 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4586 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4587 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4588 gimplify_and_add (x, stmt_seqp);
4589 return;
4591 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4593 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4595 if (is_reference (var)
4596 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4597 TREE_TYPE (ref)))
4598 ref = build_fold_addr_expr_loc (clause_loc, ref);
4599 SET_DECL_VALUE_EXPR (placeholder, ref);
4600 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4601 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4602 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4603 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4604 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4606 else
4608 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4609 ref = build_outer_var_ref (var, ctx);
4610 gimplify_assign (ref, x, &sub_seq);
4614 if (is_gimple_omp_oacc (ctx->stmt))
4615 return;
4617 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4619 gimple_seq_add_stmt (stmt_seqp, stmt);
4621 gimple_seq_add_seq (stmt_seqp, sub_seq);
4623 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4625 gimple_seq_add_stmt (stmt_seqp, stmt);
4629 /* Generate code to implement the COPYPRIVATE clauses. */
4631 static void
4632 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4633 omp_context *ctx)
4635 tree c;
4637 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4639 tree var, new_var, ref, x;
4640 bool by_ref;
4641 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4643 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4644 continue;
4646 var = OMP_CLAUSE_DECL (c);
4647 by_ref = use_pointer_for_field (var, NULL);
4649 ref = build_sender_ref (var, ctx);
4650 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4651 if (by_ref)
4653 x = build_fold_addr_expr_loc (clause_loc, new_var);
4654 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4656 gimplify_assign (ref, x, slist);
4658 ref = build_receiver_ref (var, false, ctx);
4659 if (by_ref)
4661 ref = fold_convert_loc (clause_loc,
4662 build_pointer_type (TREE_TYPE (new_var)),
4663 ref);
4664 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4666 if (is_reference (var))
4668 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4669 ref = build_simple_mem_ref_loc (clause_loc, ref);
4670 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4672 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4673 gimplify_and_add (x, rlist);
4678 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4679 and REDUCTION from the sender (aka parent) side. */
4681 static void
4682 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4683 omp_context *ctx)
4685 tree c;
4687 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4689 tree val, ref, x, var;
4690 bool by_ref, do_in = false, do_out = false;
4691 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4693 switch (OMP_CLAUSE_CODE (c))
4695 case OMP_CLAUSE_PRIVATE:
4696 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4697 break;
4698 continue;
4699 case OMP_CLAUSE_FIRSTPRIVATE:
4700 case OMP_CLAUSE_COPYIN:
4701 case OMP_CLAUSE_LASTPRIVATE:
4702 case OMP_CLAUSE_REDUCTION:
4703 case OMP_CLAUSE__LOOPTEMP_:
4704 break;
4705 default:
4706 continue;
4709 val = OMP_CLAUSE_DECL (c);
4710 var = lookup_decl_in_outer_ctx (val, ctx);
4712 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4713 && is_global_var (var))
4714 continue;
4715 if (is_variable_sized (val))
4716 continue;
4717 by_ref = use_pointer_for_field (val, NULL);
4719 switch (OMP_CLAUSE_CODE (c))
4721 case OMP_CLAUSE_PRIVATE:
4722 case OMP_CLAUSE_FIRSTPRIVATE:
4723 case OMP_CLAUSE_COPYIN:
4724 case OMP_CLAUSE__LOOPTEMP_:
4725 do_in = true;
4726 break;
4728 case OMP_CLAUSE_LASTPRIVATE:
4729 if (by_ref || is_reference (val))
4731 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4732 continue;
4733 do_in = true;
4735 else
4737 do_out = true;
4738 if (lang_hooks.decls.omp_private_outer_ref (val))
4739 do_in = true;
4741 break;
4743 case OMP_CLAUSE_REDUCTION:
4744 do_in = true;
4745 do_out = !(by_ref || is_reference (val));
4746 break;
4748 default:
4749 gcc_unreachable ();
4752 if (do_in)
4754 ref = build_sender_ref (val, ctx);
4755 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4756 gimplify_assign (ref, x, ilist);
4757 if (is_task_ctx (ctx))
4758 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4761 if (do_out)
4763 ref = build_sender_ref (val, ctx);
4764 gimplify_assign (var, ref, olist);
4769 /* Generate code to implement SHARED from the sender (aka parent)
4770 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4771 list things that got automatically shared. */
4773 static void
4774 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4776 tree var, ovar, nvar, f, x, record_type;
4778 if (ctx->record_type == NULL)
4779 return;
4781 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4782 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4784 ovar = DECL_ABSTRACT_ORIGIN (f);
4785 nvar = maybe_lookup_decl (ovar, ctx);
4786 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4787 continue;
4789 /* If CTX is a nested parallel directive. Find the immediately
4790 enclosing parallel or workshare construct that contains a
4791 mapping for OVAR. */
4792 var = lookup_decl_in_outer_ctx (ovar, ctx);
4794 if (use_pointer_for_field (ovar, ctx))
4796 x = build_sender_ref (ovar, ctx);
4797 var = build_fold_addr_expr (var);
4798 gimplify_assign (x, var, ilist);
4800 else
4802 x = build_sender_ref (ovar, ctx);
4803 gimplify_assign (x, var, ilist);
4805 if (!TREE_READONLY (var)
4806 /* We don't need to receive a new reference to a result
4807 or parm decl. In fact we may not store to it as we will
4808 invalidate any pending RSO and generate wrong gimple
4809 during inlining. */
4810 && !((TREE_CODE (var) == RESULT_DECL
4811 || TREE_CODE (var) == PARM_DECL)
4812 && DECL_BY_REFERENCE (var)))
4814 x = build_sender_ref (ovar, ctx);
4815 gimplify_assign (var, x, olist);
4822 /* A convenience function to build an empty GIMPLE_COND with just the
4823 condition. */
4825 static gcond *
4826 gimple_build_cond_empty (tree cond)
4828 enum tree_code pred_code;
4829 tree lhs, rhs;
4831 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4832 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4836 /* Build the function calls to GOMP_parallel_start etc to actually
4837 generate the parallel operation. REGION is the parallel region
4838 being expanded. BB is the block where to insert the code. WS_ARGS
4839 will be set if this is a call to a combined parallel+workshare
4840 construct, it contains the list of additional arguments needed by
4841 the workshare construct. */
4843 static void
4844 expand_parallel_call (struct omp_region *region, basic_block bb,
4845 gomp_parallel *entry_stmt,
4846 vec<tree, va_gc> *ws_args)
4848 tree t, t1, t2, val, cond, c, clauses, flags;
4849 gimple_stmt_iterator gsi;
4850 gimple stmt;
4851 enum built_in_function start_ix;
4852 int start_ix2;
4853 location_t clause_loc;
4854 vec<tree, va_gc> *args;
4856 clauses = gimple_omp_parallel_clauses (entry_stmt);
4858 /* Determine what flavor of GOMP_parallel we will be
4859 emitting. */
4860 start_ix = BUILT_IN_GOMP_PARALLEL;
4861 if (is_combined_parallel (region))
4863 switch (region->inner->type)
4865 case GIMPLE_OMP_FOR:
4866 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4867 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4868 + (region->inner->sched_kind
4869 == OMP_CLAUSE_SCHEDULE_RUNTIME
4870 ? 3 : region->inner->sched_kind));
4871 start_ix = (enum built_in_function)start_ix2;
4872 break;
4873 case GIMPLE_OMP_SECTIONS:
4874 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4875 break;
4876 default:
4877 gcc_unreachable ();
4881 /* By default, the value of NUM_THREADS is zero (selected at run time)
4882 and there is no conditional. */
4883 cond = NULL_TREE;
4884 val = build_int_cst (unsigned_type_node, 0);
4885 flags = build_int_cst (unsigned_type_node, 0);
4887 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4888 if (c)
4889 cond = OMP_CLAUSE_IF_EXPR (c);
4891 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4892 if (c)
4894 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4895 clause_loc = OMP_CLAUSE_LOCATION (c);
4897 else
4898 clause_loc = gimple_location (entry_stmt);
4900 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4901 if (c)
4902 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4904 /* Ensure 'val' is of the correct type. */
4905 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4907 /* If we found the clause 'if (cond)', build either
4908 (cond != 0) or (cond ? val : 1u). */
4909 if (cond)
4911 cond = gimple_boolify (cond);
4913 if (integer_zerop (val))
4914 val = fold_build2_loc (clause_loc,
4915 EQ_EXPR, unsigned_type_node, cond,
4916 build_int_cst (TREE_TYPE (cond), 0));
4917 else
4919 basic_block cond_bb, then_bb, else_bb;
4920 edge e, e_then, e_else;
4921 tree tmp_then, tmp_else, tmp_join, tmp_var;
4923 tmp_var = create_tmp_var (TREE_TYPE (val));
4924 if (gimple_in_ssa_p (cfun))
4926 tmp_then = make_ssa_name (tmp_var);
4927 tmp_else = make_ssa_name (tmp_var);
4928 tmp_join = make_ssa_name (tmp_var);
4930 else
4932 tmp_then = tmp_var;
4933 tmp_else = tmp_var;
4934 tmp_join = tmp_var;
4937 e = split_block_after_labels (bb);
4938 cond_bb = e->src;
4939 bb = e->dest;
4940 remove_edge (e);
4942 then_bb = create_empty_bb (cond_bb);
4943 else_bb = create_empty_bb (then_bb);
4944 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4945 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4947 stmt = gimple_build_cond_empty (cond);
4948 gsi = gsi_start_bb (cond_bb);
4949 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4951 gsi = gsi_start_bb (then_bb);
4952 stmt = gimple_build_assign (tmp_then, val);
4953 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4955 gsi = gsi_start_bb (else_bb);
4956 stmt = gimple_build_assign
4957 (tmp_else, build_int_cst (unsigned_type_node, 1));
4958 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4960 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4961 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4962 add_bb_to_loop (then_bb, cond_bb->loop_father);
4963 add_bb_to_loop (else_bb, cond_bb->loop_father);
4964 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4965 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4967 if (gimple_in_ssa_p (cfun))
4969 gphi *phi = create_phi_node (tmp_join, bb);
4970 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4971 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4974 val = tmp_join;
4977 gsi = gsi_start_bb (bb);
4978 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4979 false, GSI_CONTINUE_LINKING);
4982 gsi = gsi_last_bb (bb);
4983 t = gimple_omp_parallel_data_arg (entry_stmt);
4984 if (t == NULL)
4985 t1 = null_pointer_node;
4986 else
4987 t1 = build_fold_addr_expr (t);
4988 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
4990 if (1
4991 && !ws_args && !cond && start_ix == BUILT_IN_GOMP_PARALLEL)
4993 tree child_fn = gimple_omp_parallel_child_fn (entry_stmt);
4994 vec_alloc (args, region->kernelize ? 3 : 1);
4995 args->quick_push (t1);
4997 if (region->kernelize)
4999 struct gimple_omp_for_iter *pfi = region->inner->orig_first_iter;
5000 location_t loc = gimple_location (entry_stmt);
5001 tree itype, type = TREE_TYPE (pfi->index);
5002 if (POINTER_TYPE_P (type))
5003 itype = signed_type_for (type);
5004 else
5005 itype = type;
5007 enum tree_code cond_code = pfi->cond;
5008 tree n1 = pfi->initial;
5009 tree n2 = pfi->final;
5010 adjust_for_condition (loc, &cond_code, &n2);
5011 tree step = get_omp_for_step_from_incr (loc, pfi->incr);
5013 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
5014 true, NULL_TREE, false,
5015 GSI_CONTINUE_LINKING);
5016 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
5017 true, NULL_TREE, false,
5018 GSI_CONTINUE_LINKING);
5020 t = fold_binary (cond_code, boolean_type_node,
5021 fold_convert (type, n1), fold_convert (type, n2));
5022 if (t == NULL_TREE || !integer_onep (t))
5024 gimple cond = gimple_build_cond (cond_code, n1, n2, NULL_TREE,
5025 NULL_TREE);
5027 gsi_insert_after (&gsi, cond, GSI_NEW_STMT);
5028 edge ef = split_block (bb, cond);
5029 ef->flags = EDGE_FALSE_VALUE;
5030 ef->probability = REG_BR_PROB_BASE / 2000 - 1;
5031 basic_block cbb = create_empty_bb (ef->src);
5032 edge et = make_edge (ef->src, cbb, EDGE_TRUE_VALUE);
5033 set_immediate_dominator (CDI_DOMINATORS, cbb, ef->src);
5034 add_bb_to_loop (cbb, bb->loop_father);
5035 et->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000
5036 - 1);
5037 make_edge (cbb, ef->dest, EDGE_TRUE_VALUE)->flags = EDGE_FALLTHRU;
5038 gsi = gsi_start_bb (cbb);
5041 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
5042 true, NULL_TREE, false,
5043 GSI_CONTINUE_LINKING);
5044 tree t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
5045 t = fold_build2 (PLUS_EXPR, itype, step, t);
5046 t = fold_build2 (PLUS_EXPR, itype, t, n2);
5047 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
5048 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
5049 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5050 fold_build1 (NEGATE_EXPR, itype, t),
5051 fold_build1 (NEGATE_EXPR, itype, step));
5052 else
5053 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
5054 t = fold_convert (itype, t);
5055 tree n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5056 GSI_CONTINUE_LINKING);
5058 args->quick_push (n);
5059 if (region->inner->req_group_size)
5060 t = fold_convert (uint32_type_node, region->inner->req_group_size);
5061 else
5063 t = build_int_cst (uint32_type_node, 64);
5064 t = fold_build2_loc (loc, MIN_EXPR, uint32_type_node,
5065 fold_convert (uint32_type_node, n), t);
5066 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5067 GSI_CONTINUE_LINKING);
5069 args->quick_push (t);
5071 DECL_ATTRIBUTES (child_fn) = tree_cons (get_identifier ("hsakernel"),
5072 NULL_TREE,
5073 DECL_ATTRIBUTES (child_fn));
5075 else
5076 DECL_ATTRIBUTES (child_fn) = tree_cons (get_identifier ("hsa"),
5077 NULL_TREE,
5078 DECL_ATTRIBUTES (child_fn));
5080 DECL_ATTRIBUTES (child_fn) = tree_cons (get_identifier ("flatten"),
5081 NULL_TREE,
5082 DECL_ATTRIBUTES (child_fn));
5084 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, child_fn, args);
5086 else
5088 vec_alloc (args, 4 + vec_safe_length (ws_args));
5089 args->quick_push (t2);
5090 args->quick_push (t1);
5091 args->quick_push (val);
5092 if (ws_args)
5093 args->splice (*ws_args);
5094 args->quick_push (flags);
5096 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
5097 builtin_decl_explicit (start_ix), args);
5100 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5101 false, GSI_CONTINUE_LINKING);
5104 /* Insert a function call whose name is FUNC_NAME with the information from
5105 ENTRY_STMT into the basic_block BB. */
5107 static void
5108 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
5109 vec <tree, va_gc> *ws_args)
5111 tree t, t1, t2;
5112 gimple_stmt_iterator gsi;
5113 vec <tree, va_gc> *args;
5115 gcc_assert (vec_safe_length (ws_args) == 2);
5116 tree func_name = (*ws_args)[0];
5117 tree grain = (*ws_args)[1];
5119 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5120 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5121 gcc_assert (count != NULL_TREE);
5122 count = OMP_CLAUSE_OPERAND (count, 0);
5124 gsi = gsi_last_bb (bb);
5125 t = gimple_omp_parallel_data_arg (entry_stmt);
5126 if (t == NULL)
5127 t1 = null_pointer_node;
5128 else
5129 t1 = build_fold_addr_expr (t);
5130 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5132 vec_alloc (args, 4);
5133 args->quick_push (t2);
5134 args->quick_push (t1);
5135 args->quick_push (count);
5136 args->quick_push (grain);
5137 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5139 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5140 GSI_CONTINUE_LINKING);
5143 /* Build the function call to GOMP_task to actually
5144 generate the task operation. BB is the block where to insert the code. */
5146 static void
5147 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5149 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5150 gimple_stmt_iterator gsi;
5151 location_t loc = gimple_location (entry_stmt);
5153 clauses = gimple_omp_task_clauses (entry_stmt);
5155 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5156 if (c)
5157 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5158 else
5159 cond = boolean_true_node;
5161 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5162 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5163 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5164 flags = build_int_cst (unsigned_type_node,
5165 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5167 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5168 if (c)
5170 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5171 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5172 build_int_cst (unsigned_type_node, 2),
5173 build_int_cst (unsigned_type_node, 0));
5174 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5176 if (depend)
5177 depend = OMP_CLAUSE_DECL (depend);
5178 else
5179 depend = build_int_cst (ptr_type_node, 0);
5181 gsi = gsi_last_bb (bb);
5182 t = gimple_omp_task_data_arg (entry_stmt);
5183 if (t == NULL)
5184 t2 = null_pointer_node;
5185 else
5186 t2 = build_fold_addr_expr_loc (loc, t);
5187 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5188 t = gimple_omp_task_copy_fn (entry_stmt);
5189 if (t == NULL)
5190 t3 = null_pointer_node;
5191 else
5192 t3 = build_fold_addr_expr_loc (loc, t);
5194 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5195 8, t1, t2, t3,
5196 gimple_omp_task_arg_size (entry_stmt),
5197 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5198 depend);
5200 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5201 false, GSI_CONTINUE_LINKING);
5205 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5206 catch handler and return it. This prevents programs from violating the
5207 structured block semantics with throws. */
5209 static gimple_seq
5210 maybe_catch_exception (gimple_seq body)
5212 gimple g;
5213 tree decl;
5215 if (!flag_exceptions)
5216 return body;
5218 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5219 decl = lang_hooks.eh_protect_cleanup_actions ();
5220 else
5221 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5223 g = gimple_build_eh_must_not_throw (decl);
5224 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5225 GIMPLE_TRY_CATCH);
5227 return gimple_seq_alloc_with_stmt (g);
5230 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5232 static tree
5233 vec2chain (vec<tree, va_gc> *v)
5235 tree chain = NULL_TREE, t;
5236 unsigned ix;
5238 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5240 DECL_CHAIN (t) = chain;
5241 chain = t;
5244 return chain;
5248 /* Remove barriers in REGION->EXIT's block. Note that this is only
5249 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5250 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5251 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5252 removed. */
5254 static void
5255 remove_exit_barrier (struct omp_region *region)
5257 gimple_stmt_iterator gsi;
5258 basic_block exit_bb;
5259 edge_iterator ei;
5260 edge e;
5261 gimple stmt;
5262 int any_addressable_vars = -1;
5264 exit_bb = region->exit;
5266 /* If the parallel region doesn't return, we don't have REGION->EXIT
5267 block at all. */
5268 if (! exit_bb)
5269 return;
5271 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5272 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5273 statements that can appear in between are extremely limited -- no
5274 memory operations at all. Here, we allow nothing at all, so the
5275 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5276 gsi = gsi_last_bb (exit_bb);
5277 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5278 gsi_prev (&gsi);
5279 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5280 return;
5282 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5284 gsi = gsi_last_bb (e->src);
5285 if (gsi_end_p (gsi))
5286 continue;
5287 stmt = gsi_stmt (gsi);
5288 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5289 && !gimple_omp_return_nowait_p (stmt))
5291 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5292 in many cases. If there could be tasks queued, the barrier
5293 might be needed to let the tasks run before some local
5294 variable of the parallel that the task uses as shared
5295 runs out of scope. The task can be spawned either
5296 from within current function (this would be easy to check)
5297 or from some function it calls and gets passed an address
5298 of such a variable. */
5299 if (any_addressable_vars < 0)
5301 gomp_parallel *parallel_stmt
5302 = as_a <gomp_parallel *> (last_stmt (region->entry));
5303 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5304 tree local_decls, block, decl;
5305 unsigned ix;
5307 any_addressable_vars = 0;
5308 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5309 if (TREE_ADDRESSABLE (decl))
5311 any_addressable_vars = 1;
5312 break;
5314 for (block = gimple_block (stmt);
5315 !any_addressable_vars
5316 && block
5317 && TREE_CODE (block) == BLOCK;
5318 block = BLOCK_SUPERCONTEXT (block))
5320 for (local_decls = BLOCK_VARS (block);
5321 local_decls;
5322 local_decls = DECL_CHAIN (local_decls))
5323 if (TREE_ADDRESSABLE (local_decls))
5325 any_addressable_vars = 1;
5326 break;
5328 if (block == gimple_block (parallel_stmt))
5329 break;
5332 if (!any_addressable_vars)
5333 gimple_omp_return_set_nowait (stmt);
5338 static void
5339 remove_exit_barriers (struct omp_region *region)
5341 if (region->type == GIMPLE_OMP_PARALLEL)
5342 remove_exit_barrier (region);
5344 if (region->inner)
5346 region = region->inner;
5347 remove_exit_barriers (region);
5348 while (region->next)
5350 region = region->next;
5351 remove_exit_barriers (region);
5356 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5357 calls. These can't be declared as const functions, but
5358 within one parallel body they are constant, so they can be
5359 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5360 which are declared const. Similarly for task body, except
5361 that in untied task omp_get_thread_num () can change at any task
5362 scheduling point. */
5364 static void
5365 optimize_omp_library_calls (gimple entry_stmt)
5367 basic_block bb;
5368 gimple_stmt_iterator gsi;
5369 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5370 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5371 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5372 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5373 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5374 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5375 OMP_CLAUSE_UNTIED) != NULL);
5377 FOR_EACH_BB_FN (bb, cfun)
5378 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5380 gimple call = gsi_stmt (gsi);
5381 tree decl;
5383 if (is_gimple_call (call)
5384 && (decl = gimple_call_fndecl (call))
5385 && DECL_EXTERNAL (decl)
5386 && TREE_PUBLIC (decl)
5387 && DECL_INITIAL (decl) == NULL)
5389 tree built_in;
5391 if (DECL_NAME (decl) == thr_num_id)
5393 /* In #pragma omp task untied omp_get_thread_num () can change
5394 during the execution of the task region. */
5395 if (untied_task)
5396 continue;
5397 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5399 else if (DECL_NAME (decl) == num_thr_id)
5400 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5401 else
5402 continue;
5404 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5405 || gimple_call_num_args (call) != 0)
5406 continue;
5408 if (flag_exceptions && !TREE_NOTHROW (decl))
5409 continue;
5411 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5412 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5413 TREE_TYPE (TREE_TYPE (built_in))))
5414 continue;
5416 gimple_call_set_fndecl (call, built_in);
5421 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5422 regimplified. */
5424 static tree
5425 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5427 tree t = *tp;
5429 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5430 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5431 return t;
5433 if (TREE_CODE (t) == ADDR_EXPR)
5434 recompute_tree_invariant_for_addr_expr (t);
5436 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5437 return NULL_TREE;
5440 /* Prepend TO = FROM assignment before *GSI_P. */
5442 static void
5443 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5445 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5446 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5447 true, GSI_SAME_STMT);
5448 gimple stmt = gimple_build_assign (to, from);
5449 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5450 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5451 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5453 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5454 gimple_regimplify_operands (stmt, &gsi);
5458 /* Expand the OpenMP parallel or task directive starting at REGION. */
5460 static void
5461 expand_omp_taskreg (struct omp_region *region)
5463 basic_block entry_bb, exit_bb, new_bb;
5464 struct function *child_cfun;
5465 tree child_fn, block, t;
5466 gimple_stmt_iterator gsi;
5467 gimple entry_stmt, stmt;
5468 edge e;
5469 vec<tree, va_gc> *ws_args;
5471 entry_stmt = last_stmt (region->entry);
5472 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5473 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5475 entry_bb = region->entry;
5476 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
5477 exit_bb = region->cont;
5478 else
5479 exit_bb = region->exit;
5481 bool is_cilk_for
5482 = (flag_cilkplus
5483 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5484 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5485 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5487 if (is_cilk_for)
5488 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5489 and the inner statement contains the name of the built-in function
5490 and grain. */
5491 ws_args = region->inner->ws_args;
5492 else if (is_combined_parallel (region))
5493 ws_args = region->ws_args;
5494 else
5495 ws_args = NULL;
5497 if (child_cfun->cfg)
5499 /* Due to inlining, it may happen that we have already outlined
5500 the region, in which case all we need to do is make the
5501 sub-graph unreachable and emit the parallel call. */
5502 edge entry_succ_e, exit_succ_e;
5504 entry_succ_e = single_succ_edge (entry_bb);
5506 gsi = gsi_last_bb (entry_bb);
5507 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5508 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5509 gsi_remove (&gsi, true);
5511 new_bb = entry_bb;
5512 if (exit_bb)
5514 exit_succ_e = single_succ_edge (exit_bb);
5515 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5517 remove_edge_and_dominated_blocks (entry_succ_e);
5519 else
5521 unsigned srcidx, dstidx, num;
5523 /* If the parallel region needs data sent from the parent
5524 function, then the very first statement (except possible
5525 tree profile counter updates) of the parallel body
5526 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5527 &.OMP_DATA_O is passed as an argument to the child function,
5528 we need to replace it with the argument as seen by the child
5529 function.
5531 In most cases, this will end up being the identity assignment
5532 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5533 a function call that has been inlined, the original PARM_DECL
5534 .OMP_DATA_I may have been converted into a different local
5535 variable. In which case, we need to keep the assignment. */
5536 if (gimple_omp_taskreg_data_arg (entry_stmt))
5538 basic_block entry_succ_bb
5539 = single_succ_p (entry_bb) ? single_succ (entry_bb)
5540 : FALLTHRU_EDGE (entry_bb)->dest;
5541 tree arg, narg;
5542 gimple parcopy_stmt = NULL;
5544 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5546 gimple stmt;
5548 gcc_assert (!gsi_end_p (gsi));
5549 stmt = gsi_stmt (gsi);
5550 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5551 continue;
5553 if (gimple_num_ops (stmt) == 2)
5555 tree arg = gimple_assign_rhs1 (stmt);
5557 /* We're ignore the subcode because we're
5558 effectively doing a STRIP_NOPS. */
5560 if (TREE_CODE (arg) == ADDR_EXPR
5561 && TREE_OPERAND (arg, 0)
5562 == gimple_omp_taskreg_data_arg (entry_stmt))
5564 parcopy_stmt = stmt;
5565 break;
5570 gcc_assert (parcopy_stmt != NULL);
5571 arg = DECL_ARGUMENTS (child_fn);
5573 if (!gimple_in_ssa_p (cfun))
5575 if (gimple_assign_lhs (parcopy_stmt) == arg)
5576 gsi_remove (&gsi, true);
5577 else
5579 /* ?? Is setting the subcode really necessary ?? */
5580 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5581 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5584 else
5586 /* If we are in ssa form, we must load the value from the default
5587 definition of the argument. That should not be defined now,
5588 since the argument is not used uninitialized. */
5589 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5590 narg = make_ssa_name (arg, gimple_build_nop ());
5591 set_ssa_default_def (cfun, arg, narg);
5592 /* ?? Is setting the subcode really necessary ?? */
5593 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5594 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5595 update_stmt (parcopy_stmt);
5599 /* Declare local variables needed in CHILD_CFUN. */
5600 block = DECL_INITIAL (child_fn);
5601 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5602 /* The gimplifier could record temporaries in parallel/task block
5603 rather than in containing function's local_decls chain,
5604 which would mean cgraph missed finalizing them. Do it now. */
5605 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5606 if (TREE_CODE (t) == VAR_DECL
5607 && TREE_STATIC (t)
5608 && !DECL_EXTERNAL (t))
5609 varpool_node::finalize_decl (t);
5610 DECL_SAVED_TREE (child_fn) = NULL;
5611 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5612 gimple_set_body (child_fn, NULL);
5613 TREE_USED (block) = 1;
5615 /* Reset DECL_CONTEXT on function arguments. */
5616 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5617 DECL_CONTEXT (t) = child_fn;
5619 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5620 so that it can be moved to the child function. */
5621 gsi = gsi_last_bb (entry_bb);
5622 stmt = gsi_stmt (gsi);
5623 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5624 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5625 e = split_block (entry_bb, stmt);
5626 gsi_remove (&gsi, true);
5627 entry_bb = e->dest;
5628 edge e2 = NULL;
5629 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5630 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5631 else
5633 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
5634 gcc_assert (e2->dest == region->exit);
5635 remove_edge (BRANCH_EDGE (entry_bb));
5636 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
5637 gsi = gsi_last_bb (region->exit);
5638 gcc_assert (!gsi_end_p (gsi)
5639 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5640 gsi_remove (&gsi, true);
5643 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
5644 if (exit_bb)
5646 gsi = gsi_last_bb (exit_bb);
5647 gcc_assert (!gsi_end_p (gsi)
5648 && (gimple_code (gsi_stmt (gsi))
5649 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
5650 stmt = gimple_build_return (NULL);
5651 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5652 gsi_remove (&gsi, true);
5655 /* Move the parallel region into CHILD_CFUN. */
5657 if (gimple_in_ssa_p (cfun))
5659 init_tree_ssa (child_cfun);
5660 init_ssa_operands (child_cfun);
5661 child_cfun->gimple_df->in_ssa_p = true;
5662 block = NULL_TREE;
5664 else
5665 block = gimple_block (entry_stmt);
5667 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5668 if (exit_bb)
5669 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5670 if (e2)
5672 basic_block dest_bb = e2->dest;
5673 if (!exit_bb)
5674 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
5675 remove_edge (e2);
5676 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
5678 /* When the OMP expansion process cannot guarantee an up-to-date
5679 loop tree arrange for the child function to fixup loops. */
5680 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5681 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5683 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5684 num = vec_safe_length (child_cfun->local_decls);
5685 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5687 t = (*child_cfun->local_decls)[srcidx];
5688 if (DECL_CONTEXT (t) == cfun->decl)
5689 continue;
5690 if (srcidx != dstidx)
5691 (*child_cfun->local_decls)[dstidx] = t;
5692 dstidx++;
5694 if (dstidx != num)
5695 vec_safe_truncate (child_cfun->local_decls, dstidx);
5697 /* Inform the callgraph about the new function. */
5698 child_cfun->curr_properties = cfun->curr_properties;
5699 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
5700 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
5701 cgraph_node *node = cgraph_node::get_create (child_fn);
5702 node->parallelized_function = 1;
5703 cgraph_node::add_new_function (child_fn, true);
5705 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5706 fixed in a following pass. */
5707 push_cfun (child_cfun);
5708 if (optimize)
5709 optimize_omp_library_calls (entry_stmt);
5710 cgraph_edge::rebuild_edges ();
5712 /* Some EH regions might become dead, see PR34608. If
5713 pass_cleanup_cfg isn't the first pass to happen with the
5714 new child, these dead EH edges might cause problems.
5715 Clean them up now. */
5716 if (flag_exceptions)
5718 basic_block bb;
5719 bool changed = false;
5721 FOR_EACH_BB_FN (bb, cfun)
5722 changed |= gimple_purge_dead_eh_edges (bb);
5723 if (changed)
5724 cleanup_tree_cfg ();
5726 if (gimple_in_ssa_p (cfun))
5727 update_ssa (TODO_update_ssa);
5728 pop_cfun ();
5731 /* Emit a library call to launch the children threads. */
5732 if (is_cilk_for)
5733 expand_cilk_for_call (new_bb,
5734 as_a <gomp_parallel *> (entry_stmt), ws_args);
5735 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5736 expand_parallel_call (region, new_bb,
5737 as_a <gomp_parallel *> (entry_stmt), ws_args);
5738 else
5739 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5740 if (gimple_in_ssa_p (cfun))
5741 update_ssa (TODO_update_ssa_only_virtuals);
5745 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5746 of the combined collapse > 1 loop constructs, generate code like:
5747 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5748 if (cond3 is <)
5749 adj = STEP3 - 1;
5750 else
5751 adj = STEP3 + 1;
5752 count3 = (adj + N32 - N31) / STEP3;
5753 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5754 if (cond2 is <)
5755 adj = STEP2 - 1;
5756 else
5757 adj = STEP2 + 1;
5758 count2 = (adj + N22 - N21) / STEP2;
5759 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5760 if (cond1 is <)
5761 adj = STEP1 - 1;
5762 else
5763 adj = STEP1 + 1;
5764 count1 = (adj + N12 - N11) / STEP1;
5765 count = count1 * count2 * count3;
5766 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5767 count = 0;
5768 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5769 of the combined loop constructs, just initialize COUNTS array
5770 from the _looptemp_ clauses. */
5772 /* NOTE: It *could* be better to moosh all of the BBs together,
5773 creating one larger BB with all the computation and the unexpected
5774 jump at the end. I.e.
5776 bool zero3, zero2, zero1, zero;
5778 zero3 = N32 c3 N31;
5779 count3 = (N32 - N31) /[cl] STEP3;
5780 zero2 = N22 c2 N21;
5781 count2 = (N22 - N21) /[cl] STEP2;
5782 zero1 = N12 c1 N11;
5783 count1 = (N12 - N11) /[cl] STEP1;
5784 zero = zero3 || zero2 || zero1;
5785 count = count1 * count2 * count3;
5786 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5788 After all, we expect the zero=false, and thus we expect to have to
5789 evaluate all of the comparison expressions, so short-circuiting
5790 oughtn't be a win. Since the condition isn't protecting a
5791 denominator, we're not concerned about divide-by-zero, so we can
5792 fully evaluate count even if a numerator turned out to be wrong.
5794 It seems like putting this all together would create much better
5795 scheduling opportunities, and less pressure on the chip's branch
5796 predictor. */
5798 static void
5799 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5800 basic_block &entry_bb, tree *counts,
5801 basic_block &zero_iter_bb, int &first_zero_iter,
5802 basic_block &l2_dom_bb)
5804 tree t, type = TREE_TYPE (fd->loop.v);
5805 edge e, ne;
5806 int i;
5808 /* Collapsed loops need work for expansion into SSA form. */
5809 gcc_assert (!gimple_in_ssa_p (cfun));
5811 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5812 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5814 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5815 isn't supposed to be handled, as the inner loop doesn't
5816 use it. */
5817 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5818 OMP_CLAUSE__LOOPTEMP_);
5819 gcc_assert (innerc);
5820 for (i = 0; i < fd->collapse; i++)
5822 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5823 OMP_CLAUSE__LOOPTEMP_);
5824 gcc_assert (innerc);
5825 if (i)
5826 counts[i] = OMP_CLAUSE_DECL (innerc);
5827 else
5828 counts[0] = NULL_TREE;
5830 return;
5833 for (i = 0; i < fd->collapse; i++)
5835 tree itype = TREE_TYPE (fd->loops[i].v);
5837 if (SSA_VAR_P (fd->loop.n2)
5838 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5839 fold_convert (itype, fd->loops[i].n1),
5840 fold_convert (itype, fd->loops[i].n2)))
5841 == NULL_TREE || !integer_onep (t)))
5843 gcond *cond_stmt;
5844 tree n1, n2;
5845 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5846 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5847 true, GSI_SAME_STMT);
5848 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5849 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5850 true, GSI_SAME_STMT);
5851 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5852 NULL_TREE, NULL_TREE);
5853 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5854 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5855 expand_omp_regimplify_p, NULL, NULL)
5856 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5857 expand_omp_regimplify_p, NULL, NULL))
5859 *gsi = gsi_for_stmt (cond_stmt);
5860 gimple_regimplify_operands (cond_stmt, gsi);
5862 e = split_block (entry_bb, cond_stmt);
5863 if (zero_iter_bb == NULL)
5865 gassign *assign_stmt;
5866 first_zero_iter = i;
5867 zero_iter_bb = create_empty_bb (entry_bb);
5868 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5869 *gsi = gsi_after_labels (zero_iter_bb);
5870 assign_stmt = gimple_build_assign (fd->loop.n2,
5871 build_zero_cst (type));
5872 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5873 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5874 entry_bb);
5876 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5877 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5878 e->flags = EDGE_TRUE_VALUE;
5879 e->probability = REG_BR_PROB_BASE - ne->probability;
5880 if (l2_dom_bb == NULL)
5881 l2_dom_bb = entry_bb;
5882 entry_bb = e->dest;
5883 *gsi = gsi_last_bb (entry_bb);
5886 if (POINTER_TYPE_P (itype))
5887 itype = signed_type_for (itype);
5888 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5889 ? -1 : 1));
5890 t = fold_build2 (PLUS_EXPR, itype,
5891 fold_convert (itype, fd->loops[i].step), t);
5892 t = fold_build2 (PLUS_EXPR, itype, t,
5893 fold_convert (itype, fd->loops[i].n2));
5894 t = fold_build2 (MINUS_EXPR, itype, t,
5895 fold_convert (itype, fd->loops[i].n1));
5896 /* ?? We could probably use CEIL_DIV_EXPR instead of
5897 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5898 generate the same code in the end because generically we
5899 don't know that the values involved must be negative for
5900 GT?? */
5901 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5902 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5903 fold_build1 (NEGATE_EXPR, itype, t),
5904 fold_build1 (NEGATE_EXPR, itype,
5905 fold_convert (itype,
5906 fd->loops[i].step)));
5907 else
5908 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5909 fold_convert (itype, fd->loops[i].step));
5910 t = fold_convert (type, t);
5911 if (TREE_CODE (t) == INTEGER_CST)
5912 counts[i] = t;
5913 else
5915 counts[i] = create_tmp_reg (type, ".count");
5916 expand_omp_build_assign (gsi, counts[i], t);
5918 if (SSA_VAR_P (fd->loop.n2))
5920 if (i == 0)
5921 t = counts[0];
5922 else
5923 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5924 expand_omp_build_assign (gsi, fd->loop.n2, t);
5930 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5931 T = V;
5932 V3 = N31 + (T % count3) * STEP3;
5933 T = T / count3;
5934 V2 = N21 + (T % count2) * STEP2;
5935 T = T / count2;
5936 V1 = N11 + T * STEP1;
5937 if this loop doesn't have an inner loop construct combined with it.
5938 If it does have an inner loop construct combined with it and the
5939 iteration count isn't known constant, store values from counts array
5940 into its _looptemp_ temporaries instead. */
5942 static void
5943 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5944 tree *counts, gimple inner_stmt, tree startvar)
5946 int i;
5947 if (gimple_omp_for_combined_p (fd->for_stmt))
5949 /* If fd->loop.n2 is constant, then no propagation of the counts
5950 is needed, they are constant. */
5951 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5952 return;
5954 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5955 ? gimple_omp_parallel_clauses (inner_stmt)
5956 : gimple_omp_for_clauses (inner_stmt);
5957 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5958 isn't supposed to be handled, as the inner loop doesn't
5959 use it. */
5960 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5961 gcc_assert (innerc);
5962 for (i = 0; i < fd->collapse; i++)
5964 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5965 OMP_CLAUSE__LOOPTEMP_);
5966 gcc_assert (innerc);
5967 if (i)
5969 tree tem = OMP_CLAUSE_DECL (innerc);
5970 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5971 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5972 false, GSI_CONTINUE_LINKING);
5973 gassign *stmt = gimple_build_assign (tem, t);
5974 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5977 return;
5980 tree type = TREE_TYPE (fd->loop.v);
5981 tree tem = create_tmp_reg (type, ".tem");
5982 gassign *stmt = gimple_build_assign (tem, startvar);
5983 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5985 for (i = fd->collapse - 1; i >= 0; i--)
5987 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5988 itype = vtype;
5989 if (POINTER_TYPE_P (vtype))
5990 itype = signed_type_for (vtype);
5991 if (i != 0)
5992 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5993 else
5994 t = tem;
5995 t = fold_convert (itype, t);
5996 t = fold_build2 (MULT_EXPR, itype, t,
5997 fold_convert (itype, fd->loops[i].step));
5998 if (POINTER_TYPE_P (vtype))
5999 t = fold_build_pointer_plus (fd->loops[i].n1, t);
6000 else
6001 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
6002 t = force_gimple_operand_gsi (gsi, t,
6003 DECL_P (fd->loops[i].v)
6004 && TREE_ADDRESSABLE (fd->loops[i].v),
6005 NULL_TREE, false,
6006 GSI_CONTINUE_LINKING);
6007 stmt = gimple_build_assign (fd->loops[i].v, t);
6008 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
6009 if (i != 0)
6011 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
6012 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
6013 false, GSI_CONTINUE_LINKING);
6014 stmt = gimple_build_assign (tem, t);
6015 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
6021 /* Helper function for expand_omp_for_*. Generate code like:
6022 L10:
6023 V3 += STEP3;
6024 if (V3 cond3 N32) goto BODY_BB; else goto L11;
6025 L11:
6026 V3 = N31;
6027 V2 += STEP2;
6028 if (V2 cond2 N22) goto BODY_BB; else goto L12;
6029 L12:
6030 V2 = N21;
6031 V1 += STEP1;
6032 goto BODY_BB; */
6034 static basic_block
6035 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
6036 basic_block body_bb)
6038 basic_block last_bb, bb, collapse_bb = NULL;
6039 int i;
6040 gimple_stmt_iterator gsi;
6041 edge e;
6042 tree t;
6043 gimple stmt;
6045 last_bb = cont_bb;
6046 for (i = fd->collapse - 1; i >= 0; i--)
6048 tree vtype = TREE_TYPE (fd->loops[i].v);
6050 bb = create_empty_bb (last_bb);
6051 add_bb_to_loop (bb, last_bb->loop_father);
6052 gsi = gsi_start_bb (bb);
6054 if (i < fd->collapse - 1)
6056 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
6057 e->probability = REG_BR_PROB_BASE / 8;
6059 t = fd->loops[i + 1].n1;
6060 t = force_gimple_operand_gsi (&gsi, t,
6061 DECL_P (fd->loops[i + 1].v)
6062 && TREE_ADDRESSABLE (fd->loops[i
6063 + 1].v),
6064 NULL_TREE, false,
6065 GSI_CONTINUE_LINKING);
6066 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
6067 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6069 else
6070 collapse_bb = bb;
6072 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
6074 if (POINTER_TYPE_P (vtype))
6075 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
6076 else
6077 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
6078 t = force_gimple_operand_gsi (&gsi, t,
6079 DECL_P (fd->loops[i].v)
6080 && TREE_ADDRESSABLE (fd->loops[i].v),
6081 NULL_TREE, false, GSI_CONTINUE_LINKING);
6082 stmt = gimple_build_assign (fd->loops[i].v, t);
6083 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6085 if (i > 0)
6087 t = fd->loops[i].n2;
6088 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6089 false, GSI_CONTINUE_LINKING);
6090 tree v = fd->loops[i].v;
6091 if (DECL_P (v) && TREE_ADDRESSABLE (v))
6092 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
6093 false, GSI_CONTINUE_LINKING);
6094 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
6095 stmt = gimple_build_cond_empty (t);
6096 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6097 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
6098 e->probability = REG_BR_PROB_BASE * 7 / 8;
6100 else
6101 make_edge (bb, body_bb, EDGE_FALLTHRU);
6102 last_bb = bb;
6105 return collapse_bb;
6109 /* A subroutine of expand_omp_for. Generate code for a parallel
6110 loop with any schedule. Given parameters:
6112 for (V = N1; V cond N2; V += STEP) BODY;
6114 where COND is "<" or ">", we generate pseudocode
6116 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
6117 if (more) goto L0; else goto L3;
6119 V = istart0;
6120 iend = iend0;
6122 BODY;
6123 V += STEP;
6124 if (V cond iend) goto L1; else goto L2;
6126 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6129 If this is a combined omp parallel loop, instead of the call to
6130 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6131 If this is gimple_omp_for_combined_p loop, then instead of assigning
6132 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6133 inner GIMPLE_OMP_FOR and V += STEP; and
6134 if (V cond iend) goto L1; else goto L2; are removed.
6136 For collapsed loops, given parameters:
6137 collapse(3)
6138 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6139 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6140 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6141 BODY;
6143 we generate pseudocode
6145 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6146 if (cond3 is <)
6147 adj = STEP3 - 1;
6148 else
6149 adj = STEP3 + 1;
6150 count3 = (adj + N32 - N31) / STEP3;
6151 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6152 if (cond2 is <)
6153 adj = STEP2 - 1;
6154 else
6155 adj = STEP2 + 1;
6156 count2 = (adj + N22 - N21) / STEP2;
6157 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6158 if (cond1 is <)
6159 adj = STEP1 - 1;
6160 else
6161 adj = STEP1 + 1;
6162 count1 = (adj + N12 - N11) / STEP1;
6163 count = count1 * count2 * count3;
6164 goto Z1;
6166 count = 0;
6168 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6169 if (more) goto L0; else goto L3;
6171 V = istart0;
6172 T = V;
6173 V3 = N31 + (T % count3) * STEP3;
6174 T = T / count3;
6175 V2 = N21 + (T % count2) * STEP2;
6176 T = T / count2;
6177 V1 = N11 + T * STEP1;
6178 iend = iend0;
6180 BODY;
6181 V += 1;
6182 if (V < iend) goto L10; else goto L2;
6183 L10:
6184 V3 += STEP3;
6185 if (V3 cond3 N32) goto L1; else goto L11;
6186 L11:
6187 V3 = N31;
6188 V2 += STEP2;
6189 if (V2 cond2 N22) goto L1; else goto L12;
6190 L12:
6191 V2 = N21;
6192 V1 += STEP1;
6193 goto L1;
6195 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6200 static void
6201 expand_omp_for_generic (struct omp_region *region,
6202 struct omp_for_data *fd,
6203 enum built_in_function start_fn,
6204 enum built_in_function next_fn,
6205 gimple inner_stmt)
6207 tree type, istart0, iend0, iend;
6208 tree t, vmain, vback, bias = NULL_TREE;
6209 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6210 basic_block l2_bb = NULL, l3_bb = NULL;
6211 gimple_stmt_iterator gsi;
6212 gassign *assign_stmt;
6213 bool in_combined_parallel = is_combined_parallel (region);
6214 bool broken_loop = region->cont == NULL;
6215 edge e, ne;
6216 tree *counts = NULL;
6217 int i;
6219 gcc_assert (!broken_loop || !in_combined_parallel);
6220 gcc_assert (fd->iter_type == long_integer_type_node
6221 || !in_combined_parallel);
6223 type = TREE_TYPE (fd->loop.v);
6224 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6225 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6226 TREE_ADDRESSABLE (istart0) = 1;
6227 TREE_ADDRESSABLE (iend0) = 1;
6229 /* See if we need to bias by LLONG_MIN. */
6230 if (fd->iter_type == long_long_unsigned_type_node
6231 && TREE_CODE (type) == INTEGER_TYPE
6232 && !TYPE_UNSIGNED (type))
6234 tree n1, n2;
6236 if (fd->loop.cond_code == LT_EXPR)
6238 n1 = fd->loop.n1;
6239 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6241 else
6243 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6244 n2 = fd->loop.n1;
6246 if (TREE_CODE (n1) != INTEGER_CST
6247 || TREE_CODE (n2) != INTEGER_CST
6248 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6249 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6252 entry_bb = region->entry;
6253 cont_bb = region->cont;
6254 collapse_bb = NULL;
6255 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6256 gcc_assert (broken_loop
6257 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6258 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6259 l1_bb = single_succ (l0_bb);
6260 if (!broken_loop)
6262 l2_bb = create_empty_bb (cont_bb);
6263 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6264 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6266 else
6267 l2_bb = NULL;
6268 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6269 exit_bb = region->exit;
6271 gsi = gsi_last_bb (entry_bb);
6273 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6274 if (fd->collapse > 1)
6276 int first_zero_iter = -1;
6277 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6279 counts = XALLOCAVEC (tree, fd->collapse);
6280 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6281 zero_iter_bb, first_zero_iter,
6282 l2_dom_bb);
6284 if (zero_iter_bb)
6286 /* Some counts[i] vars might be uninitialized if
6287 some loop has zero iterations. But the body shouldn't
6288 be executed in that case, so just avoid uninit warnings. */
6289 for (i = first_zero_iter; i < fd->collapse; i++)
6290 if (SSA_VAR_P (counts[i]))
6291 TREE_NO_WARNING (counts[i]) = 1;
6292 gsi_prev (&gsi);
6293 e = split_block (entry_bb, gsi_stmt (gsi));
6294 entry_bb = e->dest;
6295 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6296 gsi = gsi_last_bb (entry_bb);
6297 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6298 get_immediate_dominator (CDI_DOMINATORS,
6299 zero_iter_bb));
6302 if (in_combined_parallel)
6304 /* In a combined parallel loop, emit a call to
6305 GOMP_loop_foo_next. */
6306 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6307 build_fold_addr_expr (istart0),
6308 build_fold_addr_expr (iend0));
6310 else
6312 tree t0, t1, t2, t3, t4;
6313 /* If this is not a combined parallel loop, emit a call to
6314 GOMP_loop_foo_start in ENTRY_BB. */
6315 t4 = build_fold_addr_expr (iend0);
6316 t3 = build_fold_addr_expr (istart0);
6317 t2 = fold_convert (fd->iter_type, fd->loop.step);
6318 t1 = fd->loop.n2;
6319 t0 = fd->loop.n1;
6320 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6322 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6323 OMP_CLAUSE__LOOPTEMP_);
6324 gcc_assert (innerc);
6325 t0 = OMP_CLAUSE_DECL (innerc);
6326 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6327 OMP_CLAUSE__LOOPTEMP_);
6328 gcc_assert (innerc);
6329 t1 = OMP_CLAUSE_DECL (innerc);
6331 if (POINTER_TYPE_P (TREE_TYPE (t0))
6332 && TYPE_PRECISION (TREE_TYPE (t0))
6333 != TYPE_PRECISION (fd->iter_type))
6335 /* Avoid casting pointers to integer of a different size. */
6336 tree itype = signed_type_for (type);
6337 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6338 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6340 else
6342 t1 = fold_convert (fd->iter_type, t1);
6343 t0 = fold_convert (fd->iter_type, t0);
6345 if (bias)
6347 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6348 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6350 if (fd->iter_type == long_integer_type_node)
6352 if (fd->chunk_size)
6354 t = fold_convert (fd->iter_type, fd->chunk_size);
6355 t = build_call_expr (builtin_decl_explicit (start_fn),
6356 6, t0, t1, t2, t, t3, t4);
6358 else
6359 t = build_call_expr (builtin_decl_explicit (start_fn),
6360 5, t0, t1, t2, t3, t4);
6362 else
6364 tree t5;
6365 tree c_bool_type;
6366 tree bfn_decl;
6368 /* The GOMP_loop_ull_*start functions have additional boolean
6369 argument, true for < loops and false for > loops.
6370 In Fortran, the C bool type can be different from
6371 boolean_type_node. */
6372 bfn_decl = builtin_decl_explicit (start_fn);
6373 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6374 t5 = build_int_cst (c_bool_type,
6375 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6376 if (fd->chunk_size)
6378 tree bfn_decl = builtin_decl_explicit (start_fn);
6379 t = fold_convert (fd->iter_type, fd->chunk_size);
6380 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6382 else
6383 t = build_call_expr (builtin_decl_explicit (start_fn),
6384 6, t5, t0, t1, t2, t3, t4);
6387 if (TREE_TYPE (t) != boolean_type_node)
6388 t = fold_build2 (NE_EXPR, boolean_type_node,
6389 t, build_int_cst (TREE_TYPE (t), 0));
6390 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6391 true, GSI_SAME_STMT);
6392 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6394 /* Remove the GIMPLE_OMP_FOR statement. */
6395 gsi_remove (&gsi, true);
6397 /* Iteration setup for sequential loop goes in L0_BB. */
6398 tree startvar = fd->loop.v;
6399 tree endvar = NULL_TREE;
6401 if (gimple_omp_for_combined_p (fd->for_stmt))
6403 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6404 && gimple_omp_for_kind (inner_stmt)
6405 == GF_OMP_FOR_KIND_SIMD);
6406 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6407 OMP_CLAUSE__LOOPTEMP_);
6408 gcc_assert (innerc);
6409 startvar = OMP_CLAUSE_DECL (innerc);
6410 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6411 OMP_CLAUSE__LOOPTEMP_);
6412 gcc_assert (innerc);
6413 endvar = OMP_CLAUSE_DECL (innerc);
6416 gsi = gsi_start_bb (l0_bb);
6417 t = istart0;
6418 if (bias)
6419 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6420 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6421 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6422 t = fold_convert (TREE_TYPE (startvar), t);
6423 t = force_gimple_operand_gsi (&gsi, t,
6424 DECL_P (startvar)
6425 && TREE_ADDRESSABLE (startvar),
6426 NULL_TREE, false, GSI_CONTINUE_LINKING);
6427 assign_stmt = gimple_build_assign (startvar, t);
6428 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6430 t = iend0;
6431 if (bias)
6432 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6433 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6434 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6435 t = fold_convert (TREE_TYPE (startvar), t);
6436 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6437 false, GSI_CONTINUE_LINKING);
6438 if (endvar)
6440 assign_stmt = gimple_build_assign (endvar, iend);
6441 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6442 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6443 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6444 else
6445 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6446 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6448 if (fd->collapse > 1)
6449 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6451 if (!broken_loop)
6453 /* Code to control the increment and predicate for the sequential
6454 loop goes in the CONT_BB. */
6455 gsi = gsi_last_bb (cont_bb);
6456 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6457 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6458 vmain = gimple_omp_continue_control_use (cont_stmt);
6459 vback = gimple_omp_continue_control_def (cont_stmt);
6461 if (!gimple_omp_for_combined_p (fd->for_stmt))
6463 if (POINTER_TYPE_P (type))
6464 t = fold_build_pointer_plus (vmain, fd->loop.step);
6465 else
6466 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6467 t = force_gimple_operand_gsi (&gsi, t,
6468 DECL_P (vback)
6469 && TREE_ADDRESSABLE (vback),
6470 NULL_TREE, true, GSI_SAME_STMT);
6471 assign_stmt = gimple_build_assign (vback, t);
6472 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6474 t = build2 (fd->loop.cond_code, boolean_type_node,
6475 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6476 iend);
6477 gcond *cond_stmt = gimple_build_cond_empty (t);
6478 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6481 /* Remove GIMPLE_OMP_CONTINUE. */
6482 gsi_remove (&gsi, true);
6484 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6485 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6487 /* Emit code to get the next parallel iteration in L2_BB. */
6488 gsi = gsi_start_bb (l2_bb);
6490 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6491 build_fold_addr_expr (istart0),
6492 build_fold_addr_expr (iend0));
6493 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6494 false, GSI_CONTINUE_LINKING);
6495 if (TREE_TYPE (t) != boolean_type_node)
6496 t = fold_build2 (NE_EXPR, boolean_type_node,
6497 t, build_int_cst (TREE_TYPE (t), 0));
6498 gcond *cond_stmt = gimple_build_cond_empty (t);
6499 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6502 /* Add the loop cleanup function. */
6503 gsi = gsi_last_bb (exit_bb);
6504 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6505 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6506 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6507 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6508 else
6509 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6510 gcall *call_stmt = gimple_build_call (t, 0);
6511 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6512 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6513 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6514 gsi_remove (&gsi, true);
6516 /* Connect the new blocks. */
6517 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6518 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6520 if (!broken_loop)
6522 gimple_seq phis;
6524 e = find_edge (cont_bb, l3_bb);
6525 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6527 phis = phi_nodes (l3_bb);
6528 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6530 gimple phi = gsi_stmt (gsi);
6531 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6532 PHI_ARG_DEF_FROM_EDGE (phi, e));
6534 remove_edge (e);
6536 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6537 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6538 e = find_edge (cont_bb, l1_bb);
6539 if (gimple_omp_for_combined_p (fd->for_stmt))
6541 remove_edge (e);
6542 e = NULL;
6544 else if (fd->collapse > 1)
6546 remove_edge (e);
6547 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6549 else
6550 e->flags = EDGE_TRUE_VALUE;
6551 if (e)
6553 e->probability = REG_BR_PROB_BASE * 7 / 8;
6554 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6556 else
6558 e = find_edge (cont_bb, l2_bb);
6559 e->flags = EDGE_FALLTHRU;
6561 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6563 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6564 recompute_dominator (CDI_DOMINATORS, l2_bb));
6565 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6566 recompute_dominator (CDI_DOMINATORS, l3_bb));
6567 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6568 recompute_dominator (CDI_DOMINATORS, l0_bb));
6569 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6570 recompute_dominator (CDI_DOMINATORS, l1_bb));
6572 struct loop *outer_loop = alloc_loop ();
6573 outer_loop->header = l0_bb;
6574 outer_loop->latch = l2_bb;
6575 add_loop (outer_loop, l0_bb->loop_father);
6577 if (!gimple_omp_for_combined_p (fd->for_stmt))
6579 struct loop *loop = alloc_loop ();
6580 loop->header = l1_bb;
6581 /* The loop may have multiple latches. */
6582 add_loop (loop, outer_loop);
6588 /* A subroutine of expand_omp_for. Generate code for a parallel
6589 loop with static schedule and no specified chunk size. Given
6590 parameters:
6592 for (V = N1; V cond N2; V += STEP) BODY;
6594 where COND is "<" or ">", we generate pseudocode
6596 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6597 if (cond is <)
6598 adj = STEP - 1;
6599 else
6600 adj = STEP + 1;
6601 if ((__typeof (V)) -1 > 0 && cond is >)
6602 n = -(adj + N2 - N1) / -STEP;
6603 else
6604 n = (adj + N2 - N1) / STEP;
6605 q = n / nthreads;
6606 tt = n % nthreads;
6607 if (threadid < tt) goto L3; else goto L4;
6609 tt = 0;
6610 q = q + 1;
6612 s0 = q * threadid + tt;
6613 e0 = s0 + q;
6614 V = s0 * STEP + N1;
6615 if (s0 >= e0) goto L2; else goto L0;
6617 e = e0 * STEP + N1;
6619 BODY;
6620 V += STEP;
6621 if (V cond e) goto L1;
6625 static void
6626 expand_omp_for_static_nochunk (struct omp_region *region,
6627 struct omp_for_data *fd,
6628 gimple inner_stmt)
6630 tree n, q, s0 = NULL, e0 = NULL, e = NULL, t, tt, nthreads = NULL, threadid;
6631 tree type, itype, vmain, vback;
6632 basic_block entry_bb, second_bb = NULL, third_bb = NULL, exit_bb, seq_start_bb;
6633 basic_block body_bb, cont_bb, collapse_bb = NULL;
6634 basic_block fin_bb;
6635 gimple_stmt_iterator gsi;
6636 edge ep;
6637 bool broken_loop = region->cont == NULL;
6638 tree *counts = NULL;
6639 tree n1, n2, step;
6641 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6642 != GF_OMP_FOR_KIND_OACC_LOOP)
6643 || !inner_stmt);
6645 itype = type = TREE_TYPE (fd->loop.v);
6646 if (POINTER_TYPE_P (type))
6647 itype = signed_type_for (type);
6649 entry_bb = region->entry;
6650 cont_bb = region->cont;
6651 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6652 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6653 gcc_assert (broken_loop
6654 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6655 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6656 body_bb = single_succ (seq_start_bb);
6657 if (!broken_loop)
6659 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6660 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6662 exit_bb = region->exit;
6664 /* Iteration space partitioning goes in ENTRY_BB. */
6665 gsi = gsi_last_bb (entry_bb);
6666 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6668 if (fd->collapse > 1)
6670 int first_zero_iter = -1;
6671 basic_block l2_dom_bb = NULL;
6673 counts = XALLOCAVEC (tree, fd->collapse);
6674 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6675 fin_bb, first_zero_iter,
6676 l2_dom_bb);
6677 t = NULL_TREE;
6679 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6680 t = integer_one_node;
6681 else
6682 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6683 fold_convert (type, fd->loop.n1),
6684 fold_convert (type, fd->loop.n2));
6685 if (fd->collapse == 1
6686 && TYPE_UNSIGNED (type)
6687 && (t == NULL_TREE || !integer_onep (t)))
6689 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6690 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6691 true, GSI_SAME_STMT);
6692 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6693 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6694 true, GSI_SAME_STMT);
6695 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6696 NULL_TREE, NULL_TREE);
6697 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6698 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6699 expand_omp_regimplify_p, NULL, NULL)
6700 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6701 expand_omp_regimplify_p, NULL, NULL))
6703 gsi = gsi_for_stmt (cond_stmt);
6704 gimple_regimplify_operands (cond_stmt, &gsi);
6706 ep = split_block (entry_bb, cond_stmt);
6707 ep->flags = EDGE_TRUE_VALUE;
6708 entry_bb = ep->dest;
6709 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6710 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6711 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6712 if (gimple_in_ssa_p (cfun))
6714 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6715 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6716 !gsi_end_p (gpi); gsi_next (&gpi))
6718 gphi *phi = gpi.phi ();
6719 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6720 ep, UNKNOWN_LOCATION);
6723 gsi = gsi_last_bb (entry_bb);
6726 switch (gimple_omp_for_kind (fd->for_stmt))
6728 case GF_OMP_FOR_KIND_FOR:
6729 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6730 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6731 break;
6732 case GF_OMP_FOR_KIND_DISTRIBUTE:
6733 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6734 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6735 break;
6736 case GF_OMP_FOR_KIND_OACC_LOOP:
6737 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6738 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6739 break;
6740 default:
6741 gcc_unreachable ();
6743 if (!region->kernelize)
6745 nthreads = build_call_expr (nthreads, 0);
6746 nthreads = fold_convert (itype, nthreads);
6747 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6748 true, GSI_SAME_STMT);
6750 threadid = build_call_expr (threadid, 0);
6751 threadid = fold_convert (itype, threadid);
6752 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6753 true, GSI_SAME_STMT);
6755 n1 = fd->loop.n1;
6756 n2 = fd->loop.n2;
6757 step = fd->loop.step;
6758 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6760 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6761 OMP_CLAUSE__LOOPTEMP_);
6762 gcc_assert (innerc);
6763 n1 = OMP_CLAUSE_DECL (innerc);
6764 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6765 OMP_CLAUSE__LOOPTEMP_);
6766 gcc_assert (innerc);
6767 n2 = OMP_CLAUSE_DECL (innerc);
6769 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6770 true, NULL_TREE, true, GSI_SAME_STMT);
6771 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6772 true, NULL_TREE, true, GSI_SAME_STMT);
6773 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6774 true, NULL_TREE, true, GSI_SAME_STMT);
6776 if (!region->kernelize)
6778 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6779 t = fold_build2 (PLUS_EXPR, itype, step, t);
6780 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6781 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6782 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6783 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6784 fold_build1 (NEGATE_EXPR, itype, t),
6785 fold_build1 (NEGATE_EXPR, itype, step));
6786 else
6787 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6788 t = fold_convert (itype, t);
6789 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true,
6790 GSI_SAME_STMT);
6792 q = create_tmp_reg (itype, "q");
6793 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6794 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true,
6795 GSI_SAME_STMT);
6796 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6798 tt = create_tmp_reg (itype, "tt");
6799 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6800 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true,
6801 GSI_SAME_STMT);
6802 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6804 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6805 gcond *cond_stmt = gimple_build_cond_empty (t);
6806 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6808 second_bb = split_block (entry_bb, cond_stmt)->dest;
6809 gsi = gsi_last_bb (second_bb);
6810 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6812 gsi_insert_before (&gsi, gimple_build_assign (tt,
6813 build_int_cst (itype, 0)),
6814 GSI_SAME_STMT);
6815 gassign *assign_stmt
6816 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6817 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6819 third_bb = split_block (second_bb, assign_stmt)->dest;
6820 gsi = gsi_last_bb (third_bb);
6821 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6823 t = build2 (MULT_EXPR, itype, q, threadid);
6824 t = build2 (PLUS_EXPR, itype, t, tt);
6825 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true,
6826 GSI_SAME_STMT);
6828 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6829 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true,
6830 GSI_SAME_STMT);
6832 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6833 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6836 /* Remove the GIMPLE_OMP_FOR statement. */
6837 gsi_remove (&gsi, true);
6839 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6840 gsi = gsi_start_bb (seq_start_bb);
6842 tree startvar = fd->loop.v;
6843 tree endvar = NULL_TREE;
6845 if (gimple_omp_for_combined_p (fd->for_stmt))
6847 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6848 ? gimple_omp_parallel_clauses (inner_stmt)
6849 : gimple_omp_for_clauses (inner_stmt);
6850 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6851 gcc_assert (innerc);
6852 startvar = OMP_CLAUSE_DECL (innerc);
6853 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6854 OMP_CLAUSE__LOOPTEMP_);
6855 gcc_assert (innerc);
6856 endvar = OMP_CLAUSE_DECL (innerc);
6858 t = fold_convert (itype, region->kernelize ? threadid : s0);
6859 t = fold_build2 (MULT_EXPR, itype, t, step);
6860 if (POINTER_TYPE_P (type))
6861 t = fold_build_pointer_plus (n1, t);
6862 else
6863 t = fold_build2 (PLUS_EXPR, type, t, n1);
6864 t = fold_convert (TREE_TYPE (startvar), t);
6865 t = force_gimple_operand_gsi (&gsi, t,
6866 DECL_P (startvar)
6867 && TREE_ADDRESSABLE (startvar),
6868 NULL_TREE, false, GSI_CONTINUE_LINKING);
6869 gassign *assign_stmt = gimple_build_assign (startvar, t);
6870 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6872 if (!region->kernelize)
6874 t = fold_convert (itype, e0);
6875 t = fold_build2 (MULT_EXPR, itype, t, step);
6876 if (POINTER_TYPE_P (type))
6877 t = fold_build_pointer_plus (n1, t);
6878 else
6879 t = fold_build2 (PLUS_EXPR, type, t, n1);
6880 t = fold_convert (TREE_TYPE (startvar), t);
6881 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6882 false, GSI_CONTINUE_LINKING);
6883 if (endvar)
6885 assign_stmt = gimple_build_assign (endvar, e);
6886 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6887 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6888 assign_stmt = gimple_build_assign (fd->loop.v, e);
6889 else
6890 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6891 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6894 if (fd->collapse > 1)
6895 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6897 if (!broken_loop)
6899 /* The code controlling the sequential loop replaces the
6900 GIMPLE_OMP_CONTINUE. */
6901 gsi = gsi_last_bb (cont_bb);
6902 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6903 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6905 if (!region->kernelize)
6907 vmain = gimple_omp_continue_control_use (cont_stmt);
6908 vback = gimple_omp_continue_control_def (cont_stmt);
6910 if (!gimple_omp_for_combined_p (fd->for_stmt))
6912 if (POINTER_TYPE_P (type))
6913 t = fold_build_pointer_plus (vmain, step);
6914 else
6915 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6916 t = force_gimple_operand_gsi (&gsi, t,
6917 DECL_P (vback)
6918 && TREE_ADDRESSABLE (vback),
6919 NULL_TREE, true, GSI_SAME_STMT);
6920 assign_stmt = gimple_build_assign (vback, t);
6921 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6923 t = build2 (fd->loop.cond_code, boolean_type_node,
6924 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6925 ? t : vback, e);
6926 gsi_insert_before (&gsi, gimple_build_cond_empty (t),
6927 GSI_SAME_STMT);
6930 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6931 gsi_remove (&gsi, true);
6933 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6934 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6937 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6938 gsi = gsi_last_bb (exit_bb);
6939 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6941 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6942 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6943 gcc_checking_assert (t == NULL_TREE);
6944 else
6945 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6947 gsi_remove (&gsi, true);
6949 /* Connect all the blocks. */
6950 if (!region->kernelize)
6952 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6953 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6954 ep = find_edge (entry_bb, second_bb);
6955 ep->flags = EDGE_TRUE_VALUE;
6956 ep->probability = REG_BR_PROB_BASE / 4;
6957 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6958 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6960 else
6962 remove_edge (find_edge (entry_bb, fin_bb));
6963 find_edge (entry_bb, seq_start_bb)->flags = EDGE_FALLTHRU;
6966 if (!broken_loop)
6968 ep = find_edge (cont_bb, body_bb);
6969 if (gimple_omp_for_combined_p (fd->for_stmt)
6970 || region->kernelize)
6972 remove_edge (ep);
6973 ep = NULL;
6975 else if (fd->collapse > 1)
6977 remove_edge (ep);
6978 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6980 else
6981 ep->flags = EDGE_TRUE_VALUE;
6982 find_edge (cont_bb, fin_bb)->flags
6983 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6986 if (!region->kernelize)
6988 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6989 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6990 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6992 else
6993 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, entry_bb);
6995 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6996 recompute_dominator (CDI_DOMINATORS, body_bb));
6997 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6998 recompute_dominator (CDI_DOMINATORS, fin_bb));
7000 if (!broken_loop
7001 && !region->kernelize
7002 && !gimple_omp_for_combined_p (fd->for_stmt))
7004 struct loop *loop = alloc_loop ();
7005 loop->header = body_bb;
7006 if (collapse_bb == NULL)
7007 loop->latch = cont_bb;
7008 add_loop (loop, body_bb->loop_father);
7013 /* A subroutine of expand_omp_for. Generate code for a parallel
7014 loop with static schedule and a specified chunk size. Given
7015 parameters:
7017 for (V = N1; V cond N2; V += STEP) BODY;
7019 where COND is "<" or ">", we generate pseudocode
7021 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
7022 if (cond is <)
7023 adj = STEP - 1;
7024 else
7025 adj = STEP + 1;
7026 if ((__typeof (V)) -1 > 0 && cond is >)
7027 n = -(adj + N2 - N1) / -STEP;
7028 else
7029 n = (adj + N2 - N1) / STEP;
7030 trip = 0;
7031 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
7032 here so that V is defined
7033 if the loop is not entered
7035 s0 = (trip * nthreads + threadid) * CHUNK;
7036 e0 = min(s0 + CHUNK, n);
7037 if (s0 < n) goto L1; else goto L4;
7039 V = s0 * STEP + N1;
7040 e = e0 * STEP + N1;
7042 BODY;
7043 V += STEP;
7044 if (V cond e) goto L2; else goto L3;
7046 trip += 1;
7047 goto L0;
7051 static void
7052 expand_omp_for_static_chunk (struct omp_region *region,
7053 struct omp_for_data *fd, gimple inner_stmt)
7055 tree n, s0, e0, e, t;
7056 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
7057 tree type, itype, vmain, vback, vextra;
7058 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
7059 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
7060 gimple_stmt_iterator gsi;
7061 edge se;
7062 bool broken_loop = region->cont == NULL;
7063 tree *counts = NULL;
7064 tree n1, n2, step;
7066 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
7067 != GF_OMP_FOR_KIND_OACC_LOOP)
7068 || !inner_stmt);
7070 itype = type = TREE_TYPE (fd->loop.v);
7071 if (POINTER_TYPE_P (type))
7072 itype = signed_type_for (type);
7074 entry_bb = region->entry;
7075 se = split_block (entry_bb, last_stmt (entry_bb));
7076 entry_bb = se->src;
7077 iter_part_bb = se->dest;
7078 cont_bb = region->cont;
7079 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
7080 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
7081 gcc_assert (broken_loop
7082 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
7083 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
7084 body_bb = single_succ (seq_start_bb);
7085 if (!broken_loop)
7087 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
7088 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7089 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
7091 exit_bb = region->exit;
7093 /* Trip and adjustment setup goes in ENTRY_BB. */
7094 gsi = gsi_last_bb (entry_bb);
7095 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7097 if (fd->collapse > 1)
7099 int first_zero_iter = -1;
7100 basic_block l2_dom_bb = NULL;
7102 counts = XALLOCAVEC (tree, fd->collapse);
7103 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7104 fin_bb, first_zero_iter,
7105 l2_dom_bb);
7106 t = NULL_TREE;
7108 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
7109 t = integer_one_node;
7110 else
7111 t = fold_binary (fd->loop.cond_code, boolean_type_node,
7112 fold_convert (type, fd->loop.n1),
7113 fold_convert (type, fd->loop.n2));
7114 if (fd->collapse == 1
7115 && TYPE_UNSIGNED (type)
7116 && (t == NULL_TREE || !integer_onep (t)))
7118 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
7119 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
7120 true, GSI_SAME_STMT);
7121 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
7122 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
7123 true, GSI_SAME_STMT);
7124 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
7125 NULL_TREE, NULL_TREE);
7126 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
7127 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7128 expand_omp_regimplify_p, NULL, NULL)
7129 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7130 expand_omp_regimplify_p, NULL, NULL))
7132 gsi = gsi_for_stmt (cond_stmt);
7133 gimple_regimplify_operands (cond_stmt, &gsi);
7135 se = split_block (entry_bb, cond_stmt);
7136 se->flags = EDGE_TRUE_VALUE;
7137 entry_bb = se->dest;
7138 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
7139 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
7140 se->probability = REG_BR_PROB_BASE / 2000 - 1;
7141 if (gimple_in_ssa_p (cfun))
7143 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
7144 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
7145 !gsi_end_p (gpi); gsi_next (&gpi))
7147 gphi *phi = gpi.phi ();
7148 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
7149 se, UNKNOWN_LOCATION);
7152 gsi = gsi_last_bb (entry_bb);
7155 switch (gimple_omp_for_kind (fd->for_stmt))
7157 case GF_OMP_FOR_KIND_FOR:
7158 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7159 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7160 break;
7161 case GF_OMP_FOR_KIND_DISTRIBUTE:
7162 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7163 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7164 break;
7165 case GF_OMP_FOR_KIND_OACC_LOOP:
7166 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7167 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7168 break;
7169 default:
7170 gcc_unreachable ();
7172 nthreads = build_call_expr (nthreads, 0);
7173 nthreads = fold_convert (itype, nthreads);
7174 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7175 true, GSI_SAME_STMT);
7176 threadid = build_call_expr (threadid, 0);
7177 threadid = fold_convert (itype, threadid);
7178 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7179 true, GSI_SAME_STMT);
7181 n1 = fd->loop.n1;
7182 n2 = fd->loop.n2;
7183 step = fd->loop.step;
7184 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7186 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7187 OMP_CLAUSE__LOOPTEMP_);
7188 gcc_assert (innerc);
7189 n1 = OMP_CLAUSE_DECL (innerc);
7190 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7191 OMP_CLAUSE__LOOPTEMP_);
7192 gcc_assert (innerc);
7193 n2 = OMP_CLAUSE_DECL (innerc);
7195 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7196 true, NULL_TREE, true, GSI_SAME_STMT);
7197 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7198 true, NULL_TREE, true, GSI_SAME_STMT);
7199 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7200 true, NULL_TREE, true, GSI_SAME_STMT);
7201 fd->chunk_size
7202 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7203 true, NULL_TREE, true, GSI_SAME_STMT);
7205 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7206 t = fold_build2 (PLUS_EXPR, itype, step, t);
7207 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7208 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7209 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7210 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7211 fold_build1 (NEGATE_EXPR, itype, t),
7212 fold_build1 (NEGATE_EXPR, itype, step));
7213 else
7214 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7215 t = fold_convert (itype, t);
7216 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7217 true, GSI_SAME_STMT);
7219 trip_var = create_tmp_reg (itype, ".trip");
7220 if (gimple_in_ssa_p (cfun))
7222 trip_init = make_ssa_name (trip_var);
7223 trip_main = make_ssa_name (trip_var);
7224 trip_back = make_ssa_name (trip_var);
7226 else
7228 trip_init = trip_var;
7229 trip_main = trip_var;
7230 trip_back = trip_var;
7233 gassign *assign_stmt
7234 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7235 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7237 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7238 t = fold_build2 (MULT_EXPR, itype, t, step);
7239 if (POINTER_TYPE_P (type))
7240 t = fold_build_pointer_plus (n1, t);
7241 else
7242 t = fold_build2 (PLUS_EXPR, type, t, n1);
7243 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7244 true, GSI_SAME_STMT);
7246 /* Remove the GIMPLE_OMP_FOR. */
7247 gsi_remove (&gsi, true);
7249 /* Iteration space partitioning goes in ITER_PART_BB. */
7250 gsi = gsi_last_bb (iter_part_bb);
7252 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7253 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7254 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7255 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7256 false, GSI_CONTINUE_LINKING);
7258 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7259 t = fold_build2 (MIN_EXPR, itype, t, n);
7260 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7261 false, GSI_CONTINUE_LINKING);
7263 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7264 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7266 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7267 gsi = gsi_start_bb (seq_start_bb);
7269 tree startvar = fd->loop.v;
7270 tree endvar = NULL_TREE;
7272 if (gimple_omp_for_combined_p (fd->for_stmt))
7274 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7275 ? gimple_omp_parallel_clauses (inner_stmt)
7276 : gimple_omp_for_clauses (inner_stmt);
7277 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7278 gcc_assert (innerc);
7279 startvar = OMP_CLAUSE_DECL (innerc);
7280 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7281 OMP_CLAUSE__LOOPTEMP_);
7282 gcc_assert (innerc);
7283 endvar = OMP_CLAUSE_DECL (innerc);
7286 t = fold_convert (itype, s0);
7287 t = fold_build2 (MULT_EXPR, itype, t, step);
7288 if (POINTER_TYPE_P (type))
7289 t = fold_build_pointer_plus (n1, t);
7290 else
7291 t = fold_build2 (PLUS_EXPR, type, t, n1);
7292 t = fold_convert (TREE_TYPE (startvar), t);
7293 t = force_gimple_operand_gsi (&gsi, t,
7294 DECL_P (startvar)
7295 && TREE_ADDRESSABLE (startvar),
7296 NULL_TREE, false, GSI_CONTINUE_LINKING);
7297 assign_stmt = gimple_build_assign (startvar, t);
7298 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7300 t = fold_convert (itype, e0);
7301 t = fold_build2 (MULT_EXPR, itype, t, step);
7302 if (POINTER_TYPE_P (type))
7303 t = fold_build_pointer_plus (n1, t);
7304 else
7305 t = fold_build2 (PLUS_EXPR, type, t, n1);
7306 t = fold_convert (TREE_TYPE (startvar), t);
7307 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7308 false, GSI_CONTINUE_LINKING);
7309 if (endvar)
7311 assign_stmt = gimple_build_assign (endvar, e);
7312 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7313 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7314 assign_stmt = gimple_build_assign (fd->loop.v, e);
7315 else
7316 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7317 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7319 if (fd->collapse > 1)
7320 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7322 if (!broken_loop)
7324 /* The code controlling the sequential loop goes in CONT_BB,
7325 replacing the GIMPLE_OMP_CONTINUE. */
7326 gsi = gsi_last_bb (cont_bb);
7327 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7328 vmain = gimple_omp_continue_control_use (cont_stmt);
7329 vback = gimple_omp_continue_control_def (cont_stmt);
7331 if (!gimple_omp_for_combined_p (fd->for_stmt))
7333 if (POINTER_TYPE_P (type))
7334 t = fold_build_pointer_plus (vmain, step);
7335 else
7336 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7337 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7338 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7339 true, GSI_SAME_STMT);
7340 assign_stmt = gimple_build_assign (vback, t);
7341 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7343 t = build2 (fd->loop.cond_code, boolean_type_node,
7344 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7345 ? t : vback, e);
7346 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7349 /* Remove GIMPLE_OMP_CONTINUE. */
7350 gsi_remove (&gsi, true);
7352 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7353 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7355 /* Trip update code goes into TRIP_UPDATE_BB. */
7356 gsi = gsi_start_bb (trip_update_bb);
7358 t = build_int_cst (itype, 1);
7359 t = build2 (PLUS_EXPR, itype, trip_main, t);
7360 assign_stmt = gimple_build_assign (trip_back, t);
7361 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7364 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7365 gsi = gsi_last_bb (exit_bb);
7366 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7368 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7369 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7370 gcc_checking_assert (t == NULL_TREE);
7371 else
7372 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7374 gsi_remove (&gsi, true);
7376 /* Connect the new blocks. */
7377 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7378 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7380 if (!broken_loop)
7382 se = find_edge (cont_bb, body_bb);
7383 if (gimple_omp_for_combined_p (fd->for_stmt))
7385 remove_edge (se);
7386 se = NULL;
7388 else if (fd->collapse > 1)
7390 remove_edge (se);
7391 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7393 else
7394 se->flags = EDGE_TRUE_VALUE;
7395 find_edge (cont_bb, trip_update_bb)->flags
7396 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7398 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7401 if (gimple_in_ssa_p (cfun))
7403 gphi_iterator psi;
7404 gphi *phi;
7405 edge re, ene;
7406 edge_var_map *vm;
7407 size_t i;
7409 gcc_assert (fd->collapse == 1 && !broken_loop);
7411 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7412 remove arguments of the phi nodes in fin_bb. We need to create
7413 appropriate phi nodes in iter_part_bb instead. */
7414 se = single_pred_edge (fin_bb);
7415 re = single_succ_edge (trip_update_bb);
7416 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7417 ene = single_succ_edge (entry_bb);
7419 psi = gsi_start_phis (fin_bb);
7420 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7421 gsi_next (&psi), ++i)
7423 gphi *nphi;
7424 source_location locus;
7426 phi = psi.phi ();
7427 t = gimple_phi_result (phi);
7428 gcc_assert (t == redirect_edge_var_map_result (vm));
7429 nphi = create_phi_node (t, iter_part_bb);
7431 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7432 locus = gimple_phi_arg_location_from_edge (phi, se);
7434 /* A special case -- fd->loop.v is not yet computed in
7435 iter_part_bb, we need to use vextra instead. */
7436 if (t == fd->loop.v)
7437 t = vextra;
7438 add_phi_arg (nphi, t, ene, locus);
7439 locus = redirect_edge_var_map_location (vm);
7440 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7442 gcc_assert (gsi_end_p (psi) && i == head->length ());
7443 redirect_edge_var_map_clear (re);
7444 while (1)
7446 psi = gsi_start_phis (fin_bb);
7447 if (gsi_end_p (psi))
7448 break;
7449 remove_phi_node (&psi, false);
7452 /* Make phi node for trip. */
7453 phi = create_phi_node (trip_main, iter_part_bb);
7454 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7455 UNKNOWN_LOCATION);
7456 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7457 UNKNOWN_LOCATION);
7460 if (!broken_loop)
7461 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7462 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7463 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7464 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7465 recompute_dominator (CDI_DOMINATORS, fin_bb));
7466 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7467 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7468 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7469 recompute_dominator (CDI_DOMINATORS, body_bb));
7471 if (!broken_loop)
7473 struct loop *trip_loop = alloc_loop ();
7474 trip_loop->header = iter_part_bb;
7475 trip_loop->latch = trip_update_bb;
7476 add_loop (trip_loop, iter_part_bb->loop_father);
7478 if (!gimple_omp_for_combined_p (fd->for_stmt))
7480 struct loop *loop = alloc_loop ();
7481 loop->header = body_bb;
7482 if (collapse_bb == NULL)
7483 loop->latch = cont_bb;
7484 add_loop (loop, trip_loop);
7489 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7490 Given parameters:
7491 for (V = N1; V cond N2; V += STEP) BODY;
7493 where COND is "<" or ">" or "!=", we generate pseudocode
7495 for (ind_var = low; ind_var < high; ind_var++)
7497 V = n1 + (ind_var * STEP)
7499 <BODY>
7502 In the above pseudocode, low and high are function parameters of the
7503 child function. In the function below, we are inserting a temp.
7504 variable that will be making a call to two OMP functions that will not be
7505 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7506 with _Cilk_for). These functions are replaced with low and high
7507 by the function that handles taskreg. */
7510 static void
7511 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7513 bool broken_loop = region->cont == NULL;
7514 basic_block entry_bb = region->entry;
7515 basic_block cont_bb = region->cont;
7517 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7518 gcc_assert (broken_loop
7519 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7520 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7521 basic_block l1_bb, l2_bb;
7523 if (!broken_loop)
7525 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7526 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7527 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7528 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7530 else
7532 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7533 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7534 l2_bb = single_succ (l1_bb);
7536 basic_block exit_bb = region->exit;
7537 basic_block l2_dom_bb = NULL;
7539 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7541 /* Below statements until the "tree high_val = ..." are pseudo statements
7542 used to pass information to be used by expand_omp_taskreg.
7543 low_val and high_val will be replaced by the __low and __high
7544 parameter from the child function.
7546 The call_exprs part is a place-holder, it is mainly used
7547 to distinctly identify to the top-level part that this is
7548 where we should put low and high (reasoning given in header
7549 comment). */
7551 tree child_fndecl
7552 = gimple_omp_parallel_child_fn (
7553 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7554 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7555 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7557 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7558 high_val = t;
7559 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7560 low_val = t;
7562 gcc_assert (low_val && high_val);
7564 tree type = TREE_TYPE (low_val);
7565 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7566 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7568 /* Not needed in SSA form right now. */
7569 gcc_assert (!gimple_in_ssa_p (cfun));
7570 if (l2_dom_bb == NULL)
7571 l2_dom_bb = l1_bb;
7573 tree n1 = low_val;
7574 tree n2 = high_val;
7576 gimple stmt = gimple_build_assign (ind_var, n1);
7578 /* Replace the GIMPLE_OMP_FOR statement. */
7579 gsi_replace (&gsi, stmt, true);
7581 if (!broken_loop)
7583 /* Code to control the increment goes in the CONT_BB. */
7584 gsi = gsi_last_bb (cont_bb);
7585 stmt = gsi_stmt (gsi);
7586 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7587 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7588 build_one_cst (type));
7590 /* Replace GIMPLE_OMP_CONTINUE. */
7591 gsi_replace (&gsi, stmt, true);
7594 /* Emit the condition in L1_BB. */
7595 gsi = gsi_after_labels (l1_bb);
7596 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7597 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7598 fd->loop.step);
7599 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7600 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7601 fd->loop.n1, fold_convert (sizetype, t));
7602 else
7603 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7604 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7605 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7606 expand_omp_build_assign (&gsi, fd->loop.v, t);
7608 /* The condition is always '<' since the runtime will fill in the low
7609 and high values. */
7610 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7611 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7613 /* Remove GIMPLE_OMP_RETURN. */
7614 gsi = gsi_last_bb (exit_bb);
7615 gsi_remove (&gsi, true);
7617 /* Connect the new blocks. */
7618 remove_edge (FALLTHRU_EDGE (entry_bb));
7620 edge e, ne;
7621 if (!broken_loop)
7623 remove_edge (BRANCH_EDGE (entry_bb));
7624 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7626 e = BRANCH_EDGE (l1_bb);
7627 ne = FALLTHRU_EDGE (l1_bb);
7628 e->flags = EDGE_TRUE_VALUE;
7630 else
7632 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7634 ne = single_succ_edge (l1_bb);
7635 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7638 ne->flags = EDGE_FALSE_VALUE;
7639 e->probability = REG_BR_PROB_BASE * 7 / 8;
7640 ne->probability = REG_BR_PROB_BASE / 8;
7642 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7643 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7644 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7646 if (!broken_loop)
7648 struct loop *loop = alloc_loop ();
7649 loop->header = l1_bb;
7650 loop->latch = cont_bb;
7651 add_loop (loop, l1_bb->loop_father);
7652 loop->safelen = INT_MAX;
7655 /* Pick the correct library function based on the precision of the
7656 induction variable type. */
7657 tree lib_fun = NULL_TREE;
7658 if (TYPE_PRECISION (type) == 32)
7659 lib_fun = cilk_for_32_fndecl;
7660 else if (TYPE_PRECISION (type) == 64)
7661 lib_fun = cilk_for_64_fndecl;
7662 else
7663 gcc_unreachable ();
7665 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7667 /* WS_ARGS contains the library function flavor to call:
7668 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7669 user-defined grain value. If the user does not define one, then zero
7670 is passed in by the parser. */
7671 vec_alloc (region->ws_args, 2);
7672 region->ws_args->quick_push (lib_fun);
7673 region->ws_args->quick_push (fd->chunk_size);
7676 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7677 loop. Given parameters:
7679 for (V = N1; V cond N2; V += STEP) BODY;
7681 where COND is "<" or ">", we generate pseudocode
7683 V = N1;
7684 goto L1;
7686 BODY;
7687 V += STEP;
7689 if (V cond N2) goto L0; else goto L2;
7692 For collapsed loops, given parameters:
7693 collapse(3)
7694 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7695 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7696 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7697 BODY;
7699 we generate pseudocode
7701 if (cond3 is <)
7702 adj = STEP3 - 1;
7703 else
7704 adj = STEP3 + 1;
7705 count3 = (adj + N32 - N31) / STEP3;
7706 if (cond2 is <)
7707 adj = STEP2 - 1;
7708 else
7709 adj = STEP2 + 1;
7710 count2 = (adj + N22 - N21) / STEP2;
7711 if (cond1 is <)
7712 adj = STEP1 - 1;
7713 else
7714 adj = STEP1 + 1;
7715 count1 = (adj + N12 - N11) / STEP1;
7716 count = count1 * count2 * count3;
7717 V = 0;
7718 V1 = N11;
7719 V2 = N21;
7720 V3 = N31;
7721 goto L1;
7723 BODY;
7724 V += 1;
7725 V3 += STEP3;
7726 V2 += (V3 cond3 N32) ? 0 : STEP2;
7727 V3 = (V3 cond3 N32) ? V3 : N31;
7728 V1 += (V2 cond2 N22) ? 0 : STEP1;
7729 V2 = (V2 cond2 N22) ? V2 : N21;
7731 if (V < count) goto L0; else goto L2;
7736 static void
7737 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7739 tree type, t;
7740 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7741 gimple_stmt_iterator gsi;
7742 gimple stmt;
7743 gcond *cond_stmt;
7744 bool broken_loop = region->cont == NULL;
7745 edge e, ne;
7746 tree *counts = NULL;
7747 int i;
7748 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7749 OMP_CLAUSE_SAFELEN);
7750 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7751 OMP_CLAUSE__SIMDUID_);
7752 tree n1, n2;
7754 type = TREE_TYPE (fd->loop.v);
7755 entry_bb = region->entry;
7756 cont_bb = region->cont;
7757 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7758 gcc_assert (broken_loop
7759 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7760 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7761 if (!broken_loop)
7763 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7764 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7765 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7766 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7768 else
7770 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7771 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7772 l2_bb = single_succ (l1_bb);
7774 exit_bb = region->exit;
7775 l2_dom_bb = NULL;
7777 gsi = gsi_last_bb (entry_bb);
7779 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7780 /* Not needed in SSA form right now. */
7781 gcc_assert (!gimple_in_ssa_p (cfun));
7782 if (fd->collapse > 1)
7784 int first_zero_iter = -1;
7785 basic_block zero_iter_bb = l2_bb;
7787 counts = XALLOCAVEC (tree, fd->collapse);
7788 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7789 zero_iter_bb, first_zero_iter,
7790 l2_dom_bb);
7792 if (l2_dom_bb == NULL)
7793 l2_dom_bb = l1_bb;
7795 n1 = fd->loop.n1;
7796 n2 = fd->loop.n2;
7797 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7799 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7800 OMP_CLAUSE__LOOPTEMP_);
7801 gcc_assert (innerc);
7802 n1 = OMP_CLAUSE_DECL (innerc);
7803 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7804 OMP_CLAUSE__LOOPTEMP_);
7805 gcc_assert (innerc);
7806 n2 = OMP_CLAUSE_DECL (innerc);
7807 expand_omp_build_assign (&gsi, fd->loop.v,
7808 fold_convert (type, n1));
7809 if (fd->collapse > 1)
7811 gsi_prev (&gsi);
7812 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7813 gsi_next (&gsi);
7816 else
7818 expand_omp_build_assign (&gsi, fd->loop.v,
7819 fold_convert (type, fd->loop.n1));
7820 if (fd->collapse > 1)
7821 for (i = 0; i < fd->collapse; i++)
7823 tree itype = TREE_TYPE (fd->loops[i].v);
7824 if (POINTER_TYPE_P (itype))
7825 itype = signed_type_for (itype);
7826 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7827 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7831 /* Remove the GIMPLE_OMP_FOR statement. */
7832 gsi_remove (&gsi, true);
7834 if (!broken_loop)
7836 /* Code to control the increment goes in the CONT_BB. */
7837 gsi = gsi_last_bb (cont_bb);
7838 stmt = gsi_stmt (gsi);
7839 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7841 if (POINTER_TYPE_P (type))
7842 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7843 else
7844 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7845 expand_omp_build_assign (&gsi, fd->loop.v, t);
7847 if (fd->collapse > 1)
7849 i = fd->collapse - 1;
7850 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7852 t = fold_convert (sizetype, fd->loops[i].step);
7853 t = fold_build_pointer_plus (fd->loops[i].v, t);
7855 else
7857 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7858 fd->loops[i].step);
7859 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7860 fd->loops[i].v, t);
7862 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7864 for (i = fd->collapse - 1; i > 0; i--)
7866 tree itype = TREE_TYPE (fd->loops[i].v);
7867 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7868 if (POINTER_TYPE_P (itype2))
7869 itype2 = signed_type_for (itype2);
7870 t = build3 (COND_EXPR, itype2,
7871 build2 (fd->loops[i].cond_code, boolean_type_node,
7872 fd->loops[i].v,
7873 fold_convert (itype, fd->loops[i].n2)),
7874 build_int_cst (itype2, 0),
7875 fold_convert (itype2, fd->loops[i - 1].step));
7876 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7877 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7878 else
7879 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7880 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7882 t = build3 (COND_EXPR, itype,
7883 build2 (fd->loops[i].cond_code, boolean_type_node,
7884 fd->loops[i].v,
7885 fold_convert (itype, fd->loops[i].n2)),
7886 fd->loops[i].v,
7887 fold_convert (itype, fd->loops[i].n1));
7888 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7892 /* Remove GIMPLE_OMP_CONTINUE. */
7893 gsi_remove (&gsi, true);
7896 /* Emit the condition in L1_BB. */
7897 gsi = gsi_start_bb (l1_bb);
7899 t = fold_convert (type, n2);
7900 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7901 false, GSI_CONTINUE_LINKING);
7902 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7903 cond_stmt = gimple_build_cond_empty (t);
7904 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7905 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7906 NULL, NULL)
7907 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7908 NULL, NULL))
7910 gsi = gsi_for_stmt (cond_stmt);
7911 gimple_regimplify_operands (cond_stmt, &gsi);
7914 /* Remove GIMPLE_OMP_RETURN. */
7915 gsi = gsi_last_bb (exit_bb);
7916 gsi_remove (&gsi, true);
7918 /* Connect the new blocks. */
7919 remove_edge (FALLTHRU_EDGE (entry_bb));
7921 if (!broken_loop)
7923 remove_edge (BRANCH_EDGE (entry_bb));
7924 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7926 e = BRANCH_EDGE (l1_bb);
7927 ne = FALLTHRU_EDGE (l1_bb);
7928 e->flags = EDGE_TRUE_VALUE;
7930 else
7932 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7934 ne = single_succ_edge (l1_bb);
7935 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7938 ne->flags = EDGE_FALSE_VALUE;
7939 e->probability = REG_BR_PROB_BASE * 7 / 8;
7940 ne->probability = REG_BR_PROB_BASE / 8;
7942 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7943 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7944 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7946 if (!broken_loop)
7948 struct loop *loop = alloc_loop ();
7949 loop->header = l1_bb;
7950 loop->latch = cont_bb;
7951 add_loop (loop, l1_bb->loop_father);
7952 if (safelen == NULL_TREE)
7953 loop->safelen = INT_MAX;
7954 else
7956 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7957 if (TREE_CODE (safelen) != INTEGER_CST)
7958 loop->safelen = 0;
7959 else if (!tree_fits_uhwi_p (safelen)
7960 || tree_to_uhwi (safelen) > INT_MAX)
7961 loop->safelen = INT_MAX;
7962 else
7963 loop->safelen = tree_to_uhwi (safelen);
7964 if (loop->safelen == 1)
7965 loop->safelen = 0;
7967 if (simduid)
7969 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7970 cfun->has_simduid_loops = true;
7972 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7973 the loop. */
7974 if ((flag_tree_loop_vectorize
7975 || (!global_options_set.x_flag_tree_loop_vectorize
7976 && !global_options_set.x_flag_tree_vectorize))
7977 && flag_tree_loop_optimize
7978 && loop->safelen > 1)
7980 loop->force_vectorize = true;
7981 cfun->has_force_vectorize_loops = true;
7984 else if (simduid)
7985 cfun->has_simduid_loops = true;
7989 /* Expand the OMP loop defined by REGION. */
7991 static void
7992 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7994 struct omp_for_data fd;
7995 struct omp_for_data_loop *loops;
7997 loops
7998 = (struct omp_for_data_loop *)
7999 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
8000 * sizeof (struct omp_for_data_loop));
8001 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
8002 &fd, loops);
8003 region->sched_kind = fd.sched_kind;
8005 if (region->kernelize)
8007 gomp_for *omp_for_stmt = as_a <gomp_for *> (last_stmt (region->entry));
8008 region->orig_first_iter = omp_for_stmt->orig_first_iter;
8010 else
8011 region->orig_first_iter = NULL;
8013 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
8014 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
8015 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
8016 if (region->cont)
8018 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
8019 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
8020 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
8022 else
8023 /* If there isn't a continue then this is a degerate case where
8024 the introduction of abnormal edges during lowering will prevent
8025 original loops from being detected. Fix that up. */
8026 loops_state_set (LOOPS_NEED_FIXUP);
8028 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
8029 expand_omp_simd (region, &fd);
8030 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
8031 expand_cilk_for (region, &fd);
8032 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
8033 && !fd.have_ordered)
8035 region->req_group_size = fd.chunk_size;
8036 if (fd.chunk_size == NULL || region->kernelize)
8037 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
8038 else
8039 expand_omp_for_static_chunk (region, &fd, inner_stmt);
8041 else
8043 int fn_index, start_ix, next_ix;
8045 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
8046 == GF_OMP_FOR_KIND_FOR);
8047 if (fd.chunk_size == NULL
8048 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
8049 fd.chunk_size = integer_zero_node;
8050 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
8051 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
8052 ? 3 : fd.sched_kind;
8053 fn_index += fd.have_ordered * 4;
8054 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
8055 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
8056 if (fd.iter_type == long_long_unsigned_type_node)
8058 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
8059 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
8060 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
8061 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
8063 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
8064 (enum built_in_function) next_ix, inner_stmt);
8067 if (gimple_in_ssa_p (cfun))
8068 update_ssa (TODO_update_ssa_only_virtuals);
8072 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
8074 v = GOMP_sections_start (n);
8076 switch (v)
8078 case 0:
8079 goto L2;
8080 case 1:
8081 section 1;
8082 goto L1;
8083 case 2:
8085 case n:
8087 default:
8088 abort ();
8091 v = GOMP_sections_next ();
8092 goto L0;
8094 reduction;
8096 If this is a combined parallel sections, replace the call to
8097 GOMP_sections_start with call to GOMP_sections_next. */
8099 static void
8100 expand_omp_sections (struct omp_region *region)
8102 tree t, u, vin = NULL, vmain, vnext, l2;
8103 unsigned len;
8104 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
8105 gimple_stmt_iterator si, switch_si;
8106 gomp_sections *sections_stmt;
8107 gimple stmt;
8108 gomp_continue *cont;
8109 edge_iterator ei;
8110 edge e;
8111 struct omp_region *inner;
8112 unsigned i, casei;
8113 bool exit_reachable = region->cont != NULL;
8115 gcc_assert (region->exit != NULL);
8116 entry_bb = region->entry;
8117 l0_bb = single_succ (entry_bb);
8118 l1_bb = region->cont;
8119 l2_bb = region->exit;
8120 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
8121 l2 = gimple_block_label (l2_bb);
8122 else
8124 /* This can happen if there are reductions. */
8125 len = EDGE_COUNT (l0_bb->succs);
8126 gcc_assert (len > 0);
8127 e = EDGE_SUCC (l0_bb, len - 1);
8128 si = gsi_last_bb (e->dest);
8129 l2 = NULL_TREE;
8130 if (gsi_end_p (si)
8131 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
8132 l2 = gimple_block_label (e->dest);
8133 else
8134 FOR_EACH_EDGE (e, ei, l0_bb->succs)
8136 si = gsi_last_bb (e->dest);
8137 if (gsi_end_p (si)
8138 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
8140 l2 = gimple_block_label (e->dest);
8141 break;
8145 if (exit_reachable)
8146 default_bb = create_empty_bb (l1_bb->prev_bb);
8147 else
8148 default_bb = create_empty_bb (l0_bb);
8150 /* We will build a switch() with enough cases for all the
8151 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
8152 and a default case to abort if something goes wrong. */
8153 len = EDGE_COUNT (l0_bb->succs);
8155 /* Use vec::quick_push on label_vec throughout, since we know the size
8156 in advance. */
8157 auto_vec<tree> label_vec (len);
8159 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
8160 GIMPLE_OMP_SECTIONS statement. */
8161 si = gsi_last_bb (entry_bb);
8162 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
8163 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8164 vin = gimple_omp_sections_control (sections_stmt);
8165 if (!is_combined_parallel (region))
8167 /* If we are not inside a combined parallel+sections region,
8168 call GOMP_sections_start. */
8169 t = build_int_cst (unsigned_type_node, len - 1);
8170 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
8171 stmt = gimple_build_call (u, 1, t);
8173 else
8175 /* Otherwise, call GOMP_sections_next. */
8176 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8177 stmt = gimple_build_call (u, 0);
8179 gimple_call_set_lhs (stmt, vin);
8180 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8181 gsi_remove (&si, true);
8183 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8184 L0_BB. */
8185 switch_si = gsi_last_bb (l0_bb);
8186 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8187 if (exit_reachable)
8189 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8190 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8191 vmain = gimple_omp_continue_control_use (cont);
8192 vnext = gimple_omp_continue_control_def (cont);
8194 else
8196 vmain = vin;
8197 vnext = NULL_TREE;
8200 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8201 label_vec.quick_push (t);
8202 i = 1;
8204 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8205 for (inner = region->inner, casei = 1;
8206 inner;
8207 inner = inner->next, i++, casei++)
8209 basic_block s_entry_bb, s_exit_bb;
8211 /* Skip optional reduction region. */
8212 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8214 --i;
8215 --casei;
8216 continue;
8219 s_entry_bb = inner->entry;
8220 s_exit_bb = inner->exit;
8222 t = gimple_block_label (s_entry_bb);
8223 u = build_int_cst (unsigned_type_node, casei);
8224 u = build_case_label (u, NULL, t);
8225 label_vec.quick_push (u);
8227 si = gsi_last_bb (s_entry_bb);
8228 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8229 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8230 gsi_remove (&si, true);
8231 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8233 if (s_exit_bb == NULL)
8234 continue;
8236 si = gsi_last_bb (s_exit_bb);
8237 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8238 gsi_remove (&si, true);
8240 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8243 /* Error handling code goes in DEFAULT_BB. */
8244 t = gimple_block_label (default_bb);
8245 u = build_case_label (NULL, NULL, t);
8246 make_edge (l0_bb, default_bb, 0);
8247 add_bb_to_loop (default_bb, current_loops->tree_root);
8249 stmt = gimple_build_switch (vmain, u, label_vec);
8250 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8251 gsi_remove (&switch_si, true);
8253 si = gsi_start_bb (default_bb);
8254 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8255 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8257 if (exit_reachable)
8259 tree bfn_decl;
8261 /* Code to get the next section goes in L1_BB. */
8262 si = gsi_last_bb (l1_bb);
8263 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8265 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8266 stmt = gimple_build_call (bfn_decl, 0);
8267 gimple_call_set_lhs (stmt, vnext);
8268 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8269 gsi_remove (&si, true);
8271 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8274 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8275 si = gsi_last_bb (l2_bb);
8276 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8277 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8278 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8279 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8280 else
8281 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8282 stmt = gimple_build_call (t, 0);
8283 if (gimple_omp_return_lhs (gsi_stmt (si)))
8284 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8285 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8286 gsi_remove (&si, true);
8288 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8292 /* Expand code for an OpenMP single directive. We've already expanded
8293 much of the code, here we simply place the GOMP_barrier call. */
8295 static void
8296 expand_omp_single (struct omp_region *region)
8298 basic_block entry_bb, exit_bb;
8299 gimple_stmt_iterator si;
8301 entry_bb = region->entry;
8302 exit_bb = region->exit;
8304 si = gsi_last_bb (entry_bb);
8305 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8306 gsi_remove (&si, true);
8307 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8309 si = gsi_last_bb (exit_bb);
8310 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8312 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8313 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8315 gsi_remove (&si, true);
8316 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8320 /* Generic expansion for OpenMP synchronization directives: master,
8321 ordered and critical. All we need to do here is remove the entry
8322 and exit markers for REGION. */
8324 static void
8325 expand_omp_synch (struct omp_region *region)
8327 basic_block entry_bb, exit_bb;
8328 gimple_stmt_iterator si;
8330 entry_bb = region->entry;
8331 exit_bb = region->exit;
8333 si = gsi_last_bb (entry_bb);
8334 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8335 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8336 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8337 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8338 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8339 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8340 gsi_remove (&si, true);
8341 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8343 if (exit_bb)
8345 si = gsi_last_bb (exit_bb);
8346 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8347 gsi_remove (&si, true);
8348 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8352 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8353 operation as a normal volatile load. */
8355 static bool
8356 expand_omp_atomic_load (basic_block load_bb, tree addr,
8357 tree loaded_val, int index)
8359 enum built_in_function tmpbase;
8360 gimple_stmt_iterator gsi;
8361 basic_block store_bb;
8362 location_t loc;
8363 gimple stmt;
8364 tree decl, call, type, itype;
8366 gsi = gsi_last_bb (load_bb);
8367 stmt = gsi_stmt (gsi);
8368 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8369 loc = gimple_location (stmt);
8371 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8372 is smaller than word size, then expand_atomic_load assumes that the load
8373 is atomic. We could avoid the builtin entirely in this case. */
8375 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8376 decl = builtin_decl_explicit (tmpbase);
8377 if (decl == NULL_TREE)
8378 return false;
8380 type = TREE_TYPE (loaded_val);
8381 itype = TREE_TYPE (TREE_TYPE (decl));
8383 call = build_call_expr_loc (loc, decl, 2, addr,
8384 build_int_cst (NULL,
8385 gimple_omp_atomic_seq_cst_p (stmt)
8386 ? MEMMODEL_SEQ_CST
8387 : MEMMODEL_RELAXED));
8388 if (!useless_type_conversion_p (type, itype))
8389 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8390 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8392 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8393 gsi_remove (&gsi, true);
8395 store_bb = single_succ (load_bb);
8396 gsi = gsi_last_bb (store_bb);
8397 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8398 gsi_remove (&gsi, true);
8400 if (gimple_in_ssa_p (cfun))
8401 update_ssa (TODO_update_ssa_no_phi);
8403 return true;
8406 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8407 operation as a normal volatile store. */
8409 static bool
8410 expand_omp_atomic_store (basic_block load_bb, tree addr,
8411 tree loaded_val, tree stored_val, int index)
8413 enum built_in_function tmpbase;
8414 gimple_stmt_iterator gsi;
8415 basic_block store_bb = single_succ (load_bb);
8416 location_t loc;
8417 gimple stmt;
8418 tree decl, call, type, itype;
8419 machine_mode imode;
8420 bool exchange;
8422 gsi = gsi_last_bb (load_bb);
8423 stmt = gsi_stmt (gsi);
8424 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8426 /* If the load value is needed, then this isn't a store but an exchange. */
8427 exchange = gimple_omp_atomic_need_value_p (stmt);
8429 gsi = gsi_last_bb (store_bb);
8430 stmt = gsi_stmt (gsi);
8431 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8432 loc = gimple_location (stmt);
8434 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8435 is smaller than word size, then expand_atomic_store assumes that the store
8436 is atomic. We could avoid the builtin entirely in this case. */
8438 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8439 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8440 decl = builtin_decl_explicit (tmpbase);
8441 if (decl == NULL_TREE)
8442 return false;
8444 type = TREE_TYPE (stored_val);
8446 /* Dig out the type of the function's second argument. */
8447 itype = TREE_TYPE (decl);
8448 itype = TYPE_ARG_TYPES (itype);
8449 itype = TREE_CHAIN (itype);
8450 itype = TREE_VALUE (itype);
8451 imode = TYPE_MODE (itype);
8453 if (exchange && !can_atomic_exchange_p (imode, true))
8454 return false;
8456 if (!useless_type_conversion_p (itype, type))
8457 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8458 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8459 build_int_cst (NULL,
8460 gimple_omp_atomic_seq_cst_p (stmt)
8461 ? MEMMODEL_SEQ_CST
8462 : MEMMODEL_RELAXED));
8463 if (exchange)
8465 if (!useless_type_conversion_p (type, itype))
8466 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8467 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8470 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8471 gsi_remove (&gsi, true);
8473 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8474 gsi = gsi_last_bb (load_bb);
8475 gsi_remove (&gsi, true);
8477 if (gimple_in_ssa_p (cfun))
8478 update_ssa (TODO_update_ssa_no_phi);
8480 return true;
8483 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8484 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8485 size of the data type, and thus usable to find the index of the builtin
8486 decl. Returns false if the expression is not of the proper form. */
8488 static bool
8489 expand_omp_atomic_fetch_op (basic_block load_bb,
8490 tree addr, tree loaded_val,
8491 tree stored_val, int index)
8493 enum built_in_function oldbase, newbase, tmpbase;
8494 tree decl, itype, call;
8495 tree lhs, rhs;
8496 basic_block store_bb = single_succ (load_bb);
8497 gimple_stmt_iterator gsi;
8498 gimple stmt;
8499 location_t loc;
8500 enum tree_code code;
8501 bool need_old, need_new;
8502 machine_mode imode;
8503 bool seq_cst;
8505 /* We expect to find the following sequences:
8507 load_bb:
8508 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8510 store_bb:
8511 val = tmp OP something; (or: something OP tmp)
8512 GIMPLE_OMP_STORE (val)
8514 ???FIXME: Allow a more flexible sequence.
8515 Perhaps use data flow to pick the statements.
8519 gsi = gsi_after_labels (store_bb);
8520 stmt = gsi_stmt (gsi);
8521 loc = gimple_location (stmt);
8522 if (!is_gimple_assign (stmt))
8523 return false;
8524 gsi_next (&gsi);
8525 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8526 return false;
8527 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8528 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8529 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8530 gcc_checking_assert (!need_old || !need_new);
8532 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8533 return false;
8535 /* Check for one of the supported fetch-op operations. */
8536 code = gimple_assign_rhs_code (stmt);
8537 switch (code)
8539 case PLUS_EXPR:
8540 case POINTER_PLUS_EXPR:
8541 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8542 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8543 break;
8544 case MINUS_EXPR:
8545 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8546 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8547 break;
8548 case BIT_AND_EXPR:
8549 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8550 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8551 break;
8552 case BIT_IOR_EXPR:
8553 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8554 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8555 break;
8556 case BIT_XOR_EXPR:
8557 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8558 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8559 break;
8560 default:
8561 return false;
8564 /* Make sure the expression is of the proper form. */
8565 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8566 rhs = gimple_assign_rhs2 (stmt);
8567 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8568 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8569 rhs = gimple_assign_rhs1 (stmt);
8570 else
8571 return false;
8573 tmpbase = ((enum built_in_function)
8574 ((need_new ? newbase : oldbase) + index + 1));
8575 decl = builtin_decl_explicit (tmpbase);
8576 if (decl == NULL_TREE)
8577 return false;
8578 itype = TREE_TYPE (TREE_TYPE (decl));
8579 imode = TYPE_MODE (itype);
8581 /* We could test all of the various optabs involved, but the fact of the
8582 matter is that (with the exception of i486 vs i586 and xadd) all targets
8583 that support any atomic operaton optab also implements compare-and-swap.
8584 Let optabs.c take care of expanding any compare-and-swap loop. */
8585 if (!can_compare_and_swap_p (imode, true))
8586 return false;
8588 gsi = gsi_last_bb (load_bb);
8589 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8591 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8592 It only requires that the operation happen atomically. Thus we can
8593 use the RELAXED memory model. */
8594 call = build_call_expr_loc (loc, decl, 3, addr,
8595 fold_convert_loc (loc, itype, rhs),
8596 build_int_cst (NULL,
8597 seq_cst ? MEMMODEL_SEQ_CST
8598 : MEMMODEL_RELAXED));
8600 if (need_old || need_new)
8602 lhs = need_old ? loaded_val : stored_val;
8603 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8604 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8606 else
8607 call = fold_convert_loc (loc, void_type_node, call);
8608 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8609 gsi_remove (&gsi, true);
8611 gsi = gsi_last_bb (store_bb);
8612 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8613 gsi_remove (&gsi, true);
8614 gsi = gsi_last_bb (store_bb);
8615 gsi_remove (&gsi, true);
8617 if (gimple_in_ssa_p (cfun))
8618 update_ssa (TODO_update_ssa_no_phi);
8620 return true;
8623 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8625 oldval = *addr;
8626 repeat:
8627 newval = rhs; // with oldval replacing *addr in rhs
8628 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8629 if (oldval != newval)
8630 goto repeat;
8632 INDEX is log2 of the size of the data type, and thus usable to find the
8633 index of the builtin decl. */
8635 static bool
8636 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8637 tree addr, tree loaded_val, tree stored_val,
8638 int index)
8640 tree loadedi, storedi, initial, new_storedi, old_vali;
8641 tree type, itype, cmpxchg, iaddr;
8642 gimple_stmt_iterator si;
8643 basic_block loop_header = single_succ (load_bb);
8644 gimple phi, stmt;
8645 edge e;
8646 enum built_in_function fncode;
8648 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8649 order to use the RELAXED memory model effectively. */
8650 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8651 + index + 1);
8652 cmpxchg = builtin_decl_explicit (fncode);
8653 if (cmpxchg == NULL_TREE)
8654 return false;
8655 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8656 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8658 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8659 return false;
8661 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8662 si = gsi_last_bb (load_bb);
8663 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8665 /* For floating-point values, we'll need to view-convert them to integers
8666 so that we can perform the atomic compare and swap. Simplify the
8667 following code by always setting up the "i"ntegral variables. */
8668 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8670 tree iaddr_val;
8672 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8673 true));
8674 iaddr_val
8675 = force_gimple_operand_gsi (&si,
8676 fold_convert (TREE_TYPE (iaddr), addr),
8677 false, NULL_TREE, true, GSI_SAME_STMT);
8678 stmt = gimple_build_assign (iaddr, iaddr_val);
8679 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8680 loadedi = create_tmp_var (itype);
8681 if (gimple_in_ssa_p (cfun))
8682 loadedi = make_ssa_name (loadedi);
8684 else
8686 iaddr = addr;
8687 loadedi = loaded_val;
8690 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8691 tree loaddecl = builtin_decl_explicit (fncode);
8692 if (loaddecl)
8693 initial
8694 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8695 build_call_expr (loaddecl, 2, iaddr,
8696 build_int_cst (NULL_TREE,
8697 MEMMODEL_RELAXED)));
8698 else
8699 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8700 build_int_cst (TREE_TYPE (iaddr), 0));
8702 initial
8703 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8704 GSI_SAME_STMT);
8706 /* Move the value to the LOADEDI temporary. */
8707 if (gimple_in_ssa_p (cfun))
8709 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8710 phi = create_phi_node (loadedi, loop_header);
8711 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8712 initial);
8714 else
8715 gsi_insert_before (&si,
8716 gimple_build_assign (loadedi, initial),
8717 GSI_SAME_STMT);
8718 if (loadedi != loaded_val)
8720 gimple_stmt_iterator gsi2;
8721 tree x;
8723 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8724 gsi2 = gsi_start_bb (loop_header);
8725 if (gimple_in_ssa_p (cfun))
8727 gassign *stmt;
8728 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8729 true, GSI_SAME_STMT);
8730 stmt = gimple_build_assign (loaded_val, x);
8731 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8733 else
8735 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8736 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8737 true, GSI_SAME_STMT);
8740 gsi_remove (&si, true);
8742 si = gsi_last_bb (store_bb);
8743 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8745 if (iaddr == addr)
8746 storedi = stored_val;
8747 else
8748 storedi =
8749 force_gimple_operand_gsi (&si,
8750 build1 (VIEW_CONVERT_EXPR, itype,
8751 stored_val), true, NULL_TREE, true,
8752 GSI_SAME_STMT);
8754 /* Build the compare&swap statement. */
8755 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8756 new_storedi = force_gimple_operand_gsi (&si,
8757 fold_convert (TREE_TYPE (loadedi),
8758 new_storedi),
8759 true, NULL_TREE,
8760 true, GSI_SAME_STMT);
8762 if (gimple_in_ssa_p (cfun))
8763 old_vali = loadedi;
8764 else
8766 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8767 stmt = gimple_build_assign (old_vali, loadedi);
8768 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8770 stmt = gimple_build_assign (loadedi, new_storedi);
8771 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8774 /* Note that we always perform the comparison as an integer, even for
8775 floating point. This allows the atomic operation to properly
8776 succeed even with NaNs and -0.0. */
8777 stmt = gimple_build_cond_empty
8778 (build2 (NE_EXPR, boolean_type_node,
8779 new_storedi, old_vali));
8780 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8782 /* Update cfg. */
8783 e = single_succ_edge (store_bb);
8784 e->flags &= ~EDGE_FALLTHRU;
8785 e->flags |= EDGE_FALSE_VALUE;
8787 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8789 /* Copy the new value to loadedi (we already did that before the condition
8790 if we are not in SSA). */
8791 if (gimple_in_ssa_p (cfun))
8793 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8794 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8797 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8798 gsi_remove (&si, true);
8800 struct loop *loop = alloc_loop ();
8801 loop->header = loop_header;
8802 loop->latch = store_bb;
8803 add_loop (loop, loop_header->loop_father);
8805 if (gimple_in_ssa_p (cfun))
8806 update_ssa (TODO_update_ssa_no_phi);
8808 return true;
8811 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8813 GOMP_atomic_start ();
8814 *addr = rhs;
8815 GOMP_atomic_end ();
8817 The result is not globally atomic, but works so long as all parallel
8818 references are within #pragma omp atomic directives. According to
8819 responses received from omp@openmp.org, appears to be within spec.
8820 Which makes sense, since that's how several other compilers handle
8821 this situation as well.
8822 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8823 expanding. STORED_VAL is the operand of the matching
8824 GIMPLE_OMP_ATOMIC_STORE.
8826 We replace
8827 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8828 loaded_val = *addr;
8830 and replace
8831 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8832 *addr = stored_val;
8835 static bool
8836 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8837 tree addr, tree loaded_val, tree stored_val)
8839 gimple_stmt_iterator si;
8840 gassign *stmt;
8841 tree t;
8843 si = gsi_last_bb (load_bb);
8844 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8846 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8847 t = build_call_expr (t, 0);
8848 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8850 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8851 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8852 gsi_remove (&si, true);
8854 si = gsi_last_bb (store_bb);
8855 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8857 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8858 stored_val);
8859 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8861 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8862 t = build_call_expr (t, 0);
8863 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8864 gsi_remove (&si, true);
8866 if (gimple_in_ssa_p (cfun))
8867 update_ssa (TODO_update_ssa_no_phi);
8868 return true;
8871 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8872 using expand_omp_atomic_fetch_op. If it failed, we try to
8873 call expand_omp_atomic_pipeline, and if it fails too, the
8874 ultimate fallback is wrapping the operation in a mutex
8875 (expand_omp_atomic_mutex). REGION is the atomic region built
8876 by build_omp_regions_1(). */
8878 static void
8879 expand_omp_atomic (struct omp_region *region)
8881 basic_block load_bb = region->entry, store_bb = region->exit;
8882 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8883 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8884 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8885 tree addr = gimple_omp_atomic_load_rhs (load);
8886 tree stored_val = gimple_omp_atomic_store_val (store);
8887 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8888 HOST_WIDE_INT index;
8890 /* Make sure the type is one of the supported sizes. */
8891 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8892 index = exact_log2 (index);
8893 if (index >= 0 && index <= 4)
8895 unsigned int align = TYPE_ALIGN_UNIT (type);
8897 /* __sync builtins require strict data alignment. */
8898 if (exact_log2 (align) >= index)
8900 /* Atomic load. */
8901 if (loaded_val == stored_val
8902 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8903 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8904 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8905 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8906 return;
8908 /* Atomic store. */
8909 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8910 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8911 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8912 && store_bb == single_succ (load_bb)
8913 && first_stmt (store_bb) == store
8914 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8915 stored_val, index))
8916 return;
8918 /* When possible, use specialized atomic update functions. */
8919 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8920 && store_bb == single_succ (load_bb)
8921 && expand_omp_atomic_fetch_op (load_bb, addr,
8922 loaded_val, stored_val, index))
8923 return;
8925 /* If we don't have specialized __sync builtins, try and implement
8926 as a compare and swap loop. */
8927 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8928 loaded_val, stored_val, index))
8929 return;
8933 /* The ultimate fallback is wrapping the operation in a mutex. */
8934 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8938 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8940 static void
8941 expand_omp_target (struct omp_region *region)
8943 basic_block entry_bb, exit_bb, new_bb;
8944 struct function *child_cfun;
8945 tree child_fn, block, t;
8946 gimple_stmt_iterator gsi;
8947 gomp_target *entry_stmt;
8948 gimple stmt;
8949 edge e;
8950 bool offloaded, data_region;
8952 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8953 new_bb = region->entry;
8955 offloaded = is_gimple_omp_offloaded (entry_stmt);
8956 switch (gimple_omp_target_kind (entry_stmt))
8958 case GF_OMP_TARGET_KIND_REGION:
8959 case GF_OMP_TARGET_KIND_UPDATE:
8960 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8961 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8962 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8963 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8964 data_region = false;
8965 break;
8966 case GF_OMP_TARGET_KIND_DATA:
8967 case GF_OMP_TARGET_KIND_OACC_DATA:
8968 data_region = true;
8969 break;
8970 default:
8971 gcc_unreachable ();
8974 child_fn = NULL_TREE;
8975 child_cfun = NULL;
8976 if (offloaded)
8978 child_fn = gimple_omp_target_child_fn (entry_stmt);
8979 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8982 /* Supported by expand_omp_taskreg, but not here. */
8983 if (child_cfun != NULL)
8984 gcc_checking_assert (!child_cfun->cfg);
8985 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8987 entry_bb = region->entry;
8988 exit_bb = region->exit;
8990 if (offloaded)
8992 unsigned srcidx, dstidx, num;
8994 /* If the offloading region needs data sent from the parent
8995 function, then the very first statement (except possible
8996 tree profile counter updates) of the offloading body
8997 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8998 &.OMP_DATA_O is passed as an argument to the child function,
8999 we need to replace it with the argument as seen by the child
9000 function.
9002 In most cases, this will end up being the identity assignment
9003 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
9004 a function call that has been inlined, the original PARM_DECL
9005 .OMP_DATA_I may have been converted into a different local
9006 variable. In which case, we need to keep the assignment. */
9007 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
9008 if (data_arg)
9010 basic_block entry_succ_bb = single_succ (entry_bb);
9011 gimple_stmt_iterator gsi;
9012 tree arg;
9013 gimple tgtcopy_stmt = NULL;
9014 tree sender = TREE_VEC_ELT (data_arg, 0);
9016 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
9018 gcc_assert (!gsi_end_p (gsi));
9019 stmt = gsi_stmt (gsi);
9020 if (gimple_code (stmt) != GIMPLE_ASSIGN)
9021 continue;
9023 if (gimple_num_ops (stmt) == 2)
9025 tree arg = gimple_assign_rhs1 (stmt);
9027 /* We're ignoring the subcode because we're
9028 effectively doing a STRIP_NOPS. */
9030 if (TREE_CODE (arg) == ADDR_EXPR
9031 && TREE_OPERAND (arg, 0) == sender)
9033 tgtcopy_stmt = stmt;
9034 break;
9039 gcc_assert (tgtcopy_stmt != NULL);
9040 arg = DECL_ARGUMENTS (child_fn);
9042 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
9043 gsi_remove (&gsi, true);
9046 /* Declare local variables needed in CHILD_CFUN. */
9047 block = DECL_INITIAL (child_fn);
9048 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
9049 /* The gimplifier could record temporaries in the offloading block
9050 rather than in containing function's local_decls chain,
9051 which would mean cgraph missed finalizing them. Do it now. */
9052 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
9053 if (TREE_CODE (t) == VAR_DECL
9054 && TREE_STATIC (t)
9055 && !DECL_EXTERNAL (t))
9056 varpool_node::finalize_decl (t);
9057 DECL_SAVED_TREE (child_fn) = NULL;
9058 /* We'll create a CFG for child_fn, so no gimple body is needed. */
9059 gimple_set_body (child_fn, NULL);
9060 TREE_USED (block) = 1;
9062 /* Reset DECL_CONTEXT on function arguments. */
9063 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
9064 DECL_CONTEXT (t) = child_fn;
9066 /* Split ENTRY_BB at GIMPLE_*,
9067 so that it can be moved to the child function. */
9068 gsi = gsi_last_bb (entry_bb);
9069 stmt = gsi_stmt (gsi);
9070 gcc_assert (stmt
9071 && gimple_code (stmt) == gimple_code (entry_stmt));
9072 e = split_block (entry_bb, stmt);
9073 gsi_remove (&gsi, true);
9074 entry_bb = e->dest;
9075 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
9077 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
9078 if (exit_bb)
9080 gsi = gsi_last_bb (exit_bb);
9081 gcc_assert (!gsi_end_p (gsi)
9082 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
9083 stmt = gimple_build_return (NULL);
9084 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
9085 gsi_remove (&gsi, true);
9088 /* Move the offloading region into CHILD_CFUN. */
9090 block = gimple_block (entry_stmt);
9092 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
9093 if (exit_bb)
9094 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
9095 /* When the OMP expansion process cannot guarantee an up-to-date
9096 loop tree arrange for the child function to fixup loops. */
9097 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
9098 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
9100 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
9101 num = vec_safe_length (child_cfun->local_decls);
9102 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
9104 t = (*child_cfun->local_decls)[srcidx];
9105 if (DECL_CONTEXT (t) == cfun->decl)
9106 continue;
9107 if (srcidx != dstidx)
9108 (*child_cfun->local_decls)[dstidx] = t;
9109 dstidx++;
9111 if (dstidx != num)
9112 vec_safe_truncate (child_cfun->local_decls, dstidx);
9114 /* Inform the callgraph about the new function. */
9115 child_cfun->curr_properties = cfun->curr_properties;
9116 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
9117 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
9118 cgraph_node *node = cgraph_node::get_create (child_fn);
9119 node->parallelized_function = 1;
9120 cgraph_node::add_new_function (child_fn, true);
9122 #ifdef ENABLE_OFFLOADING
9123 /* Add the new function to the offload table. */
9124 vec_safe_push (offload_funcs, child_fn);
9125 #endif
9127 /* Fix the callgraph edges for child_cfun. Those for cfun will be
9128 fixed in a following pass. */
9129 push_cfun (child_cfun);
9130 cgraph_edge::rebuild_edges ();
9132 #ifdef ENABLE_OFFLOADING
9133 /* Prevent IPA from removing child_fn as unreachable, since there are no
9134 refs from the parent function to child_fn in offload LTO mode. */
9135 cgraph_node::get (child_fn)->mark_force_output ();
9136 #endif
9138 /* Some EH regions might become dead, see PR34608. If
9139 pass_cleanup_cfg isn't the first pass to happen with the
9140 new child, these dead EH edges might cause problems.
9141 Clean them up now. */
9142 if (flag_exceptions)
9144 basic_block bb;
9145 bool changed = false;
9147 FOR_EACH_BB_FN (bb, cfun)
9148 changed |= gimple_purge_dead_eh_edges (bb);
9149 if (changed)
9150 cleanup_tree_cfg ();
9152 pop_cfun ();
9155 /* Emit a library call to launch the offloading region, or do data
9156 transfers. */
9157 tree t1, t2, t3, t4, device, cond, c, clauses;
9158 enum built_in_function start_ix;
9159 location_t clause_loc;
9161 switch (gimple_omp_target_kind (entry_stmt))
9163 case GF_OMP_TARGET_KIND_REGION:
9164 start_ix = BUILT_IN_GOMP_TARGET;
9165 break;
9166 case GF_OMP_TARGET_KIND_DATA:
9167 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9168 break;
9169 case GF_OMP_TARGET_KIND_UPDATE:
9170 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9171 break;
9172 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9173 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9174 start_ix = BUILT_IN_GOACC_PARALLEL;
9175 break;
9176 case GF_OMP_TARGET_KIND_OACC_DATA:
9177 start_ix = BUILT_IN_GOACC_DATA_START;
9178 break;
9179 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9180 start_ix = BUILT_IN_GOACC_UPDATE;
9181 break;
9182 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9183 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9184 break;
9185 default:
9186 gcc_unreachable ();
9189 clauses = gimple_omp_target_clauses (entry_stmt);
9191 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9192 library choose) and there is no conditional. */
9193 cond = NULL_TREE;
9194 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
9196 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9197 if (c)
9198 cond = OMP_CLAUSE_IF_EXPR (c);
9200 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9201 if (c)
9203 /* Even if we pass it to all library function calls, it is currently only
9204 defined/used for the OpenMP target ones. */
9205 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9206 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9207 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9209 device = OMP_CLAUSE_DEVICE_ID (c);
9210 clause_loc = OMP_CLAUSE_LOCATION (c);
9212 else
9213 clause_loc = gimple_location (entry_stmt);
9215 /* Ensure 'device' is of the correct type. */
9216 device = fold_convert_loc (clause_loc, integer_type_node, device);
9218 /* If we found the clause 'if (cond)', build
9219 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9220 if (cond)
9222 cond = gimple_boolify (cond);
9224 basic_block cond_bb, then_bb, else_bb;
9225 edge e;
9226 tree tmp_var;
9228 tmp_var = create_tmp_var (TREE_TYPE (device));
9229 if (offloaded)
9230 e = split_block_after_labels (new_bb);
9231 else
9233 gsi = gsi_last_bb (new_bb);
9234 gsi_prev (&gsi);
9235 e = split_block (new_bb, gsi_stmt (gsi));
9237 cond_bb = e->src;
9238 new_bb = e->dest;
9239 remove_edge (e);
9241 then_bb = create_empty_bb (cond_bb);
9242 else_bb = create_empty_bb (then_bb);
9243 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9244 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9246 stmt = gimple_build_cond_empty (cond);
9247 gsi = gsi_last_bb (cond_bb);
9248 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9250 gsi = gsi_start_bb (then_bb);
9251 stmt = gimple_build_assign (tmp_var, device);
9252 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9254 gsi = gsi_start_bb (else_bb);
9255 stmt = gimple_build_assign (tmp_var,
9256 build_int_cst (integer_type_node,
9257 GOMP_DEVICE_HOST_FALLBACK));
9258 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9260 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9261 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9262 add_bb_to_loop (then_bb, cond_bb->loop_father);
9263 add_bb_to_loop (else_bb, cond_bb->loop_father);
9264 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9265 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9267 device = tmp_var;
9270 gsi = gsi_last_bb (new_bb);
9271 t = gimple_omp_target_data_arg (entry_stmt);
9272 if (t == NULL)
9274 t1 = size_zero_node;
9275 t2 = build_zero_cst (ptr_type_node);
9276 t3 = t2;
9277 t4 = t2;
9279 else
9281 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9282 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9283 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9284 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9285 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9288 gimple g;
9289 /* The maximum number used by any start_ix, without varargs. */
9290 auto_vec<tree, 11> args;
9291 args.quick_push (device);
9292 if (offloaded)
9293 args.quick_push (build_fold_addr_expr (child_fn));
9294 switch (start_ix)
9296 case BUILT_IN_GOMP_TARGET:
9297 case BUILT_IN_GOMP_TARGET_DATA:
9298 case BUILT_IN_GOMP_TARGET_UPDATE:
9299 /* This const void * is part of the current ABI, but we're not actually
9300 using it. */
9301 args.quick_push (build_zero_cst (ptr_type_node));
9302 break;
9303 case BUILT_IN_GOACC_DATA_START:
9304 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9305 case BUILT_IN_GOACC_PARALLEL:
9306 case BUILT_IN_GOACC_UPDATE:
9307 break;
9308 default:
9309 gcc_unreachable ();
9311 args.quick_push (t1);
9312 args.quick_push (t2);
9313 args.quick_push (t3);
9314 args.quick_push (t4);
9315 switch (start_ix)
9317 case BUILT_IN_GOACC_DATA_START:
9318 case BUILT_IN_GOMP_TARGET:
9319 case BUILT_IN_GOMP_TARGET_DATA:
9320 case BUILT_IN_GOMP_TARGET_UPDATE:
9321 break;
9322 case BUILT_IN_GOACC_PARALLEL:
9324 tree t_num_gangs, t_num_workers, t_vector_length;
9326 /* Default values for num_gangs, num_workers, and vector_length. */
9327 t_num_gangs = t_num_workers = t_vector_length
9328 = fold_convert_loc (gimple_location (entry_stmt),
9329 integer_type_node, integer_one_node);
9330 /* ..., but if present, use the value specified by the respective
9331 clause, making sure that are of the correct type. */
9332 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9333 if (c)
9334 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9335 integer_type_node,
9336 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9337 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9338 if (c)
9339 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9340 integer_type_node,
9341 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9342 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9343 if (c)
9344 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9345 integer_type_node,
9346 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9347 args.quick_push (t_num_gangs);
9348 args.quick_push (t_num_workers);
9349 args.quick_push (t_vector_length);
9351 /* FALLTHRU */
9352 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9353 case BUILT_IN_GOACC_UPDATE:
9355 tree t_async;
9356 int t_wait_idx;
9358 /* Default values for t_async. */
9359 t_async = fold_convert_loc (gimple_location (entry_stmt),
9360 integer_type_node,
9361 build_int_cst (integer_type_node,
9362 GOMP_ASYNC_SYNC));
9363 /* ..., but if present, use the value specified by the respective
9364 clause, making sure that is of the correct type. */
9365 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9366 if (c)
9367 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9368 integer_type_node,
9369 OMP_CLAUSE_ASYNC_EXPR (c));
9371 args.quick_push (t_async);
9372 /* Save the index, and... */
9373 t_wait_idx = args.length ();
9374 /* ... push a default value. */
9375 args.quick_push (fold_convert_loc (gimple_location (entry_stmt),
9376 integer_type_node,
9377 integer_zero_node));
9378 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9379 if (c)
9381 int n = 0;
9383 for (; c; c = OMP_CLAUSE_CHAIN (c))
9385 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9387 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9388 integer_type_node,
9389 OMP_CLAUSE_WAIT_EXPR (c)));
9390 n++;
9394 /* Now that we know the number, replace the default value. */
9395 args.ordered_remove (t_wait_idx);
9396 args.quick_insert (t_wait_idx,
9397 fold_convert_loc (gimple_location (entry_stmt),
9398 integer_type_node,
9399 build_int_cst (integer_type_node, n)));
9402 break;
9403 default:
9404 gcc_unreachable ();
9407 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
9408 gimple_set_location (g, gimple_location (entry_stmt));
9409 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9410 if (!offloaded)
9412 g = gsi_stmt (gsi);
9413 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9414 gsi_remove (&gsi, true);
9416 if (data_region
9417 && region->exit)
9419 gsi = gsi_last_bb (region->exit);
9420 g = gsi_stmt (gsi);
9421 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9422 gsi_remove (&gsi, true);
9426 /* Analyze a PARALLEL region and decide whether it should be turned into an HSA
9427 kernel, i.e. whether it should just contain the body of the loop and work
9428 sharing should be decided by kernel attributes and HSA run time. */
9430 static void
9431 analyze_kernelizability (struct omp_region *parallel)
9433 gcc_checking_assert (parallel->type == GIMPLE_OMP_PARALLEL);
9434 struct omp_region *inner = parallel->inner;
9435 if (!inner)
9437 if (dump_enabled_p ())
9438 dump_printf_loc (MSG_NOTE,
9439 gimple_location (last_stmt (parallel->entry)),
9440 "Will not turn parallel construct into kernel "
9441 "because it contains no nested constructs\n");
9442 return;
9444 if (inner->next)
9446 if (dump_enabled_p ())
9447 dump_printf_loc (MSG_NOTE,
9448 gimple_location (last_stmt (parallel->entry)),
9449 "Will not turn parallel construct into kernel "
9450 "because it contains multiple OMP constructs\n");
9451 return;
9453 if (inner->type != GIMPLE_OMP_FOR)
9455 if (dump_enabled_p ())
9456 dump_printf_loc (MSG_NOTE,
9457 gimple_location (last_stmt (parallel->entry)),
9458 "Will not turn parallel construct into kernel "
9459 "because it contains a non-looping construct\n");
9460 return;
9462 struct omp_region *in2 = inner->inner;
9463 while (in2 && (in2->type == GIMPLE_OMP_ATOMIC_LOAD
9464 || in2->type == GIMPLE_OMP_ATOMIC_STORE))
9465 in2 = inner->next;
9466 if (in2)
9468 if (dump_enabled_p ())
9469 dump_printf_loc (MSG_NOTE,
9470 gimple_location (last_stmt (parallel->entry)),
9471 "Will not turn parallel construct into kernel "
9472 "because the inner construct has nested constructs\n");
9473 return;
9475 if (!inner->cont)
9477 if (dump_enabled_p ())
9478 dump_printf_loc (MSG_NOTE,
9479 gimple_location (last_stmt (parallel->entry)),
9480 "Will not turn parallel construct into kernel "
9481 "because it is not clear where its loop ends\n");
9482 return;
9484 gcc_assert (inner->exit);
9485 gomp_for *for_stmt = as_a <gomp_for *> (last_stmt (inner->entry));
9486 if (gimple_omp_for_combined_p (for_stmt))
9488 if (dump_enabled_p ())
9489 dump_printf_loc (MSG_NOTE,
9490 gimple_location (last_stmt (parallel->entry)),
9491 "Will not turn parallel construct into kernel "
9492 "because it is gimple_omp_for_combined_p\n");
9493 return;
9495 struct omp_for_data fd;
9496 extract_omp_for_data (for_stmt, &fd, NULL);
9497 if (fd.collapse > 1)
9499 dump_printf_loc (MSG_NOTE,
9500 gimple_location (last_stmt (parallel->entry)),
9501 "Will not turn parallel construct into kernel "
9502 "because it uses collapse clause\n");
9503 return;
9505 if (fd.sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
9506 && fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO)
9508 if (dump_enabled_p ())
9509 dump_printf_loc (MSG_NOTE,
9510 gimple_location (last_stmt (parallel->entry)),
9511 "Will not turn parallel construct into kernel "
9512 "because we cannot handle the selected scheduling\n");
9513 return;
9515 if (fd.have_ordered)
9517 if (dump_enabled_p ())
9518 dump_printf_loc (MSG_NOTE,
9519 gimple_location (last_stmt (parallel->entry)),
9520 "Will not turn parallel construct into kernel "
9521 "because it has ordered clause\n");
9522 return;
9524 if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9526 if (dump_enabled_p ())
9527 dump_printf_loc (MSG_NOTE,
9528 gimple_location (last_stmt (parallel->entry)),
9529 "Will not turn parallel construct into kernel "
9530 "because it contains distribute construct\n");
9531 return;
9534 if (dump_enabled_p ())
9535 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS,
9536 gimple_location (last_stmt (parallel->entry)),
9537 "Parallel construct will be turned into an HSA kernel\n");
9538 parallel->kernelize = true;
9539 inner->kernelize = true;
9542 /* Expand the parallel region tree rooted at REGION. Expansion
9543 proceeds in depth-first order. Innermost regions are expanded
9544 first. This way, parallel regions that require a new function to
9545 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9546 internal dependencies in their body. WITHIN_PARALLEL must be true if
9547 REGION is located within a parallel construct. */
9549 static void
9550 expand_omp (struct omp_region *region, bool within_parallel)
9552 while (region)
9554 location_t saved_location;
9555 gimple inner_stmt = NULL;
9557 /* First, determine whether this is a combined parallel+workshare
9558 region. */
9559 if (region->type == GIMPLE_OMP_PARALLEL)
9561 determine_parallel_type (region);
9562 if (!within_parallel)
9563 analyze_kernelizability (region);
9564 else if (dump_enabled_p ())
9565 dump_printf_loc (MSG_NOTE,
9566 gimple_location (last_stmt (region->entry)),
9567 "Will not turn parallel construct into kernel "
9568 "because it is located within another parallel "
9569 "construct\n");
9572 if (region->type == GIMPLE_OMP_FOR
9573 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9574 inner_stmt = last_stmt (region->inner->entry);
9576 if (region->inner)
9577 expand_omp (region->inner,
9578 within_parallel || (region->type == GIMPLE_OMP_PARALLEL));
9580 saved_location = input_location;
9581 if (gimple_has_location (last_stmt (region->entry)))
9582 input_location = gimple_location (last_stmt (region->entry));
9584 switch (region->type)
9586 case GIMPLE_OMP_PARALLEL:
9587 case GIMPLE_OMP_TASK:
9588 expand_omp_taskreg (region);
9589 break;
9591 case GIMPLE_OMP_FOR:
9592 expand_omp_for (region, inner_stmt);
9593 break;
9595 case GIMPLE_OMP_SECTIONS:
9596 expand_omp_sections (region);
9597 break;
9599 case GIMPLE_OMP_SECTION:
9600 /* Individual omp sections are handled together with their
9601 parent GIMPLE_OMP_SECTIONS region. */
9602 break;
9604 case GIMPLE_OMP_SINGLE:
9605 expand_omp_single (region);
9606 break;
9608 case GIMPLE_OMP_MASTER:
9609 case GIMPLE_OMP_TASKGROUP:
9610 case GIMPLE_OMP_ORDERED:
9611 case GIMPLE_OMP_CRITICAL:
9612 case GIMPLE_OMP_TEAMS:
9613 expand_omp_synch (region);
9614 break;
9616 case GIMPLE_OMP_ATOMIC_LOAD:
9617 expand_omp_atomic (region);
9618 break;
9620 case GIMPLE_OMP_TARGET:
9621 expand_omp_target (region);
9622 break;
9624 default:
9625 gcc_unreachable ();
9628 input_location = saved_location;
9629 region = region->next;
9634 /* Helper for build_omp_regions. Scan the dominator tree starting at
9635 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9636 true, the function ends once a single tree is built (otherwise, whole
9637 forest of OMP constructs may be built). */
9639 static void
9640 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9641 bool single_tree)
9643 gimple_stmt_iterator gsi;
9644 gimple stmt;
9645 basic_block son;
9647 gsi = gsi_last_bb (bb);
9648 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9650 struct omp_region *region;
9651 enum gimple_code code;
9653 stmt = gsi_stmt (gsi);
9654 code = gimple_code (stmt);
9655 if (code == GIMPLE_OMP_RETURN)
9657 /* STMT is the return point out of region PARENT. Mark it
9658 as the exit point and make PARENT the immediately
9659 enclosing region. */
9660 gcc_assert (parent);
9661 region = parent;
9662 region->exit = bb;
9663 parent = parent->outer;
9665 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9667 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9668 GIMPLE_OMP_RETURN, but matches with
9669 GIMPLE_OMP_ATOMIC_LOAD. */
9670 gcc_assert (parent);
9671 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9672 region = parent;
9673 region->exit = bb;
9674 parent = parent->outer;
9676 else if (code == GIMPLE_OMP_CONTINUE)
9678 gcc_assert (parent);
9679 parent->cont = bb;
9681 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9683 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9684 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9686 else
9688 region = new_omp_region (bb, code, parent);
9689 /* Otherwise... */
9690 if (code == GIMPLE_OMP_TARGET)
9692 switch (gimple_omp_target_kind (stmt))
9694 case GF_OMP_TARGET_KIND_REGION:
9695 case GF_OMP_TARGET_KIND_DATA:
9696 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9697 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9698 case GF_OMP_TARGET_KIND_OACC_DATA:
9699 break;
9700 case GF_OMP_TARGET_KIND_UPDATE:
9701 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9702 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9703 /* ..., other than for those stand-alone directives... */
9704 region = NULL;
9705 break;
9706 default:
9707 gcc_unreachable ();
9710 /* ..., this directive becomes the parent for a new region. */
9711 if (region)
9712 parent = region;
9716 if (single_tree && !parent)
9717 return;
9719 for (son = first_dom_son (CDI_DOMINATORS, bb);
9720 son;
9721 son = next_dom_son (CDI_DOMINATORS, son))
9722 build_omp_regions_1 (son, parent, single_tree);
9725 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9726 root_omp_region. */
9728 static void
9729 build_omp_regions_root (basic_block root)
9731 gcc_assert (root_omp_region == NULL);
9732 build_omp_regions_1 (root, NULL, true);
9733 gcc_assert (root_omp_region != NULL);
9736 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9738 void
9739 omp_expand_local (basic_block head)
9741 build_omp_regions_root (head);
9742 if (dump_file && (dump_flags & TDF_DETAILS))
9744 fprintf (dump_file, "\nOMP region tree\n\n");
9745 dump_omp_region (dump_file, root_omp_region, 0);
9746 fprintf (dump_file, "\n");
9749 remove_exit_barriers (root_omp_region);
9750 expand_omp (root_omp_region, false);
9752 free_omp_regions ();
9755 /* Scan the CFG and build a tree of OMP regions. Return the root of
9756 the OMP region tree. */
9758 static void
9759 build_omp_regions (void)
9761 gcc_assert (root_omp_region == NULL);
9762 calculate_dominance_info (CDI_DOMINATORS);
9763 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9766 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9768 static unsigned int
9769 execute_expand_omp (void)
9771 build_omp_regions ();
9773 if (!root_omp_region)
9774 return 0;
9776 if (dump_file)
9778 fprintf (dump_file, "\nOMP region tree\n\n");
9779 dump_omp_region (dump_file, root_omp_region, 0);
9780 fprintf (dump_file, "\n");
9783 remove_exit_barriers (root_omp_region);
9785 expand_omp (root_omp_region, false);
9787 cleanup_tree_cfg ();
9789 free_omp_regions ();
9791 return 0;
9794 /* OMP expansion -- the default pass, run before creation of SSA form. */
9796 namespace {
9798 const pass_data pass_data_expand_omp =
9800 GIMPLE_PASS, /* type */
9801 "ompexp", /* name */
9802 OPTGROUP_NONE, /* optinfo_flags */
9803 TV_NONE, /* tv_id */
9804 PROP_gimple_any, /* properties_required */
9805 PROP_gimple_eomp, /* properties_provided */
9806 0, /* properties_destroyed */
9807 0, /* todo_flags_start */
9808 0, /* todo_flags_finish */
9811 class pass_expand_omp : public gimple_opt_pass
9813 public:
9814 pass_expand_omp (gcc::context *ctxt)
9815 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9818 /* opt_pass methods: */
9819 virtual unsigned int execute (function *)
9821 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9822 || flag_openmp_simd != 0)
9823 && !seen_error ());
9825 /* This pass always runs, to provide PROP_gimple_eomp.
9826 But often, there is nothing to do. */
9827 if (!gate)
9828 return 0;
9830 return execute_expand_omp ();
9833 }; // class pass_expand_omp
9835 } // anon namespace
9837 gimple_opt_pass *
9838 make_pass_expand_omp (gcc::context *ctxt)
9840 return new pass_expand_omp (ctxt);
9843 namespace {
9845 const pass_data pass_data_expand_omp_ssa =
9847 GIMPLE_PASS, /* type */
9848 "ompexpssa", /* name */
9849 OPTGROUP_NONE, /* optinfo_flags */
9850 TV_NONE, /* tv_id */
9851 PROP_cfg | PROP_ssa, /* properties_required */
9852 PROP_gimple_eomp, /* properties_provided */
9853 0, /* properties_destroyed */
9854 0, /* todo_flags_start */
9855 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9858 class pass_expand_omp_ssa : public gimple_opt_pass
9860 public:
9861 pass_expand_omp_ssa (gcc::context *ctxt)
9862 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9865 /* opt_pass methods: */
9866 virtual bool gate (function *fun)
9868 return !(fun->curr_properties & PROP_gimple_eomp);
9870 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9872 }; // class pass_expand_omp_ssa
9874 } // anon namespace
9876 gimple_opt_pass *
9877 make_pass_expand_omp_ssa (gcc::context *ctxt)
9879 return new pass_expand_omp_ssa (ctxt);
9882 /* Routines to lower OMP directives into OMP-GIMPLE. */
9884 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9885 convert it to gimple. */
9886 static void
9887 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9889 gimple stmt;
9891 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9893 stmt = gimple_build_assign (dest, op, dest, src);
9894 gimple_seq_add_stmt (seq, stmt);
9895 return;
9898 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9899 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9900 gimplify_assign (t, rdest, seq);
9901 rdest = t;
9903 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9904 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9905 gimplify_assign (t, idest, seq);
9906 idest = t;
9908 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9909 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9910 gimplify_assign (t, rsrc, seq);
9911 rsrc = t;
9913 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9914 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9915 gimplify_assign (t, isrc, seq);
9916 isrc = t;
9918 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9919 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9920 tree result;
9922 if (op == PLUS_EXPR)
9924 stmt = gimple_build_assign (r, op, rdest, rsrc);
9925 gimple_seq_add_stmt (seq, stmt);
9927 stmt = gimple_build_assign (i, op, idest, isrc);
9928 gimple_seq_add_stmt (seq, stmt);
9930 else if (op == MULT_EXPR)
9932 /* Let x = a + ib = dest, y = c + id = src.
9933 x * y = (ac - bd) + i(ad + bc) */
9934 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9935 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9936 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9937 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9939 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9940 gimple_seq_add_stmt (seq, stmt);
9942 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9943 gimple_seq_add_stmt (seq, stmt);
9945 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9946 gimple_seq_add_stmt (seq, stmt);
9948 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9949 gimple_seq_add_stmt (seq, stmt);
9951 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9952 gimple_seq_add_stmt (seq, stmt);
9954 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9955 gimple_seq_add_stmt (seq, stmt);
9957 else
9958 gcc_unreachable ();
9960 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9961 gimplify_assign (dest, result, seq);
9964 /* Helper function to initialize local data for the reduction arrays.
9965 The reduction arrays need to be placed inside the calling function
9966 for accelerators, or else the host won't be able to preform the final
9967 reduction. */
9969 static void
9970 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9971 gimple_seq *stmt_seqp, omp_context *ctx)
9973 tree c, t, oc;
9974 gimple stmt;
9975 omp_context *octx;
9977 /* Find the innermost OpenACC parallel context. */
9978 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9979 && (gimple_omp_target_kind (ctx->stmt)
9980 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9981 octx = ctx;
9982 else
9983 octx = ctx->outer;
9984 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9985 && (gimple_omp_target_kind (octx->stmt)
9986 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9988 /* Extract the clauses. */
9989 oc = gimple_omp_target_clauses (octx->stmt);
9991 /* Find the last outer clause. */
9992 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9995 /* Allocate arrays for each reduction variable. */
9996 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9998 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9999 continue;
10001 tree var = OMP_CLAUSE_DECL (c);
10002 tree type = get_base_type (var);
10003 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
10004 ctx);
10005 tree size, call;
10007 /* Calculate size of the reduction array. */
10008 t = create_tmp_var (TREE_TYPE (nthreads));
10009 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
10010 fold_convert (TREE_TYPE (nthreads),
10011 TYPE_SIZE_UNIT (type)));
10012 gimple_seq_add_stmt (stmt_seqp, stmt);
10014 size = create_tmp_var (sizetype);
10015 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
10017 /* Now allocate memory for it. */
10018 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
10019 stmt = gimple_build_call (call, 1, size);
10020 gimple_call_set_lhs (stmt, array);
10021 gimple_seq_add_stmt (stmt_seqp, stmt);
10023 /* Map this array into the accelerator. */
10025 /* Add the reduction array to the list of clauses. */
10026 tree x = array;
10027 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
10028 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
10029 OMP_CLAUSE_DECL (t) = x;
10030 OMP_CLAUSE_CHAIN (t) = NULL;
10031 if (oc)
10032 OMP_CLAUSE_CHAIN (oc) = t;
10033 else
10034 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
10035 OMP_CLAUSE_SIZE (t) = size;
10036 oc = t;
10040 /* Helper function to process the array of partial reductions. Nthreads
10041 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
10042 cannot be used here, because nthreads on the host may be different than
10043 on the accelerator. */
10045 static void
10046 oacc_finalize_reduction_data (tree clauses, tree nthreads,
10047 gimple_seq *stmt_seqp, omp_context *ctx)
10049 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
10050 gimple stmt;
10052 /* Create for loop.
10054 let var = the original reduction variable
10055 let array = reduction variable array
10057 for (i = 0; i < nthreads; i++)
10058 var op= array[i]
10061 loop_header = create_artificial_label (UNKNOWN_LOCATION);
10062 loop_body = create_artificial_label (UNKNOWN_LOCATION);
10063 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
10065 /* Create and initialize an index variable. */
10066 tree ix = create_tmp_var (sizetype);
10067 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
10068 stmt_seqp);
10070 /* Insert the loop header label here. */
10071 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
10073 /* Exit loop if ix >= nthreads. */
10074 x = create_tmp_var (sizetype);
10075 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
10076 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
10077 gimple_seq_add_stmt (stmt_seqp, stmt);
10079 /* Insert the loop body label here. */
10080 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
10082 /* Collapse each reduction array, one element at a time. */
10083 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10085 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
10086 continue;
10088 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
10090 /* reduction(-:var) sums up the partial results, so it acts
10091 identically to reduction(+:var). */
10092 if (reduction_code == MINUS_EXPR)
10093 reduction_code = PLUS_EXPR;
10095 /* Set up reduction variable var. */
10096 var = OMP_CLAUSE_DECL (c);
10097 type = get_base_type (var);
10098 array = lookup_oacc_reduction (oacc_get_reduction_array_id
10099 (OMP_CLAUSE_DECL (c)), ctx);
10101 /* Calculate the array offset. */
10102 tree offset = create_tmp_var (sizetype);
10103 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
10104 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
10105 gimple_seq_add_stmt (stmt_seqp, stmt);
10107 tree ptr = create_tmp_var (TREE_TYPE (array));
10108 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
10109 gimple_seq_add_stmt (stmt_seqp, stmt);
10111 /* Extract array[ix] into mem. */
10112 tree mem = create_tmp_var (type);
10113 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
10115 /* Find the original reduction variable. */
10116 if (is_reference (var))
10117 var = build_simple_mem_ref (var);
10119 tree t = create_tmp_var (type);
10121 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
10122 gimplify_and_add (unshare_expr(x), stmt_seqp);
10124 /* var = var op mem */
10125 switch (OMP_CLAUSE_REDUCTION_CODE (c))
10127 case TRUTH_ANDIF_EXPR:
10128 case TRUTH_ORIF_EXPR:
10129 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
10130 t, mem);
10131 gimplify_and_add (t, stmt_seqp);
10132 break;
10133 default:
10134 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
10135 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
10136 stmt_seqp);
10139 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
10140 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
10141 gimplify_and_add (unshare_expr(x), stmt_seqp);
10144 /* Increment the induction variable. */
10145 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
10146 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
10147 gimple_seq_add_stmt (stmt_seqp, stmt);
10149 /* Go back to the top of the loop. */
10150 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
10152 /* Place the loop exit label here. */
10153 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
10156 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
10157 scan that for reductions. */
10159 static void
10160 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
10161 gimple_seq *out_stmt_seqp, omp_context *ctx)
10163 gimple_stmt_iterator gsi;
10164 gimple_seq inner = NULL;
10166 /* A collapse clause may have inserted a new bind block. */
10167 gsi = gsi_start (*body);
10168 while (!gsi_end_p (gsi))
10170 gimple stmt = gsi_stmt (gsi);
10171 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
10173 inner = gimple_bind_body (bind_stmt);
10174 body = &inner;
10175 gsi = gsi_start (*body);
10177 else if (dyn_cast <gomp_for *> (stmt))
10178 break;
10179 else
10180 gsi_next (&gsi);
10183 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
10185 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
10186 enter, exit;
10187 bool reduction_found = false;
10189 gimple stmt = gsi_stmt (gsi);
10191 switch (gimple_code (stmt))
10193 case GIMPLE_OMP_FOR:
10194 clauses = gimple_omp_for_clauses (stmt);
10196 /* Search for a reduction clause. */
10197 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
10198 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
10200 reduction_found = true;
10201 break;
10204 if (!reduction_found)
10205 break;
10207 ctx = maybe_lookup_ctx (stmt);
10208 t = NULL_TREE;
10210 /* Extract the number of threads. */
10211 nthreads = create_tmp_var (sizetype);
10212 t = oacc_max_threads (ctx);
10213 gimplify_assign (nthreads, t, in_stmt_seqp);
10215 /* Determine if this is kernel will be executed on the host. */
10216 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
10217 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
10218 stmt = gimple_build_call (call, 0);
10219 gimple_call_set_lhs (stmt, acc_device);
10220 gimple_seq_add_stmt (in_stmt_seqp, stmt);
10222 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
10223 acc_device_host = create_tmp_var (integer_type_node,
10224 ".acc_device_host");
10225 gimplify_assign (acc_device_host,
10226 build_int_cst (integer_type_node,
10227 GOMP_DEVICE_HOST),
10228 in_stmt_seqp);
10230 enter = create_artificial_label (UNKNOWN_LOCATION);
10231 exit = create_artificial_label (UNKNOWN_LOCATION);
10233 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
10234 enter, exit);
10235 gimple_seq_add_stmt (in_stmt_seqp, stmt);
10236 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
10237 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
10238 integer_one_node),
10239 in_stmt_seqp);
10240 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
10242 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
10243 gimplify_assign (acc_device_host,
10244 build_int_cst (integer_type_node,
10245 GOMP_DEVICE_HOST_NONSHM),
10246 in_stmt_seqp);
10248 enter = create_artificial_label (UNKNOWN_LOCATION);
10249 exit = create_artificial_label (UNKNOWN_LOCATION);
10251 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
10252 enter, exit);
10253 gimple_seq_add_stmt (in_stmt_seqp, stmt);
10254 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
10255 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
10256 integer_one_node),
10257 in_stmt_seqp);
10258 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
10260 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
10261 ctx);
10262 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
10263 break;
10264 default:
10265 // Scan for other directives which support reduction here.
10266 break;
10271 /* If ctx is a worksharing context inside of a cancellable parallel
10272 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
10273 and conditional branch to parallel's cancel_label to handle
10274 cancellation in the implicit barrier. */
10276 static void
10277 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
10279 gimple omp_return = gimple_seq_last_stmt (*body);
10280 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
10281 if (gimple_omp_return_nowait_p (omp_return))
10282 return;
10283 if (ctx->outer
10284 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
10285 && ctx->outer->cancellable)
10287 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
10288 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
10289 tree lhs = create_tmp_var (c_bool_type);
10290 gimple_omp_return_set_lhs (omp_return, lhs);
10291 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
10292 gimple g = gimple_build_cond (NE_EXPR, lhs,
10293 fold_convert (c_bool_type,
10294 boolean_false_node),
10295 ctx->outer->cancel_label, fallthru_label);
10296 gimple_seq_add_stmt (body, g);
10297 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
10301 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10302 CTX is the enclosing OMP context for the current statement. */
10304 static void
10305 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10307 tree block, control;
10308 gimple_stmt_iterator tgsi;
10309 gomp_sections *stmt;
10310 gimple t;
10311 gbind *new_stmt, *bind;
10312 gimple_seq ilist, dlist, olist, new_body;
10314 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
10316 push_gimplify_context ();
10318 dlist = NULL;
10319 ilist = NULL;
10320 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10321 &ilist, &dlist, ctx, NULL);
10323 new_body = gimple_omp_body (stmt);
10324 gimple_omp_set_body (stmt, NULL);
10325 tgsi = gsi_start (new_body);
10326 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10328 omp_context *sctx;
10329 gimple sec_start;
10331 sec_start = gsi_stmt (tgsi);
10332 sctx = maybe_lookup_ctx (sec_start);
10333 gcc_assert (sctx);
10335 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10336 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10337 GSI_CONTINUE_LINKING);
10338 gimple_omp_set_body (sec_start, NULL);
10340 if (gsi_one_before_end_p (tgsi))
10342 gimple_seq l = NULL;
10343 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10344 &l, ctx);
10345 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10346 gimple_omp_section_set_last (sec_start);
10349 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10350 GSI_CONTINUE_LINKING);
10353 block = make_node (BLOCK);
10354 bind = gimple_build_bind (NULL, new_body, block);
10356 olist = NULL;
10357 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10359 block = make_node (BLOCK);
10360 new_stmt = gimple_build_bind (NULL, NULL, block);
10361 gsi_replace (gsi_p, new_stmt, true);
10363 pop_gimplify_context (new_stmt);
10364 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10365 BLOCK_VARS (block) = gimple_bind_vars (bind);
10366 if (BLOCK_VARS (block))
10367 TREE_USED (block) = 1;
10369 new_body = NULL;
10370 gimple_seq_add_seq (&new_body, ilist);
10371 gimple_seq_add_stmt (&new_body, stmt);
10372 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10373 gimple_seq_add_stmt (&new_body, bind);
10375 control = create_tmp_var (unsigned_type_node, ".section");
10376 t = gimple_build_omp_continue (control, control);
10377 gimple_omp_sections_set_control (stmt, control);
10378 gimple_seq_add_stmt (&new_body, t);
10380 gimple_seq_add_seq (&new_body, olist);
10381 if (ctx->cancellable)
10382 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10383 gimple_seq_add_seq (&new_body, dlist);
10385 new_body = maybe_catch_exception (new_body);
10387 t = gimple_build_omp_return
10388 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10389 OMP_CLAUSE_NOWAIT));
10390 gimple_seq_add_stmt (&new_body, t);
10391 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10393 gimple_bind_set_body (new_stmt, new_body);
10397 /* A subroutine of lower_omp_single. Expand the simple form of
10398 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10400 if (GOMP_single_start ())
10401 BODY;
10402 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10404 FIXME. It may be better to delay expanding the logic of this until
10405 pass_expand_omp. The expanded logic may make the job more difficult
10406 to a synchronization analysis pass. */
10408 static void
10409 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10411 location_t loc = gimple_location (single_stmt);
10412 tree tlabel = create_artificial_label (loc);
10413 tree flabel = create_artificial_label (loc);
10414 gimple call, cond;
10415 tree lhs, decl;
10417 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10418 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10419 call = gimple_build_call (decl, 0);
10420 gimple_call_set_lhs (call, lhs);
10421 gimple_seq_add_stmt (pre_p, call);
10423 cond = gimple_build_cond (EQ_EXPR, lhs,
10424 fold_convert_loc (loc, TREE_TYPE (lhs),
10425 boolean_true_node),
10426 tlabel, flabel);
10427 gimple_seq_add_stmt (pre_p, cond);
10428 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10429 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10430 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10434 /* A subroutine of lower_omp_single. Expand the simple form of
10435 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10437 #pragma omp single copyprivate (a, b, c)
10439 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10442 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10444 BODY;
10445 copyout.a = a;
10446 copyout.b = b;
10447 copyout.c = c;
10448 GOMP_single_copy_end (&copyout);
10450 else
10452 a = copyout_p->a;
10453 b = copyout_p->b;
10454 c = copyout_p->c;
10456 GOMP_barrier ();
10459 FIXME. It may be better to delay expanding the logic of this until
10460 pass_expand_omp. The expanded logic may make the job more difficult
10461 to a synchronization analysis pass. */
10463 static void
10464 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10465 omp_context *ctx)
10467 tree ptr_type, t, l0, l1, l2, bfn_decl;
10468 gimple_seq copyin_seq;
10469 location_t loc = gimple_location (single_stmt);
10471 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10473 ptr_type = build_pointer_type (ctx->record_type);
10474 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10476 l0 = create_artificial_label (loc);
10477 l1 = create_artificial_label (loc);
10478 l2 = create_artificial_label (loc);
10480 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10481 t = build_call_expr_loc (loc, bfn_decl, 0);
10482 t = fold_convert_loc (loc, ptr_type, t);
10483 gimplify_assign (ctx->receiver_decl, t, pre_p);
10485 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10486 build_int_cst (ptr_type, 0));
10487 t = build3 (COND_EXPR, void_type_node, t,
10488 build_and_jump (&l0), build_and_jump (&l1));
10489 gimplify_and_add (t, pre_p);
10491 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10493 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10495 copyin_seq = NULL;
10496 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10497 &copyin_seq, ctx);
10499 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10500 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10501 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10502 gimplify_and_add (t, pre_p);
10504 t = build_and_jump (&l2);
10505 gimplify_and_add (t, pre_p);
10507 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10509 gimple_seq_add_seq (pre_p, copyin_seq);
10511 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10515 /* Expand code for an OpenMP single directive. */
10517 static void
10518 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10520 tree block;
10521 gimple t;
10522 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10523 gbind *bind;
10524 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10526 push_gimplify_context ();
10528 block = make_node (BLOCK);
10529 bind = gimple_build_bind (NULL, NULL, block);
10530 gsi_replace (gsi_p, bind, true);
10531 bind_body = NULL;
10532 dlist = NULL;
10533 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10534 &bind_body, &dlist, ctx, NULL);
10535 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10537 gimple_seq_add_stmt (&bind_body, single_stmt);
10539 if (ctx->record_type)
10540 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10541 else
10542 lower_omp_single_simple (single_stmt, &bind_body);
10544 gimple_omp_set_body (single_stmt, NULL);
10546 gimple_seq_add_seq (&bind_body, dlist);
10548 bind_body = maybe_catch_exception (bind_body);
10550 t = gimple_build_omp_return
10551 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10552 OMP_CLAUSE_NOWAIT));
10553 gimple_seq_add_stmt (&bind_body_tail, t);
10554 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10555 if (ctx->record_type)
10557 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10558 tree clobber = build_constructor (ctx->record_type, NULL);
10559 TREE_THIS_VOLATILE (clobber) = 1;
10560 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10561 clobber), GSI_SAME_STMT);
10563 gimple_seq_add_seq (&bind_body, bind_body_tail);
10564 gimple_bind_set_body (bind, bind_body);
10566 pop_gimplify_context (bind);
10568 gimple_bind_append_vars (bind, ctx->block_vars);
10569 BLOCK_VARS (block) = ctx->block_vars;
10570 if (BLOCK_VARS (block))
10571 TREE_USED (block) = 1;
10575 /* Expand code for an OpenMP master directive. */
10577 static void
10578 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10580 tree block, lab = NULL, x, bfn_decl;
10581 gimple stmt = gsi_stmt (*gsi_p);
10582 gbind *bind;
10583 location_t loc = gimple_location (stmt);
10584 gimple_seq tseq;
10586 push_gimplify_context ();
10588 block = make_node (BLOCK);
10589 bind = gimple_build_bind (NULL, NULL, block);
10590 gsi_replace (gsi_p, bind, true);
10591 gimple_bind_add_stmt (bind, stmt);
10593 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10594 x = build_call_expr_loc (loc, bfn_decl, 0);
10595 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10596 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10597 tseq = NULL;
10598 gimplify_and_add (x, &tseq);
10599 gimple_bind_add_seq (bind, tseq);
10601 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10602 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10603 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10604 gimple_omp_set_body (stmt, NULL);
10606 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10608 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10610 pop_gimplify_context (bind);
10612 gimple_bind_append_vars (bind, ctx->block_vars);
10613 BLOCK_VARS (block) = ctx->block_vars;
10617 /* Expand code for an OpenMP taskgroup directive. */
10619 static void
10620 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10622 gimple stmt = gsi_stmt (*gsi_p);
10623 gcall *x;
10624 gbind *bind;
10625 tree block = make_node (BLOCK);
10627 bind = gimple_build_bind (NULL, NULL, block);
10628 gsi_replace (gsi_p, bind, true);
10629 gimple_bind_add_stmt (bind, stmt);
10631 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10633 gimple_bind_add_stmt (bind, x);
10635 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10636 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10637 gimple_omp_set_body (stmt, NULL);
10639 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10641 gimple_bind_append_vars (bind, ctx->block_vars);
10642 BLOCK_VARS (block) = ctx->block_vars;
10646 /* Expand code for an OpenMP ordered directive. */
10648 static void
10649 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10651 tree block;
10652 gimple stmt = gsi_stmt (*gsi_p);
10653 gcall *x;
10654 gbind *bind;
10656 push_gimplify_context ();
10658 block = make_node (BLOCK);
10659 bind = gimple_build_bind (NULL, NULL, block);
10660 gsi_replace (gsi_p, bind, true);
10661 gimple_bind_add_stmt (bind, stmt);
10663 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10665 gimple_bind_add_stmt (bind, x);
10667 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10668 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10669 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10670 gimple_omp_set_body (stmt, NULL);
10672 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10673 gimple_bind_add_stmt (bind, x);
10675 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10677 pop_gimplify_context (bind);
10679 gimple_bind_append_vars (bind, ctx->block_vars);
10680 BLOCK_VARS (block) = gimple_bind_vars (bind);
10684 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10685 substitution of a couple of function calls. But in the NAMED case,
10686 requires that languages coordinate a symbol name. It is therefore
10687 best put here in common code. */
10689 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10691 static void
10692 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10694 tree block;
10695 tree name, lock, unlock;
10696 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10697 gbind *bind;
10698 location_t loc = gimple_location (stmt);
10699 gimple_seq tbody;
10701 name = gimple_omp_critical_name (stmt);
10702 if (name)
10704 tree decl;
10706 if (!critical_name_mutexes)
10707 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10709 tree *n = critical_name_mutexes->get (name);
10710 if (n == NULL)
10712 char *new_str;
10714 decl = create_tmp_var_raw (ptr_type_node);
10716 new_str = ACONCAT ((".gomp_critical_user_",
10717 IDENTIFIER_POINTER (name), NULL));
10718 DECL_NAME (decl) = get_identifier (new_str);
10719 TREE_PUBLIC (decl) = 1;
10720 TREE_STATIC (decl) = 1;
10721 DECL_COMMON (decl) = 1;
10722 DECL_ARTIFICIAL (decl) = 1;
10723 DECL_IGNORED_P (decl) = 1;
10725 varpool_node::finalize_decl (decl);
10727 critical_name_mutexes->put (name, decl);
10729 else
10730 decl = *n;
10732 /* If '#pragma omp critical' is inside offloaded region or
10733 inside function marked as offloadable, the symbol must be
10734 marked as offloadable too. */
10735 omp_context *octx;
10736 if (cgraph_node::get (current_function_decl)->offloadable)
10737 varpool_node::get_create (decl)->offloadable = 1;
10738 else
10739 for (octx = ctx->outer; octx; octx = octx->outer)
10740 if (is_gimple_omp_offloaded (octx->stmt))
10742 varpool_node::get_create (decl)->offloadable = 1;
10743 break;
10746 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10747 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10749 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10750 unlock = build_call_expr_loc (loc, unlock, 1,
10751 build_fold_addr_expr_loc (loc, decl));
10753 else
10755 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10756 lock = build_call_expr_loc (loc, lock, 0);
10758 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10759 unlock = build_call_expr_loc (loc, unlock, 0);
10762 push_gimplify_context ();
10764 block = make_node (BLOCK);
10765 bind = gimple_build_bind (NULL, NULL, block);
10766 gsi_replace (gsi_p, bind, true);
10767 gimple_bind_add_stmt (bind, stmt);
10769 tbody = gimple_bind_body (bind);
10770 gimplify_and_add (lock, &tbody);
10771 gimple_bind_set_body (bind, tbody);
10773 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10774 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10775 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10776 gimple_omp_set_body (stmt, NULL);
10778 tbody = gimple_bind_body (bind);
10779 gimplify_and_add (unlock, &tbody);
10780 gimple_bind_set_body (bind, tbody);
10782 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10784 pop_gimplify_context (bind);
10785 gimple_bind_append_vars (bind, ctx->block_vars);
10786 BLOCK_VARS (block) = gimple_bind_vars (bind);
10790 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10791 for a lastprivate clause. Given a loop control predicate of (V
10792 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10793 is appended to *DLIST, iterator initialization is appended to
10794 *BODY_P. */
10796 static void
10797 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10798 gimple_seq *dlist, struct omp_context *ctx)
10800 tree clauses, cond, vinit;
10801 enum tree_code cond_code;
10802 gimple_seq stmts;
10804 cond_code = fd->loop.cond_code;
10805 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10807 /* When possible, use a strict equality expression. This can let VRP
10808 type optimizations deduce the value and remove a copy. */
10809 if (tree_fits_shwi_p (fd->loop.step))
10811 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10812 if (step == 1 || step == -1)
10813 cond_code = EQ_EXPR;
10816 tree n2 = fd->loop.n2;
10817 if (fd->collapse > 1
10818 && TREE_CODE (n2) != INTEGER_CST
10819 && gimple_omp_for_combined_into_p (fd->for_stmt)
10820 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
10822 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
10823 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR)
10825 struct omp_for_data outer_fd;
10826 extract_omp_for_data (gfor, &outer_fd, NULL);
10827 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
10830 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
10832 clauses = gimple_omp_for_clauses (fd->for_stmt);
10833 stmts = NULL;
10834 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10835 if (!gimple_seq_empty_p (stmts))
10837 gimple_seq_add_seq (&stmts, *dlist);
10838 *dlist = stmts;
10840 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10841 vinit = fd->loop.n1;
10842 if (cond_code == EQ_EXPR
10843 && tree_fits_shwi_p (fd->loop.n2)
10844 && ! integer_zerop (fd->loop.n2))
10845 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10846 else
10847 vinit = unshare_expr (vinit);
10849 /* Initialize the iterator variable, so that threads that don't execute
10850 any iterations don't execute the lastprivate clauses by accident. */
10851 gimplify_assign (fd->loop.v, vinit, body_p);
10856 /* Lower code for an OMP loop directive. */
10858 static void
10859 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10861 tree *rhs_p, block;
10862 struct omp_for_data fd, *fdp = NULL;
10863 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10864 gbind *new_stmt;
10865 gimple_seq omp_for_body, body, dlist;
10866 size_t i;
10868 push_gimplify_context ();
10870 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10872 block = make_node (BLOCK);
10873 new_stmt = gimple_build_bind (NULL, NULL, block);
10874 /* Replace at gsi right away, so that 'stmt' is no member
10875 of a sequence anymore as we're going to add to a different
10876 one below. */
10877 gsi_replace (gsi_p, new_stmt, true);
10879 /* Move declaration of temporaries in the loop body before we make
10880 it go away. */
10881 omp_for_body = gimple_omp_body (stmt);
10882 if (!gimple_seq_empty_p (omp_for_body)
10883 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10885 gbind *inner_bind
10886 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10887 tree vars = gimple_bind_vars (inner_bind);
10888 gimple_bind_append_vars (new_stmt, vars);
10889 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10890 keep them on the inner_bind and it's block. */
10891 gimple_bind_set_vars (inner_bind, NULL_TREE);
10892 if (gimple_bind_block (inner_bind))
10893 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10896 if (gimple_omp_for_combined_into_p (stmt))
10898 extract_omp_for_data (stmt, &fd, NULL);
10899 fdp = &fd;
10901 /* We need two temporaries with fd.loop.v type (istart/iend)
10902 and then (fd.collapse - 1) temporaries with the same
10903 type for count2 ... countN-1 vars if not constant. */
10904 size_t count = 2;
10905 tree type = fd.iter_type;
10906 if (fd.collapse > 1
10907 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10908 count += fd.collapse - 1;
10909 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10910 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10911 tree clauses = *pc;
10912 if (parallel_for)
10913 outerc
10914 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10915 OMP_CLAUSE__LOOPTEMP_);
10916 for (i = 0; i < count; i++)
10918 tree temp;
10919 if (parallel_for)
10921 gcc_assert (outerc);
10922 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10923 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10924 OMP_CLAUSE__LOOPTEMP_);
10926 else
10928 temp = create_tmp_var (type);
10929 insert_decl_map (&ctx->outer->cb, temp, temp);
10931 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10932 OMP_CLAUSE_DECL (*pc) = temp;
10933 pc = &OMP_CLAUSE_CHAIN (*pc);
10935 *pc = clauses;
10938 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10939 dlist = NULL;
10940 body = NULL;
10941 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10942 fdp);
10943 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10945 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10947 /* Lower the header expressions. At this point, we can assume that
10948 the header is of the form:
10950 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10952 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10953 using the .omp_data_s mapping, if needed. */
10954 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10956 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10957 if (!is_gimple_min_invariant (*rhs_p))
10958 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10960 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10961 if (!is_gimple_min_invariant (*rhs_p))
10962 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10964 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10965 if (!is_gimple_min_invariant (*rhs_p))
10966 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10969 /* Once lowered, extract the bounds and clauses. */
10970 extract_omp_for_data (stmt, &fd, NULL);
10972 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10974 gimple_seq_add_stmt (&body, stmt);
10975 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10977 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10978 fd.loop.v));
10980 /* After the loop, add exit clauses. */
10981 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10983 if (ctx->cancellable)
10984 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10986 gimple_seq_add_seq (&body, dlist);
10988 body = maybe_catch_exception (body);
10990 /* Region exit marker goes at the end of the loop body. */
10991 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10992 maybe_add_implicit_barrier_cancel (ctx, &body);
10993 pop_gimplify_context (new_stmt);
10995 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10996 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10997 if (BLOCK_VARS (block))
10998 TREE_USED (block) = 1;
11000 gimple_bind_set_body (new_stmt, body);
11001 gimple_omp_set_body (stmt, NULL);
11002 gimple_omp_for_set_pre_body (stmt, NULL);
11005 /* Callback for walk_stmts. Check if the current statement only contains
11006 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
11008 static tree
11009 check_combined_parallel (gimple_stmt_iterator *gsi_p,
11010 bool *handled_ops_p,
11011 struct walk_stmt_info *wi)
11013 int *info = (int *) wi->info;
11014 gimple stmt = gsi_stmt (*gsi_p);
11016 *handled_ops_p = true;
11017 switch (gimple_code (stmt))
11019 WALK_SUBSTMTS;
11021 case GIMPLE_OMP_FOR:
11022 case GIMPLE_OMP_SECTIONS:
11023 *info = *info == 0 ? 1 : -1;
11024 break;
11025 default:
11026 *info = -1;
11027 break;
11029 return NULL;
11032 struct omp_taskcopy_context
11034 /* This field must be at the beginning, as we do "inheritance": Some
11035 callback functions for tree-inline.c (e.g., omp_copy_decl)
11036 receive a copy_body_data pointer that is up-casted to an
11037 omp_context pointer. */
11038 copy_body_data cb;
11039 omp_context *ctx;
11042 static tree
11043 task_copyfn_copy_decl (tree var, copy_body_data *cb)
11045 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
11047 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
11048 return create_tmp_var (TREE_TYPE (var));
11050 return var;
11053 static tree
11054 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
11056 tree name, new_fields = NULL, type, f;
11058 type = lang_hooks.types.make_type (RECORD_TYPE);
11059 name = DECL_NAME (TYPE_NAME (orig_type));
11060 name = build_decl (gimple_location (tcctx->ctx->stmt),
11061 TYPE_DECL, name, type);
11062 TYPE_NAME (type) = name;
11064 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
11066 tree new_f = copy_node (f);
11067 DECL_CONTEXT (new_f) = type;
11068 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
11069 TREE_CHAIN (new_f) = new_fields;
11070 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
11071 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
11072 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
11073 &tcctx->cb, NULL);
11074 new_fields = new_f;
11075 tcctx->cb.decl_map->put (f, new_f);
11077 TYPE_FIELDS (type) = nreverse (new_fields);
11078 layout_type (type);
11079 return type;
11082 /* Create task copyfn. */
11084 static void
11085 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
11087 struct function *child_cfun;
11088 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
11089 tree record_type, srecord_type, bind, list;
11090 bool record_needs_remap = false, srecord_needs_remap = false;
11091 splay_tree_node n;
11092 struct omp_taskcopy_context tcctx;
11093 location_t loc = gimple_location (task_stmt);
11095 child_fn = gimple_omp_task_copy_fn (task_stmt);
11096 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
11097 gcc_assert (child_cfun->cfg == NULL);
11098 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
11100 /* Reset DECL_CONTEXT on function arguments. */
11101 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
11102 DECL_CONTEXT (t) = child_fn;
11104 /* Populate the function. */
11105 push_gimplify_context ();
11106 push_cfun (child_cfun);
11108 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
11109 TREE_SIDE_EFFECTS (bind) = 1;
11110 list = NULL;
11111 DECL_SAVED_TREE (child_fn) = bind;
11112 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
11114 /* Remap src and dst argument types if needed. */
11115 record_type = ctx->record_type;
11116 srecord_type = ctx->srecord_type;
11117 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
11118 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
11120 record_needs_remap = true;
11121 break;
11123 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
11124 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
11126 srecord_needs_remap = true;
11127 break;
11130 if (record_needs_remap || srecord_needs_remap)
11132 memset (&tcctx, '\0', sizeof (tcctx));
11133 tcctx.cb.src_fn = ctx->cb.src_fn;
11134 tcctx.cb.dst_fn = child_fn;
11135 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
11136 gcc_checking_assert (tcctx.cb.src_node);
11137 tcctx.cb.dst_node = tcctx.cb.src_node;
11138 tcctx.cb.src_cfun = ctx->cb.src_cfun;
11139 tcctx.cb.copy_decl = task_copyfn_copy_decl;
11140 tcctx.cb.eh_lp_nr = 0;
11141 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
11142 tcctx.cb.decl_map = new hash_map<tree, tree>;
11143 tcctx.ctx = ctx;
11145 if (record_needs_remap)
11146 record_type = task_copyfn_remap_type (&tcctx, record_type);
11147 if (srecord_needs_remap)
11148 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
11150 else
11151 tcctx.cb.decl_map = NULL;
11153 arg = DECL_ARGUMENTS (child_fn);
11154 TREE_TYPE (arg) = build_pointer_type (record_type);
11155 sarg = DECL_CHAIN (arg);
11156 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
11158 /* First pass: initialize temporaries used in record_type and srecord_type
11159 sizes and field offsets. */
11160 if (tcctx.cb.decl_map)
11161 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
11162 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
11164 tree *p;
11166 decl = OMP_CLAUSE_DECL (c);
11167 p = tcctx.cb.decl_map->get (decl);
11168 if (p == NULL)
11169 continue;
11170 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11171 sf = (tree) n->value;
11172 sf = *tcctx.cb.decl_map->get (sf);
11173 src = build_simple_mem_ref_loc (loc, sarg);
11174 src = omp_build_component_ref (src, sf);
11175 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
11176 append_to_statement_list (t, &list);
11179 /* Second pass: copy shared var pointers and copy construct non-VLA
11180 firstprivate vars. */
11181 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
11182 switch (OMP_CLAUSE_CODE (c))
11184 case OMP_CLAUSE_SHARED:
11185 decl = OMP_CLAUSE_DECL (c);
11186 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11187 if (n == NULL)
11188 break;
11189 f = (tree) n->value;
11190 if (tcctx.cb.decl_map)
11191 f = *tcctx.cb.decl_map->get (f);
11192 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11193 sf = (tree) n->value;
11194 if (tcctx.cb.decl_map)
11195 sf = *tcctx.cb.decl_map->get (sf);
11196 src = build_simple_mem_ref_loc (loc, sarg);
11197 src = omp_build_component_ref (src, sf);
11198 dst = build_simple_mem_ref_loc (loc, arg);
11199 dst = omp_build_component_ref (dst, f);
11200 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
11201 append_to_statement_list (t, &list);
11202 break;
11203 case OMP_CLAUSE_FIRSTPRIVATE:
11204 decl = OMP_CLAUSE_DECL (c);
11205 if (is_variable_sized (decl))
11206 break;
11207 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11208 if (n == NULL)
11209 break;
11210 f = (tree) n->value;
11211 if (tcctx.cb.decl_map)
11212 f = *tcctx.cb.decl_map->get (f);
11213 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11214 if (n != NULL)
11216 sf = (tree) n->value;
11217 if (tcctx.cb.decl_map)
11218 sf = *tcctx.cb.decl_map->get (sf);
11219 src = build_simple_mem_ref_loc (loc, sarg);
11220 src = omp_build_component_ref (src, sf);
11221 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
11222 src = build_simple_mem_ref_loc (loc, src);
11224 else
11225 src = decl;
11226 dst = build_simple_mem_ref_loc (loc, arg);
11227 dst = omp_build_component_ref (dst, f);
11228 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11229 append_to_statement_list (t, &list);
11230 break;
11231 case OMP_CLAUSE_PRIVATE:
11232 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
11233 break;
11234 decl = OMP_CLAUSE_DECL (c);
11235 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11236 f = (tree) n->value;
11237 if (tcctx.cb.decl_map)
11238 f = *tcctx.cb.decl_map->get (f);
11239 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
11240 if (n != NULL)
11242 sf = (tree) n->value;
11243 if (tcctx.cb.decl_map)
11244 sf = *tcctx.cb.decl_map->get (sf);
11245 src = build_simple_mem_ref_loc (loc, sarg);
11246 src = omp_build_component_ref (src, sf);
11247 if (use_pointer_for_field (decl, NULL))
11248 src = build_simple_mem_ref_loc (loc, src);
11250 else
11251 src = decl;
11252 dst = build_simple_mem_ref_loc (loc, arg);
11253 dst = omp_build_component_ref (dst, f);
11254 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
11255 append_to_statement_list (t, &list);
11256 break;
11257 default:
11258 break;
11261 /* Last pass: handle VLA firstprivates. */
11262 if (tcctx.cb.decl_map)
11263 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
11264 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
11266 tree ind, ptr, df;
11268 decl = OMP_CLAUSE_DECL (c);
11269 if (!is_variable_sized (decl))
11270 continue;
11271 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
11272 if (n == NULL)
11273 continue;
11274 f = (tree) n->value;
11275 f = *tcctx.cb.decl_map->get (f);
11276 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
11277 ind = DECL_VALUE_EXPR (decl);
11278 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
11279 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
11280 n = splay_tree_lookup (ctx->sfield_map,
11281 (splay_tree_key) TREE_OPERAND (ind, 0));
11282 sf = (tree) n->value;
11283 sf = *tcctx.cb.decl_map->get (sf);
11284 src = build_simple_mem_ref_loc (loc, sarg);
11285 src = omp_build_component_ref (src, sf);
11286 src = build_simple_mem_ref_loc (loc, src);
11287 dst = build_simple_mem_ref_loc (loc, arg);
11288 dst = omp_build_component_ref (dst, f);
11289 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
11290 append_to_statement_list (t, &list);
11291 n = splay_tree_lookup (ctx->field_map,
11292 (splay_tree_key) TREE_OPERAND (ind, 0));
11293 df = (tree) n->value;
11294 df = *tcctx.cb.decl_map->get (df);
11295 ptr = build_simple_mem_ref_loc (loc, arg);
11296 ptr = omp_build_component_ref (ptr, df);
11297 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
11298 build_fold_addr_expr_loc (loc, dst));
11299 append_to_statement_list (t, &list);
11302 t = build1 (RETURN_EXPR, void_type_node, NULL);
11303 append_to_statement_list (t, &list);
11305 if (tcctx.cb.decl_map)
11306 delete tcctx.cb.decl_map;
11307 pop_gimplify_context (NULL);
11308 BIND_EXPR_BODY (bind) = list;
11309 pop_cfun ();
11312 static void
11313 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
11315 tree c, clauses;
11316 gimple g;
11317 size_t n_in = 0, n_out = 0, idx = 2, i;
11319 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11320 OMP_CLAUSE_DEPEND);
11321 gcc_assert (clauses);
11322 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11323 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11324 switch (OMP_CLAUSE_DEPEND_KIND (c))
11326 case OMP_CLAUSE_DEPEND_IN:
11327 n_in++;
11328 break;
11329 case OMP_CLAUSE_DEPEND_OUT:
11330 case OMP_CLAUSE_DEPEND_INOUT:
11331 n_out++;
11332 break;
11333 default:
11334 gcc_unreachable ();
11336 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11337 tree array = create_tmp_var (type);
11338 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11339 NULL_TREE);
11340 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11341 gimple_seq_add_stmt (iseq, g);
11342 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11343 NULL_TREE);
11344 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11345 gimple_seq_add_stmt (iseq, g);
11346 for (i = 0; i < 2; i++)
11348 if ((i ? n_in : n_out) == 0)
11349 continue;
11350 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11351 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11352 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11354 tree t = OMP_CLAUSE_DECL (c);
11355 t = fold_convert (ptr_type_node, t);
11356 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11357 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11358 NULL_TREE, NULL_TREE);
11359 g = gimple_build_assign (r, t);
11360 gimple_seq_add_stmt (iseq, g);
11363 tree *p = gimple_omp_task_clauses_ptr (stmt);
11364 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11365 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11366 OMP_CLAUSE_CHAIN (c) = *p;
11367 *p = c;
11368 tree clobber = build_constructor (type, NULL);
11369 TREE_THIS_VOLATILE (clobber) = 1;
11370 g = gimple_build_assign (array, clobber);
11371 gimple_seq_add_stmt (oseq, g);
11374 /* Lower the OpenMP parallel or task directive in the current statement
11375 in GSI_P. CTX holds context information for the directive. */
11377 static void
11378 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11380 tree clauses;
11381 tree child_fn, t;
11382 gimple stmt = gsi_stmt (*gsi_p);
11383 gbind *par_bind, *bind, *dep_bind = NULL;
11384 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11385 location_t loc = gimple_location (stmt);
11387 clauses = gimple_omp_taskreg_clauses (stmt);
11388 par_bind
11389 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11390 par_body = gimple_bind_body (par_bind);
11391 child_fn = ctx->cb.dst_fn;
11392 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11393 && !gimple_omp_parallel_combined_p (stmt))
11395 struct walk_stmt_info wi;
11396 int ws_num = 0;
11398 memset (&wi, 0, sizeof (wi));
11399 wi.info = &ws_num;
11400 wi.val_only = true;
11401 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11402 if (ws_num == 1)
11403 gimple_omp_parallel_set_combined_p (stmt, true);
11405 gimple_seq dep_ilist = NULL;
11406 gimple_seq dep_olist = NULL;
11407 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11408 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11410 push_gimplify_context ();
11411 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11412 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11415 if (ctx->srecord_type)
11416 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11418 push_gimplify_context ();
11420 par_olist = NULL;
11421 par_ilist = NULL;
11422 par_rlist = NULL;
11423 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11424 lower_omp (&par_body, ctx);
11425 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11426 lower_reduction_clauses (clauses, &par_rlist, ctx);
11428 /* Declare all the variables created by mapping and the variables
11429 declared in the scope of the parallel body. */
11430 record_vars_into (ctx->block_vars, child_fn);
11431 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11433 if (ctx->record_type)
11435 ctx->sender_decl
11436 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11437 : ctx->record_type, ".omp_data_o");
11438 DECL_NAMELESS (ctx->sender_decl) = 1;
11439 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11440 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11443 olist = NULL;
11444 ilist = NULL;
11445 lower_send_clauses (clauses, &ilist, &olist, ctx);
11446 lower_send_shared_vars (&ilist, &olist, ctx);
11448 if (ctx->record_type)
11450 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11451 TREE_THIS_VOLATILE (clobber) = 1;
11452 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11453 clobber));
11456 /* Once all the expansions are done, sequence all the different
11457 fragments inside gimple_omp_body. */
11459 new_body = NULL;
11461 if (ctx->record_type)
11463 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11464 /* fixup_child_record_type might have changed receiver_decl's type. */
11465 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11466 gimple_seq_add_stmt (&new_body,
11467 gimple_build_assign (ctx->receiver_decl, t));
11470 gimple_seq_add_seq (&new_body, par_ilist);
11471 gimple_seq_add_seq (&new_body, par_body);
11472 gimple_seq_add_seq (&new_body, par_rlist);
11473 if (ctx->cancellable)
11474 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11475 gimple_seq_add_seq (&new_body, par_olist);
11476 new_body = maybe_catch_exception (new_body);
11477 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
11478 gimple_seq_add_stmt (&new_body,
11479 gimple_build_omp_continue (integer_zero_node,
11480 integer_zero_node));
11481 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11482 gimple_omp_set_body (stmt, new_body);
11484 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11485 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11486 gimple_bind_add_seq (bind, ilist);
11487 gimple_bind_add_stmt (bind, stmt);
11488 gimple_bind_add_seq (bind, olist);
11490 pop_gimplify_context (NULL);
11492 if (dep_bind)
11494 gimple_bind_add_seq (dep_bind, dep_ilist);
11495 gimple_bind_add_stmt (dep_bind, bind);
11496 gimple_bind_add_seq (dep_bind, dep_olist);
11497 pop_gimplify_context (dep_bind);
11501 /* Lower the GIMPLE_OMP_TARGET in the current statement
11502 in GSI_P. CTX holds context information for the directive. */
11504 static void
11505 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11507 tree clauses;
11508 tree child_fn, t, c;
11509 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11510 gbind *tgt_bind, *bind;
11511 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11512 location_t loc = gimple_location (stmt);
11513 bool offloaded, data_region;
11514 unsigned int map_cnt = 0;
11516 offloaded = is_gimple_omp_offloaded (stmt);
11517 switch (gimple_omp_target_kind (stmt))
11519 case GF_OMP_TARGET_KIND_REGION:
11520 case GF_OMP_TARGET_KIND_UPDATE:
11521 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11522 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11523 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11524 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11525 data_region = false;
11526 break;
11527 case GF_OMP_TARGET_KIND_DATA:
11528 case GF_OMP_TARGET_KIND_OACC_DATA:
11529 data_region = true;
11530 break;
11531 default:
11532 gcc_unreachable ();
11535 clauses = gimple_omp_target_clauses (stmt);
11537 tgt_bind = NULL;
11538 tgt_body = NULL;
11539 if (offloaded)
11541 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11542 tgt_body = gimple_bind_body (tgt_bind);
11544 else if (data_region)
11545 tgt_body = gimple_omp_body (stmt);
11546 child_fn = ctx->cb.dst_fn;
11548 push_gimplify_context ();
11550 irlist = NULL;
11551 orlist = NULL;
11552 if (offloaded
11553 && is_gimple_omp_oacc (stmt))
11554 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11556 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11557 switch (OMP_CLAUSE_CODE (c))
11559 tree var, x;
11561 default:
11562 break;
11563 case OMP_CLAUSE_MAP:
11564 #ifdef ENABLE_CHECKING
11565 /* First check what we're prepared to handle in the following. */
11566 switch (OMP_CLAUSE_MAP_KIND (c))
11568 case GOMP_MAP_ALLOC:
11569 case GOMP_MAP_TO:
11570 case GOMP_MAP_FROM:
11571 case GOMP_MAP_TOFROM:
11572 case GOMP_MAP_POINTER:
11573 case GOMP_MAP_TO_PSET:
11574 break;
11575 case GOMP_MAP_FORCE_ALLOC:
11576 case GOMP_MAP_FORCE_TO:
11577 case GOMP_MAP_FORCE_FROM:
11578 case GOMP_MAP_FORCE_TOFROM:
11579 case GOMP_MAP_FORCE_PRESENT:
11580 case GOMP_MAP_FORCE_DEALLOC:
11581 case GOMP_MAP_FORCE_DEVICEPTR:
11582 gcc_assert (is_gimple_omp_oacc (stmt));
11583 break;
11584 default:
11585 gcc_unreachable ();
11587 #endif
11588 /* FALLTHRU */
11589 case OMP_CLAUSE_TO:
11590 case OMP_CLAUSE_FROM:
11591 var = OMP_CLAUSE_DECL (c);
11592 if (!DECL_P (var))
11594 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11595 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11596 map_cnt++;
11597 continue;
11600 if (DECL_SIZE (var)
11601 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11603 tree var2 = DECL_VALUE_EXPR (var);
11604 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11605 var2 = TREE_OPERAND (var2, 0);
11606 gcc_assert (DECL_P (var2));
11607 var = var2;
11610 if (!maybe_lookup_field (var, ctx))
11611 continue;
11613 if (offloaded)
11615 x = build_receiver_ref (var, true, ctx);
11616 tree new_var = lookup_decl (var, ctx);
11617 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11618 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11619 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11620 x = build_simple_mem_ref (x);
11621 SET_DECL_VALUE_EXPR (new_var, x);
11622 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11624 map_cnt++;
11627 if (offloaded)
11629 target_nesting_level++;
11630 lower_omp (&tgt_body, ctx);
11631 target_nesting_level--;
11633 else if (data_region)
11634 lower_omp (&tgt_body, ctx);
11636 if (offloaded)
11638 /* Declare all the variables created by mapping and the variables
11639 declared in the scope of the target body. */
11640 record_vars_into (ctx->block_vars, child_fn);
11641 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11644 olist = NULL;
11645 ilist = NULL;
11646 if (ctx->record_type)
11648 ctx->sender_decl
11649 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11650 DECL_NAMELESS (ctx->sender_decl) = 1;
11651 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11652 t = make_tree_vec (3);
11653 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11654 TREE_VEC_ELT (t, 1)
11655 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11656 ".omp_data_sizes");
11657 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11658 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11659 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11660 tree tkind_type;
11661 int talign_shift;
11662 if (is_gimple_omp_oacc (stmt))
11664 tkind_type = short_unsigned_type_node;
11665 talign_shift = 8;
11667 else
11669 tkind_type = unsigned_char_type_node;
11670 talign_shift = 3;
11672 TREE_VEC_ELT (t, 2)
11673 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11674 ".omp_data_kinds");
11675 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11676 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11677 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11678 gimple_omp_target_set_data_arg (stmt, t);
11680 vec<constructor_elt, va_gc> *vsize;
11681 vec<constructor_elt, va_gc> *vkind;
11682 vec_alloc (vsize, map_cnt);
11683 vec_alloc (vkind, map_cnt);
11684 unsigned int map_idx = 0;
11686 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11687 switch (OMP_CLAUSE_CODE (c))
11689 tree ovar, nc;
11691 default:
11692 break;
11693 case OMP_CLAUSE_MAP:
11694 case OMP_CLAUSE_TO:
11695 case OMP_CLAUSE_FROM:
11696 nc = c;
11697 ovar = OMP_CLAUSE_DECL (c);
11698 if (!DECL_P (ovar))
11700 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11701 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11703 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11704 == get_base_address (ovar));
11705 nc = OMP_CLAUSE_CHAIN (c);
11706 ovar = OMP_CLAUSE_DECL (nc);
11708 else
11710 tree x = build_sender_ref (ovar, ctx);
11711 tree v
11712 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11713 gimplify_assign (x, v, &ilist);
11714 nc = NULL_TREE;
11717 else
11719 if (DECL_SIZE (ovar)
11720 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11722 tree ovar2 = DECL_VALUE_EXPR (ovar);
11723 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11724 ovar2 = TREE_OPERAND (ovar2, 0);
11725 gcc_assert (DECL_P (ovar2));
11726 ovar = ovar2;
11728 if (!maybe_lookup_field (ovar, ctx))
11729 continue;
11732 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11733 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11734 talign = DECL_ALIGN_UNIT (ovar);
11735 if (nc)
11737 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11738 tree x = build_sender_ref (ovar, ctx);
11739 if (maybe_lookup_oacc_reduction (var, ctx))
11741 gcc_checking_assert (offloaded
11742 && is_gimple_omp_oacc (stmt));
11743 gimplify_assign (x, var, &ilist);
11745 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11746 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11747 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11748 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11750 gcc_assert (offloaded);
11751 tree avar
11752 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11753 mark_addressable (avar);
11754 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11755 talign = DECL_ALIGN_UNIT (avar);
11756 avar = build_fold_addr_expr (avar);
11757 gimplify_assign (x, avar, &ilist);
11759 else if (is_gimple_reg (var))
11761 gcc_assert (offloaded);
11762 tree avar = create_tmp_var (TREE_TYPE (var));
11763 mark_addressable (avar);
11764 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11765 if (GOMP_MAP_COPY_TO_P (map_kind)
11766 || map_kind == GOMP_MAP_POINTER
11767 || map_kind == GOMP_MAP_TO_PSET
11768 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11769 gimplify_assign (avar, var, &ilist);
11770 avar = build_fold_addr_expr (avar);
11771 gimplify_assign (x, avar, &ilist);
11772 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11773 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11774 && !TYPE_READONLY (TREE_TYPE (var)))
11776 x = build_sender_ref (ovar, ctx);
11777 x = build_simple_mem_ref (x);
11778 gimplify_assign (var, x, &olist);
11781 else
11783 var = build_fold_addr_expr (var);
11784 gimplify_assign (x, var, &ilist);
11787 tree s = OMP_CLAUSE_SIZE (c);
11788 if (s == NULL_TREE)
11789 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11790 s = fold_convert (size_type_node, s);
11791 tree purpose = size_int (map_idx++);
11792 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11793 if (TREE_CODE (s) != INTEGER_CST)
11794 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11796 unsigned HOST_WIDE_INT tkind;
11797 switch (OMP_CLAUSE_CODE (c))
11799 case OMP_CLAUSE_MAP:
11800 tkind = OMP_CLAUSE_MAP_KIND (c);
11801 break;
11802 case OMP_CLAUSE_TO:
11803 tkind = GOMP_MAP_TO;
11804 break;
11805 case OMP_CLAUSE_FROM:
11806 tkind = GOMP_MAP_FROM;
11807 break;
11808 default:
11809 gcc_unreachable ();
11811 gcc_checking_assert (tkind
11812 < (HOST_WIDE_INT_C (1U) << talign_shift));
11813 talign = ceil_log2 (talign);
11814 tkind |= talign << talign_shift;
11815 gcc_checking_assert (tkind
11816 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11817 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11818 build_int_cstu (tkind_type, tkind));
11819 if (nc && nc != c)
11820 c = nc;
11823 gcc_assert (map_idx == map_cnt);
11825 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11826 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11827 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11828 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11829 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11831 gimple_seq initlist = NULL;
11832 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11833 TREE_VEC_ELT (t, 1)),
11834 &initlist, true, NULL_TREE);
11835 gimple_seq_add_seq (&ilist, initlist);
11837 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11838 NULL);
11839 TREE_THIS_VOLATILE (clobber) = 1;
11840 gimple_seq_add_stmt (&olist,
11841 gimple_build_assign (TREE_VEC_ELT (t, 1),
11842 clobber));
11845 tree clobber = build_constructor (ctx->record_type, NULL);
11846 TREE_THIS_VOLATILE (clobber) = 1;
11847 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11848 clobber));
11851 /* Once all the expansions are done, sequence all the different
11852 fragments inside gimple_omp_body. */
11854 new_body = NULL;
11856 if (offloaded
11857 && ctx->record_type)
11859 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11860 /* fixup_child_record_type might have changed receiver_decl's type. */
11861 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11862 gimple_seq_add_stmt (&new_body,
11863 gimple_build_assign (ctx->receiver_decl, t));
11866 if (offloaded)
11868 gimple_seq_add_seq (&new_body, tgt_body);
11869 new_body = maybe_catch_exception (new_body);
11871 else if (data_region)
11872 new_body = tgt_body;
11873 if (offloaded || data_region)
11875 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11876 gimple_omp_set_body (stmt, new_body);
11879 bind = gimple_build_bind (NULL, NULL,
11880 tgt_bind ? gimple_bind_block (tgt_bind)
11881 : NULL_TREE);
11882 gsi_replace (gsi_p, bind, true);
11883 gimple_bind_add_seq (bind, irlist);
11884 gimple_bind_add_seq (bind, ilist);
11885 gimple_bind_add_stmt (bind, stmt);
11886 gimple_bind_add_seq (bind, olist);
11887 gimple_bind_add_seq (bind, orlist);
11889 pop_gimplify_context (NULL);
11892 /* Expand code for an OpenMP teams directive. */
11894 static void
11895 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11897 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11898 push_gimplify_context ();
11900 tree block = make_node (BLOCK);
11901 gbind *bind = gimple_build_bind (NULL, NULL, block);
11902 gsi_replace (gsi_p, bind, true);
11903 gimple_seq bind_body = NULL;
11904 gimple_seq dlist = NULL;
11905 gimple_seq olist = NULL;
11907 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11908 OMP_CLAUSE_NUM_TEAMS);
11909 if (num_teams == NULL_TREE)
11910 num_teams = build_int_cst (unsigned_type_node, 0);
11911 else
11913 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11914 num_teams = fold_convert (unsigned_type_node, num_teams);
11915 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11917 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11918 OMP_CLAUSE_THREAD_LIMIT);
11919 if (thread_limit == NULL_TREE)
11920 thread_limit = build_int_cst (unsigned_type_node, 0);
11921 else
11923 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11924 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11925 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11926 fb_rvalue);
11929 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11930 &bind_body, &dlist, ctx, NULL);
11931 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11932 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11933 gimple_seq_add_stmt (&bind_body, teams_stmt);
11935 location_t loc = gimple_location (teams_stmt);
11936 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11937 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11938 gimple_set_location (call, loc);
11939 gimple_seq_add_stmt (&bind_body, call);
11941 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11942 gimple_omp_set_body (teams_stmt, NULL);
11943 gimple_seq_add_seq (&bind_body, olist);
11944 gimple_seq_add_seq (&bind_body, dlist);
11945 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11946 gimple_bind_set_body (bind, bind_body);
11948 pop_gimplify_context (bind);
11950 gimple_bind_append_vars (bind, ctx->block_vars);
11951 BLOCK_VARS (block) = ctx->block_vars;
11952 if (BLOCK_VARS (block))
11953 TREE_USED (block) = 1;
11957 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11958 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11959 of OMP context, but with task_shared_vars set. */
11961 static tree
11962 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11963 void *data)
11965 tree t = *tp;
11967 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11968 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11969 return t;
11971 if (task_shared_vars
11972 && DECL_P (t)
11973 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11974 return t;
11976 /* If a global variable has been privatized, TREE_CONSTANT on
11977 ADDR_EXPR might be wrong. */
11978 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11979 recompute_tree_invariant_for_addr_expr (t);
11981 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11982 return NULL_TREE;
11985 static void
11986 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11988 gimple stmt = gsi_stmt (*gsi_p);
11989 struct walk_stmt_info wi;
11990 gcall *call_stmt;
11992 if (gimple_has_location (stmt))
11993 input_location = gimple_location (stmt);
11995 if (task_shared_vars)
11996 memset (&wi, '\0', sizeof (wi));
11998 /* If we have issued syntax errors, avoid doing any heavy lifting.
11999 Just replace the OMP directives with a NOP to avoid
12000 confusing RTL expansion. */
12001 if (seen_error () && is_gimple_omp (stmt))
12003 gsi_replace (gsi_p, gimple_build_nop (), true);
12004 return;
12007 switch (gimple_code (stmt))
12009 case GIMPLE_COND:
12011 gcond *cond_stmt = as_a <gcond *> (stmt);
12012 if ((ctx || task_shared_vars)
12013 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
12014 lower_omp_regimplify_p,
12015 ctx ? NULL : &wi, NULL)
12016 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
12017 lower_omp_regimplify_p,
12018 ctx ? NULL : &wi, NULL)))
12019 gimple_regimplify_operands (cond_stmt, gsi_p);
12021 break;
12022 case GIMPLE_CATCH:
12023 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
12024 break;
12025 case GIMPLE_EH_FILTER:
12026 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
12027 break;
12028 case GIMPLE_TRY:
12029 lower_omp (gimple_try_eval_ptr (stmt), ctx);
12030 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
12031 break;
12032 case GIMPLE_TRANSACTION:
12033 lower_omp (gimple_transaction_body_ptr (
12034 as_a <gtransaction *> (stmt)),
12035 ctx);
12036 break;
12037 case GIMPLE_BIND:
12038 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
12039 break;
12040 case GIMPLE_OMP_PARALLEL:
12041 case GIMPLE_OMP_TASK:
12042 ctx = maybe_lookup_ctx (stmt);
12043 gcc_assert (ctx);
12044 if (ctx->cancellable)
12045 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
12046 lower_omp_taskreg (gsi_p, ctx);
12047 break;
12048 case GIMPLE_OMP_FOR:
12049 ctx = maybe_lookup_ctx (stmt);
12050 gcc_assert (ctx);
12051 if (ctx->cancellable)
12052 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
12053 lower_omp_for (gsi_p, ctx);
12054 break;
12055 case GIMPLE_OMP_SECTIONS:
12056 ctx = maybe_lookup_ctx (stmt);
12057 gcc_assert (ctx);
12058 if (ctx->cancellable)
12059 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
12060 lower_omp_sections (gsi_p, ctx);
12061 break;
12062 case GIMPLE_OMP_SINGLE:
12063 ctx = maybe_lookup_ctx (stmt);
12064 gcc_assert (ctx);
12065 lower_omp_single (gsi_p, ctx);
12066 break;
12067 case GIMPLE_OMP_MASTER:
12068 ctx = maybe_lookup_ctx (stmt);
12069 gcc_assert (ctx);
12070 lower_omp_master (gsi_p, ctx);
12071 break;
12072 case GIMPLE_OMP_TASKGROUP:
12073 ctx = maybe_lookup_ctx (stmt);
12074 gcc_assert (ctx);
12075 lower_omp_taskgroup (gsi_p, ctx);
12076 break;
12077 case GIMPLE_OMP_ORDERED:
12078 ctx = maybe_lookup_ctx (stmt);
12079 gcc_assert (ctx);
12080 lower_omp_ordered (gsi_p, ctx);
12081 break;
12082 case GIMPLE_OMP_CRITICAL:
12083 ctx = maybe_lookup_ctx (stmt);
12084 gcc_assert (ctx);
12085 lower_omp_critical (gsi_p, ctx);
12086 break;
12087 case GIMPLE_OMP_ATOMIC_LOAD:
12088 if ((ctx || task_shared_vars)
12089 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
12090 as_a <gomp_atomic_load *> (stmt)),
12091 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
12092 gimple_regimplify_operands (stmt, gsi_p);
12093 break;
12094 case GIMPLE_OMP_TARGET:
12095 ctx = maybe_lookup_ctx (stmt);
12096 gcc_assert (ctx);
12097 lower_omp_target (gsi_p, ctx);
12098 break;
12099 case GIMPLE_OMP_TEAMS:
12100 ctx = maybe_lookup_ctx (stmt);
12101 gcc_assert (ctx);
12102 lower_omp_teams (gsi_p, ctx);
12103 break;
12104 case GIMPLE_CALL:
12105 tree fndecl;
12106 call_stmt = as_a <gcall *> (stmt);
12107 fndecl = gimple_call_fndecl (call_stmt);
12108 if (fndecl
12109 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
12110 switch (DECL_FUNCTION_CODE (fndecl))
12112 case BUILT_IN_GOMP_BARRIER:
12113 if (ctx == NULL)
12114 break;
12115 /* FALLTHRU */
12116 case BUILT_IN_GOMP_CANCEL:
12117 case BUILT_IN_GOMP_CANCELLATION_POINT:
12118 omp_context *cctx;
12119 cctx = ctx;
12120 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
12121 cctx = cctx->outer;
12122 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
12123 if (!cctx->cancellable)
12125 if (DECL_FUNCTION_CODE (fndecl)
12126 == BUILT_IN_GOMP_CANCELLATION_POINT)
12128 stmt = gimple_build_nop ();
12129 gsi_replace (gsi_p, stmt, false);
12131 break;
12133 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
12135 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
12136 gimple_call_set_fndecl (call_stmt, fndecl);
12137 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
12139 tree lhs;
12140 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
12141 gimple_call_set_lhs (call_stmt, lhs);
12142 tree fallthru_label;
12143 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
12144 gimple g;
12145 g = gimple_build_label (fallthru_label);
12146 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
12147 g = gimple_build_cond (NE_EXPR, lhs,
12148 fold_convert (TREE_TYPE (lhs),
12149 boolean_false_node),
12150 cctx->cancel_label, fallthru_label);
12151 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
12152 break;
12153 default:
12154 break;
12156 /* FALLTHRU */
12157 default:
12158 if ((ctx || task_shared_vars)
12159 && walk_gimple_op (stmt, lower_omp_regimplify_p,
12160 ctx ? NULL : &wi))
12162 /* Just remove clobbers, this should happen only if we have
12163 "privatized" local addressable variables in SIMD regions,
12164 the clobber isn't needed in that case and gimplifying address
12165 of the ARRAY_REF into a pointer and creating MEM_REF based
12166 clobber would create worse code than we get with the clobber
12167 dropped. */
12168 if (gimple_clobber_p (stmt))
12170 gsi_replace (gsi_p, gimple_build_nop (), true);
12171 break;
12173 gimple_regimplify_operands (stmt, gsi_p);
12175 break;
12179 static void
12180 lower_omp (gimple_seq *body, omp_context *ctx)
12182 location_t saved_location = input_location;
12183 gimple_stmt_iterator gsi;
12184 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
12185 lower_omp_1 (&gsi, ctx);
12186 /* During gimplification, we haven't folded statments inside offloading
12187 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
12188 if (target_nesting_level || taskreg_nesting_level)
12189 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
12190 fold_stmt (&gsi);
12191 input_location = saved_location;
12194 /* Main entry point. */
12196 static unsigned int
12197 execute_lower_omp (void)
12199 gimple_seq body;
12200 int i;
12201 omp_context *ctx;
12203 /* This pass always runs, to provide PROP_gimple_lomp.
12204 But often, there is nothing to do. */
12205 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
12206 && flag_openmp_simd == 0)
12207 return 0;
12209 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
12210 delete_omp_context);
12212 body = gimple_body (current_function_decl);
12213 scan_omp (&body, NULL);
12214 gcc_assert (taskreg_nesting_level == 0);
12215 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
12216 finish_taskreg_scan (ctx);
12217 taskreg_contexts.release ();
12219 if (all_contexts->root)
12221 if (task_shared_vars)
12222 push_gimplify_context ();
12223 lower_omp (&body, NULL);
12224 if (task_shared_vars)
12225 pop_gimplify_context (NULL);
12228 if (all_contexts)
12230 splay_tree_delete (all_contexts);
12231 all_contexts = NULL;
12233 BITMAP_FREE (task_shared_vars);
12234 return 0;
12237 namespace {
12239 const pass_data pass_data_lower_omp =
12241 GIMPLE_PASS, /* type */
12242 "omplower", /* name */
12243 OPTGROUP_NONE, /* optinfo_flags */
12244 TV_NONE, /* tv_id */
12245 PROP_gimple_any, /* properties_required */
12246 PROP_gimple_lomp, /* properties_provided */
12247 0, /* properties_destroyed */
12248 0, /* todo_flags_start */
12249 0, /* todo_flags_finish */
12252 class pass_lower_omp : public gimple_opt_pass
12254 public:
12255 pass_lower_omp (gcc::context *ctxt)
12256 : gimple_opt_pass (pass_data_lower_omp, ctxt)
12259 /* opt_pass methods: */
12260 virtual unsigned int execute (function *) { return execute_lower_omp (); }
12262 }; // class pass_lower_omp
12264 } // anon namespace
12266 gimple_opt_pass *
12267 make_pass_lower_omp (gcc::context *ctxt)
12269 return new pass_lower_omp (ctxt);
12272 /* The following is a utility to diagnose structured block violations.
12273 It is not part of the "omplower" pass, as that's invoked too late. It
12274 should be invoked by the respective front ends after gimplification. */
12276 static splay_tree all_labels;
12278 /* Check for mismatched contexts and generate an error if needed. Return
12279 true if an error is detected. */
12281 static bool
12282 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
12283 gimple branch_ctx, gimple label_ctx)
12285 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
12286 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
12288 if (label_ctx == branch_ctx)
12289 return false;
12291 const char* kind = NULL;
12293 if (flag_cilkplus)
12295 if ((branch_ctx
12296 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
12297 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
12298 || (label_ctx
12299 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
12300 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
12301 kind = "Cilk Plus";
12303 if (flag_openacc)
12305 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
12306 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
12308 gcc_checking_assert (kind == NULL);
12309 kind = "OpenACC";
12312 if (kind == NULL)
12314 gcc_checking_assert (flag_openmp);
12315 kind = "OpenMP";
12319 Previously we kept track of the label's entire context in diagnose_sb_[12]
12320 so we could traverse it and issue a correct "exit" or "enter" error
12321 message upon a structured block violation.
12323 We built the context by building a list with tree_cons'ing, but there is
12324 no easy counterpart in gimple tuples. It seems like far too much work
12325 for issuing exit/enter error messages. If someone really misses the
12326 distinct error message... patches welcome.
12329 #if 0
12330 /* Try to avoid confusing the user by producing and error message
12331 with correct "exit" or "enter" verbiage. We prefer "exit"
12332 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12333 if (branch_ctx == NULL)
12334 exit_p = false;
12335 else
12337 while (label_ctx)
12339 if (TREE_VALUE (label_ctx) == branch_ctx)
12341 exit_p = false;
12342 break;
12344 label_ctx = TREE_CHAIN (label_ctx);
12348 if (exit_p)
12349 error ("invalid exit from %s structured block", kind);
12350 else
12351 error ("invalid entry to %s structured block", kind);
12352 #endif
12354 /* If it's obvious we have an invalid entry, be specific about the error. */
12355 if (branch_ctx == NULL)
12356 error ("invalid entry to %s structured block", kind);
12357 else
12359 /* Otherwise, be vague and lazy, but efficient. */
12360 error ("invalid branch to/from %s structured block", kind);
12363 gsi_replace (gsi_p, gimple_build_nop (), false);
12364 return true;
12367 /* Pass 1: Create a minimal tree of structured blocks, and record
12368 where each label is found. */
12370 static tree
12371 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12372 struct walk_stmt_info *wi)
12374 gimple context = (gimple) wi->info;
12375 gimple inner_context;
12376 gimple stmt = gsi_stmt (*gsi_p);
12378 *handled_ops_p = true;
12380 switch (gimple_code (stmt))
12382 WALK_SUBSTMTS;
12384 case GIMPLE_OMP_PARALLEL:
12385 case GIMPLE_OMP_TASK:
12386 case GIMPLE_OMP_SECTIONS:
12387 case GIMPLE_OMP_SINGLE:
12388 case GIMPLE_OMP_SECTION:
12389 case GIMPLE_OMP_MASTER:
12390 case GIMPLE_OMP_ORDERED:
12391 case GIMPLE_OMP_CRITICAL:
12392 case GIMPLE_OMP_TARGET:
12393 case GIMPLE_OMP_TEAMS:
12394 case GIMPLE_OMP_TASKGROUP:
12395 /* The minimal context here is just the current OMP construct. */
12396 inner_context = stmt;
12397 wi->info = inner_context;
12398 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12399 wi->info = context;
12400 break;
12402 case GIMPLE_OMP_FOR:
12403 inner_context = stmt;
12404 wi->info = inner_context;
12405 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12406 walk them. */
12407 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12408 diagnose_sb_1, NULL, wi);
12409 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12410 wi->info = context;
12411 break;
12413 case GIMPLE_LABEL:
12414 splay_tree_insert (all_labels,
12415 (splay_tree_key) gimple_label_label (
12416 as_a <glabel *> (stmt)),
12417 (splay_tree_value) context);
12418 break;
12420 default:
12421 break;
12424 return NULL_TREE;
12427 /* Pass 2: Check each branch and see if its context differs from that of
12428 the destination label's context. */
12430 static tree
12431 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12432 struct walk_stmt_info *wi)
12434 gimple context = (gimple) wi->info;
12435 splay_tree_node n;
12436 gimple stmt = gsi_stmt (*gsi_p);
12438 *handled_ops_p = true;
12440 switch (gimple_code (stmt))
12442 WALK_SUBSTMTS;
12444 case GIMPLE_OMP_PARALLEL:
12445 case GIMPLE_OMP_TASK:
12446 case GIMPLE_OMP_SECTIONS:
12447 case GIMPLE_OMP_SINGLE:
12448 case GIMPLE_OMP_SECTION:
12449 case GIMPLE_OMP_MASTER:
12450 case GIMPLE_OMP_ORDERED:
12451 case GIMPLE_OMP_CRITICAL:
12452 case GIMPLE_OMP_TARGET:
12453 case GIMPLE_OMP_TEAMS:
12454 case GIMPLE_OMP_TASKGROUP:
12455 wi->info = stmt;
12456 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12457 wi->info = context;
12458 break;
12460 case GIMPLE_OMP_FOR:
12461 wi->info = stmt;
12462 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12463 walk them. */
12464 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12465 diagnose_sb_2, NULL, wi);
12466 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12467 wi->info = context;
12468 break;
12470 case GIMPLE_COND:
12472 gcond *cond_stmt = as_a <gcond *> (stmt);
12473 tree lab = gimple_cond_true_label (cond_stmt);
12474 if (lab)
12476 n = splay_tree_lookup (all_labels,
12477 (splay_tree_key) lab);
12478 diagnose_sb_0 (gsi_p, context,
12479 n ? (gimple) n->value : NULL);
12481 lab = gimple_cond_false_label (cond_stmt);
12482 if (lab)
12484 n = splay_tree_lookup (all_labels,
12485 (splay_tree_key) lab);
12486 diagnose_sb_0 (gsi_p, context,
12487 n ? (gimple) n->value : NULL);
12490 break;
12492 case GIMPLE_GOTO:
12494 tree lab = gimple_goto_dest (stmt);
12495 if (TREE_CODE (lab) != LABEL_DECL)
12496 break;
12498 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12499 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
12501 break;
12503 case GIMPLE_SWITCH:
12505 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12506 unsigned int i;
12507 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12509 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12510 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12511 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
12512 break;
12515 break;
12517 case GIMPLE_RETURN:
12518 diagnose_sb_0 (gsi_p, context, NULL);
12519 break;
12521 default:
12522 break;
12525 return NULL_TREE;
12528 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12529 GIMPLE_* codes. */
12530 bool
12531 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12532 int *region_idx)
12534 gimple last = last_stmt (bb);
12535 enum gimple_code code = gimple_code (last);
12536 struct omp_region *cur_region = *region;
12537 bool fallthru = false;
12539 switch (code)
12541 case GIMPLE_OMP_PARALLEL:
12542 case GIMPLE_OMP_TASK:
12543 case GIMPLE_OMP_FOR:
12544 case GIMPLE_OMP_SINGLE:
12545 case GIMPLE_OMP_TEAMS:
12546 case GIMPLE_OMP_MASTER:
12547 case GIMPLE_OMP_TASKGROUP:
12548 case GIMPLE_OMP_ORDERED:
12549 case GIMPLE_OMP_CRITICAL:
12550 case GIMPLE_OMP_SECTION:
12551 cur_region = new_omp_region (bb, code, cur_region);
12552 fallthru = true;
12553 break;
12555 case GIMPLE_OMP_TARGET:
12556 cur_region = new_omp_region (bb, code, cur_region);
12557 fallthru = true;
12558 switch (gimple_omp_target_kind (last))
12560 case GF_OMP_TARGET_KIND_REGION:
12561 case GF_OMP_TARGET_KIND_DATA:
12562 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12563 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12564 case GF_OMP_TARGET_KIND_OACC_DATA:
12565 break;
12566 case GF_OMP_TARGET_KIND_UPDATE:
12567 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12568 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12569 cur_region = cur_region->outer;
12570 break;
12571 default:
12572 gcc_unreachable ();
12574 break;
12576 case GIMPLE_OMP_SECTIONS:
12577 cur_region = new_omp_region (bb, code, cur_region);
12578 fallthru = true;
12579 break;
12581 case GIMPLE_OMP_SECTIONS_SWITCH:
12582 fallthru = false;
12583 break;
12585 case GIMPLE_OMP_ATOMIC_LOAD:
12586 case GIMPLE_OMP_ATOMIC_STORE:
12587 fallthru = true;
12588 break;
12590 case GIMPLE_OMP_RETURN:
12591 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12592 somewhere other than the next block. This will be
12593 created later. */
12594 cur_region->exit = bb;
12595 if (cur_region->type == GIMPLE_OMP_TASK)
12596 /* Add an edge corresponding to not scheduling the task
12597 immediately. */
12598 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
12599 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12600 cur_region = cur_region->outer;
12601 break;
12603 case GIMPLE_OMP_CONTINUE:
12604 cur_region->cont = bb;
12605 switch (cur_region->type)
12607 case GIMPLE_OMP_FOR:
12608 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12609 succs edges as abnormal to prevent splitting
12610 them. */
12611 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12612 /* Make the loopback edge. */
12613 make_edge (bb, single_succ (cur_region->entry),
12614 EDGE_ABNORMAL);
12616 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12617 corresponds to the case that the body of the loop
12618 is not executed at all. */
12619 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12620 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12621 fallthru = false;
12622 break;
12624 case GIMPLE_OMP_SECTIONS:
12625 /* Wire up the edges into and out of the nested sections. */
12627 basic_block switch_bb = single_succ (cur_region->entry);
12629 struct omp_region *i;
12630 for (i = cur_region->inner; i ; i = i->next)
12632 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12633 make_edge (switch_bb, i->entry, 0);
12634 make_edge (i->exit, bb, EDGE_FALLTHRU);
12637 /* Make the loopback edge to the block with
12638 GIMPLE_OMP_SECTIONS_SWITCH. */
12639 make_edge (bb, switch_bb, 0);
12641 /* Make the edge from the switch to exit. */
12642 make_edge (switch_bb, bb->next_bb, 0);
12643 fallthru = false;
12645 break;
12647 case GIMPLE_OMP_TASK:
12648 fallthru = true;
12649 break;
12651 default:
12652 gcc_unreachable ();
12654 break;
12656 default:
12657 gcc_unreachable ();
12660 if (*region != cur_region)
12662 *region = cur_region;
12663 if (cur_region)
12664 *region_idx = cur_region->entry->index;
12665 else
12666 *region_idx = 0;
12669 return fallthru;
12672 static unsigned int
12673 diagnose_omp_structured_block_errors (void)
12675 struct walk_stmt_info wi;
12676 gimple_seq body = gimple_body (current_function_decl);
12678 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12680 memset (&wi, 0, sizeof (wi));
12681 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12683 memset (&wi, 0, sizeof (wi));
12684 wi.want_locations = true;
12685 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12687 gimple_set_body (current_function_decl, body);
12689 splay_tree_delete (all_labels);
12690 all_labels = NULL;
12692 return 0;
12695 namespace {
12697 const pass_data pass_data_diagnose_omp_blocks =
12699 GIMPLE_PASS, /* type */
12700 "*diagnose_omp_blocks", /* name */
12701 OPTGROUP_NONE, /* optinfo_flags */
12702 TV_NONE, /* tv_id */
12703 PROP_gimple_any, /* properties_required */
12704 0, /* properties_provided */
12705 0, /* properties_destroyed */
12706 0, /* todo_flags_start */
12707 0, /* todo_flags_finish */
12710 class pass_diagnose_omp_blocks : public gimple_opt_pass
12712 public:
12713 pass_diagnose_omp_blocks (gcc::context *ctxt)
12714 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12717 /* opt_pass methods: */
12718 virtual bool gate (function *)
12720 return flag_cilkplus || flag_openacc || flag_openmp;
12722 virtual unsigned int execute (function *)
12724 return diagnose_omp_structured_block_errors ();
12727 }; // class pass_diagnose_omp_blocks
12729 } // anon namespace
12731 gimple_opt_pass *
12732 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12734 return new pass_diagnose_omp_blocks (ctxt);
12737 /* SIMD clone supporting code. */
12739 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12740 of arguments to reserve space for. */
12742 static struct cgraph_simd_clone *
12743 simd_clone_struct_alloc (int nargs)
12745 struct cgraph_simd_clone *clone_info;
12746 size_t len = (sizeof (struct cgraph_simd_clone)
12747 + nargs * sizeof (struct cgraph_simd_clone_arg));
12748 clone_info = (struct cgraph_simd_clone *)
12749 ggc_internal_cleared_alloc (len);
12750 return clone_info;
12753 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12755 static inline void
12756 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12757 struct cgraph_simd_clone *from)
12759 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12760 + ((from->nargs - from->inbranch)
12761 * sizeof (struct cgraph_simd_clone_arg))));
12764 /* Return vector of parameter types of function FNDECL. This uses
12765 TYPE_ARG_TYPES if available, otherwise falls back to types of
12766 DECL_ARGUMENTS types. */
12768 vec<tree>
12769 simd_clone_vector_of_formal_parm_types (tree fndecl)
12771 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12772 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12773 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12774 unsigned int i;
12775 tree arg;
12776 FOR_EACH_VEC_ELT (args, i, arg)
12777 args[i] = TREE_TYPE (args[i]);
12778 return args;
12781 /* Given a simd function in NODE, extract the simd specific
12782 information from the OMP clauses passed in CLAUSES, and return
12783 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12784 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12785 otherwise set to FALSE. */
12787 static struct cgraph_simd_clone *
12788 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12789 bool *inbranch_specified)
12791 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12792 tree t;
12793 int n;
12794 *inbranch_specified = false;
12796 n = args.length ();
12797 if (n > 0 && args.last () == void_type_node)
12798 n--;
12800 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12801 be cloned have a distinctive artificial label in addition to "omp
12802 declare simd". */
12803 bool cilk_clone
12804 = (flag_cilkplus
12805 && lookup_attribute ("cilk simd function",
12806 DECL_ATTRIBUTES (node->decl)));
12808 /* Allocate one more than needed just in case this is an in-branch
12809 clone which will require a mask argument. */
12810 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12811 clone_info->nargs = n;
12812 clone_info->cilk_elemental = cilk_clone;
12814 if (!clauses)
12816 args.release ();
12817 return clone_info;
12819 clauses = TREE_VALUE (clauses);
12820 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12821 return clone_info;
12823 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12825 switch (OMP_CLAUSE_CODE (t))
12827 case OMP_CLAUSE_INBRANCH:
12828 clone_info->inbranch = 1;
12829 *inbranch_specified = true;
12830 break;
12831 case OMP_CLAUSE_NOTINBRANCH:
12832 clone_info->inbranch = 0;
12833 *inbranch_specified = true;
12834 break;
12835 case OMP_CLAUSE_SIMDLEN:
12836 clone_info->simdlen
12837 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12838 break;
12839 case OMP_CLAUSE_LINEAR:
12841 tree decl = OMP_CLAUSE_DECL (t);
12842 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12843 int argno = TREE_INT_CST_LOW (decl);
12844 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12846 clone_info->args[argno].arg_type
12847 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12848 clone_info->args[argno].linear_step = tree_to_shwi (step);
12849 gcc_assert (clone_info->args[argno].linear_step >= 0
12850 && clone_info->args[argno].linear_step < n);
12852 else
12854 if (POINTER_TYPE_P (args[argno]))
12855 step = fold_convert (ssizetype, step);
12856 if (!tree_fits_shwi_p (step))
12858 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12859 "ignoring large linear step");
12860 args.release ();
12861 return NULL;
12863 else if (integer_zerop (step))
12865 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12866 "ignoring zero linear step");
12867 args.release ();
12868 return NULL;
12870 else
12872 clone_info->args[argno].arg_type
12873 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12874 clone_info->args[argno].linear_step = tree_to_shwi (step);
12877 break;
12879 case OMP_CLAUSE_UNIFORM:
12881 tree decl = OMP_CLAUSE_DECL (t);
12882 int argno = tree_to_uhwi (decl);
12883 clone_info->args[argno].arg_type
12884 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12885 break;
12887 case OMP_CLAUSE_ALIGNED:
12889 tree decl = OMP_CLAUSE_DECL (t);
12890 int argno = tree_to_uhwi (decl);
12891 clone_info->args[argno].alignment
12892 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12893 break;
12895 default:
12896 break;
12899 args.release ();
12900 return clone_info;
12903 /* Given a SIMD clone in NODE, calculate the characteristic data
12904 type and return the coresponding type. The characteristic data
12905 type is computed as described in the Intel Vector ABI. */
12907 static tree
12908 simd_clone_compute_base_data_type (struct cgraph_node *node,
12909 struct cgraph_simd_clone *clone_info)
12911 tree type = integer_type_node;
12912 tree fndecl = node->decl;
12914 /* a) For non-void function, the characteristic data type is the
12915 return type. */
12916 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12917 type = TREE_TYPE (TREE_TYPE (fndecl));
12919 /* b) If the function has any non-uniform, non-linear parameters,
12920 then the characteristic data type is the type of the first
12921 such parameter. */
12922 else
12924 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12925 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12926 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12928 type = map[i];
12929 break;
12931 map.release ();
12934 /* c) If the characteristic data type determined by a) or b) above
12935 is struct, union, or class type which is pass-by-value (except
12936 for the type that maps to the built-in complex data type), the
12937 characteristic data type is int. */
12938 if (RECORD_OR_UNION_TYPE_P (type)
12939 && !aggregate_value_p (type, NULL)
12940 && TREE_CODE (type) != COMPLEX_TYPE)
12941 return integer_type_node;
12943 /* d) If none of the above three classes is applicable, the
12944 characteristic data type is int. */
12946 return type;
12948 /* e) For Intel Xeon Phi native and offload compilation, if the
12949 resulting characteristic data type is 8-bit or 16-bit integer
12950 data type, the characteristic data type is int. */
12951 /* Well, we don't handle Xeon Phi yet. */
12954 static tree
12955 simd_clone_mangle (struct cgraph_node *node,
12956 struct cgraph_simd_clone *clone_info)
12958 char vecsize_mangle = clone_info->vecsize_mangle;
12959 char mask = clone_info->inbranch ? 'M' : 'N';
12960 unsigned int simdlen = clone_info->simdlen;
12961 unsigned int n;
12962 pretty_printer pp;
12964 gcc_assert (vecsize_mangle && simdlen);
12966 pp_string (&pp, "_ZGV");
12967 pp_character (&pp, vecsize_mangle);
12968 pp_character (&pp, mask);
12969 pp_decimal_int (&pp, simdlen);
12971 for (n = 0; n < clone_info->nargs; ++n)
12973 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12975 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12976 pp_character (&pp, 'u');
12977 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12979 gcc_assert (arg.linear_step != 0);
12980 pp_character (&pp, 'l');
12981 if (arg.linear_step > 1)
12982 pp_unsigned_wide_integer (&pp, arg.linear_step);
12983 else if (arg.linear_step < 0)
12985 pp_character (&pp, 'n');
12986 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12987 arg.linear_step));
12990 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12992 pp_character (&pp, 's');
12993 pp_unsigned_wide_integer (&pp, arg.linear_step);
12995 else
12996 pp_character (&pp, 'v');
12997 if (arg.alignment)
12999 pp_character (&pp, 'a');
13000 pp_decimal_int (&pp, arg.alignment);
13004 pp_underscore (&pp);
13005 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
13006 if (*str == '*')
13007 ++str;
13008 pp_string (&pp, str);
13009 str = pp_formatted_text (&pp);
13011 /* If there already is a SIMD clone with the same mangled name, don't
13012 add another one. This can happen e.g. for
13013 #pragma omp declare simd
13014 #pragma omp declare simd simdlen(8)
13015 int foo (int, int);
13016 if the simdlen is assumed to be 8 for the first one, etc. */
13017 for (struct cgraph_node *clone = node->simd_clones; clone;
13018 clone = clone->simdclone->next_clone)
13019 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
13020 str) == 0)
13021 return NULL_TREE;
13023 return get_identifier (str);
13026 /* Create a simd clone of OLD_NODE and return it. */
13028 static struct cgraph_node *
13029 simd_clone_create (struct cgraph_node *old_node)
13031 struct cgraph_node *new_node;
13032 if (old_node->definition)
13034 if (!old_node->has_gimple_body_p ())
13035 return NULL;
13036 old_node->get_body ();
13037 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
13038 false, NULL, NULL,
13039 "simdclone");
13041 else
13043 tree old_decl = old_node->decl;
13044 tree new_decl = copy_node (old_node->decl);
13045 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
13046 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
13047 SET_DECL_RTL (new_decl, NULL);
13048 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
13049 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
13050 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
13051 symtab->call_cgraph_insertion_hooks (new_node);
13053 if (new_node == NULL)
13054 return new_node;
13056 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
13058 /* The function cgraph_function_versioning () will force the new
13059 symbol local. Undo this, and inherit external visability from
13060 the old node. */
13061 new_node->local.local = old_node->local.local;
13062 new_node->externally_visible = old_node->externally_visible;
13064 return new_node;
13067 /* Adjust the return type of the given function to its appropriate
13068 vector counterpart. Returns a simd array to be used throughout the
13069 function as a return value. */
13071 static tree
13072 simd_clone_adjust_return_type (struct cgraph_node *node)
13074 tree fndecl = node->decl;
13075 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
13076 unsigned int veclen;
13077 tree t;
13079 /* Adjust the function return type. */
13080 if (orig_rettype == void_type_node)
13081 return NULL_TREE;
13082 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
13083 t = TREE_TYPE (TREE_TYPE (fndecl));
13084 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
13085 veclen = node->simdclone->vecsize_int;
13086 else
13087 veclen = node->simdclone->vecsize_float;
13088 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
13089 if (veclen > node->simdclone->simdlen)
13090 veclen = node->simdclone->simdlen;
13091 if (POINTER_TYPE_P (t))
13092 t = pointer_sized_int_node;
13093 if (veclen == node->simdclone->simdlen)
13094 t = build_vector_type (t, node->simdclone->simdlen);
13095 else
13097 t = build_vector_type (t, veclen);
13098 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
13100 TREE_TYPE (TREE_TYPE (fndecl)) = t;
13101 if (!node->definition)
13102 return NULL_TREE;
13104 t = DECL_RESULT (fndecl);
13105 /* Adjust the DECL_RESULT. */
13106 gcc_assert (TREE_TYPE (t) != void_type_node);
13107 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
13108 relayout_decl (t);
13110 tree atype = build_array_type_nelts (orig_rettype,
13111 node->simdclone->simdlen);
13112 if (veclen != node->simdclone->simdlen)
13113 return build1 (VIEW_CONVERT_EXPR, atype, t);
13115 /* Set up a SIMD array to use as the return value. */
13116 tree retval = create_tmp_var_raw (atype, "retval");
13117 gimple_add_tmp_var (retval);
13118 return retval;
13121 /* Each vector argument has a corresponding array to be used locally
13122 as part of the eventual loop. Create such temporary array and
13123 return it.
13125 PREFIX is the prefix to be used for the temporary.
13127 TYPE is the inner element type.
13129 SIMDLEN is the number of elements. */
13131 static tree
13132 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
13134 tree atype = build_array_type_nelts (type, simdlen);
13135 tree avar = create_tmp_var_raw (atype, prefix);
13136 gimple_add_tmp_var (avar);
13137 return avar;
13140 /* Modify the function argument types to their corresponding vector
13141 counterparts if appropriate. Also, create one array for each simd
13142 argument to be used locally when using the function arguments as
13143 part of the loop.
13145 NODE is the function whose arguments are to be adjusted.
13147 Returns an adjustment vector that will be filled describing how the
13148 argument types will be adjusted. */
13150 static ipa_parm_adjustment_vec
13151 simd_clone_adjust_argument_types (struct cgraph_node *node)
13153 vec<tree> args;
13154 ipa_parm_adjustment_vec adjustments;
13156 if (node->definition)
13157 args = ipa_get_vector_of_formal_parms (node->decl);
13158 else
13159 args = simd_clone_vector_of_formal_parm_types (node->decl);
13160 adjustments.create (args.length ());
13161 unsigned i, j, veclen;
13162 struct ipa_parm_adjustment adj;
13163 for (i = 0; i < node->simdclone->nargs; ++i)
13165 memset (&adj, 0, sizeof (adj));
13166 tree parm = args[i];
13167 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
13168 adj.base_index = i;
13169 adj.base = parm;
13171 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
13172 node->simdclone->args[i].orig_type = parm_type;
13174 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
13176 /* No adjustment necessary for scalar arguments. */
13177 adj.op = IPA_PARM_OP_COPY;
13179 else
13181 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
13182 veclen = node->simdclone->vecsize_int;
13183 else
13184 veclen = node->simdclone->vecsize_float;
13185 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
13186 if (veclen > node->simdclone->simdlen)
13187 veclen = node->simdclone->simdlen;
13188 adj.arg_prefix = "simd";
13189 if (POINTER_TYPE_P (parm_type))
13190 adj.type = build_vector_type (pointer_sized_int_node, veclen);
13191 else
13192 adj.type = build_vector_type (parm_type, veclen);
13193 node->simdclone->args[i].vector_type = adj.type;
13194 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
13196 adjustments.safe_push (adj);
13197 if (j == veclen)
13199 memset (&adj, 0, sizeof (adj));
13200 adj.op = IPA_PARM_OP_NEW;
13201 adj.arg_prefix = "simd";
13202 adj.base_index = i;
13203 adj.type = node->simdclone->args[i].vector_type;
13207 if (node->definition)
13208 node->simdclone->args[i].simd_array
13209 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
13210 parm_type, node->simdclone->simdlen);
13212 adjustments.safe_push (adj);
13215 if (node->simdclone->inbranch)
13217 tree base_type
13218 = simd_clone_compute_base_data_type (node->simdclone->origin,
13219 node->simdclone);
13221 memset (&adj, 0, sizeof (adj));
13222 adj.op = IPA_PARM_OP_NEW;
13223 adj.arg_prefix = "mask";
13225 adj.base_index = i;
13226 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
13227 veclen = node->simdclone->vecsize_int;
13228 else
13229 veclen = node->simdclone->vecsize_float;
13230 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
13231 if (veclen > node->simdclone->simdlen)
13232 veclen = node->simdclone->simdlen;
13233 if (POINTER_TYPE_P (base_type))
13234 adj.type = build_vector_type (pointer_sized_int_node, veclen);
13235 else
13236 adj.type = build_vector_type (base_type, veclen);
13237 adjustments.safe_push (adj);
13239 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
13240 adjustments.safe_push (adj);
13242 /* We have previously allocated one extra entry for the mask. Use
13243 it and fill it. */
13244 struct cgraph_simd_clone *sc = node->simdclone;
13245 sc->nargs++;
13246 if (node->definition)
13248 sc->args[i].orig_arg
13249 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
13250 sc->args[i].simd_array
13251 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
13253 sc->args[i].orig_type = base_type;
13254 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
13257 if (node->definition)
13258 ipa_modify_formal_parameters (node->decl, adjustments);
13259 else
13261 tree new_arg_types = NULL_TREE, new_reversed;
13262 bool last_parm_void = false;
13263 if (args.length () > 0 && args.last () == void_type_node)
13264 last_parm_void = true;
13266 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
13267 j = adjustments.length ();
13268 for (i = 0; i < j; i++)
13270 struct ipa_parm_adjustment *adj = &adjustments[i];
13271 tree ptype;
13272 if (adj->op == IPA_PARM_OP_COPY)
13273 ptype = args[adj->base_index];
13274 else
13275 ptype = adj->type;
13276 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
13278 new_reversed = nreverse (new_arg_types);
13279 if (last_parm_void)
13281 if (new_reversed)
13282 TREE_CHAIN (new_arg_types) = void_list_node;
13283 else
13284 new_reversed = void_list_node;
13287 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
13288 TYPE_ARG_TYPES (new_type) = new_reversed;
13289 TREE_TYPE (node->decl) = new_type;
13291 adjustments.release ();
13293 args.release ();
13294 return adjustments;
13297 /* Initialize and copy the function arguments in NODE to their
13298 corresponding local simd arrays. Returns a fresh gimple_seq with
13299 the instruction sequence generated. */
13301 static gimple_seq
13302 simd_clone_init_simd_arrays (struct cgraph_node *node,
13303 ipa_parm_adjustment_vec adjustments)
13305 gimple_seq seq = NULL;
13306 unsigned i = 0, j = 0, k;
13308 for (tree arg = DECL_ARGUMENTS (node->decl);
13309 arg;
13310 arg = DECL_CHAIN (arg), i++, j++)
13312 if (adjustments[j].op == IPA_PARM_OP_COPY)
13313 continue;
13315 node->simdclone->args[i].vector_arg = arg;
13317 tree array = node->simdclone->args[i].simd_array;
13318 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
13320 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13321 tree ptr = build_fold_addr_expr (array);
13322 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13323 build_int_cst (ptype, 0));
13324 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13325 gimplify_and_add (t, &seq);
13327 else
13329 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13330 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13331 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13333 tree ptr = build_fold_addr_expr (array);
13334 int elemsize;
13335 if (k)
13337 arg = DECL_CHAIN (arg);
13338 j++;
13340 elemsize
13341 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13342 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13343 build_int_cst (ptype, k * elemsize));
13344 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13345 gimplify_and_add (t, &seq);
13349 return seq;
13352 /* Callback info for ipa_simd_modify_stmt_ops below. */
13354 struct modify_stmt_info {
13355 ipa_parm_adjustment_vec adjustments;
13356 gimple stmt;
13357 /* True if the parent statement was modified by
13358 ipa_simd_modify_stmt_ops. */
13359 bool modified;
13362 /* Callback for walk_gimple_op.
13364 Adjust operands from a given statement as specified in the
13365 adjustments vector in the callback data. */
13367 static tree
13368 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13370 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13371 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13372 tree *orig_tp = tp;
13373 if (TREE_CODE (*tp) == ADDR_EXPR)
13374 tp = &TREE_OPERAND (*tp, 0);
13375 struct ipa_parm_adjustment *cand = NULL;
13376 if (TREE_CODE (*tp) == PARM_DECL)
13377 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13378 else
13380 if (TYPE_P (*tp))
13381 *walk_subtrees = 0;
13384 tree repl = NULL_TREE;
13385 if (cand)
13386 repl = unshare_expr (cand->new_decl);
13387 else
13389 if (tp != orig_tp)
13391 *walk_subtrees = 0;
13392 bool modified = info->modified;
13393 info->modified = false;
13394 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13395 if (!info->modified)
13397 info->modified = modified;
13398 return NULL_TREE;
13400 info->modified = modified;
13401 repl = *tp;
13403 else
13404 return NULL_TREE;
13407 if (tp != orig_tp)
13409 repl = build_fold_addr_expr (repl);
13410 gimple stmt;
13411 if (is_gimple_debug (info->stmt))
13413 tree vexpr = make_node (DEBUG_EXPR_DECL);
13414 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13415 DECL_ARTIFICIAL (vexpr) = 1;
13416 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13417 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13418 repl = vexpr;
13420 else
13422 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13423 repl = gimple_assign_lhs (stmt);
13425 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13426 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13427 *orig_tp = repl;
13429 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13431 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13432 *tp = vce;
13434 else
13435 *tp = repl;
13437 info->modified = true;
13438 return NULL_TREE;
13441 /* Traverse the function body and perform all modifications as
13442 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13443 modified such that the replacement/reduction value will now be an
13444 offset into the corresponding simd_array.
13446 This function will replace all function argument uses with their
13447 corresponding simd array elements, and ajust the return values
13448 accordingly. */
13450 static void
13451 ipa_simd_modify_function_body (struct cgraph_node *node,
13452 ipa_parm_adjustment_vec adjustments,
13453 tree retval_array, tree iter)
13455 basic_block bb;
13456 unsigned int i, j, l;
13458 /* Re-use the adjustments array, but this time use it to replace
13459 every function argument use to an offset into the corresponding
13460 simd_array. */
13461 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13463 if (!node->simdclone->args[i].vector_arg)
13464 continue;
13466 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13467 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13468 adjustments[j].new_decl
13469 = build4 (ARRAY_REF,
13470 basetype,
13471 node->simdclone->args[i].simd_array,
13472 iter,
13473 NULL_TREE, NULL_TREE);
13474 if (adjustments[j].op == IPA_PARM_OP_NONE
13475 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13476 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13479 l = adjustments.length ();
13480 for (i = 1; i < num_ssa_names; i++)
13482 tree name = ssa_name (i);
13483 if (name
13484 && SSA_NAME_VAR (name)
13485 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13487 for (j = 0; j < l; j++)
13488 if (SSA_NAME_VAR (name) == adjustments[j].base
13489 && adjustments[j].new_decl)
13491 tree base_var;
13492 if (adjustments[j].new_ssa_base == NULL_TREE)
13494 base_var
13495 = copy_var_decl (adjustments[j].base,
13496 DECL_NAME (adjustments[j].base),
13497 TREE_TYPE (adjustments[j].base));
13498 adjustments[j].new_ssa_base = base_var;
13500 else
13501 base_var = adjustments[j].new_ssa_base;
13502 if (SSA_NAME_IS_DEFAULT_DEF (name))
13504 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13505 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13506 tree new_decl = unshare_expr (adjustments[j].new_decl);
13507 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13508 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13509 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13510 gimple stmt = gimple_build_assign (name, new_decl);
13511 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13513 else
13514 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13519 struct modify_stmt_info info;
13520 info.adjustments = adjustments;
13522 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13524 gimple_stmt_iterator gsi;
13526 gsi = gsi_start_bb (bb);
13527 while (!gsi_end_p (gsi))
13529 gimple stmt = gsi_stmt (gsi);
13530 info.stmt = stmt;
13531 struct walk_stmt_info wi;
13533 memset (&wi, 0, sizeof (wi));
13534 info.modified = false;
13535 wi.info = &info;
13536 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13538 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13540 tree retval = gimple_return_retval (return_stmt);
13541 if (!retval)
13543 gsi_remove (&gsi, true);
13544 continue;
13547 /* Replace `return foo' with `retval_array[iter] = foo'. */
13548 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13549 retval_array, iter, NULL, NULL);
13550 stmt = gimple_build_assign (ref, retval);
13551 gsi_replace (&gsi, stmt, true);
13552 info.modified = true;
13555 if (info.modified)
13557 update_stmt (stmt);
13558 if (maybe_clean_eh_stmt (stmt))
13559 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13561 gsi_next (&gsi);
13566 /* Adjust the argument types in NODE to their appropriate vector
13567 counterparts. */
13569 static void
13570 simd_clone_adjust (struct cgraph_node *node)
13572 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13574 targetm.simd_clone.adjust (node);
13576 tree retval = simd_clone_adjust_return_type (node);
13577 ipa_parm_adjustment_vec adjustments
13578 = simd_clone_adjust_argument_types (node);
13580 push_gimplify_context ();
13582 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13584 /* Adjust all uses of vector arguments accordingly. Adjust all
13585 return values accordingly. */
13586 tree iter = create_tmp_var (unsigned_type_node, "iter");
13587 tree iter1 = make_ssa_name (iter);
13588 tree iter2 = make_ssa_name (iter);
13589 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13591 /* Initialize the iteration variable. */
13592 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13593 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13594 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13595 /* Insert the SIMD array and iv initialization at function
13596 entry. */
13597 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13599 pop_gimplify_context (NULL);
13601 /* Create a new BB right before the original exit BB, to hold the
13602 iteration increment and the condition/branch. */
13603 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13604 basic_block incr_bb = create_empty_bb (orig_exit);
13605 add_bb_to_loop (incr_bb, body_bb->loop_father);
13606 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13607 flag. Set it now to be a FALLTHRU_EDGE. */
13608 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13609 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13610 for (unsigned i = 0;
13611 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13613 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13614 redirect_edge_succ (e, incr_bb);
13616 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13617 e->probability = REG_BR_PROB_BASE;
13618 gsi = gsi_last_bb (incr_bb);
13619 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13620 build_int_cst (unsigned_type_node, 1));
13621 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13623 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13624 struct loop *loop = alloc_loop ();
13625 cfun->has_force_vectorize_loops = true;
13626 loop->safelen = node->simdclone->simdlen;
13627 loop->force_vectorize = true;
13628 loop->header = body_bb;
13630 /* Branch around the body if the mask applies. */
13631 if (node->simdclone->inbranch)
13633 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13634 tree mask_array
13635 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13636 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13637 tree aref = build4 (ARRAY_REF,
13638 TREE_TYPE (TREE_TYPE (mask_array)),
13639 mask_array, iter1,
13640 NULL, NULL);
13641 g = gimple_build_assign (mask, aref);
13642 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13643 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13644 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13646 aref = build1 (VIEW_CONVERT_EXPR,
13647 build_nonstandard_integer_type (bitsize, 0), mask);
13648 mask = make_ssa_name (TREE_TYPE (aref));
13649 g = gimple_build_assign (mask, aref);
13650 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13653 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13654 NULL, NULL);
13655 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13656 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13657 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13660 /* Generate the condition. */
13661 g = gimple_build_cond (LT_EXPR,
13662 iter2,
13663 build_int_cst (unsigned_type_node,
13664 node->simdclone->simdlen),
13665 NULL, NULL);
13666 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13667 e = split_block (incr_bb, gsi_stmt (gsi));
13668 basic_block latch_bb = e->dest;
13669 basic_block new_exit_bb;
13670 new_exit_bb = split_block_after_labels (latch_bb)->dest;
13671 loop->latch = latch_bb;
13673 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13675 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13676 /* The successor of incr_bb is already pointing to latch_bb; just
13677 change the flags.
13678 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13679 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13681 gphi *phi = create_phi_node (iter1, body_bb);
13682 edge preheader_edge = find_edge (entry_bb, body_bb);
13683 edge latch_edge = single_succ_edge (latch_bb);
13684 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13685 UNKNOWN_LOCATION);
13686 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13688 /* Generate the new return. */
13689 gsi = gsi_last_bb (new_exit_bb);
13690 if (retval
13691 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13692 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13693 retval = TREE_OPERAND (retval, 0);
13694 else if (retval)
13696 retval = build1 (VIEW_CONVERT_EXPR,
13697 TREE_TYPE (TREE_TYPE (node->decl)),
13698 retval);
13699 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13700 false, GSI_CONTINUE_LINKING);
13702 g = gimple_build_return (retval);
13703 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13705 /* Handle aligned clauses by replacing default defs of the aligned
13706 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13707 lhs. Handle linear by adding PHIs. */
13708 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13709 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13710 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
13711 || !is_gimple_reg_type
13712 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
13714 tree orig_arg = node->simdclone->args[i].orig_arg;
13715 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
13716 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
13717 else
13719 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
13720 gimple_add_tmp_var (iter1);
13722 gsi = gsi_after_labels (entry_bb);
13723 g = gimple_build_assign (iter1, orig_arg);
13724 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13725 gsi = gsi_after_labels (body_bb);
13726 g = gimple_build_assign (orig_arg, iter1);
13727 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13729 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13730 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
13731 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13732 == REFERENCE_TYPE
13733 && TREE_ADDRESSABLE
13734 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
13736 tree orig_arg = node->simdclone->args[i].orig_arg;
13737 tree def = ssa_default_def (cfun, orig_arg);
13738 if (def && !has_zero_uses (def))
13740 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
13741 gimple_add_tmp_var (iter1);
13742 gsi = gsi_after_labels (entry_bb);
13743 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
13744 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13745 gsi = gsi_after_labels (body_bb);
13746 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
13747 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13750 else if (node->simdclone->args[i].alignment
13751 && node->simdclone->args[i].arg_type
13752 == SIMD_CLONE_ARG_TYPE_UNIFORM
13753 && (node->simdclone->args[i].alignment
13754 & (node->simdclone->args[i].alignment - 1)) == 0
13755 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13756 == POINTER_TYPE)
13758 unsigned int alignment = node->simdclone->args[i].alignment;
13759 tree orig_arg = node->simdclone->args[i].orig_arg;
13760 tree def = ssa_default_def (cfun, orig_arg);
13761 if (def && !has_zero_uses (def))
13763 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13764 gimple_seq seq = NULL;
13765 bool need_cvt = false;
13766 gcall *call
13767 = gimple_build_call (fn, 2, def, size_int (alignment));
13768 g = call;
13769 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13770 ptr_type_node))
13771 need_cvt = true;
13772 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13773 gimple_call_set_lhs (g, t);
13774 gimple_seq_add_stmt_without_update (&seq, g);
13775 if (need_cvt)
13777 t = make_ssa_name (orig_arg);
13778 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13779 gimple_seq_add_stmt_without_update (&seq, g);
13781 gsi_insert_seq_on_edge_immediate
13782 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13784 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13785 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13786 entry_bb);
13787 node->create_edge (cgraph_node::get_create (fn),
13788 call, entry_bb->count, freq);
13790 imm_use_iterator iter;
13791 use_operand_p use_p;
13792 gimple use_stmt;
13793 tree repl = gimple_get_lhs (g);
13794 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13795 if (is_gimple_debug (use_stmt) || use_stmt == call)
13796 continue;
13797 else
13798 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13799 SET_USE (use_p, repl);
13802 else if (node->simdclone->args[i].arg_type
13803 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13805 tree orig_arg = node->simdclone->args[i].orig_arg;
13806 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13807 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13808 tree def = NULL_TREE;
13809 if (TREE_ADDRESSABLE (orig_arg))
13811 def = make_ssa_name (TREE_TYPE (orig_arg));
13812 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
13813 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
13814 gsi = gsi_after_labels (entry_bb);
13815 g = gimple_build_assign (def, orig_arg);
13816 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13818 else
13820 def = ssa_default_def (cfun, orig_arg);
13821 if (!def || has_zero_uses (def))
13822 def = NULL_TREE;
13823 else
13825 iter1 = make_ssa_name (orig_arg);
13826 iter2 = make_ssa_name (orig_arg);
13829 if (def)
13831 phi = create_phi_node (iter1, body_bb);
13832 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13833 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13834 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13835 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13836 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13837 ? TREE_TYPE (orig_arg) : sizetype;
13838 tree addcst
13839 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13840 g = gimple_build_assign (iter2, code, iter1, addcst);
13841 gsi = gsi_last_bb (incr_bb);
13842 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13844 imm_use_iterator iter;
13845 use_operand_p use_p;
13846 gimple use_stmt;
13847 if (TREE_ADDRESSABLE (orig_arg))
13849 gsi = gsi_after_labels (body_bb);
13850 g = gimple_build_assign (orig_arg, iter1);
13851 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
13853 else
13854 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13855 if (use_stmt == phi)
13856 continue;
13857 else
13858 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13859 SET_USE (use_p, iter1);
13863 calculate_dominance_info (CDI_DOMINATORS);
13864 add_loop (loop, loop->header->loop_father);
13865 update_ssa (TODO_update_ssa);
13867 pop_cfun ();
13870 /* If the function in NODE is tagged as an elemental SIMD function,
13871 create the appropriate SIMD clones. */
13873 static void
13874 expand_simd_clones (struct cgraph_node *node)
13876 tree attr = lookup_attribute ("omp declare simd",
13877 DECL_ATTRIBUTES (node->decl));
13878 if (attr == NULL_TREE
13879 || node->global.inlined_to
13880 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13881 return;
13883 /* Ignore
13884 #pragma omp declare simd
13885 extern int foo ();
13886 in C, there we don't know the argument types at all. */
13887 if (!node->definition
13888 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13889 return;
13893 /* Start with parsing the "omp declare simd" attribute(s). */
13894 bool inbranch_clause_specified;
13895 struct cgraph_simd_clone *clone_info
13896 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13897 &inbranch_clause_specified);
13898 if (clone_info == NULL)
13899 continue;
13901 int orig_simdlen = clone_info->simdlen;
13902 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13903 /* The target can return 0 (no simd clones should be created),
13904 1 (just one ISA of simd clones should be created) or higher
13905 count of ISA variants. In that case, clone_info is initialized
13906 for the first ISA variant. */
13907 int count
13908 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13909 base_type, 0);
13910 if (count == 0)
13911 continue;
13913 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13914 also create one inbranch and one !inbranch clone of it. */
13915 for (int i = 0; i < count * 2; i++)
13917 struct cgraph_simd_clone *clone = clone_info;
13918 if (inbranch_clause_specified && (i & 1) != 0)
13919 continue;
13921 if (i != 0)
13923 clone = simd_clone_struct_alloc (clone_info->nargs
13924 + ((i & 1) != 0));
13925 simd_clone_struct_copy (clone, clone_info);
13926 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13927 and simd_clone_adjust_argument_types did to the first
13928 clone's info. */
13929 clone->nargs -= clone_info->inbranch;
13930 clone->simdlen = orig_simdlen;
13931 /* And call the target hook again to get the right ISA. */
13932 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13933 base_type,
13934 i / 2);
13935 if ((i & 1) != 0)
13936 clone->inbranch = 1;
13939 /* simd_clone_mangle might fail if such a clone has been created
13940 already. */
13941 tree id = simd_clone_mangle (node, clone);
13942 if (id == NULL_TREE)
13943 continue;
13945 /* Only when we are sure we want to create the clone actually
13946 clone the function (or definitions) or create another
13947 extern FUNCTION_DECL (for prototypes without definitions). */
13948 struct cgraph_node *n = simd_clone_create (node);
13949 if (n == NULL)
13950 continue;
13952 n->simdclone = clone;
13953 clone->origin = node;
13954 clone->next_clone = NULL;
13955 if (node->simd_clones == NULL)
13957 clone->prev_clone = n;
13958 node->simd_clones = n;
13960 else
13962 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13963 clone->prev_clone->simdclone->next_clone = n;
13964 node->simd_clones->simdclone->prev_clone = n;
13966 symtab->change_decl_assembler_name (n->decl, id);
13967 /* And finally adjust the return type, parameters and for
13968 definitions also function body. */
13969 if (node->definition)
13970 simd_clone_adjust (n);
13971 else
13973 simd_clone_adjust_return_type (n);
13974 simd_clone_adjust_argument_types (n);
13978 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13981 /* Entry point for IPA simd clone creation pass. */
13983 static unsigned int
13984 ipa_omp_simd_clone (void)
13986 struct cgraph_node *node;
13987 FOR_EACH_FUNCTION (node)
13988 expand_simd_clones (node);
13989 return 0;
13992 namespace {
13994 const pass_data pass_data_omp_simd_clone =
13996 SIMPLE_IPA_PASS, /* type */
13997 "simdclone", /* name */
13998 OPTGROUP_NONE, /* optinfo_flags */
13999 TV_NONE, /* tv_id */
14000 ( PROP_ssa | PROP_cfg ), /* properties_required */
14001 0, /* properties_provided */
14002 0, /* properties_destroyed */
14003 0, /* todo_flags_start */
14004 0, /* todo_flags_finish */
14007 class pass_omp_simd_clone : public simple_ipa_opt_pass
14009 public:
14010 pass_omp_simd_clone(gcc::context *ctxt)
14011 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
14014 /* opt_pass methods: */
14015 virtual bool gate (function *);
14016 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
14019 bool
14020 pass_omp_simd_clone::gate (function *)
14022 return ((flag_openmp || flag_openmp_simd
14023 || flag_cilkplus
14024 || (in_lto_p && !flag_wpa))
14025 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
14028 } // anon namespace
14030 simple_ipa_opt_pass *
14031 make_pass_omp_simd_clone (gcc::context *ctxt)
14033 return new pass_omp_simd_clone (ctxt);
14036 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
14037 adds their addresses and sizes to constructor-vector V_CTOR. */
14038 static void
14039 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
14040 vec<constructor_elt, va_gc> *v_ctor)
14042 unsigned len = vec_safe_length (v_decls);
14043 for (unsigned i = 0; i < len; i++)
14045 tree it = (*v_decls)[i];
14046 bool is_function = TREE_CODE (it) != VAR_DECL;
14048 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
14049 if (!is_function)
14050 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
14051 fold_convert (const_ptr_type_node,
14052 DECL_SIZE_UNIT (it)));
14056 /* Create new symbols containing (address, size) pairs for global variables,
14057 marked with "omp declare target" attribute, as well as addresses for the
14058 functions, which are outlined offloading regions. */
14059 void
14060 omp_finish_file (void)
14062 unsigned num_funcs = vec_safe_length (offload_funcs);
14063 unsigned num_vars = vec_safe_length (offload_vars);
14065 if (num_funcs == 0 && num_vars == 0)
14066 return;
14068 if (targetm_common.have_named_sections)
14070 vec<constructor_elt, va_gc> *v_f, *v_v;
14071 vec_alloc (v_f, num_funcs);
14072 vec_alloc (v_v, num_vars * 2);
14074 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
14075 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
14077 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
14078 num_vars * 2);
14079 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
14080 num_funcs);
14081 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
14082 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
14083 tree ctor_v = build_constructor (vars_decl_type, v_v);
14084 tree ctor_f = build_constructor (funcs_decl_type, v_f);
14085 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
14086 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
14087 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
14088 get_identifier (".offload_func_table"),
14089 funcs_decl_type);
14090 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
14091 get_identifier (".offload_var_table"),
14092 vars_decl_type);
14093 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
14094 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
14095 otherwise a joint table in a binary will contain padding between
14096 tables from multiple object files. */
14097 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
14098 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
14099 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
14100 DECL_INITIAL (funcs_decl) = ctor_f;
14101 DECL_INITIAL (vars_decl) = ctor_v;
14102 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
14103 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
14105 varpool_node::finalize_decl (vars_decl);
14106 varpool_node::finalize_decl (funcs_decl);
14108 else
14110 for (unsigned i = 0; i < num_funcs; i++)
14112 tree it = (*offload_funcs)[i];
14113 targetm.record_offload_symbol (it);
14115 for (unsigned i = 0; i < num_vars; i++)
14117 tree it = (*offload_vars)[i];
14118 targetm.record_offload_symbol (it);
14123 #include "gt-omp-low.h"