svn merge -r 219425:219681 svn+ssh://gcc.gnu.org/svn/gcc/trunk
[official-gcc.git] / gcc / omp-low.c
blob00a7ca1fb3cde88642ad1e6bfaa12fa74fa635a8
1 /* Lowering pass for OMP directives. Converts OMP directives into explicit
2 calls to the runtime library (libgomp), data marshalling to implement data
3 sharing and copying clauses, offloading to accelerators, and more.
5 Contributed by Diego Novillo <dnovillo@redhat.com>
7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
9 This file is part of GCC.
11 GCC is free software; you can redistribute it and/or modify it under
12 the terms of the GNU General Public License as published by the Free
13 Software Foundation; either version 3, or (at your option) any later
14 version.
16 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 for more details.
21 You should have received a copy of the GNU General Public License
22 along with GCC; see the file COPYING3. If not see
23 <http://www.gnu.org/licenses/>. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
29 #include "hash-set.h"
30 #include "machmode.h"
31 #include "vec.h"
32 #include "double-int.h"
33 #include "input.h"
34 #include "alias.h"
35 #include "symtab.h"
36 #include "wide-int.h"
37 #include "inchash.h"
38 #include "tree.h"
39 #include "fold-const.h"
40 #include "stringpool.h"
41 #include "stor-layout.h"
42 #include "rtl.h"
43 #include "predict.h"
44 #include "hard-reg-set.h"
45 #include "function.h"
46 #include "dominance.h"
47 #include "cfg.h"
48 #include "cfganal.h"
49 #include "basic-block.h"
50 #include "tree-ssa-alias.h"
51 #include "internal-fn.h"
52 #include "gimple-fold.h"
53 #include "gimple-expr.h"
54 #include "is-a.h"
55 #include "gimple.h"
56 #include "gimplify.h"
57 #include "gimple-iterator.h"
58 #include "gimplify-me.h"
59 #include "gimple-walk.h"
60 #include "tree-iterator.h"
61 #include "tree-inline.h"
62 #include "langhooks.h"
63 #include "diagnostic-core.h"
64 #include "gimple-ssa.h"
65 #include "hash-map.h"
66 #include "plugin-api.h"
67 #include "ipa-ref.h"
68 #include "cgraph.h"
69 #include "tree-cfg.h"
70 #include "tree-phinodes.h"
71 #include "ssa-iterators.h"
72 #include "tree-ssanames.h"
73 #include "tree-into-ssa.h"
74 #include "hashtab.h"
75 #include "flags.h"
76 #include "statistics.h"
77 #include "real.h"
78 #include "fixed-value.h"
79 #include "insn-config.h"
80 #include "expmed.h"
81 #include "dojump.h"
82 #include "explow.h"
83 #include "calls.h"
84 #include "emit-rtl.h"
85 #include "varasm.h"
86 #include "stmt.h"
87 #include "expr.h"
88 #include "tree-dfa.h"
89 #include "tree-ssa.h"
90 #include "tree-pass.h"
91 #include "except.h"
92 #include "splay-tree.h"
93 #include "insn-codes.h"
94 #include "optabs.h"
95 #include "cfgloop.h"
96 #include "target.h"
97 #include "common/common-target.h"
98 #include "omp-low.h"
99 #include "gimple-low.h"
100 #include "tree-cfgcleanup.h"
101 #include "pretty-print.h"
102 #include "alloc-pool.h"
103 #include "symbol-summary.h"
104 #include "ipa-prop.h"
105 #include "tree-nested.h"
106 #include "tree-eh.h"
107 #include "cilk.h"
108 #include "context.h"
109 #include "lto-section-names.h"
110 #include "gomp-constants.h"
113 /* Lowering of OMP parallel and workshare constructs proceeds in two
114 phases. The first phase scans the function looking for OMP statements
115 and then for variables that must be replaced to satisfy data sharing
116 clauses. The second phase expands code for the constructs, as well as
117 re-gimplifying things when variables have been replaced with complex
118 expressions.
120 Final code generation is done by pass_expand_omp. The flowgraph is
121 scanned for regions which are then moved to a new
122 function, to be invoked by the thread library, or offloaded. */
124 /* OMP region information. Every parallel and workshare
125 directive is enclosed between two markers, the OMP_* directive
126 and a corresponding OMP_RETURN statement. */
128 struct omp_region
130 /* The enclosing region. */
131 struct omp_region *outer;
133 /* First child region. */
134 struct omp_region *inner;
136 /* Next peer region. */
137 struct omp_region *next;
139 /* Block containing the omp directive as its last stmt. */
140 basic_block entry;
142 /* Block containing the OMP_RETURN as its last stmt. */
143 basic_block exit;
145 /* Block containing the OMP_CONTINUE as its last stmt. */
146 basic_block cont;
148 /* If this is a combined parallel+workshare region, this is a list
149 of additional arguments needed by the combined parallel+workshare
150 library call. */
151 vec<tree, va_gc> *ws_args;
153 /* The code for the omp directive of this region. */
154 enum gimple_code type;
156 /* Schedule kind, only used for OMP_FOR type regions. */
157 enum omp_clause_schedule_kind sched_kind;
159 /* True if this is a combined parallel+workshare region. */
160 bool is_combined_parallel;
163 /* Levels of parallelism as defined by OpenACC. Increasing numbers
164 correspond to deeper loop nesting levels. */
165 #define MASK_GANG 1
166 #define MASK_WORKER 2
167 #define MASK_VECTOR 4
169 /* Context structure. Used to store information about each parallel
170 directive in the code. */
172 typedef struct omp_context
174 /* This field must be at the beginning, as we do "inheritance": Some
175 callback functions for tree-inline.c (e.g., omp_copy_decl)
176 receive a copy_body_data pointer that is up-casted to an
177 omp_context pointer. */
178 copy_body_data cb;
180 /* The tree of contexts corresponding to the encountered constructs. */
181 struct omp_context *outer;
182 gimple stmt;
184 /* Map variables to fields in a structure that allows communication
185 between sending and receiving threads. */
186 splay_tree field_map;
187 tree record_type;
188 tree sender_decl;
189 tree receiver_decl;
191 /* These are used just by task contexts, if task firstprivate fn is
192 needed. srecord_type is used to communicate from the thread
193 that encountered the task construct to task firstprivate fn,
194 record_type is allocated by GOMP_task, initialized by task firstprivate
195 fn and passed to the task body fn. */
196 splay_tree sfield_map;
197 tree srecord_type;
199 /* A chain of variables to add to the top-level block surrounding the
200 construct. In the case of a parallel, this is in the child function. */
201 tree block_vars;
203 /* A map of reduction pointer variables. For accelerators, each
204 reduction variable is replaced with an array. Each thread, in turn,
205 is assigned to a slot on that array. */
206 splay_tree reduction_map;
208 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
209 barriers should jump to during omplower pass. */
210 tree cancel_label;
212 /* What to do with variables with implicitly determined sharing
213 attributes. */
214 enum omp_clause_default_kind default_kind;
216 /* Nesting depth of this context. Used to beautify error messages re
217 invalid gotos. The outermost ctx is depth 1, with depth 0 being
218 reserved for the main body of the function. */
219 int depth;
221 /* True if this parallel directive is nested within another. */
222 bool is_nested;
224 /* True if this construct can be cancelled. */
225 bool cancellable;
227 /* For OpenACC loops, a mask of gang, worker and vector used at
228 levels below this one. */
229 int gwv_below;
230 /* For OpenACC loops, a mask of gang, worker and vector used at
231 this level and above. For parallel and kernels clauses, a mask
232 indicating which of num_gangs/num_workers/num_vectors was used. */
233 int gwv_this;
234 } omp_context;
236 /* A structure holding the elements of:
237 for (V = N1; V cond N2; V += STEP) [...] */
239 struct omp_for_data_loop
241 tree v, n1, n2, step;
242 enum tree_code cond_code;
245 /* A structure describing the main elements of a parallel loop. */
247 struct omp_for_data
249 struct omp_for_data_loop loop;
250 tree chunk_size;
251 gomp_for *for_stmt;
252 tree pre, iter_type;
253 int collapse;
254 bool have_nowait, have_ordered;
255 enum omp_clause_schedule_kind sched_kind;
256 struct omp_for_data_loop *loops;
260 static splay_tree all_contexts;
261 static int taskreg_nesting_level;
262 static int target_nesting_level;
263 static struct omp_region *root_omp_region;
264 static bitmap task_shared_vars;
265 static vec<omp_context *> taskreg_contexts;
267 static void scan_omp (gimple_seq *, omp_context *);
268 static tree scan_omp_1_op (tree *, int *, void *);
270 #define WALK_SUBSTMTS \
271 case GIMPLE_BIND: \
272 case GIMPLE_TRY: \
273 case GIMPLE_CATCH: \
274 case GIMPLE_EH_FILTER: \
275 case GIMPLE_TRANSACTION: \
276 /* The sub-statements for these should be walked. */ \
277 *handled_ops_p = false; \
278 break;
280 /* Helper function to get the name of the array containing the partial
281 reductions for OpenACC reductions. */
282 static const char *
283 oacc_get_reduction_array_id (tree node)
285 const char *id = IDENTIFIER_POINTER (DECL_NAME (node));
286 int len = strlen ("OACC") + strlen (id);
287 char *temp_name = XALLOCAVEC (char, len + 1);
288 snprintf (temp_name, len + 1, "OACC%s", id);
289 return IDENTIFIER_POINTER (get_identifier (temp_name));
292 /* Determine the number of threads OpenACC threads used to determine the
293 size of the array of partial reductions. Currently, this is num_gangs
294 * vector_length. This value may be different than GOACC_GET_NUM_THREADS,
295 because it is independed of the device used. */
297 static tree
298 oacc_max_threads (omp_context *ctx)
300 tree nthreads, vector_length, gangs, clauses;
302 gangs = fold_convert (sizetype, integer_one_node);
303 vector_length = gangs;
305 /* The reduction clause may be nested inside a loop directive.
306 Scan for the innermost vector_length clause. */
307 for (omp_context *oc = ctx; oc; oc = oc->outer)
309 if (gimple_code (oc->stmt) != GIMPLE_OMP_TARGET
310 || (gimple_omp_target_kind (oc->stmt)
311 != GF_OMP_TARGET_KIND_OACC_PARALLEL))
312 continue;
314 clauses = gimple_omp_target_clauses (oc->stmt);
316 vector_length = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
317 if (vector_length)
318 vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (vector_length),
319 sizetype,
320 OMP_CLAUSE_VECTOR_LENGTH_EXPR
321 (vector_length));
322 else
323 vector_length = fold_convert (sizetype, integer_one_node);
325 gangs = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
326 if (gangs)
327 gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (gangs), sizetype,
328 OMP_CLAUSE_NUM_GANGS_EXPR (gangs));
329 else
330 gangs = fold_convert (sizetype, integer_one_node);
332 break;
335 nthreads = fold_build2 (MULT_EXPR, sizetype, gangs, vector_length);
337 return nthreads;
340 /* Holds offload tables with decls. */
341 vec<tree, va_gc> *offload_funcs, *offload_vars;
343 /* Holds a decl for __OFFLOAD_TABLE__. */
344 static GTY(()) tree offload_symbol_decl;
346 /* Get the __OFFLOAD_TABLE__ symbol. */
347 static tree
348 get_offload_symbol_decl (void)
350 if (!offload_symbol_decl)
352 tree decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
353 get_identifier ("__OFFLOAD_TABLE__"),
354 ptr_type_node);
355 TREE_ADDRESSABLE (decl) = 1;
356 TREE_PUBLIC (decl) = 1;
357 DECL_EXTERNAL (decl) = 1;
358 DECL_WEAK (decl) = 1;
359 DECL_ATTRIBUTES (decl)
360 = tree_cons (get_identifier ("weak"),
361 NULL_TREE, DECL_ATTRIBUTES (decl));
362 offload_symbol_decl = decl;
364 return offload_symbol_decl;
367 /* Convenience function for calling scan_omp_1_op on tree operands. */
369 static inline tree
370 scan_omp_op (tree *tp, omp_context *ctx)
372 struct walk_stmt_info wi;
374 memset (&wi, 0, sizeof (wi));
375 wi.info = ctx;
376 wi.want_locations = true;
378 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
381 static void lower_omp (gimple_seq *, omp_context *);
382 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
383 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
385 /* Find an OMP clause of type KIND within CLAUSES. */
387 tree
388 find_omp_clause (tree clauses, enum omp_clause_code kind)
390 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
391 if (OMP_CLAUSE_CODE (clauses) == kind)
392 return clauses;
394 return NULL_TREE;
397 /* Return true if CTX is for an omp parallel. */
399 static inline bool
400 is_parallel_ctx (omp_context *ctx)
402 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
406 /* Return true if CTX is for an omp task. */
408 static inline bool
409 is_task_ctx (omp_context *ctx)
411 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
415 /* Return true if CTX is for an omp parallel or omp task. */
417 static inline bool
418 is_taskreg_ctx (omp_context *ctx)
420 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL
421 || gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
425 /* Return true if REGION is a combined parallel+workshare region. */
427 static inline bool
428 is_combined_parallel (struct omp_region *region)
430 return region->is_combined_parallel;
434 /* Extract the header elements of parallel loop FOR_STMT and store
435 them into *FD. */
437 static void
438 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
439 struct omp_for_data_loop *loops)
441 tree t, var, *collapse_iter, *collapse_count;
442 tree count = NULL_TREE, iter_type = long_integer_type_node;
443 struct omp_for_data_loop *loop;
444 int i;
445 struct omp_for_data_loop dummy_loop;
446 location_t loc = gimple_location (for_stmt);
447 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
448 bool distribute = gimple_omp_for_kind (for_stmt)
449 == GF_OMP_FOR_KIND_DISTRIBUTE;
451 fd->for_stmt = for_stmt;
452 fd->pre = NULL;
453 fd->collapse = gimple_omp_for_collapse (for_stmt);
454 if (fd->collapse > 1)
455 fd->loops = loops;
456 else
457 fd->loops = &fd->loop;
459 fd->have_nowait = distribute || simd;
460 fd->have_ordered = false;
461 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
462 fd->chunk_size = NULL_TREE;
463 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
464 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
465 collapse_iter = NULL;
466 collapse_count = NULL;
468 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
469 switch (OMP_CLAUSE_CODE (t))
471 case OMP_CLAUSE_NOWAIT:
472 fd->have_nowait = true;
473 break;
474 case OMP_CLAUSE_ORDERED:
475 fd->have_ordered = true;
476 break;
477 case OMP_CLAUSE_SCHEDULE:
478 gcc_assert (!distribute);
479 fd->sched_kind = OMP_CLAUSE_SCHEDULE_KIND (t);
480 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
481 break;
482 case OMP_CLAUSE_DIST_SCHEDULE:
483 gcc_assert (distribute);
484 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
485 break;
486 case OMP_CLAUSE_COLLAPSE:
487 if (fd->collapse > 1)
489 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
490 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
492 break;
493 default:
494 break;
497 /* FIXME: for now map schedule(auto) to schedule(static).
498 There should be analysis to determine whether all iterations
499 are approximately the same amount of work (then schedule(static)
500 is best) or if it varies (then schedule(dynamic,N) is better). */
501 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
503 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
504 gcc_assert (fd->chunk_size == NULL);
506 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
507 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
508 gcc_assert (fd->chunk_size == NULL);
509 else if (fd->chunk_size == NULL)
511 /* We only need to compute a default chunk size for ordered
512 static loops and dynamic loops. */
513 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
514 || fd->have_ordered)
515 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
516 ? integer_zero_node : integer_one_node;
519 for (i = 0; i < fd->collapse; i++)
521 if (fd->collapse == 1)
522 loop = &fd->loop;
523 else if (loops != NULL)
524 loop = loops + i;
525 else
526 loop = &dummy_loop;
528 loop->v = gimple_omp_for_index (for_stmt, i);
529 gcc_assert (SSA_VAR_P (loop->v));
530 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
531 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
532 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
533 loop->n1 = gimple_omp_for_initial (for_stmt, i);
535 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
536 loop->n2 = gimple_omp_for_final (for_stmt, i);
537 switch (loop->cond_code)
539 case LT_EXPR:
540 case GT_EXPR:
541 break;
542 case NE_EXPR:
543 gcc_assert (gimple_omp_for_kind (for_stmt)
544 == GF_OMP_FOR_KIND_CILKSIMD
545 || (gimple_omp_for_kind (for_stmt)
546 == GF_OMP_FOR_KIND_CILKFOR));
547 break;
548 case LE_EXPR:
549 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
550 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
551 else
552 loop->n2 = fold_build2_loc (loc,
553 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
554 build_int_cst (TREE_TYPE (loop->n2), 1));
555 loop->cond_code = LT_EXPR;
556 break;
557 case GE_EXPR:
558 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
559 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
560 else
561 loop->n2 = fold_build2_loc (loc,
562 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
563 build_int_cst (TREE_TYPE (loop->n2), 1));
564 loop->cond_code = GT_EXPR;
565 break;
566 default:
567 gcc_unreachable ();
570 t = gimple_omp_for_incr (for_stmt, i);
571 gcc_assert (TREE_OPERAND (t, 0) == var);
572 switch (TREE_CODE (t))
574 case PLUS_EXPR:
575 loop->step = TREE_OPERAND (t, 1);
576 break;
577 case POINTER_PLUS_EXPR:
578 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
579 break;
580 case MINUS_EXPR:
581 loop->step = TREE_OPERAND (t, 1);
582 loop->step = fold_build1_loc (loc,
583 NEGATE_EXPR, TREE_TYPE (loop->step),
584 loop->step);
585 break;
586 default:
587 gcc_unreachable ();
590 if (simd
591 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
592 && !fd->have_ordered))
594 if (fd->collapse == 1)
595 iter_type = TREE_TYPE (loop->v);
596 else if (i == 0
597 || TYPE_PRECISION (iter_type)
598 < TYPE_PRECISION (TREE_TYPE (loop->v)))
599 iter_type
600 = build_nonstandard_integer_type
601 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
603 else if (iter_type != long_long_unsigned_type_node)
605 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
606 iter_type = long_long_unsigned_type_node;
607 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
608 && TYPE_PRECISION (TREE_TYPE (loop->v))
609 >= TYPE_PRECISION (iter_type))
611 tree n;
613 if (loop->cond_code == LT_EXPR)
614 n = fold_build2_loc (loc,
615 PLUS_EXPR, TREE_TYPE (loop->v),
616 loop->n2, loop->step);
617 else
618 n = loop->n1;
619 if (TREE_CODE (n) != INTEGER_CST
620 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
621 iter_type = long_long_unsigned_type_node;
623 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
624 > TYPE_PRECISION (iter_type))
626 tree n1, n2;
628 if (loop->cond_code == LT_EXPR)
630 n1 = loop->n1;
631 n2 = fold_build2_loc (loc,
632 PLUS_EXPR, TREE_TYPE (loop->v),
633 loop->n2, loop->step);
635 else
637 n1 = fold_build2_loc (loc,
638 MINUS_EXPR, TREE_TYPE (loop->v),
639 loop->n2, loop->step);
640 n2 = loop->n1;
642 if (TREE_CODE (n1) != INTEGER_CST
643 || TREE_CODE (n2) != INTEGER_CST
644 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
645 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
646 iter_type = long_long_unsigned_type_node;
650 if (collapse_count && *collapse_count == NULL)
652 t = fold_binary (loop->cond_code, boolean_type_node,
653 fold_convert (TREE_TYPE (loop->v), loop->n1),
654 fold_convert (TREE_TYPE (loop->v), loop->n2));
655 if (t && integer_zerop (t))
656 count = build_zero_cst (long_long_unsigned_type_node);
657 else if ((i == 0 || count != NULL_TREE)
658 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
659 && TREE_CONSTANT (loop->n1)
660 && TREE_CONSTANT (loop->n2)
661 && TREE_CODE (loop->step) == INTEGER_CST)
663 tree itype = TREE_TYPE (loop->v);
665 if (POINTER_TYPE_P (itype))
666 itype = signed_type_for (itype);
667 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
668 t = fold_build2_loc (loc,
669 PLUS_EXPR, itype,
670 fold_convert_loc (loc, itype, loop->step), t);
671 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
672 fold_convert_loc (loc, itype, loop->n2));
673 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
674 fold_convert_loc (loc, itype, loop->n1));
675 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
676 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
677 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
678 fold_build1_loc (loc, NEGATE_EXPR, itype,
679 fold_convert_loc (loc, itype,
680 loop->step)));
681 else
682 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
683 fold_convert_loc (loc, itype, loop->step));
684 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
685 if (count != NULL_TREE)
686 count = fold_build2_loc (loc,
687 MULT_EXPR, long_long_unsigned_type_node,
688 count, t);
689 else
690 count = t;
691 if (TREE_CODE (count) != INTEGER_CST)
692 count = NULL_TREE;
694 else if (count && !integer_zerop (count))
695 count = NULL_TREE;
699 if (count
700 && !simd
701 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
702 || fd->have_ordered))
704 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
705 iter_type = long_long_unsigned_type_node;
706 else
707 iter_type = long_integer_type_node;
709 else if (collapse_iter && *collapse_iter != NULL)
710 iter_type = TREE_TYPE (*collapse_iter);
711 fd->iter_type = iter_type;
712 if (collapse_iter && *collapse_iter == NULL)
713 *collapse_iter = create_tmp_var (iter_type, ".iter");
714 if (collapse_count && *collapse_count == NULL)
716 if (count)
717 *collapse_count = fold_convert_loc (loc, iter_type, count);
718 else
719 *collapse_count = create_tmp_var (iter_type, ".count");
722 if (fd->collapse > 1)
724 fd->loop.v = *collapse_iter;
725 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
726 fd->loop.n2 = *collapse_count;
727 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
728 fd->loop.cond_code = LT_EXPR;
731 /* For OpenACC loops, force a chunk size of one, as this avoids the default
732 scheduling where several subsequent iterations are being executed by the
733 same thread. */
734 if (gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
736 gcc_assert (fd->chunk_size == NULL_TREE);
737 fd->chunk_size = build_int_cst (TREE_TYPE (fd->loop.v), 1);
742 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
743 is the immediate dominator of PAR_ENTRY_BB, return true if there
744 are no data dependencies that would prevent expanding the parallel
745 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
747 When expanding a combined parallel+workshare region, the call to
748 the child function may need additional arguments in the case of
749 GIMPLE_OMP_FOR regions. In some cases, these arguments are
750 computed out of variables passed in from the parent to the child
751 via 'struct .omp_data_s'. For instance:
753 #pragma omp parallel for schedule (guided, i * 4)
754 for (j ...)
756 Is lowered into:
758 # BLOCK 2 (PAR_ENTRY_BB)
759 .omp_data_o.i = i;
760 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
762 # BLOCK 3 (WS_ENTRY_BB)
763 .omp_data_i = &.omp_data_o;
764 D.1667 = .omp_data_i->i;
765 D.1598 = D.1667 * 4;
766 #pragma omp for schedule (guided, D.1598)
768 When we outline the parallel region, the call to the child function
769 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
770 that value is computed *after* the call site. So, in principle we
771 cannot do the transformation.
773 To see whether the code in WS_ENTRY_BB blocks the combined
774 parallel+workshare call, we collect all the variables used in the
775 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
776 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
777 call.
779 FIXME. If we had the SSA form built at this point, we could merely
780 hoist the code in block 3 into block 2 and be done with it. But at
781 this point we don't have dataflow information and though we could
782 hack something up here, it is really not worth the aggravation. */
784 static bool
785 workshare_safe_to_combine_p (basic_block ws_entry_bb)
787 struct omp_for_data fd;
788 gimple ws_stmt = last_stmt (ws_entry_bb);
790 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
791 return true;
793 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
795 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
797 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
798 return false;
799 if (fd.iter_type != long_integer_type_node)
800 return false;
802 /* FIXME. We give up too easily here. If any of these arguments
803 are not constants, they will likely involve variables that have
804 been mapped into fields of .omp_data_s for sharing with the child
805 function. With appropriate data flow, it would be possible to
806 see through this. */
807 if (!is_gimple_min_invariant (fd.loop.n1)
808 || !is_gimple_min_invariant (fd.loop.n2)
809 || !is_gimple_min_invariant (fd.loop.step)
810 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
811 return false;
813 return true;
817 /* Collect additional arguments needed to emit a combined
818 parallel+workshare call. WS_STMT is the workshare directive being
819 expanded. */
821 static vec<tree, va_gc> *
822 get_ws_args_for (gimple par_stmt, gimple ws_stmt)
824 tree t;
825 location_t loc = gimple_location (ws_stmt);
826 vec<tree, va_gc> *ws_args;
828 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
830 struct omp_for_data fd;
831 tree n1, n2;
833 extract_omp_for_data (for_stmt, &fd, NULL);
834 n1 = fd.loop.n1;
835 n2 = fd.loop.n2;
837 if (gimple_omp_for_combined_into_p (for_stmt))
839 tree innerc
840 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
841 OMP_CLAUSE__LOOPTEMP_);
842 gcc_assert (innerc);
843 n1 = OMP_CLAUSE_DECL (innerc);
844 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
845 OMP_CLAUSE__LOOPTEMP_);
846 gcc_assert (innerc);
847 n2 = OMP_CLAUSE_DECL (innerc);
850 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
852 t = fold_convert_loc (loc, long_integer_type_node, n1);
853 ws_args->quick_push (t);
855 t = fold_convert_loc (loc, long_integer_type_node, n2);
856 ws_args->quick_push (t);
858 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
859 ws_args->quick_push (t);
861 if (fd.chunk_size)
863 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
864 ws_args->quick_push (t);
867 return ws_args;
869 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
871 /* Number of sections is equal to the number of edges from the
872 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
873 the exit of the sections region. */
874 basic_block bb = single_succ (gimple_bb (ws_stmt));
875 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
876 vec_alloc (ws_args, 1);
877 ws_args->quick_push (t);
878 return ws_args;
881 gcc_unreachable ();
885 /* Discover whether REGION is a combined parallel+workshare region. */
887 static void
888 determine_parallel_type (struct omp_region *region)
890 basic_block par_entry_bb, par_exit_bb;
891 basic_block ws_entry_bb, ws_exit_bb;
893 if (region == NULL || region->inner == NULL
894 || region->exit == NULL || region->inner->exit == NULL
895 || region->inner->cont == NULL)
896 return;
898 /* We only support parallel+for and parallel+sections. */
899 if (region->type != GIMPLE_OMP_PARALLEL
900 || (region->inner->type != GIMPLE_OMP_FOR
901 && region->inner->type != GIMPLE_OMP_SECTIONS))
902 return;
904 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
905 WS_EXIT_BB -> PAR_EXIT_BB. */
906 par_entry_bb = region->entry;
907 par_exit_bb = region->exit;
908 ws_entry_bb = region->inner->entry;
909 ws_exit_bb = region->inner->exit;
911 if (single_succ (par_entry_bb) == ws_entry_bb
912 && single_succ (ws_exit_bb) == par_exit_bb
913 && workshare_safe_to_combine_p (ws_entry_bb)
914 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
915 || (last_and_only_stmt (ws_entry_bb)
916 && last_and_only_stmt (par_exit_bb))))
918 gimple par_stmt = last_stmt (par_entry_bb);
919 gimple ws_stmt = last_stmt (ws_entry_bb);
921 if (region->inner->type == GIMPLE_OMP_FOR)
923 /* If this is a combined parallel loop, we need to determine
924 whether or not to use the combined library calls. There
925 are two cases where we do not apply the transformation:
926 static loops and any kind of ordered loop. In the first
927 case, we already open code the loop so there is no need
928 to do anything else. In the latter case, the combined
929 parallel loop call would still need extra synchronization
930 to implement ordered semantics, so there would not be any
931 gain in using the combined call. */
932 tree clauses = gimple_omp_for_clauses (ws_stmt);
933 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
934 if (c == NULL
935 || OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_STATIC
936 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
938 region->is_combined_parallel = false;
939 region->inner->is_combined_parallel = false;
940 return;
944 region->is_combined_parallel = true;
945 region->inner->is_combined_parallel = true;
946 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
951 /* Return true if EXPR is variable sized. */
953 static inline bool
954 is_variable_sized (const_tree expr)
956 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
959 /* Return true if DECL is a reference type. */
961 static inline bool
962 is_reference (tree decl)
964 return lang_hooks.decls.omp_privatize_by_reference (decl);
967 /* Return the type of a decl. If the decl is reference type,
968 return its base type. */
969 static inline tree
970 get_base_type (tree decl)
972 tree type = TREE_TYPE (decl);
973 if (is_reference (decl))
974 type = TREE_TYPE (type);
975 return type;
978 /* Lookup variables. The "maybe" form
979 allows for the variable form to not have been entered, otherwise we
980 assert that the variable must have been entered. */
982 static inline tree
983 lookup_decl (tree var, omp_context *ctx)
985 tree *n = ctx->cb.decl_map->get (var);
986 return *n;
989 static inline tree
990 maybe_lookup_decl (const_tree var, omp_context *ctx)
992 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
993 return n ? *n : NULL_TREE;
996 static inline tree
997 lookup_field (tree var, omp_context *ctx)
999 splay_tree_node n;
1000 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1001 return (tree) n->value;
1004 static inline tree
1005 lookup_sfield (tree var, omp_context *ctx)
1007 splay_tree_node n;
1008 n = splay_tree_lookup (ctx->sfield_map
1009 ? ctx->sfield_map : ctx->field_map,
1010 (splay_tree_key) var);
1011 return (tree) n->value;
1014 static inline tree
1015 maybe_lookup_field (tree var, omp_context *ctx)
1017 splay_tree_node n;
1018 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1019 return n ? (tree) n->value : NULL_TREE;
1022 static inline tree
1023 lookup_oacc_reduction (const char *id, omp_context *ctx)
1025 splay_tree_node n;
1026 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) id);
1027 return (tree) n->value;
1030 static inline tree
1031 maybe_lookup_oacc_reduction (tree var, omp_context *ctx)
1033 splay_tree_node n = NULL;
1034 if (ctx->reduction_map)
1035 n = splay_tree_lookup (ctx->reduction_map, (splay_tree_key) var);
1036 return n ? (tree) n->value : NULL_TREE;
1039 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1040 the parallel context if DECL is to be shared. */
1042 static bool
1043 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1045 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1046 return true;
1048 /* We can only use copy-in/copy-out semantics for shared variables
1049 when we know the value is not accessible from an outer scope. */
1050 if (shared_ctx)
1052 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1054 /* ??? Trivially accessible from anywhere. But why would we even
1055 be passing an address in this case? Should we simply assert
1056 this to be false, or should we have a cleanup pass that removes
1057 these from the list of mappings? */
1058 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1059 return true;
1061 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1062 without analyzing the expression whether or not its location
1063 is accessible to anyone else. In the case of nested parallel
1064 regions it certainly may be. */
1065 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1066 return true;
1068 /* Do not use copy-in/copy-out for variables that have their
1069 address taken. */
1070 if (TREE_ADDRESSABLE (decl))
1071 return true;
1073 /* lower_send_shared_vars only uses copy-in, but not copy-out
1074 for these. */
1075 if (TREE_READONLY (decl)
1076 || ((TREE_CODE (decl) == RESULT_DECL
1077 || TREE_CODE (decl) == PARM_DECL)
1078 && DECL_BY_REFERENCE (decl)))
1079 return false;
1081 /* Disallow copy-in/out in nested parallel if
1082 decl is shared in outer parallel, otherwise
1083 each thread could store the shared variable
1084 in its own copy-in location, making the
1085 variable no longer really shared. */
1086 if (shared_ctx->is_nested)
1088 omp_context *up;
1090 for (up = shared_ctx->outer; up; up = up->outer)
1091 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1092 break;
1094 if (up)
1096 tree c;
1098 for (c = gimple_omp_taskreg_clauses (up->stmt);
1099 c; c = OMP_CLAUSE_CHAIN (c))
1100 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1101 && OMP_CLAUSE_DECL (c) == decl)
1102 break;
1104 if (c)
1105 goto maybe_mark_addressable_and_ret;
1109 /* For tasks avoid using copy-in/out. As tasks can be
1110 deferred or executed in different thread, when GOMP_task
1111 returns, the task hasn't necessarily terminated. */
1112 if (is_task_ctx (shared_ctx))
1114 tree outer;
1115 maybe_mark_addressable_and_ret:
1116 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1117 if (is_gimple_reg (outer))
1119 /* Taking address of OUTER in lower_send_shared_vars
1120 might need regimplification of everything that uses the
1121 variable. */
1122 if (!task_shared_vars)
1123 task_shared_vars = BITMAP_ALLOC (NULL);
1124 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1125 TREE_ADDRESSABLE (outer) = 1;
1127 return true;
1131 return false;
1134 /* Construct a new automatic decl similar to VAR. */
1136 static tree
1137 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1139 tree copy = copy_var_decl (var, name, type);
1141 DECL_CONTEXT (copy) = current_function_decl;
1142 DECL_CHAIN (copy) = ctx->block_vars;
1143 ctx->block_vars = copy;
1145 return copy;
1148 static tree
1149 omp_copy_decl_1 (tree var, omp_context *ctx)
1151 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1154 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1155 as appropriate. */
1156 static tree
1157 omp_build_component_ref (tree obj, tree field)
1159 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1160 if (TREE_THIS_VOLATILE (field))
1161 TREE_THIS_VOLATILE (ret) |= 1;
1162 if (TREE_READONLY (field))
1163 TREE_READONLY (ret) |= 1;
1164 return ret;
1167 /* Build tree nodes to access the field for VAR on the receiver side. */
1169 static tree
1170 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1172 tree x, field = lookup_field (var, ctx);
1174 /* If the receiver record type was remapped in the child function,
1175 remap the field into the new record type. */
1176 x = maybe_lookup_field (field, ctx);
1177 if (x != NULL)
1178 field = x;
1180 x = build_simple_mem_ref (ctx->receiver_decl);
1181 x = omp_build_component_ref (x, field);
1182 if (by_ref)
1183 x = build_simple_mem_ref (x);
1185 return x;
1188 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1189 of a parallel, this is a component reference; for workshare constructs
1190 this is some variable. */
1192 static tree
1193 build_outer_var_ref (tree var, omp_context *ctx)
1195 tree x;
1197 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1198 x = var;
1199 else if (is_variable_sized (var))
1201 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1202 x = build_outer_var_ref (x, ctx);
1203 x = build_simple_mem_ref (x);
1205 else if (is_taskreg_ctx (ctx))
1207 bool by_ref = use_pointer_for_field (var, NULL);
1208 x = build_receiver_ref (var, by_ref, ctx);
1210 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1211 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1213 /* #pragma omp simd isn't a worksharing construct, and can reference even
1214 private vars in its linear etc. clauses. */
1215 x = NULL_TREE;
1216 if (ctx->outer && is_taskreg_ctx (ctx))
1217 x = lookup_decl (var, ctx->outer);
1218 else if (ctx->outer)
1219 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1220 if (x == NULL_TREE)
1221 x = var;
1223 else if (ctx->outer)
1224 x = lookup_decl (var, ctx->outer);
1225 else if (is_reference (var))
1226 /* This can happen with orphaned constructs. If var is reference, it is
1227 possible it is shared and as such valid. */
1228 x = var;
1229 else
1230 gcc_unreachable ();
1232 if (is_reference (var))
1233 x = build_simple_mem_ref (x);
1235 return x;
1238 /* Build tree nodes to access the field for VAR on the sender side. */
1240 static tree
1241 build_sender_ref (tree var, omp_context *ctx)
1243 tree field = lookup_sfield (var, ctx);
1244 return omp_build_component_ref (ctx->sender_decl, field);
1247 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1249 static void
1250 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1252 tree field, type, sfield = NULL_TREE;
1254 gcc_assert ((mask & 1) == 0
1255 || !splay_tree_lookup (ctx->field_map, (splay_tree_key) var));
1256 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1257 || !splay_tree_lookup (ctx->sfield_map, (splay_tree_key) var));
1258 gcc_assert ((mask & 3) == 3
1259 || !is_gimple_omp_oacc (ctx->stmt));
1261 type = TREE_TYPE (var);
1262 if (mask & 4)
1264 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1265 type = build_pointer_type (build_pointer_type (type));
1267 else if (by_ref)
1268 type = build_pointer_type (type);
1269 else if ((mask & 3) == 1 && is_reference (var))
1270 type = TREE_TYPE (type);
1272 field = build_decl (DECL_SOURCE_LOCATION (var),
1273 FIELD_DECL, DECL_NAME (var), type);
1275 /* Remember what variable this field was created for. This does have a
1276 side effect of making dwarf2out ignore this member, so for helpful
1277 debugging we clear it later in delete_omp_context. */
1278 DECL_ABSTRACT_ORIGIN (field) = var;
1279 if (type == TREE_TYPE (var))
1281 DECL_ALIGN (field) = DECL_ALIGN (var);
1282 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1283 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1285 else
1286 DECL_ALIGN (field) = TYPE_ALIGN (type);
1288 if ((mask & 3) == 3)
1290 insert_field_into_struct (ctx->record_type, field);
1291 if (ctx->srecord_type)
1293 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1294 FIELD_DECL, DECL_NAME (var), type);
1295 DECL_ABSTRACT_ORIGIN (sfield) = var;
1296 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1297 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1298 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1299 insert_field_into_struct (ctx->srecord_type, sfield);
1302 else
1304 if (ctx->srecord_type == NULL_TREE)
1306 tree t;
1308 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1309 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1310 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1312 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1313 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1314 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1315 insert_field_into_struct (ctx->srecord_type, sfield);
1316 splay_tree_insert (ctx->sfield_map,
1317 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1318 (splay_tree_value) sfield);
1321 sfield = field;
1322 insert_field_into_struct ((mask & 1) ? ctx->record_type
1323 : ctx->srecord_type, field);
1326 if (mask & 1)
1327 splay_tree_insert (ctx->field_map, (splay_tree_key) var,
1328 (splay_tree_value) field);
1329 if ((mask & 2) && ctx->sfield_map)
1330 splay_tree_insert (ctx->sfield_map, (splay_tree_key) var,
1331 (splay_tree_value) sfield);
1334 static tree
1335 install_var_local (tree var, omp_context *ctx)
1337 tree new_var = omp_copy_decl_1 (var, ctx);
1338 insert_decl_map (&ctx->cb, var, new_var);
1339 return new_var;
1342 /* Adjust the replacement for DECL in CTX for the new context. This means
1343 copying the DECL_VALUE_EXPR, and fixing up the type. */
1345 static void
1346 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1348 tree new_decl, size;
1350 new_decl = lookup_decl (decl, ctx);
1352 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1354 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1355 && DECL_HAS_VALUE_EXPR_P (decl))
1357 tree ve = DECL_VALUE_EXPR (decl);
1358 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1359 SET_DECL_VALUE_EXPR (new_decl, ve);
1360 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1363 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1365 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1366 if (size == error_mark_node)
1367 size = TYPE_SIZE (TREE_TYPE (new_decl));
1368 DECL_SIZE (new_decl) = size;
1370 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1371 if (size == error_mark_node)
1372 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1373 DECL_SIZE_UNIT (new_decl) = size;
1377 /* The callback for remap_decl. Search all containing contexts for a
1378 mapping of the variable; this avoids having to duplicate the splay
1379 tree ahead of time. We know a mapping doesn't already exist in the
1380 given context. Create new mappings to implement default semantics. */
1382 static tree
1383 omp_copy_decl (tree var, copy_body_data *cb)
1385 omp_context *ctx = (omp_context *) cb;
1386 tree new_var;
1388 if (TREE_CODE (var) == LABEL_DECL)
1390 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1391 DECL_CONTEXT (new_var) = current_function_decl;
1392 insert_decl_map (&ctx->cb, var, new_var);
1393 return new_var;
1396 while (!is_taskreg_ctx (ctx))
1398 ctx = ctx->outer;
1399 if (ctx == NULL)
1400 return var;
1401 new_var = maybe_lookup_decl (var, ctx);
1402 if (new_var)
1403 return new_var;
1406 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1407 return var;
1409 return error_mark_node;
1413 /* Debugging dumps for parallel regions. */
1414 void dump_omp_region (FILE *, struct omp_region *, int);
1415 void debug_omp_region (struct omp_region *);
1416 void debug_all_omp_regions (void);
1418 /* Dump the parallel region tree rooted at REGION. */
1420 void
1421 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1423 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1424 gimple_code_name[region->type]);
1426 if (region->inner)
1427 dump_omp_region (file, region->inner, indent + 4);
1429 if (region->cont)
1431 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1432 region->cont->index);
1435 if (region->exit)
1436 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1437 region->exit->index);
1438 else
1439 fprintf (file, "%*s[no exit marker]\n", indent, "");
1441 if (region->next)
1442 dump_omp_region (file, region->next, indent);
1445 DEBUG_FUNCTION void
1446 debug_omp_region (struct omp_region *region)
1448 dump_omp_region (stderr, region, 0);
1451 DEBUG_FUNCTION void
1452 debug_all_omp_regions (void)
1454 dump_omp_region (stderr, root_omp_region, 0);
1458 /* Create a new parallel region starting at STMT inside region PARENT. */
1460 static struct omp_region *
1461 new_omp_region (basic_block bb, enum gimple_code type,
1462 struct omp_region *parent)
1464 struct omp_region *region = XCNEW (struct omp_region);
1466 region->outer = parent;
1467 region->entry = bb;
1468 region->type = type;
1470 if (parent)
1472 /* This is a nested region. Add it to the list of inner
1473 regions in PARENT. */
1474 region->next = parent->inner;
1475 parent->inner = region;
1477 else
1479 /* This is a toplevel region. Add it to the list of toplevel
1480 regions in ROOT_OMP_REGION. */
1481 region->next = root_omp_region;
1482 root_omp_region = region;
1485 return region;
1488 /* Release the memory associated with the region tree rooted at REGION. */
1490 static void
1491 free_omp_region_1 (struct omp_region *region)
1493 struct omp_region *i, *n;
1495 for (i = region->inner; i ; i = n)
1497 n = i->next;
1498 free_omp_region_1 (i);
1501 free (region);
1504 /* Release the memory for the entire omp region tree. */
1506 void
1507 free_omp_regions (void)
1509 struct omp_region *r, *n;
1510 for (r = root_omp_region; r ; r = n)
1512 n = r->next;
1513 free_omp_region_1 (r);
1515 root_omp_region = NULL;
1519 /* Create a new context, with OUTER_CTX being the surrounding context. */
1521 static omp_context *
1522 new_omp_context (gimple stmt, omp_context *outer_ctx)
1524 omp_context *ctx = XCNEW (omp_context);
1526 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1527 (splay_tree_value) ctx);
1528 ctx->stmt = stmt;
1530 if (outer_ctx)
1532 ctx->outer = outer_ctx;
1533 ctx->cb = outer_ctx->cb;
1534 ctx->cb.block = NULL;
1535 ctx->depth = outer_ctx->depth + 1;
1536 ctx->reduction_map = outer_ctx->reduction_map;
1538 else
1540 ctx->cb.src_fn = current_function_decl;
1541 ctx->cb.dst_fn = current_function_decl;
1542 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1543 gcc_checking_assert (ctx->cb.src_node);
1544 ctx->cb.dst_node = ctx->cb.src_node;
1545 ctx->cb.src_cfun = cfun;
1546 ctx->cb.copy_decl = omp_copy_decl;
1547 ctx->cb.eh_lp_nr = 0;
1548 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1549 ctx->depth = 1;
1552 ctx->cb.decl_map = new hash_map<tree, tree>;
1554 return ctx;
1557 static gimple_seq maybe_catch_exception (gimple_seq);
1559 /* Finalize task copyfn. */
1561 static void
1562 finalize_task_copyfn (gomp_task *task_stmt)
1564 struct function *child_cfun;
1565 tree child_fn;
1566 gimple_seq seq = NULL, new_seq;
1567 gbind *bind;
1569 child_fn = gimple_omp_task_copy_fn (task_stmt);
1570 if (child_fn == NULL_TREE)
1571 return;
1573 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1574 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1576 push_cfun (child_cfun);
1577 bind = gimplify_body (child_fn, false);
1578 gimple_seq_add_stmt (&seq, bind);
1579 new_seq = maybe_catch_exception (seq);
1580 if (new_seq != seq)
1582 bind = gimple_build_bind (NULL, new_seq, NULL);
1583 seq = NULL;
1584 gimple_seq_add_stmt (&seq, bind);
1586 gimple_set_body (child_fn, seq);
1587 pop_cfun ();
1589 /* Inform the callgraph about the new function. */
1590 cgraph_node::add_new_function (child_fn, false);
1593 /* Destroy a omp_context data structures. Called through the splay tree
1594 value delete callback. */
1596 static void
1597 delete_omp_context (splay_tree_value value)
1599 omp_context *ctx = (omp_context *) value;
1601 delete ctx->cb.decl_map;
1603 if (ctx->field_map)
1604 splay_tree_delete (ctx->field_map);
1605 if (ctx->sfield_map)
1606 splay_tree_delete (ctx->sfield_map);
1607 if (ctx->reduction_map
1608 /* Shared over several omp_contexts. */
1609 && (ctx->outer == NULL
1610 || ctx->reduction_map != ctx->outer->reduction_map))
1611 splay_tree_delete (ctx->reduction_map);
1613 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1614 it produces corrupt debug information. */
1615 if (ctx->record_type)
1617 tree t;
1618 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1619 DECL_ABSTRACT_ORIGIN (t) = NULL;
1621 if (ctx->srecord_type)
1623 tree t;
1624 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1625 DECL_ABSTRACT_ORIGIN (t) = NULL;
1628 if (is_task_ctx (ctx))
1629 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1631 XDELETE (ctx);
1634 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1635 context. */
1637 static void
1638 fixup_child_record_type (omp_context *ctx)
1640 tree f, type = ctx->record_type;
1642 /* ??? It isn't sufficient to just call remap_type here, because
1643 variably_modified_type_p doesn't work the way we expect for
1644 record types. Testing each field for whether it needs remapping
1645 and creating a new record by hand works, however. */
1646 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1647 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1648 break;
1649 if (f)
1651 tree name, new_fields = NULL;
1653 type = lang_hooks.types.make_type (RECORD_TYPE);
1654 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1655 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1656 TYPE_DECL, name, type);
1657 TYPE_NAME (type) = name;
1659 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1661 tree new_f = copy_node (f);
1662 DECL_CONTEXT (new_f) = type;
1663 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1664 DECL_CHAIN (new_f) = new_fields;
1665 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1666 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1667 &ctx->cb, NULL);
1668 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1669 &ctx->cb, NULL);
1670 new_fields = new_f;
1672 /* Arrange to be able to look up the receiver field
1673 given the sender field. */
1674 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1675 (splay_tree_value) new_f);
1677 TYPE_FIELDS (type) = nreverse (new_fields);
1678 layout_type (type);
1681 TREE_TYPE (ctx->receiver_decl)
1682 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1685 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1686 specified by CLAUSES. */
1688 static void
1689 scan_sharing_clauses (tree clauses, omp_context *ctx)
1691 tree c, decl;
1692 bool scan_array_reductions = false;
1694 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1696 bool by_ref;
1698 switch (OMP_CLAUSE_CODE (c))
1700 case OMP_CLAUSE_PRIVATE:
1701 decl = OMP_CLAUSE_DECL (c);
1702 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1703 goto do_private;
1704 else if (!is_variable_sized (decl))
1705 install_var_local (decl, ctx);
1706 break;
1708 case OMP_CLAUSE_SHARED:
1709 decl = OMP_CLAUSE_DECL (c);
1710 /* Ignore shared directives in teams construct. */
1711 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1713 /* Global variables don't need to be copied,
1714 the receiver side will use them directly. */
1715 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1716 if (is_global_var (odecl))
1717 break;
1718 insert_decl_map (&ctx->cb, decl, odecl);
1719 break;
1721 gcc_assert (is_taskreg_ctx (ctx));
1722 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1723 || !is_variable_sized (decl));
1724 /* Global variables don't need to be copied,
1725 the receiver side will use them directly. */
1726 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1727 break;
1728 by_ref = use_pointer_for_field (decl, ctx);
1729 if (! TREE_READONLY (decl)
1730 || TREE_ADDRESSABLE (decl)
1731 || by_ref
1732 || is_reference (decl))
1734 install_var_field (decl, by_ref, 3, ctx);
1735 install_var_local (decl, ctx);
1736 break;
1738 /* We don't need to copy const scalar vars back. */
1739 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1740 goto do_private;
1742 case OMP_CLAUSE_LASTPRIVATE:
1743 /* Let the corresponding firstprivate clause create
1744 the variable. */
1745 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1746 break;
1747 /* FALLTHRU */
1749 case OMP_CLAUSE_FIRSTPRIVATE:
1750 if (is_gimple_omp_oacc (ctx->stmt))
1752 sorry ("clause not supported yet");
1753 break;
1755 /* FALLTHRU */
1756 case OMP_CLAUSE_REDUCTION:
1757 case OMP_CLAUSE_LINEAR:
1758 decl = OMP_CLAUSE_DECL (c);
1759 do_private:
1760 if (is_variable_sized (decl))
1762 if (is_task_ctx (ctx))
1763 install_var_field (decl, false, 1, ctx);
1764 break;
1766 else if (is_taskreg_ctx (ctx))
1768 bool global
1769 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1770 by_ref = use_pointer_for_field (decl, NULL);
1772 if (is_task_ctx (ctx)
1773 && (global || by_ref || is_reference (decl)))
1775 install_var_field (decl, false, 1, ctx);
1776 if (!global)
1777 install_var_field (decl, by_ref, 2, ctx);
1779 else if (!global)
1780 install_var_field (decl, by_ref, 3, ctx);
1782 install_var_local (decl, ctx);
1783 if (is_gimple_omp_oacc (ctx->stmt)
1784 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
1786 /* Create a decl for the reduction array. */
1787 tree var = OMP_CLAUSE_DECL (c);
1788 tree type = get_base_type (var);
1789 tree ptype = build_pointer_type (type);
1790 tree array = create_tmp_var (ptype,
1791 oacc_get_reduction_array_id (var));
1792 omp_context *c = (ctx->field_map ? ctx : ctx->outer);
1793 install_var_field (array, true, 3, c);
1794 install_var_local (array, c);
1796 /* Insert it into the current context. */
1797 splay_tree_insert (ctx->reduction_map, (splay_tree_key)
1798 oacc_get_reduction_array_id (var),
1799 (splay_tree_value) array);
1800 splay_tree_insert (ctx->reduction_map,
1801 (splay_tree_key) array,
1802 (splay_tree_value) array);
1804 break;
1806 case OMP_CLAUSE__LOOPTEMP_:
1807 gcc_assert (is_parallel_ctx (ctx));
1808 decl = OMP_CLAUSE_DECL (c);
1809 install_var_field (decl, false, 3, ctx);
1810 install_var_local (decl, ctx);
1811 break;
1813 case OMP_CLAUSE_COPYPRIVATE:
1814 case OMP_CLAUSE_COPYIN:
1815 decl = OMP_CLAUSE_DECL (c);
1816 by_ref = use_pointer_for_field (decl, NULL);
1817 install_var_field (decl, by_ref, 3, ctx);
1818 break;
1820 case OMP_CLAUSE_DEFAULT:
1821 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1822 break;
1824 case OMP_CLAUSE_FINAL:
1825 case OMP_CLAUSE_IF:
1826 case OMP_CLAUSE_NUM_THREADS:
1827 case OMP_CLAUSE_NUM_TEAMS:
1828 case OMP_CLAUSE_THREAD_LIMIT:
1829 case OMP_CLAUSE_DEVICE:
1830 case OMP_CLAUSE_SCHEDULE:
1831 case OMP_CLAUSE_DIST_SCHEDULE:
1832 case OMP_CLAUSE_DEPEND:
1833 case OMP_CLAUSE__CILK_FOR_COUNT_:
1834 case OMP_CLAUSE_NUM_GANGS:
1835 case OMP_CLAUSE_NUM_WORKERS:
1836 case OMP_CLAUSE_VECTOR_LENGTH:
1837 if (ctx->outer)
1838 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1839 break;
1841 case OMP_CLAUSE_TO:
1842 case OMP_CLAUSE_FROM:
1843 case OMP_CLAUSE_MAP:
1844 if (ctx->outer)
1845 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
1846 decl = OMP_CLAUSE_DECL (c);
1847 /* Global variables with "omp declare target" attribute
1848 don't need to be copied, the receiver side will use them
1849 directly. */
1850 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1851 && DECL_P (decl)
1852 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
1853 && varpool_node::get_create (decl)->offloadable)
1854 break;
1855 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1856 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
1858 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
1859 not offloaded; there is nothing to map for those. */
1860 if (!is_gimple_omp_offloaded (ctx->stmt)
1861 && !POINTER_TYPE_P (TREE_TYPE (decl)))
1862 break;
1864 if (DECL_P (decl))
1866 if (DECL_SIZE (decl)
1867 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1869 tree decl2 = DECL_VALUE_EXPR (decl);
1870 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1871 decl2 = TREE_OPERAND (decl2, 0);
1872 gcc_assert (DECL_P (decl2));
1873 install_var_field (decl2, true, 3, ctx);
1874 install_var_local (decl2, ctx);
1875 install_var_local (decl, ctx);
1877 else
1879 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
1880 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
1881 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
1882 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1883 install_var_field (decl, true, 7, ctx);
1884 else
1885 install_var_field (decl, true, 3, ctx);
1886 if (is_gimple_omp_offloaded (ctx->stmt))
1887 install_var_local (decl, ctx);
1890 else
1892 tree base = get_base_address (decl);
1893 tree nc = OMP_CLAUSE_CHAIN (c);
1894 if (DECL_P (base)
1895 && nc != NULL_TREE
1896 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
1897 && OMP_CLAUSE_DECL (nc) == base
1898 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
1899 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
1901 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
1902 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
1904 else
1906 if (ctx->outer)
1908 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
1909 decl = OMP_CLAUSE_DECL (c);
1911 gcc_assert (!splay_tree_lookup (ctx->field_map,
1912 (splay_tree_key) decl));
1913 tree field
1914 = build_decl (OMP_CLAUSE_LOCATION (c),
1915 FIELD_DECL, NULL_TREE, ptr_type_node);
1916 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
1917 insert_field_into_struct (ctx->record_type, field);
1918 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
1919 (splay_tree_value) field);
1922 break;
1924 case OMP_CLAUSE_NOWAIT:
1925 case OMP_CLAUSE_ORDERED:
1926 case OMP_CLAUSE_COLLAPSE:
1927 case OMP_CLAUSE_UNTIED:
1928 case OMP_CLAUSE_MERGEABLE:
1929 case OMP_CLAUSE_PROC_BIND:
1930 case OMP_CLAUSE_SAFELEN:
1931 case OMP_CLAUSE_ASYNC:
1932 case OMP_CLAUSE_WAIT:
1933 case OMP_CLAUSE_GANG:
1934 case OMP_CLAUSE_WORKER:
1935 case OMP_CLAUSE_VECTOR:
1936 break;
1938 case OMP_CLAUSE_ALIGNED:
1939 decl = OMP_CLAUSE_DECL (c);
1940 if (is_global_var (decl)
1941 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1942 install_var_local (decl, ctx);
1943 break;
1945 case OMP_CLAUSE_DEVICE_RESIDENT:
1946 case OMP_CLAUSE_USE_DEVICE:
1947 case OMP_CLAUSE__CACHE_:
1948 case OMP_CLAUSE_INDEPENDENT:
1949 case OMP_CLAUSE_AUTO:
1950 case OMP_CLAUSE_SEQ:
1951 sorry ("Clause not supported yet");
1952 break;
1954 default:
1955 gcc_unreachable ();
1959 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1961 switch (OMP_CLAUSE_CODE (c))
1963 case OMP_CLAUSE_LASTPRIVATE:
1964 /* Let the corresponding firstprivate clause create
1965 the variable. */
1966 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
1967 scan_array_reductions = true;
1968 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1969 break;
1970 /* FALLTHRU */
1972 case OMP_CLAUSE_FIRSTPRIVATE:
1973 if (is_gimple_omp_oacc (ctx->stmt))
1975 sorry ("clause not supported yet");
1976 break;
1978 /* FALLTHRU */
1979 case OMP_CLAUSE_PRIVATE:
1980 case OMP_CLAUSE_REDUCTION:
1981 case OMP_CLAUSE_LINEAR:
1982 decl = OMP_CLAUSE_DECL (c);
1983 if (is_variable_sized (decl))
1984 install_var_local (decl, ctx);
1985 fixup_remapped_decl (decl, ctx,
1986 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
1987 && OMP_CLAUSE_PRIVATE_DEBUG (c));
1988 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1989 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
1990 scan_array_reductions = true;
1991 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
1992 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
1993 scan_array_reductions = true;
1994 break;
1996 case OMP_CLAUSE_SHARED:
1997 /* Ignore shared directives in teams construct. */
1998 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1999 break;
2000 decl = OMP_CLAUSE_DECL (c);
2001 if (! is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2002 fixup_remapped_decl (decl, ctx, false);
2003 break;
2005 case OMP_CLAUSE_MAP:
2006 if (!is_gimple_omp_offloaded (ctx->stmt))
2007 break;
2008 decl = OMP_CLAUSE_DECL (c);
2009 if (DECL_P (decl)
2010 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2011 && varpool_node::get_create (decl)->offloadable)
2012 break;
2013 if (DECL_P (decl))
2015 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2016 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2017 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2019 tree new_decl = lookup_decl (decl, ctx);
2020 TREE_TYPE (new_decl)
2021 = remap_type (TREE_TYPE (decl), &ctx->cb);
2023 else if (DECL_SIZE (decl)
2024 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2026 tree decl2 = DECL_VALUE_EXPR (decl);
2027 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2028 decl2 = TREE_OPERAND (decl2, 0);
2029 gcc_assert (DECL_P (decl2));
2030 fixup_remapped_decl (decl2, ctx, false);
2031 fixup_remapped_decl (decl, ctx, true);
2033 else
2034 fixup_remapped_decl (decl, ctx, false);
2036 break;
2038 case OMP_CLAUSE_COPYPRIVATE:
2039 case OMP_CLAUSE_COPYIN:
2040 case OMP_CLAUSE_DEFAULT:
2041 case OMP_CLAUSE_IF:
2042 case OMP_CLAUSE_NUM_THREADS:
2043 case OMP_CLAUSE_NUM_TEAMS:
2044 case OMP_CLAUSE_THREAD_LIMIT:
2045 case OMP_CLAUSE_DEVICE:
2046 case OMP_CLAUSE_SCHEDULE:
2047 case OMP_CLAUSE_DIST_SCHEDULE:
2048 case OMP_CLAUSE_NOWAIT:
2049 case OMP_CLAUSE_ORDERED:
2050 case OMP_CLAUSE_COLLAPSE:
2051 case OMP_CLAUSE_UNTIED:
2052 case OMP_CLAUSE_FINAL:
2053 case OMP_CLAUSE_MERGEABLE:
2054 case OMP_CLAUSE_PROC_BIND:
2055 case OMP_CLAUSE_SAFELEN:
2056 case OMP_CLAUSE_ALIGNED:
2057 case OMP_CLAUSE_DEPEND:
2058 case OMP_CLAUSE__LOOPTEMP_:
2059 case OMP_CLAUSE_TO:
2060 case OMP_CLAUSE_FROM:
2061 case OMP_CLAUSE__CILK_FOR_COUNT_:
2062 case OMP_CLAUSE_ASYNC:
2063 case OMP_CLAUSE_WAIT:
2064 case OMP_CLAUSE_NUM_GANGS:
2065 case OMP_CLAUSE_NUM_WORKERS:
2066 case OMP_CLAUSE_VECTOR_LENGTH:
2067 case OMP_CLAUSE_GANG:
2068 case OMP_CLAUSE_WORKER:
2069 case OMP_CLAUSE_VECTOR:
2070 break;
2072 case OMP_CLAUSE_DEVICE_RESIDENT:
2073 case OMP_CLAUSE_USE_DEVICE:
2074 case OMP_CLAUSE__CACHE_:
2075 case OMP_CLAUSE_INDEPENDENT:
2076 case OMP_CLAUSE_AUTO:
2077 case OMP_CLAUSE_SEQ:
2078 sorry ("Clause not supported yet");
2079 break;
2081 default:
2082 gcc_unreachable ();
2086 gcc_checking_assert (!scan_array_reductions
2087 || !is_gimple_omp_oacc (ctx->stmt));
2088 if (scan_array_reductions)
2089 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2090 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2091 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2093 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2094 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2096 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2097 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2098 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2099 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2100 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2101 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2104 /* Create a new name for omp child function. Returns an identifier. If
2105 IS_CILK_FOR is true then the suffix for the child function is
2106 "_cilk_for_fn." */
2108 static tree
2109 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2111 if (is_cilk_for)
2112 return clone_function_name (current_function_decl, "_cilk_for_fn");
2113 return clone_function_name (current_function_decl,
2114 task_copy ? "_omp_cpyfn" : "_omp_fn");
2117 /* Returns the type of the induction variable for the child function for
2118 _Cilk_for and the types for _high and _low variables based on TYPE. */
2120 static tree
2121 cilk_for_check_loop_diff_type (tree type)
2123 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2125 if (TYPE_UNSIGNED (type))
2126 return uint32_type_node;
2127 else
2128 return integer_type_node;
2130 else
2132 if (TYPE_UNSIGNED (type))
2133 return uint64_type_node;
2134 else
2135 return long_long_integer_type_node;
2139 /* Build a decl for the omp child function. It'll not contain a body
2140 yet, just the bare decl. */
2142 static void
2143 create_omp_child_function (omp_context *ctx, bool task_copy)
2145 tree decl, type, name, t;
2147 tree cilk_for_count
2148 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2149 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2150 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2151 tree cilk_var_type = NULL_TREE;
2153 name = create_omp_child_function_name (task_copy,
2154 cilk_for_count != NULL_TREE);
2155 if (task_copy)
2156 type = build_function_type_list (void_type_node, ptr_type_node,
2157 ptr_type_node, NULL_TREE);
2158 else if (cilk_for_count)
2160 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2161 cilk_var_type = cilk_for_check_loop_diff_type (type);
2162 type = build_function_type_list (void_type_node, ptr_type_node,
2163 cilk_var_type, cilk_var_type, NULL_TREE);
2165 else
2166 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2168 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2170 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2171 || !task_copy);
2172 if (!task_copy)
2173 ctx->cb.dst_fn = decl;
2174 else
2175 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2177 TREE_STATIC (decl) = 1;
2178 TREE_USED (decl) = 1;
2179 DECL_ARTIFICIAL (decl) = 1;
2180 DECL_IGNORED_P (decl) = 0;
2181 TREE_PUBLIC (decl) = 0;
2182 DECL_UNINLINABLE (decl) = 1;
2183 DECL_EXTERNAL (decl) = 0;
2184 DECL_CONTEXT (decl) = NULL_TREE;
2185 DECL_INITIAL (decl) = make_node (BLOCK);
2186 if (cgraph_node::get (current_function_decl)->offloadable)
2187 cgraph_node::get_create (decl)->offloadable = 1;
2188 else
2190 omp_context *octx;
2191 for (octx = ctx; octx; octx = octx->outer)
2192 if (is_gimple_omp_offloaded (octx->stmt))
2194 cgraph_node::get_create (decl)->offloadable = 1;
2195 #ifdef ENABLE_OFFLOADING
2196 g->have_offload = true;
2197 #endif
2198 break;
2202 t = build_decl (DECL_SOURCE_LOCATION (decl),
2203 RESULT_DECL, NULL_TREE, void_type_node);
2204 DECL_ARTIFICIAL (t) = 1;
2205 DECL_IGNORED_P (t) = 1;
2206 DECL_CONTEXT (t) = decl;
2207 DECL_RESULT (decl) = t;
2209 /* _Cilk_for's child function requires two extra parameters called
2210 __low and __high that are set the by Cilk runtime when it calls this
2211 function. */
2212 if (cilk_for_count)
2214 t = build_decl (DECL_SOURCE_LOCATION (decl),
2215 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2216 DECL_ARTIFICIAL (t) = 1;
2217 DECL_NAMELESS (t) = 1;
2218 DECL_ARG_TYPE (t) = ptr_type_node;
2219 DECL_CONTEXT (t) = current_function_decl;
2220 TREE_USED (t) = 1;
2221 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2222 DECL_ARGUMENTS (decl) = t;
2224 t = build_decl (DECL_SOURCE_LOCATION (decl),
2225 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2226 DECL_ARTIFICIAL (t) = 1;
2227 DECL_NAMELESS (t) = 1;
2228 DECL_ARG_TYPE (t) = ptr_type_node;
2229 DECL_CONTEXT (t) = current_function_decl;
2230 TREE_USED (t) = 1;
2231 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2232 DECL_ARGUMENTS (decl) = t;
2235 tree data_name = get_identifier (".omp_data_i");
2236 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2237 ptr_type_node);
2238 DECL_ARTIFICIAL (t) = 1;
2239 DECL_NAMELESS (t) = 1;
2240 DECL_ARG_TYPE (t) = ptr_type_node;
2241 DECL_CONTEXT (t) = current_function_decl;
2242 TREE_USED (t) = 1;
2243 if (cilk_for_count)
2244 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2245 DECL_ARGUMENTS (decl) = t;
2246 if (!task_copy)
2247 ctx->receiver_decl = t;
2248 else
2250 t = build_decl (DECL_SOURCE_LOCATION (decl),
2251 PARM_DECL, get_identifier (".omp_data_o"),
2252 ptr_type_node);
2253 DECL_ARTIFICIAL (t) = 1;
2254 DECL_NAMELESS (t) = 1;
2255 DECL_ARG_TYPE (t) = ptr_type_node;
2256 DECL_CONTEXT (t) = current_function_decl;
2257 TREE_USED (t) = 1;
2258 TREE_ADDRESSABLE (t) = 1;
2259 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2260 DECL_ARGUMENTS (decl) = t;
2263 /* Allocate memory for the function structure. The call to
2264 allocate_struct_function clobbers CFUN, so we need to restore
2265 it afterward. */
2266 push_struct_function (decl);
2267 cfun->function_end_locus = gimple_location (ctx->stmt);
2268 pop_cfun ();
2271 /* Callback for walk_gimple_seq. Check if combined parallel
2272 contains gimple_omp_for_combined_into_p OMP_FOR. */
2274 static tree
2275 find_combined_for (gimple_stmt_iterator *gsi_p,
2276 bool *handled_ops_p,
2277 struct walk_stmt_info *wi)
2279 gimple stmt = gsi_stmt (*gsi_p);
2281 *handled_ops_p = true;
2282 switch (gimple_code (stmt))
2284 WALK_SUBSTMTS;
2286 case GIMPLE_OMP_FOR:
2287 if (gimple_omp_for_combined_into_p (stmt)
2288 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
2290 wi->info = stmt;
2291 return integer_zero_node;
2293 break;
2294 default:
2295 break;
2297 return NULL;
2300 /* Scan an OpenMP parallel directive. */
2302 static void
2303 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2305 omp_context *ctx;
2306 tree name;
2307 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2309 /* Ignore parallel directives with empty bodies, unless there
2310 are copyin clauses. */
2311 if (optimize > 0
2312 && empty_body_p (gimple_omp_body (stmt))
2313 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2314 OMP_CLAUSE_COPYIN) == NULL)
2316 gsi_replace (gsi, gimple_build_nop (), false);
2317 return;
2320 if (gimple_omp_parallel_combined_p (stmt))
2322 struct walk_stmt_info wi;
2324 memset (&wi, 0, sizeof (wi));
2325 wi.val_only = true;
2326 walk_gimple_seq (gimple_omp_body (stmt),
2327 find_combined_for, NULL, &wi);
2328 if (wi.info)
2330 gomp_for *for_stmt = as_a <gomp_for *> ((gimple) wi.info);
2331 struct omp_for_data fd;
2332 extract_omp_for_data (for_stmt, &fd, NULL);
2333 /* We need two temporaries with fd.loop.v type (istart/iend)
2334 and then (fd.collapse - 1) temporaries with the same
2335 type for count2 ... countN-1 vars if not constant. */
2336 size_t count = 2, i;
2337 tree type = fd.iter_type;
2338 if (fd.collapse > 1
2339 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2340 count += fd.collapse - 1;
2341 for (i = 0; i < count; i++)
2343 tree temp = create_tmp_var (type);
2344 tree c = build_omp_clause (UNKNOWN_LOCATION,
2345 OMP_CLAUSE__LOOPTEMP_);
2346 insert_decl_map (&outer_ctx->cb, temp, temp);
2347 OMP_CLAUSE_DECL (c) = temp;
2348 OMP_CLAUSE_CHAIN (c) = gimple_omp_parallel_clauses (stmt);
2349 gimple_omp_parallel_set_clauses (stmt, c);
2354 ctx = new_omp_context (stmt, outer_ctx);
2355 taskreg_contexts.safe_push (ctx);
2356 if (taskreg_nesting_level > 1)
2357 ctx->is_nested = true;
2358 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2359 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2360 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2361 name = create_tmp_var_name (".omp_data_s");
2362 name = build_decl (gimple_location (stmt),
2363 TYPE_DECL, name, ctx->record_type);
2364 DECL_ARTIFICIAL (name) = 1;
2365 DECL_NAMELESS (name) = 1;
2366 TYPE_NAME (ctx->record_type) = name;
2367 create_omp_child_function (ctx, false);
2368 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2370 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2371 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2373 if (TYPE_FIELDS (ctx->record_type) == NULL)
2374 ctx->record_type = ctx->receiver_decl = NULL;
2377 /* Scan an OpenMP task directive. */
2379 static void
2380 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2382 omp_context *ctx;
2383 tree name, t;
2384 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2386 /* Ignore task directives with empty bodies. */
2387 if (optimize > 0
2388 && empty_body_p (gimple_omp_body (stmt)))
2390 gsi_replace (gsi, gimple_build_nop (), false);
2391 return;
2394 ctx = new_omp_context (stmt, outer_ctx);
2395 taskreg_contexts.safe_push (ctx);
2396 if (taskreg_nesting_level > 1)
2397 ctx->is_nested = true;
2398 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2399 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2400 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2401 name = create_tmp_var_name (".omp_data_s");
2402 name = build_decl (gimple_location (stmt),
2403 TYPE_DECL, name, ctx->record_type);
2404 DECL_ARTIFICIAL (name) = 1;
2405 DECL_NAMELESS (name) = 1;
2406 TYPE_NAME (ctx->record_type) = name;
2407 create_omp_child_function (ctx, false);
2408 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2410 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2412 if (ctx->srecord_type)
2414 name = create_tmp_var_name (".omp_data_a");
2415 name = build_decl (gimple_location (stmt),
2416 TYPE_DECL, name, ctx->srecord_type);
2417 DECL_ARTIFICIAL (name) = 1;
2418 DECL_NAMELESS (name) = 1;
2419 TYPE_NAME (ctx->srecord_type) = name;
2420 create_omp_child_function (ctx, true);
2423 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2425 if (TYPE_FIELDS (ctx->record_type) == NULL)
2427 ctx->record_type = ctx->receiver_decl = NULL;
2428 t = build_int_cst (long_integer_type_node, 0);
2429 gimple_omp_task_set_arg_size (stmt, t);
2430 t = build_int_cst (long_integer_type_node, 1);
2431 gimple_omp_task_set_arg_align (stmt, t);
2436 /* If any decls have been made addressable during scan_omp,
2437 adjust their fields if needed, and layout record types
2438 of parallel/task constructs. */
2440 static void
2441 finish_taskreg_scan (omp_context *ctx)
2443 if (ctx->record_type == NULL_TREE)
2444 return;
2446 /* If any task_shared_vars were needed, verify all
2447 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2448 statements if use_pointer_for_field hasn't changed
2449 because of that. If it did, update field types now. */
2450 if (task_shared_vars)
2452 tree c;
2454 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2455 c; c = OMP_CLAUSE_CHAIN (c))
2456 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
2458 tree decl = OMP_CLAUSE_DECL (c);
2460 /* Global variables don't need to be copied,
2461 the receiver side will use them directly. */
2462 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2463 continue;
2464 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2465 || !use_pointer_for_field (decl, ctx))
2466 continue;
2467 tree field = lookup_field (decl, ctx);
2468 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2469 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2470 continue;
2471 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2472 TREE_THIS_VOLATILE (field) = 0;
2473 DECL_USER_ALIGN (field) = 0;
2474 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2475 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2476 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2477 if (ctx->srecord_type)
2479 tree sfield = lookup_sfield (decl, ctx);
2480 TREE_TYPE (sfield) = TREE_TYPE (field);
2481 TREE_THIS_VOLATILE (sfield) = 0;
2482 DECL_USER_ALIGN (sfield) = 0;
2483 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2484 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2485 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2490 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2492 layout_type (ctx->record_type);
2493 fixup_child_record_type (ctx);
2495 else
2497 location_t loc = gimple_location (ctx->stmt);
2498 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2499 /* Move VLA fields to the end. */
2500 p = &TYPE_FIELDS (ctx->record_type);
2501 while (*p)
2502 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2503 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2505 *q = *p;
2506 *p = TREE_CHAIN (*p);
2507 TREE_CHAIN (*q) = NULL_TREE;
2508 q = &TREE_CHAIN (*q);
2510 else
2511 p = &DECL_CHAIN (*p);
2512 *p = vla_fields;
2513 layout_type (ctx->record_type);
2514 fixup_child_record_type (ctx);
2515 if (ctx->srecord_type)
2516 layout_type (ctx->srecord_type);
2517 tree t = fold_convert_loc (loc, long_integer_type_node,
2518 TYPE_SIZE_UNIT (ctx->record_type));
2519 gimple_omp_task_set_arg_size (ctx->stmt, t);
2520 t = build_int_cst (long_integer_type_node,
2521 TYPE_ALIGN_UNIT (ctx->record_type));
2522 gimple_omp_task_set_arg_align (ctx->stmt, t);
2527 static omp_context *
2528 enclosing_target_ctx (omp_context *ctx)
2530 while (ctx != NULL
2531 && gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
2532 ctx = ctx->outer;
2533 gcc_assert (ctx != NULL);
2534 return ctx;
2537 static bool
2538 oacc_loop_or_target_p (gimple stmt)
2540 enum gimple_code outer_type = gimple_code (stmt);
2541 return ((outer_type == GIMPLE_OMP_TARGET
2542 && ((gimple_omp_target_kind (stmt)
2543 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2544 || (gimple_omp_target_kind (stmt)
2545 == GF_OMP_TARGET_KIND_OACC_KERNELS)))
2546 || (outer_type == GIMPLE_OMP_FOR
2547 && gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP));
2550 /* Scan a GIMPLE_OMP_FOR. */
2552 static void
2553 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2555 enum gimple_code outer_type = GIMPLE_ERROR_MARK;
2556 omp_context *ctx;
2557 size_t i;
2558 tree clauses = gimple_omp_for_clauses (stmt);
2560 if (outer_ctx)
2561 outer_type = gimple_code (outer_ctx->stmt);
2563 ctx = new_omp_context (stmt, outer_ctx);
2565 if (is_gimple_omp_oacc (stmt))
2567 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2568 ctx->gwv_this = outer_ctx->gwv_this;
2569 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2571 int val;
2572 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_GANG)
2573 val = MASK_GANG;
2574 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WORKER)
2575 val = MASK_WORKER;
2576 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR)
2577 val = MASK_VECTOR;
2578 else
2579 continue;
2580 ctx->gwv_this |= val;
2581 if (!outer_ctx)
2583 /* Skip; not nested inside a region. */
2584 continue;
2586 if (!oacc_loop_or_target_p (outer_ctx->stmt))
2588 /* Skip; not nested inside an OpenACC region. */
2589 continue;
2591 if (outer_type == GIMPLE_OMP_FOR)
2592 outer_ctx->gwv_below |= val;
2593 if (OMP_CLAUSE_OPERAND (c, 0) != NULL_TREE)
2595 omp_context *enclosing = enclosing_target_ctx (outer_ctx);
2596 if (gimple_omp_target_kind (enclosing->stmt)
2597 == GF_OMP_TARGET_KIND_OACC_PARALLEL)
2598 error_at (gimple_location (stmt),
2599 "no arguments allowed to gang, worker and vector clauses inside parallel");
2604 scan_sharing_clauses (clauses, ctx);
2606 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2607 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2609 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2610 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2611 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2612 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2614 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2616 if (is_gimple_omp_oacc (stmt))
2618 if (ctx->gwv_this & ctx->gwv_below)
2619 error_at (gimple_location (stmt),
2620 "gang, worker and vector may occur only once in a loop nest");
2621 else if (ctx->gwv_below != 0
2622 && ctx->gwv_this > ctx->gwv_below)
2623 error_at (gimple_location (stmt),
2624 "gang, worker and vector must occur in this order in a loop nest");
2625 if (outer_ctx && outer_type == GIMPLE_OMP_FOR)
2626 outer_ctx->gwv_below |= ctx->gwv_below;
2630 /* Scan an OpenMP sections directive. */
2632 static void
2633 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2635 omp_context *ctx;
2637 ctx = new_omp_context (stmt, outer_ctx);
2638 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
2639 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2642 /* Scan an OpenMP single directive. */
2644 static void
2645 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
2647 omp_context *ctx;
2648 tree name;
2650 ctx = new_omp_context (stmt, outer_ctx);
2651 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2652 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2653 name = create_tmp_var_name (".omp_copy_s");
2654 name = build_decl (gimple_location (stmt),
2655 TYPE_DECL, name, ctx->record_type);
2656 TYPE_NAME (ctx->record_type) = name;
2658 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
2659 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2661 if (TYPE_FIELDS (ctx->record_type) == NULL)
2662 ctx->record_type = NULL;
2663 else
2664 layout_type (ctx->record_type);
2667 /* Scan a GIMPLE_OMP_TARGET. */
2669 static void
2670 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
2672 omp_context *ctx;
2673 tree name;
2674 bool offloaded = is_gimple_omp_offloaded (stmt);
2675 tree clauses = gimple_omp_target_clauses (stmt);
2677 ctx = new_omp_context (stmt, outer_ctx);
2678 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2679 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2680 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2681 name = create_tmp_var_name (".omp_data_t");
2682 name = build_decl (gimple_location (stmt),
2683 TYPE_DECL, name, ctx->record_type);
2684 DECL_ARTIFICIAL (name) = 1;
2685 DECL_NAMELESS (name) = 1;
2686 TYPE_NAME (ctx->record_type) = name;
2687 if (offloaded)
2689 if (is_gimple_omp_oacc (stmt))
2690 ctx->reduction_map = splay_tree_new (splay_tree_compare_pointers,
2691 0, 0);
2693 create_omp_child_function (ctx, false);
2694 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
2697 if (is_gimple_omp_oacc (stmt))
2699 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2701 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_GANGS)
2702 ctx->gwv_this |= MASK_GANG;
2703 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_WORKERS)
2704 ctx->gwv_this |= MASK_WORKER;
2705 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_VECTOR_LENGTH)
2706 ctx->gwv_this |= MASK_VECTOR;
2710 scan_sharing_clauses (clauses, ctx);
2711 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2713 if (TYPE_FIELDS (ctx->record_type) == NULL)
2714 ctx->record_type = ctx->receiver_decl = NULL;
2715 else
2717 TYPE_FIELDS (ctx->record_type)
2718 = nreverse (TYPE_FIELDS (ctx->record_type));
2719 #ifdef ENABLE_CHECKING
2720 tree field;
2721 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
2722 for (field = TYPE_FIELDS (ctx->record_type);
2723 field;
2724 field = DECL_CHAIN (field))
2725 gcc_assert (DECL_ALIGN (field) == align);
2726 #endif
2727 layout_type (ctx->record_type);
2728 if (offloaded)
2729 fixup_child_record_type (ctx);
2733 /* Scan an OpenMP teams directive. */
2735 static void
2736 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
2738 omp_context *ctx = new_omp_context (stmt, outer_ctx);
2739 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
2740 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2743 /* Check nesting restrictions. */
2744 static bool
2745 check_omp_nesting_restrictions (gimple stmt, omp_context *ctx)
2747 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
2748 inside an OpenACC CTX. */
2749 if (!(is_gimple_omp (stmt)
2750 && is_gimple_omp_oacc (stmt)))
2752 for (omp_context *ctx_ = ctx; ctx_ != NULL; ctx_ = ctx_->outer)
2753 if (is_gimple_omp (ctx_->stmt)
2754 && is_gimple_omp_oacc (ctx_->stmt))
2756 error_at (gimple_location (stmt),
2757 "non-OpenACC construct inside of OpenACC region");
2758 return false;
2762 if (ctx != NULL)
2764 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
2765 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
2767 error_at (gimple_location (stmt),
2768 "OpenMP constructs may not be nested inside simd region");
2769 return false;
2771 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2773 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
2774 || (gimple_omp_for_kind (stmt)
2775 != GF_OMP_FOR_KIND_DISTRIBUTE))
2776 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
2778 error_at (gimple_location (stmt),
2779 "only distribute or parallel constructs are allowed to "
2780 "be closely nested inside teams construct");
2781 return false;
2785 switch (gimple_code (stmt))
2787 case GIMPLE_OMP_FOR:
2788 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
2789 return true;
2790 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
2792 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
2794 error_at (gimple_location (stmt),
2795 "distribute construct must be closely nested inside "
2796 "teams construct");
2797 return false;
2799 return true;
2801 /* FALLTHRU */
2802 case GIMPLE_CALL:
2803 if (is_gimple_call (stmt)
2804 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2805 == BUILT_IN_GOMP_CANCEL
2806 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2807 == BUILT_IN_GOMP_CANCELLATION_POINT))
2809 const char *bad = NULL;
2810 const char *kind = NULL;
2811 if (ctx == NULL)
2813 error_at (gimple_location (stmt), "orphaned %qs construct",
2814 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2815 == BUILT_IN_GOMP_CANCEL
2816 ? "#pragma omp cancel"
2817 : "#pragma omp cancellation point");
2818 return false;
2820 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
2821 ? tree_to_shwi (gimple_call_arg (stmt, 0))
2822 : 0)
2824 case 1:
2825 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
2826 bad = "#pragma omp parallel";
2827 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2828 == BUILT_IN_GOMP_CANCEL
2829 && !integer_zerop (gimple_call_arg (stmt, 1)))
2830 ctx->cancellable = true;
2831 kind = "parallel";
2832 break;
2833 case 2:
2834 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
2835 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
2836 bad = "#pragma omp for";
2837 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2838 == BUILT_IN_GOMP_CANCEL
2839 && !integer_zerop (gimple_call_arg (stmt, 1)))
2841 ctx->cancellable = true;
2842 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2843 OMP_CLAUSE_NOWAIT))
2844 warning_at (gimple_location (stmt), 0,
2845 "%<#pragma omp cancel for%> inside "
2846 "%<nowait%> for construct");
2847 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2848 OMP_CLAUSE_ORDERED))
2849 warning_at (gimple_location (stmt), 0,
2850 "%<#pragma omp cancel for%> inside "
2851 "%<ordered%> for construct");
2853 kind = "for";
2854 break;
2855 case 4:
2856 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
2857 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
2858 bad = "#pragma omp sections";
2859 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2860 == BUILT_IN_GOMP_CANCEL
2861 && !integer_zerop (gimple_call_arg (stmt, 1)))
2863 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
2865 ctx->cancellable = true;
2866 if (find_omp_clause (gimple_omp_sections_clauses
2867 (ctx->stmt),
2868 OMP_CLAUSE_NOWAIT))
2869 warning_at (gimple_location (stmt), 0,
2870 "%<#pragma omp cancel sections%> inside "
2871 "%<nowait%> sections construct");
2873 else
2875 gcc_assert (ctx->outer
2876 && gimple_code (ctx->outer->stmt)
2877 == GIMPLE_OMP_SECTIONS);
2878 ctx->outer->cancellable = true;
2879 if (find_omp_clause (gimple_omp_sections_clauses
2880 (ctx->outer->stmt),
2881 OMP_CLAUSE_NOWAIT))
2882 warning_at (gimple_location (stmt), 0,
2883 "%<#pragma omp cancel sections%> inside "
2884 "%<nowait%> sections construct");
2887 kind = "sections";
2888 break;
2889 case 8:
2890 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
2891 bad = "#pragma omp task";
2892 else
2893 ctx->cancellable = true;
2894 kind = "taskgroup";
2895 break;
2896 default:
2897 error_at (gimple_location (stmt), "invalid arguments");
2898 return false;
2900 if (bad)
2902 error_at (gimple_location (stmt),
2903 "%<%s %s%> construct not closely nested inside of %qs",
2904 DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2905 == BUILT_IN_GOMP_CANCEL
2906 ? "#pragma omp cancel"
2907 : "#pragma omp cancellation point", kind, bad);
2908 return false;
2911 /* FALLTHRU */
2912 case GIMPLE_OMP_SECTIONS:
2913 case GIMPLE_OMP_SINGLE:
2914 for (; ctx != NULL; ctx = ctx->outer)
2915 switch (gimple_code (ctx->stmt))
2917 case GIMPLE_OMP_FOR:
2918 case GIMPLE_OMP_SECTIONS:
2919 case GIMPLE_OMP_SINGLE:
2920 case GIMPLE_OMP_ORDERED:
2921 case GIMPLE_OMP_MASTER:
2922 case GIMPLE_OMP_TASK:
2923 case GIMPLE_OMP_CRITICAL:
2924 if (is_gimple_call (stmt))
2926 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
2927 != BUILT_IN_GOMP_BARRIER)
2928 return true;
2929 error_at (gimple_location (stmt),
2930 "barrier region may not be closely nested inside "
2931 "of work-sharing, critical, ordered, master or "
2932 "explicit task region");
2933 return false;
2935 error_at (gimple_location (stmt),
2936 "work-sharing region may not be closely nested inside "
2937 "of work-sharing, critical, ordered, master or explicit "
2938 "task region");
2939 return false;
2940 case GIMPLE_OMP_PARALLEL:
2941 return true;
2942 default:
2943 break;
2945 break;
2946 case GIMPLE_OMP_MASTER:
2947 for (; ctx != NULL; ctx = ctx->outer)
2948 switch (gimple_code (ctx->stmt))
2950 case GIMPLE_OMP_FOR:
2951 case GIMPLE_OMP_SECTIONS:
2952 case GIMPLE_OMP_SINGLE:
2953 case GIMPLE_OMP_TASK:
2954 error_at (gimple_location (stmt),
2955 "master region may not be closely nested inside "
2956 "of work-sharing or explicit task region");
2957 return false;
2958 case GIMPLE_OMP_PARALLEL:
2959 return true;
2960 default:
2961 break;
2963 break;
2964 case GIMPLE_OMP_ORDERED:
2965 for (; ctx != NULL; ctx = ctx->outer)
2966 switch (gimple_code (ctx->stmt))
2968 case GIMPLE_OMP_CRITICAL:
2969 case GIMPLE_OMP_TASK:
2970 error_at (gimple_location (stmt),
2971 "ordered region may not be closely nested inside "
2972 "of critical or explicit task region");
2973 return false;
2974 case GIMPLE_OMP_FOR:
2975 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
2976 OMP_CLAUSE_ORDERED) == NULL)
2978 error_at (gimple_location (stmt),
2979 "ordered region must be closely nested inside "
2980 "a loop region with an ordered clause");
2981 return false;
2983 return true;
2984 case GIMPLE_OMP_PARALLEL:
2985 error_at (gimple_location (stmt),
2986 "ordered region must be closely nested inside "
2987 "a loop region with an ordered clause");
2988 return false;
2989 default:
2990 break;
2992 break;
2993 case GIMPLE_OMP_CRITICAL:
2995 tree this_stmt_name
2996 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
2997 for (; ctx != NULL; ctx = ctx->outer)
2998 if (gomp_critical *other_crit
2999 = dyn_cast <gomp_critical *> (ctx->stmt))
3000 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3002 error_at (gimple_location (stmt),
3003 "critical region may not be nested inside a critical "
3004 "region with the same name");
3005 return false;
3008 break;
3009 case GIMPLE_OMP_TEAMS:
3010 if (ctx == NULL
3011 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3012 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3014 error_at (gimple_location (stmt),
3015 "teams construct not closely nested inside of target "
3016 "region");
3017 return false;
3019 break;
3020 case GIMPLE_OMP_TARGET:
3021 for (; ctx != NULL; ctx = ctx->outer)
3023 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3025 if (is_gimple_omp (stmt)
3026 && is_gimple_omp_oacc (stmt)
3027 && is_gimple_omp (ctx->stmt))
3029 error_at (gimple_location (stmt),
3030 "OpenACC construct inside of non-OpenACC region");
3031 return false;
3033 continue;
3036 const char *stmt_name, *ctx_stmt_name;
3037 switch (gimple_omp_target_kind (stmt))
3039 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3040 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3041 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3042 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3043 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3044 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3045 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3046 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA: stmt_name = "enter/exit data"; break;
3047 default: gcc_unreachable ();
3049 switch (gimple_omp_target_kind (ctx->stmt))
3051 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3052 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3053 case GF_OMP_TARGET_KIND_OACC_PARALLEL: ctx_stmt_name = "parallel"; break;
3054 case GF_OMP_TARGET_KIND_OACC_KERNELS: ctx_stmt_name = "kernels"; break;
3055 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3056 default: gcc_unreachable ();
3059 /* OpenACC/OpenMP mismatch? */
3060 if (is_gimple_omp_oacc (stmt)
3061 != is_gimple_omp_oacc (ctx->stmt))
3063 error_at (gimple_location (stmt),
3064 "%s %s construct inside of %s %s region",
3065 (is_gimple_omp_oacc (stmt)
3066 ? "OpenACC" : "OpenMP"), stmt_name,
3067 (is_gimple_omp_oacc (ctx->stmt)
3068 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3069 return false;
3071 if (is_gimple_omp_offloaded (ctx->stmt))
3073 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3074 if (is_gimple_omp_oacc (ctx->stmt))
3076 error_at (gimple_location (stmt),
3077 "%s construct inside of %s region",
3078 stmt_name, ctx_stmt_name);
3079 return false;
3081 else
3083 gcc_checking_assert (!is_gimple_omp_oacc (stmt));
3084 warning_at (gimple_location (stmt), 0,
3085 "%s construct inside of %s region",
3086 stmt_name, ctx_stmt_name);
3090 break;
3091 default:
3092 break;
3094 return true;
3098 /* Helper function scan_omp.
3100 Callback for walk_tree or operators in walk_gimple_stmt used to
3101 scan for OMP directives in TP. */
3103 static tree
3104 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3106 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3107 omp_context *ctx = (omp_context *) wi->info;
3108 tree t = *tp;
3110 switch (TREE_CODE (t))
3112 case VAR_DECL:
3113 case PARM_DECL:
3114 case LABEL_DECL:
3115 case RESULT_DECL:
3116 if (ctx)
3117 *tp = remap_decl (t, &ctx->cb);
3118 break;
3120 default:
3121 if (ctx && TYPE_P (t))
3122 *tp = remap_type (t, &ctx->cb);
3123 else if (!DECL_P (t))
3125 *walk_subtrees = 1;
3126 if (ctx)
3128 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3129 if (tem != TREE_TYPE (t))
3131 if (TREE_CODE (t) == INTEGER_CST)
3132 *tp = wide_int_to_tree (tem, t);
3133 else
3134 TREE_TYPE (t) = tem;
3138 break;
3141 return NULL_TREE;
3144 /* Return true if FNDECL is a setjmp or a longjmp. */
3146 static bool
3147 setjmp_or_longjmp_p (const_tree fndecl)
3149 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3150 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3151 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3152 return true;
3154 tree declname = DECL_NAME (fndecl);
3155 if (!declname)
3156 return false;
3157 const char *name = IDENTIFIER_POINTER (declname);
3158 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3162 /* Helper function for scan_omp.
3164 Callback for walk_gimple_stmt used to scan for OMP directives in
3165 the current statement in GSI. */
3167 static tree
3168 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3169 struct walk_stmt_info *wi)
3171 gimple stmt = gsi_stmt (*gsi);
3172 omp_context *ctx = (omp_context *) wi->info;
3174 if (gimple_has_location (stmt))
3175 input_location = gimple_location (stmt);
3177 /* Check the nesting restrictions. */
3178 bool remove = false;
3179 if (is_gimple_omp (stmt))
3180 remove = !check_omp_nesting_restrictions (stmt, ctx);
3181 else if (is_gimple_call (stmt))
3183 tree fndecl = gimple_call_fndecl (stmt);
3184 if (fndecl)
3186 if (setjmp_or_longjmp_p (fndecl)
3187 && ctx
3188 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3189 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3191 remove = true;
3192 error_at (gimple_location (stmt),
3193 "setjmp/longjmp inside simd construct");
3195 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3196 switch (DECL_FUNCTION_CODE (fndecl))
3198 case BUILT_IN_GOMP_BARRIER:
3199 case BUILT_IN_GOMP_CANCEL:
3200 case BUILT_IN_GOMP_CANCELLATION_POINT:
3201 case BUILT_IN_GOMP_TASKYIELD:
3202 case BUILT_IN_GOMP_TASKWAIT:
3203 case BUILT_IN_GOMP_TASKGROUP_START:
3204 case BUILT_IN_GOMP_TASKGROUP_END:
3205 remove = !check_omp_nesting_restrictions (stmt, ctx);
3206 break;
3207 default:
3208 break;
3212 if (remove)
3214 stmt = gimple_build_nop ();
3215 gsi_replace (gsi, stmt, false);
3218 *handled_ops_p = true;
3220 switch (gimple_code (stmt))
3222 case GIMPLE_OMP_PARALLEL:
3223 taskreg_nesting_level++;
3224 scan_omp_parallel (gsi, ctx);
3225 taskreg_nesting_level--;
3226 break;
3228 case GIMPLE_OMP_TASK:
3229 taskreg_nesting_level++;
3230 scan_omp_task (gsi, ctx);
3231 taskreg_nesting_level--;
3232 break;
3234 case GIMPLE_OMP_FOR:
3235 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3236 break;
3238 case GIMPLE_OMP_SECTIONS:
3239 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3240 break;
3242 case GIMPLE_OMP_SINGLE:
3243 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3244 break;
3246 case GIMPLE_OMP_SECTION:
3247 case GIMPLE_OMP_MASTER:
3248 case GIMPLE_OMP_TASKGROUP:
3249 case GIMPLE_OMP_ORDERED:
3250 case GIMPLE_OMP_CRITICAL:
3251 ctx = new_omp_context (stmt, ctx);
3252 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3253 break;
3255 case GIMPLE_OMP_TARGET:
3256 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3257 break;
3259 case GIMPLE_OMP_TEAMS:
3260 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3261 break;
3263 case GIMPLE_BIND:
3265 tree var;
3267 *handled_ops_p = false;
3268 if (ctx)
3269 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3270 var ;
3271 var = DECL_CHAIN (var))
3272 insert_decl_map (&ctx->cb, var, var);
3274 break;
3275 default:
3276 *handled_ops_p = false;
3277 break;
3280 return NULL_TREE;
3284 /* Scan all the statements starting at the current statement. CTX
3285 contains context information about the OMP directives and
3286 clauses found during the scan. */
3288 static void
3289 scan_omp (gimple_seq *body_p, omp_context *ctx)
3291 location_t saved_location;
3292 struct walk_stmt_info wi;
3294 memset (&wi, 0, sizeof (wi));
3295 wi.info = ctx;
3296 wi.want_locations = true;
3298 saved_location = input_location;
3299 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3300 input_location = saved_location;
3303 /* Re-gimplification and code generation routines. */
3305 /* Build a call to GOMP_barrier. */
3307 static gimple
3308 build_omp_barrier (tree lhs)
3310 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3311 : BUILT_IN_GOMP_BARRIER);
3312 gcall *g = gimple_build_call (fndecl, 0);
3313 if (lhs)
3314 gimple_call_set_lhs (g, lhs);
3315 return g;
3318 /* If a context was created for STMT when it was scanned, return it. */
3320 static omp_context *
3321 maybe_lookup_ctx (gimple stmt)
3323 splay_tree_node n;
3324 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3325 return n ? (omp_context *) n->value : NULL;
3329 /* Find the mapping for DECL in CTX or the immediately enclosing
3330 context that has a mapping for DECL.
3332 If CTX is a nested parallel directive, we may have to use the decl
3333 mappings created in CTX's parent context. Suppose that we have the
3334 following parallel nesting (variable UIDs showed for clarity):
3336 iD.1562 = 0;
3337 #omp parallel shared(iD.1562) -> outer parallel
3338 iD.1562 = iD.1562 + 1;
3340 #omp parallel shared (iD.1562) -> inner parallel
3341 iD.1562 = iD.1562 - 1;
3343 Each parallel structure will create a distinct .omp_data_s structure
3344 for copying iD.1562 in/out of the directive:
3346 outer parallel .omp_data_s.1.i -> iD.1562
3347 inner parallel .omp_data_s.2.i -> iD.1562
3349 A shared variable mapping will produce a copy-out operation before
3350 the parallel directive and a copy-in operation after it. So, in
3351 this case we would have:
3353 iD.1562 = 0;
3354 .omp_data_o.1.i = iD.1562;
3355 #omp parallel shared(iD.1562) -> outer parallel
3356 .omp_data_i.1 = &.omp_data_o.1
3357 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3359 .omp_data_o.2.i = iD.1562; -> **
3360 #omp parallel shared(iD.1562) -> inner parallel
3361 .omp_data_i.2 = &.omp_data_o.2
3362 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3365 ** This is a problem. The symbol iD.1562 cannot be referenced
3366 inside the body of the outer parallel region. But since we are
3367 emitting this copy operation while expanding the inner parallel
3368 directive, we need to access the CTX structure of the outer
3369 parallel directive to get the correct mapping:
3371 .omp_data_o.2.i = .omp_data_i.1->i
3373 Since there may be other workshare or parallel directives enclosing
3374 the parallel directive, it may be necessary to walk up the context
3375 parent chain. This is not a problem in general because nested
3376 parallelism happens only rarely. */
3378 static tree
3379 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3381 tree t;
3382 omp_context *up;
3384 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3385 t = maybe_lookup_decl (decl, up);
3387 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3389 return t ? t : decl;
3393 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3394 in outer contexts. */
3396 static tree
3397 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3399 tree t = NULL;
3400 omp_context *up;
3402 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3403 t = maybe_lookup_decl (decl, up);
3405 return t ? t : decl;
3409 /* Construct the initialization value for reduction CLAUSE. */
3411 tree
3412 omp_reduction_init (tree clause, tree type)
3414 location_t loc = OMP_CLAUSE_LOCATION (clause);
3415 switch (OMP_CLAUSE_REDUCTION_CODE (clause))
3417 case PLUS_EXPR:
3418 case MINUS_EXPR:
3419 case BIT_IOR_EXPR:
3420 case BIT_XOR_EXPR:
3421 case TRUTH_OR_EXPR:
3422 case TRUTH_ORIF_EXPR:
3423 case TRUTH_XOR_EXPR:
3424 case NE_EXPR:
3425 return build_zero_cst (type);
3427 case MULT_EXPR:
3428 case TRUTH_AND_EXPR:
3429 case TRUTH_ANDIF_EXPR:
3430 case EQ_EXPR:
3431 return fold_convert_loc (loc, type, integer_one_node);
3433 case BIT_AND_EXPR:
3434 return fold_convert_loc (loc, type, integer_minus_one_node);
3436 case MAX_EXPR:
3437 if (SCALAR_FLOAT_TYPE_P (type))
3439 REAL_VALUE_TYPE max, min;
3440 if (HONOR_INFINITIES (type))
3442 real_inf (&max);
3443 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
3445 else
3446 real_maxval (&min, 1, TYPE_MODE (type));
3447 return build_real (type, min);
3449 else
3451 gcc_assert (INTEGRAL_TYPE_P (type));
3452 return TYPE_MIN_VALUE (type);
3455 case MIN_EXPR:
3456 if (SCALAR_FLOAT_TYPE_P (type))
3458 REAL_VALUE_TYPE max;
3459 if (HONOR_INFINITIES (type))
3460 real_inf (&max);
3461 else
3462 real_maxval (&max, 0, TYPE_MODE (type));
3463 return build_real (type, max);
3465 else
3467 gcc_assert (INTEGRAL_TYPE_P (type));
3468 return TYPE_MAX_VALUE (type);
3471 default:
3472 gcc_unreachable ();
3476 /* Return alignment to be assumed for var in CLAUSE, which should be
3477 OMP_CLAUSE_ALIGNED. */
3479 static tree
3480 omp_clause_aligned_alignment (tree clause)
3482 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
3483 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
3485 /* Otherwise return implementation defined alignment. */
3486 unsigned int al = 1;
3487 machine_mode mode, vmode;
3488 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3489 if (vs)
3490 vs = 1 << floor_log2 (vs);
3491 static enum mode_class classes[]
3492 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
3493 for (int i = 0; i < 4; i += 2)
3494 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
3495 mode != VOIDmode;
3496 mode = GET_MODE_WIDER_MODE (mode))
3498 vmode = targetm.vectorize.preferred_simd_mode (mode);
3499 if (GET_MODE_CLASS (vmode) != classes[i + 1])
3500 continue;
3501 while (vs
3502 && GET_MODE_SIZE (vmode) < vs
3503 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
3504 vmode = GET_MODE_2XWIDER_MODE (vmode);
3506 tree type = lang_hooks.types.type_for_mode (mode, 1);
3507 if (type == NULL_TREE || TYPE_MODE (type) != mode)
3508 continue;
3509 type = build_vector_type (type, GET_MODE_SIZE (vmode)
3510 / GET_MODE_SIZE (mode));
3511 if (TYPE_MODE (type) != vmode)
3512 continue;
3513 if (TYPE_ALIGN_UNIT (type) > al)
3514 al = TYPE_ALIGN_UNIT (type);
3516 return build_int_cst (integer_type_node, al);
3519 /* Return maximum possible vectorization factor for the target. */
3521 static int
3522 omp_max_vf (void)
3524 if (!optimize
3525 || optimize_debug
3526 || !flag_tree_loop_optimize
3527 || (!flag_tree_loop_vectorize
3528 && (global_options_set.x_flag_tree_loop_vectorize
3529 || global_options_set.x_flag_tree_vectorize)))
3530 return 1;
3532 int vs = targetm.vectorize.autovectorize_vector_sizes ();
3533 if (vs)
3535 vs = 1 << floor_log2 (vs);
3536 return vs;
3538 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
3539 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
3540 return GET_MODE_NUNITS (vqimode);
3541 return 1;
3544 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
3545 privatization. */
3547 static bool
3548 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
3549 tree &idx, tree &lane, tree &ivar, tree &lvar)
3551 if (max_vf == 0)
3553 max_vf = omp_max_vf ();
3554 if (max_vf > 1)
3556 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3557 OMP_CLAUSE_SAFELEN);
3558 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
3559 max_vf = 1;
3560 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
3561 max_vf) == -1)
3562 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
3564 if (max_vf > 1)
3566 idx = create_tmp_var (unsigned_type_node);
3567 lane = create_tmp_var (unsigned_type_node);
3570 if (max_vf == 1)
3571 return false;
3573 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
3574 tree avar = create_tmp_var_raw (atype);
3575 if (TREE_ADDRESSABLE (new_var))
3576 TREE_ADDRESSABLE (avar) = 1;
3577 DECL_ATTRIBUTES (avar)
3578 = tree_cons (get_identifier ("omp simd array"), NULL,
3579 DECL_ATTRIBUTES (avar));
3580 gimple_add_tmp_var (avar);
3581 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
3582 NULL_TREE, NULL_TREE);
3583 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
3584 NULL_TREE, NULL_TREE);
3585 if (DECL_P (new_var))
3587 SET_DECL_VALUE_EXPR (new_var, lvar);
3588 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3590 return true;
3593 /* Helper function of lower_rec_input_clauses. For a reference
3594 in simd reduction, add an underlying variable it will reference. */
3596 static void
3597 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
3599 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
3600 if (TREE_CONSTANT (z))
3602 const char *name = NULL;
3603 if (DECL_NAME (new_vard))
3604 name = IDENTIFIER_POINTER (DECL_NAME (new_vard));
3606 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)), name);
3607 gimple_add_tmp_var (z);
3608 TREE_ADDRESSABLE (z) = 1;
3609 z = build_fold_addr_expr_loc (loc, z);
3610 gimplify_assign (new_vard, z, ilist);
3614 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
3615 from the receiver (aka child) side and initializers for REFERENCE_TYPE
3616 private variables. Initialization statements go in ILIST, while calls
3617 to destructors go in DLIST. */
3619 static void
3620 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
3621 omp_context *ctx, struct omp_for_data *fd)
3623 tree c, dtor, copyin_seq, x, ptr;
3624 bool copyin_by_ref = false;
3625 bool lastprivate_firstprivate = false;
3626 bool reduction_omp_orig_ref = false;
3627 int pass;
3628 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3629 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
3630 int max_vf = 0;
3631 tree lane = NULL_TREE, idx = NULL_TREE;
3632 tree ivar = NULL_TREE, lvar = NULL_TREE;
3633 gimple_seq llist[2] = { NULL, NULL };
3635 copyin_seq = NULL;
3637 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
3638 with data sharing clauses referencing variable sized vars. That
3639 is unnecessarily hard to support and very unlikely to result in
3640 vectorized code anyway. */
3641 if (is_simd)
3642 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3643 switch (OMP_CLAUSE_CODE (c))
3645 case OMP_CLAUSE_LINEAR:
3646 if (OMP_CLAUSE_LINEAR_ARRAY (c))
3647 max_vf = 1;
3648 /* FALLTHRU */
3649 case OMP_CLAUSE_REDUCTION:
3650 case OMP_CLAUSE_PRIVATE:
3651 case OMP_CLAUSE_FIRSTPRIVATE:
3652 case OMP_CLAUSE_LASTPRIVATE:
3653 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
3654 max_vf = 1;
3655 break;
3656 default:
3657 continue;
3660 /* Do all the fixed sized types in the first pass, and the variable sized
3661 types in the second pass. This makes sure that the scalar arguments to
3662 the variable sized types are processed before we use them in the
3663 variable sized operations. */
3664 for (pass = 0; pass < 2; ++pass)
3666 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
3668 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
3669 tree var, new_var;
3670 bool by_ref;
3671 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
3673 switch (c_kind)
3675 case OMP_CLAUSE_PRIVATE:
3676 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
3677 continue;
3678 break;
3679 case OMP_CLAUSE_SHARED:
3680 /* Ignore shared directives in teams construct. */
3681 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3682 continue;
3683 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
3685 gcc_assert (is_global_var (OMP_CLAUSE_DECL (c)));
3686 continue;
3688 case OMP_CLAUSE_FIRSTPRIVATE:
3689 case OMP_CLAUSE_COPYIN:
3690 case OMP_CLAUSE_LINEAR:
3691 break;
3692 case OMP_CLAUSE_REDUCTION:
3693 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
3694 reduction_omp_orig_ref = true;
3695 break;
3696 case OMP_CLAUSE__LOOPTEMP_:
3697 /* Handle _looptemp_ clauses only on parallel. */
3698 if (fd)
3699 continue;
3700 break;
3701 case OMP_CLAUSE_LASTPRIVATE:
3702 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3704 lastprivate_firstprivate = true;
3705 if (pass != 0)
3706 continue;
3708 /* Even without corresponding firstprivate, if
3709 decl is Fortran allocatable, it needs outer var
3710 reference. */
3711 else if (pass == 0
3712 && lang_hooks.decls.omp_private_outer_ref
3713 (OMP_CLAUSE_DECL (c)))
3714 lastprivate_firstprivate = true;
3715 break;
3716 case OMP_CLAUSE_ALIGNED:
3717 if (pass == 0)
3718 continue;
3719 var = OMP_CLAUSE_DECL (c);
3720 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
3721 && !is_global_var (var))
3723 new_var = maybe_lookup_decl (var, ctx);
3724 if (new_var == NULL_TREE)
3725 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
3726 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3727 x = build_call_expr_loc (clause_loc, x, 2, new_var,
3728 omp_clause_aligned_alignment (c));
3729 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3730 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
3731 gimplify_and_add (x, ilist);
3733 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
3734 && is_global_var (var))
3736 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
3737 new_var = lookup_decl (var, ctx);
3738 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
3739 t = build_fold_addr_expr_loc (clause_loc, t);
3740 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
3741 t = build_call_expr_loc (clause_loc, t2, 2, t,
3742 omp_clause_aligned_alignment (c));
3743 t = fold_convert_loc (clause_loc, ptype, t);
3744 x = create_tmp_var (ptype);
3745 t = build2 (MODIFY_EXPR, ptype, x, t);
3746 gimplify_and_add (t, ilist);
3747 t = build_simple_mem_ref_loc (clause_loc, x);
3748 SET_DECL_VALUE_EXPR (new_var, t);
3749 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3751 continue;
3752 default:
3753 continue;
3756 new_var = var = OMP_CLAUSE_DECL (c);
3757 if (c_kind != OMP_CLAUSE_COPYIN)
3758 new_var = lookup_decl (var, ctx);
3760 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
3762 if (pass != 0)
3763 continue;
3765 else if (is_variable_sized (var))
3767 /* For variable sized types, we need to allocate the
3768 actual storage here. Call alloca and store the
3769 result in the pointer decl that we created elsewhere. */
3770 if (pass == 0)
3771 continue;
3773 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
3775 gcall *stmt;
3776 tree tmp, atmp;
3778 ptr = DECL_VALUE_EXPR (new_var);
3779 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
3780 ptr = TREE_OPERAND (ptr, 0);
3781 gcc_assert (DECL_P (ptr));
3782 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
3784 /* void *tmp = __builtin_alloca */
3785 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3786 stmt = gimple_build_call (atmp, 1, x);
3787 tmp = create_tmp_var_raw (ptr_type_node);
3788 gimple_add_tmp_var (tmp);
3789 gimple_call_set_lhs (stmt, tmp);
3791 gimple_seq_add_stmt (ilist, stmt);
3793 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
3794 gimplify_assign (ptr, x, ilist);
3797 else if (is_reference (var))
3799 /* For references that are being privatized for Fortran,
3800 allocate new backing storage for the new pointer
3801 variable. This allows us to avoid changing all the
3802 code that expects a pointer to something that expects
3803 a direct variable. */
3804 if (pass == 0)
3805 continue;
3807 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
3808 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
3810 x = build_receiver_ref (var, false, ctx);
3811 x = build_fold_addr_expr_loc (clause_loc, x);
3813 else if (TREE_CONSTANT (x))
3815 /* For reduction in SIMD loop, defer adding the
3816 initialization of the reference, because if we decide
3817 to use SIMD array for it, the initilization could cause
3818 expansion ICE. */
3819 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
3820 x = NULL_TREE;
3821 else
3823 const char *name = NULL;
3824 if (DECL_NAME (var))
3825 name = IDENTIFIER_POINTER (DECL_NAME (new_var));
3827 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
3828 name);
3829 gimple_add_tmp_var (x);
3830 TREE_ADDRESSABLE (x) = 1;
3831 x = build_fold_addr_expr_loc (clause_loc, x);
3834 else
3836 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA);
3837 x = build_call_expr_loc (clause_loc, atmp, 1, x);
3840 if (x)
3842 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
3843 gimplify_assign (new_var, x, ilist);
3846 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
3848 else if (c_kind == OMP_CLAUSE_REDUCTION
3849 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
3851 if (pass == 0)
3852 continue;
3854 else if (pass != 0)
3855 continue;
3857 switch (OMP_CLAUSE_CODE (c))
3859 case OMP_CLAUSE_SHARED:
3860 /* Ignore shared directives in teams construct. */
3861 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3862 continue;
3863 /* Shared global vars are just accessed directly. */
3864 if (is_global_var (new_var))
3865 break;
3866 /* Set up the DECL_VALUE_EXPR for shared variables now. This
3867 needs to be delayed until after fixup_child_record_type so
3868 that we get the correct type during the dereference. */
3869 by_ref = use_pointer_for_field (var, ctx);
3870 x = build_receiver_ref (var, by_ref, ctx);
3871 SET_DECL_VALUE_EXPR (new_var, x);
3872 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3874 /* ??? If VAR is not passed by reference, and the variable
3875 hasn't been initialized yet, then we'll get a warning for
3876 the store into the omp_data_s structure. Ideally, we'd be
3877 able to notice this and not store anything at all, but
3878 we're generating code too early. Suppress the warning. */
3879 if (!by_ref)
3880 TREE_NO_WARNING (var) = 1;
3881 break;
3883 case OMP_CLAUSE_LASTPRIVATE:
3884 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
3885 break;
3886 /* FALLTHRU */
3888 case OMP_CLAUSE_PRIVATE:
3889 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
3890 x = build_outer_var_ref (var, ctx);
3891 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
3893 if (is_task_ctx (ctx))
3894 x = build_receiver_ref (var, false, ctx);
3895 else
3896 x = build_outer_var_ref (var, ctx);
3898 else
3899 x = NULL;
3900 do_private:
3901 tree nx;
3902 nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
3903 if (is_simd)
3905 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
3906 if ((TREE_ADDRESSABLE (new_var) || nx || y
3907 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
3908 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
3909 idx, lane, ivar, lvar))
3911 if (nx)
3912 x = lang_hooks.decls.omp_clause_default_ctor
3913 (c, unshare_expr (ivar), x);
3914 if (nx && x)
3915 gimplify_and_add (x, &llist[0]);
3916 if (y)
3918 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
3919 if (y)
3921 gimple_seq tseq = NULL;
3923 dtor = y;
3924 gimplify_stmt (&dtor, &tseq);
3925 gimple_seq_add_seq (&llist[1], tseq);
3928 break;
3931 if (nx)
3932 gimplify_and_add (nx, ilist);
3933 /* FALLTHRU */
3935 do_dtor:
3936 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
3937 if (x)
3939 gimple_seq tseq = NULL;
3941 dtor = x;
3942 gimplify_stmt (&dtor, &tseq);
3943 gimple_seq_add_seq (dlist, tseq);
3945 break;
3947 case OMP_CLAUSE_LINEAR:
3948 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
3949 goto do_firstprivate;
3950 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
3951 x = NULL;
3952 else
3953 x = build_outer_var_ref (var, ctx);
3954 goto do_private;
3956 case OMP_CLAUSE_FIRSTPRIVATE:
3957 if (is_task_ctx (ctx))
3959 if (is_reference (var) || is_variable_sized (var))
3960 goto do_dtor;
3961 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
3962 ctx))
3963 || use_pointer_for_field (var, NULL))
3965 x = build_receiver_ref (var, false, ctx);
3966 SET_DECL_VALUE_EXPR (new_var, x);
3967 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
3968 goto do_dtor;
3971 do_firstprivate:
3972 x = build_outer_var_ref (var, ctx);
3973 if (is_simd)
3975 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
3976 && gimple_omp_for_combined_into_p (ctx->stmt))
3978 tree t = OMP_CLAUSE_LINEAR_STEP (c);
3979 tree stept = TREE_TYPE (t);
3980 tree ct = find_omp_clause (clauses,
3981 OMP_CLAUSE__LOOPTEMP_);
3982 gcc_assert (ct);
3983 tree l = OMP_CLAUSE_DECL (ct);
3984 tree n1 = fd->loop.n1;
3985 tree step = fd->loop.step;
3986 tree itype = TREE_TYPE (l);
3987 if (POINTER_TYPE_P (itype))
3988 itype = signed_type_for (itype);
3989 l = fold_build2 (MINUS_EXPR, itype, l, n1);
3990 if (TYPE_UNSIGNED (itype)
3991 && fd->loop.cond_code == GT_EXPR)
3992 l = fold_build2 (TRUNC_DIV_EXPR, itype,
3993 fold_build1 (NEGATE_EXPR, itype, l),
3994 fold_build1 (NEGATE_EXPR,
3995 itype, step));
3996 else
3997 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
3998 t = fold_build2 (MULT_EXPR, stept,
3999 fold_convert (stept, l), t);
4001 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4003 x = lang_hooks.decls.omp_clause_linear_ctor
4004 (c, new_var, x, t);
4005 gimplify_and_add (x, ilist);
4006 goto do_dtor;
4009 if (POINTER_TYPE_P (TREE_TYPE (x)))
4010 x = fold_build2 (POINTER_PLUS_EXPR,
4011 TREE_TYPE (x), x, t);
4012 else
4013 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4016 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4017 || TREE_ADDRESSABLE (new_var))
4018 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4019 idx, lane, ivar, lvar))
4021 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4023 tree iv = create_tmp_var (TREE_TYPE (new_var));
4024 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4025 gimplify_and_add (x, ilist);
4026 gimple_stmt_iterator gsi
4027 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4028 gassign *g
4029 = gimple_build_assign (unshare_expr (lvar), iv);
4030 gsi_insert_before_without_update (&gsi, g,
4031 GSI_SAME_STMT);
4032 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4033 enum tree_code code = PLUS_EXPR;
4034 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4035 code = POINTER_PLUS_EXPR;
4036 g = gimple_build_assign (iv, code, iv, t);
4037 gsi_insert_before_without_update (&gsi, g,
4038 GSI_SAME_STMT);
4039 break;
4041 x = lang_hooks.decls.omp_clause_copy_ctor
4042 (c, unshare_expr (ivar), x);
4043 gimplify_and_add (x, &llist[0]);
4044 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4045 if (x)
4047 gimple_seq tseq = NULL;
4049 dtor = x;
4050 gimplify_stmt (&dtor, &tseq);
4051 gimple_seq_add_seq (&llist[1], tseq);
4053 break;
4056 x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
4057 gimplify_and_add (x, ilist);
4058 goto do_dtor;
4060 case OMP_CLAUSE__LOOPTEMP_:
4061 gcc_assert (is_parallel_ctx (ctx));
4062 x = build_outer_var_ref (var, ctx);
4063 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4064 gimplify_and_add (x, ilist);
4065 break;
4067 case OMP_CLAUSE_COPYIN:
4068 by_ref = use_pointer_for_field (var, NULL);
4069 x = build_receiver_ref (var, by_ref, ctx);
4070 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4071 append_to_statement_list (x, &copyin_seq);
4072 copyin_by_ref |= by_ref;
4073 break;
4075 case OMP_CLAUSE_REDUCTION:
4076 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4078 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4079 gimple tseq;
4080 x = build_outer_var_ref (var, ctx);
4082 if (is_reference (var)
4083 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4084 TREE_TYPE (x)))
4085 x = build_fold_addr_expr_loc (clause_loc, x);
4086 SET_DECL_VALUE_EXPR (placeholder, x);
4087 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4088 tree new_vard = new_var;
4089 if (is_reference (var))
4091 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4092 new_vard = TREE_OPERAND (new_var, 0);
4093 gcc_assert (DECL_P (new_vard));
4095 if (is_simd
4096 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4097 idx, lane, ivar, lvar))
4099 if (new_vard == new_var)
4101 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4102 SET_DECL_VALUE_EXPR (new_var, ivar);
4104 else
4106 SET_DECL_VALUE_EXPR (new_vard,
4107 build_fold_addr_expr (ivar));
4108 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4110 x = lang_hooks.decls.omp_clause_default_ctor
4111 (c, unshare_expr (ivar),
4112 build_outer_var_ref (var, ctx));
4113 if (x)
4114 gimplify_and_add (x, &llist[0]);
4115 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4117 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4118 lower_omp (&tseq, ctx);
4119 gimple_seq_add_seq (&llist[0], tseq);
4121 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4122 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4123 lower_omp (&tseq, ctx);
4124 gimple_seq_add_seq (&llist[1], tseq);
4125 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4126 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4127 if (new_vard == new_var)
4128 SET_DECL_VALUE_EXPR (new_var, lvar);
4129 else
4130 SET_DECL_VALUE_EXPR (new_vard,
4131 build_fold_addr_expr (lvar));
4132 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4133 if (x)
4135 tseq = NULL;
4136 dtor = x;
4137 gimplify_stmt (&dtor, &tseq);
4138 gimple_seq_add_seq (&llist[1], tseq);
4140 break;
4142 /* If this is a reference to constant size reduction var
4143 with placeholder, we haven't emitted the initializer
4144 for it because it is undesirable if SIMD arrays are used.
4145 But if they aren't used, we need to emit the deferred
4146 initialization now. */
4147 else if (is_reference (var) && is_simd)
4148 handle_simd_reference (clause_loc, new_vard, ilist);
4149 x = lang_hooks.decls.omp_clause_default_ctor
4150 (c, unshare_expr (new_var),
4151 build_outer_var_ref (var, ctx));
4152 if (x)
4153 gimplify_and_add (x, ilist);
4154 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4156 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4157 lower_omp (&tseq, ctx);
4158 gimple_seq_add_seq (ilist, tseq);
4160 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4161 if (is_simd)
4163 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4164 lower_omp (&tseq, ctx);
4165 gimple_seq_add_seq (dlist, tseq);
4166 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4168 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4169 goto do_dtor;
4171 else
4173 x = omp_reduction_init (c, TREE_TYPE (new_var));
4174 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
4175 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4177 /* reduction(-:var) sums up the partial results, so it
4178 acts identically to reduction(+:var). */
4179 if (code == MINUS_EXPR)
4180 code = PLUS_EXPR;
4182 tree new_vard = new_var;
4183 if (is_simd && is_reference (var))
4185 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4186 new_vard = TREE_OPERAND (new_var, 0);
4187 gcc_assert (DECL_P (new_vard));
4189 if (is_simd
4190 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4191 idx, lane, ivar, lvar))
4193 tree ref = build_outer_var_ref (var, ctx);
4195 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
4197 x = build2 (code, TREE_TYPE (ref), ref, ivar);
4198 ref = build_outer_var_ref (var, ctx);
4199 gimplify_assign (ref, x, &llist[1]);
4201 if (new_vard != new_var)
4203 SET_DECL_VALUE_EXPR (new_vard,
4204 build_fold_addr_expr (lvar));
4205 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4208 else
4210 if (is_reference (var) && is_simd)
4211 handle_simd_reference (clause_loc, new_vard, ilist);
4212 gimplify_assign (new_var, x, ilist);
4213 if (is_simd)
4215 tree ref = build_outer_var_ref (var, ctx);
4217 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4218 ref = build_outer_var_ref (var, ctx);
4219 gimplify_assign (ref, x, dlist);
4223 break;
4225 default:
4226 gcc_unreachable ();
4231 if (lane)
4233 tree uid = create_tmp_var (ptr_type_node, "simduid");
4234 /* Don't want uninit warnings on simduid, it is always uninitialized,
4235 but we use it not for the value, but for the DECL_UID only. */
4236 TREE_NO_WARNING (uid) = 1;
4237 gimple g
4238 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
4239 gimple_call_set_lhs (g, lane);
4240 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4241 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
4242 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
4243 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
4244 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4245 gimple_omp_for_set_clauses (ctx->stmt, c);
4246 g = gimple_build_assign (lane, INTEGER_CST,
4247 build_int_cst (unsigned_type_node, 0));
4248 gimple_seq_add_stmt (ilist, g);
4249 for (int i = 0; i < 2; i++)
4250 if (llist[i])
4252 tree vf = create_tmp_var (unsigned_type_node);
4253 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
4254 gimple_call_set_lhs (g, vf);
4255 gimple_seq *seq = i == 0 ? ilist : dlist;
4256 gimple_seq_add_stmt (seq, g);
4257 tree t = build_int_cst (unsigned_type_node, 0);
4258 g = gimple_build_assign (idx, INTEGER_CST, t);
4259 gimple_seq_add_stmt (seq, g);
4260 tree body = create_artificial_label (UNKNOWN_LOCATION);
4261 tree header = create_artificial_label (UNKNOWN_LOCATION);
4262 tree end = create_artificial_label (UNKNOWN_LOCATION);
4263 gimple_seq_add_stmt (seq, gimple_build_goto (header));
4264 gimple_seq_add_stmt (seq, gimple_build_label (body));
4265 gimple_seq_add_seq (seq, llist[i]);
4266 t = build_int_cst (unsigned_type_node, 1);
4267 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
4268 gimple_seq_add_stmt (seq, g);
4269 gimple_seq_add_stmt (seq, gimple_build_label (header));
4270 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
4271 gimple_seq_add_stmt (seq, g);
4272 gimple_seq_add_stmt (seq, gimple_build_label (end));
4276 /* The copyin sequence is not to be executed by the main thread, since
4277 that would result in self-copies. Perhaps not visible to scalars,
4278 but it certainly is to C++ operator=. */
4279 if (copyin_seq)
4281 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
4283 x = build2 (NE_EXPR, boolean_type_node, x,
4284 build_int_cst (TREE_TYPE (x), 0));
4285 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
4286 gimplify_and_add (x, ilist);
4289 /* If any copyin variable is passed by reference, we must ensure the
4290 master thread doesn't modify it before it is copied over in all
4291 threads. Similarly for variables in both firstprivate and
4292 lastprivate clauses we need to ensure the lastprivate copying
4293 happens after firstprivate copying in all threads. And similarly
4294 for UDRs if initializer expression refers to omp_orig. */
4295 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
4297 /* Don't add any barrier for #pragma omp simd or
4298 #pragma omp distribute. */
4299 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
4300 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
4301 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
4304 /* If max_vf is non-zero, then we can use only a vectorization factor
4305 up to the max_vf we chose. So stick it into the safelen clause. */
4306 if (max_vf)
4308 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4309 OMP_CLAUSE_SAFELEN);
4310 if (c == NULL_TREE
4311 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
4312 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4313 max_vf) == 1))
4315 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
4316 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
4317 max_vf);
4318 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
4319 gimple_omp_for_set_clauses (ctx->stmt, c);
4325 /* Generate code to implement the LASTPRIVATE clauses. This is used for
4326 both parallel and workshare constructs. PREDICATE may be NULL if it's
4327 always true. */
4329 static void
4330 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
4331 omp_context *ctx)
4333 tree x, c, label = NULL, orig_clauses = clauses;
4334 bool par_clauses = false;
4335 tree simduid = NULL, lastlane = NULL;
4337 /* Early exit if there are no lastprivate or linear clauses. */
4338 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
4339 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
4340 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
4341 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
4342 break;
4343 if (clauses == NULL)
4345 /* If this was a workshare clause, see if it had been combined
4346 with its parallel. In that case, look for the clauses on the
4347 parallel statement itself. */
4348 if (is_parallel_ctx (ctx))
4349 return;
4351 ctx = ctx->outer;
4352 if (ctx == NULL || !is_parallel_ctx (ctx))
4353 return;
4355 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4356 OMP_CLAUSE_LASTPRIVATE);
4357 if (clauses == NULL)
4358 return;
4359 par_clauses = true;
4362 if (predicate)
4364 gcond *stmt;
4365 tree label_true, arm1, arm2;
4367 label = create_artificial_label (UNKNOWN_LOCATION);
4368 label_true = create_artificial_label (UNKNOWN_LOCATION);
4369 arm1 = TREE_OPERAND (predicate, 0);
4370 arm2 = TREE_OPERAND (predicate, 1);
4371 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
4372 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
4373 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
4374 label_true, label);
4375 gimple_seq_add_stmt (stmt_list, stmt);
4376 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
4379 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4380 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4382 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
4383 if (simduid)
4384 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
4387 for (c = clauses; c ;)
4389 tree var, new_var;
4390 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4392 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4393 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4394 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
4396 var = OMP_CLAUSE_DECL (c);
4397 new_var = lookup_decl (var, ctx);
4399 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
4401 tree val = DECL_VALUE_EXPR (new_var);
4402 if (TREE_CODE (val) == ARRAY_REF
4403 && VAR_P (TREE_OPERAND (val, 0))
4404 && lookup_attribute ("omp simd array",
4405 DECL_ATTRIBUTES (TREE_OPERAND (val,
4406 0))))
4408 if (lastlane == NULL)
4410 lastlane = create_tmp_var (unsigned_type_node);
4411 gcall *g
4412 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
4413 2, simduid,
4414 TREE_OPERAND (val, 1));
4415 gimple_call_set_lhs (g, lastlane);
4416 gimple_seq_add_stmt (stmt_list, g);
4418 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
4419 TREE_OPERAND (val, 0), lastlane,
4420 NULL_TREE, NULL_TREE);
4424 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
4425 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
4427 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
4428 gimple_seq_add_seq (stmt_list,
4429 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
4430 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
4432 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4433 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
4435 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
4436 gimple_seq_add_seq (stmt_list,
4437 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
4438 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
4441 x = build_outer_var_ref (var, ctx);
4442 if (is_reference (var))
4443 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4444 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
4445 gimplify_and_add (x, stmt_list);
4447 c = OMP_CLAUSE_CHAIN (c);
4448 if (c == NULL && !par_clauses)
4450 /* If this was a workshare clause, see if it had been combined
4451 with its parallel. In that case, continue looking for the
4452 clauses also on the parallel statement itself. */
4453 if (is_parallel_ctx (ctx))
4454 break;
4456 ctx = ctx->outer;
4457 if (ctx == NULL || !is_parallel_ctx (ctx))
4458 break;
4460 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
4461 OMP_CLAUSE_LASTPRIVATE);
4462 par_clauses = true;
4466 if (label)
4467 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
4470 static void
4471 oacc_lower_reduction_var_helper (gimple_seq *stmt_seqp, omp_context *ctx,
4472 tree tid, tree var, tree new_var)
4474 /* The atomic add at the end of the sum creates unnecessary
4475 write contention on accelerators. To work around this,
4476 create an array to store the partial reductions. Later, in
4477 lower_omp_for (for openacc), the values of array will be
4478 combined. */
4480 tree t = NULL_TREE, array, x;
4481 tree type = get_base_type (var);
4482 gimple stmt;
4484 /* Now insert the partial reductions into the array. */
4486 /* Find the reduction array. */
4488 tree ptype = build_pointer_type (type);
4490 t = lookup_oacc_reduction (oacc_get_reduction_array_id (var), ctx);
4491 t = build_receiver_ref (t, false, ctx->outer);
4493 array = create_tmp_var (ptype);
4494 gimplify_assign (array, t, stmt_seqp);
4496 tree ptr = create_tmp_var (TREE_TYPE (array));
4498 /* Find the reduction array. */
4500 /* testing a unary conversion. */
4501 tree offset = create_tmp_var (sizetype);
4502 gimplify_assign (offset, TYPE_SIZE_UNIT (type),
4503 stmt_seqp);
4504 t = create_tmp_var (sizetype);
4505 gimplify_assign (t, unshare_expr (fold_build1 (NOP_EXPR, sizetype, tid)),
4506 stmt_seqp);
4507 stmt = gimple_build_assign (offset, MULT_EXPR, offset, t);
4508 gimple_seq_add_stmt (stmt_seqp, stmt);
4510 /* Offset expression. Does the POINTER_PLUS_EXPR take care
4511 of adding sizeof(var) to the array? */
4512 ptr = create_tmp_var (ptype);
4513 stmt = gimple_build_assign (unshare_expr (ptr), POINTER_PLUS_EXPR, array,
4514 offset);
4515 gimple_seq_add_stmt (stmt_seqp, stmt);
4517 /* Move the local sum to gfc$sum[i]. */
4518 x = unshare_expr (build_simple_mem_ref (ptr));
4519 stmt = gimplify_assign (x, new_var, stmt_seqp);
4522 /* Generate code to implement the REDUCTION clauses. */
4524 static void
4525 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
4527 gimple_seq sub_seq = NULL;
4528 gimple stmt;
4529 tree x, c, tid = NULL_TREE;
4530 int count = 0;
4532 /* SIMD reductions are handled in lower_rec_input_clauses. */
4533 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4534 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
4535 return;
4537 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
4538 update in that case, otherwise use a lock. */
4539 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
4540 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
4542 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4544 /* Never use OMP_ATOMIC for array reductions or UDRs. */
4545 count = -1;
4546 break;
4548 count++;
4551 if (count == 0)
4552 return;
4554 /* Initialize thread info for OpenACC. */
4555 if (is_gimple_omp_oacc (ctx->stmt))
4557 /* Get the current thread id. */
4558 tree call = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
4559 tid = create_tmp_var (TREE_TYPE (TREE_TYPE (call)));
4560 gimple stmt = gimple_build_call (call, 0);
4561 gimple_call_set_lhs (stmt, tid);
4562 gimple_seq_add_stmt (stmt_seqp, stmt);
4565 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4567 tree var, ref, new_var;
4568 enum tree_code code;
4569 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4571 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
4572 continue;
4574 var = OMP_CLAUSE_DECL (c);
4575 new_var = lookup_decl (var, ctx);
4576 if (is_reference (var))
4577 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4578 ref = build_outer_var_ref (var, ctx);
4579 code = OMP_CLAUSE_REDUCTION_CODE (c);
4581 /* reduction(-:var) sums up the partial results, so it acts
4582 identically to reduction(+:var). */
4583 if (code == MINUS_EXPR)
4584 code = PLUS_EXPR;
4586 if (is_gimple_omp_oacc (ctx->stmt))
4588 gcc_checking_assert (!OMP_CLAUSE_REDUCTION_PLACEHOLDER (c));
4590 oacc_lower_reduction_var_helper (stmt_seqp, ctx, tid, var, new_var);
4592 else if (count == 1)
4594 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
4596 addr = save_expr (addr);
4597 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
4598 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
4599 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
4600 gimplify_and_add (x, stmt_seqp);
4601 return;
4603 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4605 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4607 if (is_reference (var)
4608 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4609 TREE_TYPE (ref)))
4610 ref = build_fold_addr_expr_loc (clause_loc, ref);
4611 SET_DECL_VALUE_EXPR (placeholder, ref);
4612 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4613 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
4614 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
4615 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4616 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
4618 else
4620 x = build2 (code, TREE_TYPE (ref), ref, new_var);
4621 ref = build_outer_var_ref (var, ctx);
4622 gimplify_assign (ref, x, &sub_seq);
4626 if (is_gimple_omp_oacc (ctx->stmt))
4627 return;
4629 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
4631 gimple_seq_add_stmt (stmt_seqp, stmt);
4633 gimple_seq_add_seq (stmt_seqp, sub_seq);
4635 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
4637 gimple_seq_add_stmt (stmt_seqp, stmt);
4641 /* Generate code to implement the COPYPRIVATE clauses. */
4643 static void
4644 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
4645 omp_context *ctx)
4647 tree c;
4649 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4651 tree var, new_var, ref, x;
4652 bool by_ref;
4653 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4655 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
4656 continue;
4658 var = OMP_CLAUSE_DECL (c);
4659 by_ref = use_pointer_for_field (var, NULL);
4661 ref = build_sender_ref (var, ctx);
4662 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
4663 if (by_ref)
4665 x = build_fold_addr_expr_loc (clause_loc, new_var);
4666 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
4668 gimplify_assign (ref, x, slist);
4670 ref = build_receiver_ref (var, false, ctx);
4671 if (by_ref)
4673 ref = fold_convert_loc (clause_loc,
4674 build_pointer_type (TREE_TYPE (new_var)),
4675 ref);
4676 ref = build_fold_indirect_ref_loc (clause_loc, ref);
4678 if (is_reference (var))
4680 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
4681 ref = build_simple_mem_ref_loc (clause_loc, ref);
4682 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4684 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
4685 gimplify_and_add (x, rlist);
4690 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
4691 and REDUCTION from the sender (aka parent) side. */
4693 static void
4694 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
4695 omp_context *ctx)
4697 tree c;
4699 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4701 tree val, ref, x, var;
4702 bool by_ref, do_in = false, do_out = false;
4703 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4705 switch (OMP_CLAUSE_CODE (c))
4707 case OMP_CLAUSE_PRIVATE:
4708 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4709 break;
4710 continue;
4711 case OMP_CLAUSE_FIRSTPRIVATE:
4712 case OMP_CLAUSE_COPYIN:
4713 case OMP_CLAUSE_LASTPRIVATE:
4714 case OMP_CLAUSE_REDUCTION:
4715 case OMP_CLAUSE__LOOPTEMP_:
4716 break;
4717 default:
4718 continue;
4721 val = OMP_CLAUSE_DECL (c);
4722 var = lookup_decl_in_outer_ctx (val, ctx);
4724 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
4725 && is_global_var (var))
4726 continue;
4727 if (is_variable_sized (val))
4728 continue;
4729 by_ref = use_pointer_for_field (val, NULL);
4731 switch (OMP_CLAUSE_CODE (c))
4733 case OMP_CLAUSE_PRIVATE:
4734 case OMP_CLAUSE_FIRSTPRIVATE:
4735 case OMP_CLAUSE_COPYIN:
4736 case OMP_CLAUSE__LOOPTEMP_:
4737 do_in = true;
4738 break;
4740 case OMP_CLAUSE_LASTPRIVATE:
4741 if (by_ref || is_reference (val))
4743 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4744 continue;
4745 do_in = true;
4747 else
4749 do_out = true;
4750 if (lang_hooks.decls.omp_private_outer_ref (val))
4751 do_in = true;
4753 break;
4755 case OMP_CLAUSE_REDUCTION:
4756 do_in = true;
4757 do_out = !(by_ref || is_reference (val));
4758 break;
4760 default:
4761 gcc_unreachable ();
4764 if (do_in)
4766 ref = build_sender_ref (val, ctx);
4767 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
4768 gimplify_assign (ref, x, ilist);
4769 if (is_task_ctx (ctx))
4770 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
4773 if (do_out)
4775 ref = build_sender_ref (val, ctx);
4776 gimplify_assign (var, ref, olist);
4781 /* Generate code to implement SHARED from the sender (aka parent)
4782 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
4783 list things that got automatically shared. */
4785 static void
4786 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
4788 tree var, ovar, nvar, f, x, record_type;
4790 if (ctx->record_type == NULL)
4791 return;
4793 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
4794 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
4796 ovar = DECL_ABSTRACT_ORIGIN (f);
4797 nvar = maybe_lookup_decl (ovar, ctx);
4798 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
4799 continue;
4801 /* If CTX is a nested parallel directive. Find the immediately
4802 enclosing parallel or workshare construct that contains a
4803 mapping for OVAR. */
4804 var = lookup_decl_in_outer_ctx (ovar, ctx);
4806 if (use_pointer_for_field (ovar, ctx))
4808 x = build_sender_ref (ovar, ctx);
4809 var = build_fold_addr_expr (var);
4810 gimplify_assign (x, var, ilist);
4812 else
4814 x = build_sender_ref (ovar, ctx);
4815 gimplify_assign (x, var, ilist);
4817 if (!TREE_READONLY (var)
4818 /* We don't need to receive a new reference to a result
4819 or parm decl. In fact we may not store to it as we will
4820 invalidate any pending RSO and generate wrong gimple
4821 during inlining. */
4822 && !((TREE_CODE (var) == RESULT_DECL
4823 || TREE_CODE (var) == PARM_DECL)
4824 && DECL_BY_REFERENCE (var)))
4826 x = build_sender_ref (ovar, ctx);
4827 gimplify_assign (var, x, olist);
4834 /* A convenience function to build an empty GIMPLE_COND with just the
4835 condition. */
4837 static gcond *
4838 gimple_build_cond_empty (tree cond)
4840 enum tree_code pred_code;
4841 tree lhs, rhs;
4843 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
4844 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
4848 /* Build the function calls to GOMP_parallel_start etc to actually
4849 generate the parallel operation. REGION is the parallel region
4850 being expanded. BB is the block where to insert the code. WS_ARGS
4851 will be set if this is a call to a combined parallel+workshare
4852 construct, it contains the list of additional arguments needed by
4853 the workshare construct. */
4855 static void
4856 expand_parallel_call (struct omp_region *region, basic_block bb,
4857 gomp_parallel *entry_stmt,
4858 vec<tree, va_gc> *ws_args)
4860 tree t, t1, t2, val, cond, c, clauses, flags;
4861 gimple_stmt_iterator gsi;
4862 gimple stmt;
4863 enum built_in_function start_ix;
4864 int start_ix2;
4865 location_t clause_loc;
4866 vec<tree, va_gc> *args;
4868 clauses = gimple_omp_parallel_clauses (entry_stmt);
4870 /* Determine what flavor of GOMP_parallel we will be
4871 emitting. */
4872 start_ix = BUILT_IN_GOMP_PARALLEL;
4873 if (is_combined_parallel (region))
4875 switch (region->inner->type)
4877 case GIMPLE_OMP_FOR:
4878 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
4879 start_ix2 = ((int)BUILT_IN_GOMP_PARALLEL_LOOP_STATIC
4880 + (region->inner->sched_kind
4881 == OMP_CLAUSE_SCHEDULE_RUNTIME
4882 ? 3 : region->inner->sched_kind));
4883 start_ix = (enum built_in_function)start_ix2;
4884 break;
4885 case GIMPLE_OMP_SECTIONS:
4886 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
4887 break;
4888 default:
4889 gcc_unreachable ();
4893 /* By default, the value of NUM_THREADS is zero (selected at run time)
4894 and there is no conditional. */
4895 cond = NULL_TREE;
4896 val = build_int_cst (unsigned_type_node, 0);
4897 flags = build_int_cst (unsigned_type_node, 0);
4899 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
4900 if (c)
4901 cond = OMP_CLAUSE_IF_EXPR (c);
4903 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
4904 if (c)
4906 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
4907 clause_loc = OMP_CLAUSE_LOCATION (c);
4909 else
4910 clause_loc = gimple_location (entry_stmt);
4912 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
4913 if (c)
4914 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
4916 /* Ensure 'val' is of the correct type. */
4917 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
4919 /* If we found the clause 'if (cond)', build either
4920 (cond != 0) or (cond ? val : 1u). */
4921 if (cond)
4923 cond = gimple_boolify (cond);
4925 if (integer_zerop (val))
4926 val = fold_build2_loc (clause_loc,
4927 EQ_EXPR, unsigned_type_node, cond,
4928 build_int_cst (TREE_TYPE (cond), 0));
4929 else
4931 basic_block cond_bb, then_bb, else_bb;
4932 edge e, e_then, e_else;
4933 tree tmp_then, tmp_else, tmp_join, tmp_var;
4935 tmp_var = create_tmp_var (TREE_TYPE (val));
4936 if (gimple_in_ssa_p (cfun))
4938 tmp_then = make_ssa_name (tmp_var);
4939 tmp_else = make_ssa_name (tmp_var);
4940 tmp_join = make_ssa_name (tmp_var);
4942 else
4944 tmp_then = tmp_var;
4945 tmp_else = tmp_var;
4946 tmp_join = tmp_var;
4949 e = split_block (bb, NULL);
4950 cond_bb = e->src;
4951 bb = e->dest;
4952 remove_edge (e);
4954 then_bb = create_empty_bb (cond_bb);
4955 else_bb = create_empty_bb (then_bb);
4956 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
4957 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
4959 stmt = gimple_build_cond_empty (cond);
4960 gsi = gsi_start_bb (cond_bb);
4961 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4963 gsi = gsi_start_bb (then_bb);
4964 stmt = gimple_build_assign (tmp_then, val);
4965 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4967 gsi = gsi_start_bb (else_bb);
4968 stmt = gimple_build_assign
4969 (tmp_else, build_int_cst (unsigned_type_node, 1));
4970 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
4972 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
4973 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
4974 add_bb_to_loop (then_bb, cond_bb->loop_father);
4975 add_bb_to_loop (else_bb, cond_bb->loop_father);
4976 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
4977 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
4979 if (gimple_in_ssa_p (cfun))
4981 gphi *phi = create_phi_node (tmp_join, bb);
4982 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
4983 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
4986 val = tmp_join;
4989 gsi = gsi_start_bb (bb);
4990 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
4991 false, GSI_CONTINUE_LINKING);
4994 gsi = gsi_last_bb (bb);
4995 t = gimple_omp_parallel_data_arg (entry_stmt);
4996 if (t == NULL)
4997 t1 = null_pointer_node;
4998 else
4999 t1 = build_fold_addr_expr (t);
5000 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5002 vec_alloc (args, 4 + vec_safe_length (ws_args));
5003 args->quick_push (t2);
5004 args->quick_push (t1);
5005 args->quick_push (val);
5006 if (ws_args)
5007 args->splice (*ws_args);
5008 args->quick_push (flags);
5010 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
5011 builtin_decl_explicit (start_ix), args);
5013 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5014 false, GSI_CONTINUE_LINKING);
5017 /* Insert a function call whose name is FUNC_NAME with the information from
5018 ENTRY_STMT into the basic_block BB. */
5020 static void
5021 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
5022 vec <tree, va_gc> *ws_args)
5024 tree t, t1, t2;
5025 gimple_stmt_iterator gsi;
5026 vec <tree, va_gc> *args;
5028 gcc_assert (vec_safe_length (ws_args) == 2);
5029 tree func_name = (*ws_args)[0];
5030 tree grain = (*ws_args)[1];
5032 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
5033 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
5034 gcc_assert (count != NULL_TREE);
5035 count = OMP_CLAUSE_OPERAND (count, 0);
5037 gsi = gsi_last_bb (bb);
5038 t = gimple_omp_parallel_data_arg (entry_stmt);
5039 if (t == NULL)
5040 t1 = null_pointer_node;
5041 else
5042 t1 = build_fold_addr_expr (t);
5043 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
5045 vec_alloc (args, 4);
5046 args->quick_push (t2);
5047 args->quick_push (t1);
5048 args->quick_push (count);
5049 args->quick_push (grain);
5050 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
5052 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
5053 GSI_CONTINUE_LINKING);
5056 /* Build the function call to GOMP_task to actually
5057 generate the task operation. BB is the block where to insert the code. */
5059 static void
5060 expand_task_call (basic_block bb, gomp_task *entry_stmt)
5062 tree t, t1, t2, t3, flags, cond, c, c2, clauses, depend;
5063 gimple_stmt_iterator gsi;
5064 location_t loc = gimple_location (entry_stmt);
5066 clauses = gimple_omp_task_clauses (entry_stmt);
5068 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
5069 if (c)
5070 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (c));
5071 else
5072 cond = boolean_true_node;
5074 c = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
5075 c2 = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
5076 depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
5077 flags = build_int_cst (unsigned_type_node,
5078 (c ? 1 : 0) + (c2 ? 4 : 0) + (depend ? 8 : 0));
5080 c = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
5081 if (c)
5083 c = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (c));
5084 c = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, c,
5085 build_int_cst (unsigned_type_node, 2),
5086 build_int_cst (unsigned_type_node, 0));
5087 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, c);
5089 if (depend)
5090 depend = OMP_CLAUSE_DECL (depend);
5091 else
5092 depend = build_int_cst (ptr_type_node, 0);
5094 gsi = gsi_last_bb (bb);
5095 t = gimple_omp_task_data_arg (entry_stmt);
5096 if (t == NULL)
5097 t2 = null_pointer_node;
5098 else
5099 t2 = build_fold_addr_expr_loc (loc, t);
5100 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
5101 t = gimple_omp_task_copy_fn (entry_stmt);
5102 if (t == NULL)
5103 t3 = null_pointer_node;
5104 else
5105 t3 = build_fold_addr_expr_loc (loc, t);
5107 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
5108 8, t1, t2, t3,
5109 gimple_omp_task_arg_size (entry_stmt),
5110 gimple_omp_task_arg_align (entry_stmt), cond, flags,
5111 depend);
5113 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5114 false, GSI_CONTINUE_LINKING);
5118 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
5119 catch handler and return it. This prevents programs from violating the
5120 structured block semantics with throws. */
5122 static gimple_seq
5123 maybe_catch_exception (gimple_seq body)
5125 gimple g;
5126 tree decl;
5128 if (!flag_exceptions)
5129 return body;
5131 if (lang_hooks.eh_protect_cleanup_actions != NULL)
5132 decl = lang_hooks.eh_protect_cleanup_actions ();
5133 else
5134 decl = builtin_decl_explicit (BUILT_IN_TRAP);
5136 g = gimple_build_eh_must_not_throw (decl);
5137 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
5138 GIMPLE_TRY_CATCH);
5140 return gimple_seq_alloc_with_stmt (g);
5143 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
5145 static tree
5146 vec2chain (vec<tree, va_gc> *v)
5148 tree chain = NULL_TREE, t;
5149 unsigned ix;
5151 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
5153 DECL_CHAIN (t) = chain;
5154 chain = t;
5157 return chain;
5161 /* Remove barriers in REGION->EXIT's block. Note that this is only
5162 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
5163 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
5164 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
5165 removed. */
5167 static void
5168 remove_exit_barrier (struct omp_region *region)
5170 gimple_stmt_iterator gsi;
5171 basic_block exit_bb;
5172 edge_iterator ei;
5173 edge e;
5174 gimple stmt;
5175 int any_addressable_vars = -1;
5177 exit_bb = region->exit;
5179 /* If the parallel region doesn't return, we don't have REGION->EXIT
5180 block at all. */
5181 if (! exit_bb)
5182 return;
5184 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
5185 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
5186 statements that can appear in between are extremely limited -- no
5187 memory operations at all. Here, we allow nothing at all, so the
5188 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
5189 gsi = gsi_last_bb (exit_bb);
5190 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5191 gsi_prev (&gsi);
5192 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
5193 return;
5195 FOR_EACH_EDGE (e, ei, exit_bb->preds)
5197 gsi = gsi_last_bb (e->src);
5198 if (gsi_end_p (gsi))
5199 continue;
5200 stmt = gsi_stmt (gsi);
5201 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
5202 && !gimple_omp_return_nowait_p (stmt))
5204 /* OpenMP 3.0 tasks unfortunately prevent this optimization
5205 in many cases. If there could be tasks queued, the barrier
5206 might be needed to let the tasks run before some local
5207 variable of the parallel that the task uses as shared
5208 runs out of scope. The task can be spawned either
5209 from within current function (this would be easy to check)
5210 or from some function it calls and gets passed an address
5211 of such a variable. */
5212 if (any_addressable_vars < 0)
5214 gomp_parallel *parallel_stmt
5215 = as_a <gomp_parallel *> (last_stmt (region->entry));
5216 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
5217 tree local_decls, block, decl;
5218 unsigned ix;
5220 any_addressable_vars = 0;
5221 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
5222 if (TREE_ADDRESSABLE (decl))
5224 any_addressable_vars = 1;
5225 break;
5227 for (block = gimple_block (stmt);
5228 !any_addressable_vars
5229 && block
5230 && TREE_CODE (block) == BLOCK;
5231 block = BLOCK_SUPERCONTEXT (block))
5233 for (local_decls = BLOCK_VARS (block);
5234 local_decls;
5235 local_decls = DECL_CHAIN (local_decls))
5236 if (TREE_ADDRESSABLE (local_decls))
5238 any_addressable_vars = 1;
5239 break;
5241 if (block == gimple_block (parallel_stmt))
5242 break;
5245 if (!any_addressable_vars)
5246 gimple_omp_return_set_nowait (stmt);
5251 static void
5252 remove_exit_barriers (struct omp_region *region)
5254 if (region->type == GIMPLE_OMP_PARALLEL)
5255 remove_exit_barrier (region);
5257 if (region->inner)
5259 region = region->inner;
5260 remove_exit_barriers (region);
5261 while (region->next)
5263 region = region->next;
5264 remove_exit_barriers (region);
5269 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
5270 calls. These can't be declared as const functions, but
5271 within one parallel body they are constant, so they can be
5272 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
5273 which are declared const. Similarly for task body, except
5274 that in untied task omp_get_thread_num () can change at any task
5275 scheduling point. */
5277 static void
5278 optimize_omp_library_calls (gimple entry_stmt)
5280 basic_block bb;
5281 gimple_stmt_iterator gsi;
5282 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5283 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
5284 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5285 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
5286 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
5287 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
5288 OMP_CLAUSE_UNTIED) != NULL);
5290 FOR_EACH_BB_FN (bb, cfun)
5291 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
5293 gimple call = gsi_stmt (gsi);
5294 tree decl;
5296 if (is_gimple_call (call)
5297 && (decl = gimple_call_fndecl (call))
5298 && DECL_EXTERNAL (decl)
5299 && TREE_PUBLIC (decl)
5300 && DECL_INITIAL (decl) == NULL)
5302 tree built_in;
5304 if (DECL_NAME (decl) == thr_num_id)
5306 /* In #pragma omp task untied omp_get_thread_num () can change
5307 during the execution of the task region. */
5308 if (untied_task)
5309 continue;
5310 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
5312 else if (DECL_NAME (decl) == num_thr_id)
5313 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
5314 else
5315 continue;
5317 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
5318 || gimple_call_num_args (call) != 0)
5319 continue;
5321 if (flag_exceptions && !TREE_NOTHROW (decl))
5322 continue;
5324 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
5325 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
5326 TREE_TYPE (TREE_TYPE (built_in))))
5327 continue;
5329 gimple_call_set_fndecl (call, built_in);
5334 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
5335 regimplified. */
5337 static tree
5338 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
5340 tree t = *tp;
5342 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
5343 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
5344 return t;
5346 if (TREE_CODE (t) == ADDR_EXPR)
5347 recompute_tree_invariant_for_addr_expr (t);
5349 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
5350 return NULL_TREE;
5353 /* Prepend TO = FROM assignment before *GSI_P. */
5355 static void
5356 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from)
5358 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
5359 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
5360 true, GSI_SAME_STMT);
5361 gimple stmt = gimple_build_assign (to, from);
5362 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
5363 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
5364 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
5366 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
5367 gimple_regimplify_operands (stmt, &gsi);
5371 /* Expand the OpenMP parallel or task directive starting at REGION. */
5373 static void
5374 expand_omp_taskreg (struct omp_region *region)
5376 basic_block entry_bb, exit_bb, new_bb;
5377 struct function *child_cfun;
5378 tree child_fn, block, t;
5379 gimple_stmt_iterator gsi;
5380 gimple entry_stmt, stmt;
5381 edge e;
5382 vec<tree, va_gc> *ws_args;
5384 entry_stmt = last_stmt (region->entry);
5385 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
5386 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
5388 entry_bb = region->entry;
5389 exit_bb = region->exit;
5391 bool is_cilk_for
5392 = (flag_cilkplus
5393 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
5394 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
5395 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
5397 if (is_cilk_for)
5398 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
5399 and the inner statement contains the name of the built-in function
5400 and grain. */
5401 ws_args = region->inner->ws_args;
5402 else if (is_combined_parallel (region))
5403 ws_args = region->ws_args;
5404 else
5405 ws_args = NULL;
5407 if (child_cfun->cfg)
5409 /* Due to inlining, it may happen that we have already outlined
5410 the region, in which case all we need to do is make the
5411 sub-graph unreachable and emit the parallel call. */
5412 edge entry_succ_e, exit_succ_e;
5414 entry_succ_e = single_succ_edge (entry_bb);
5416 gsi = gsi_last_bb (entry_bb);
5417 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
5418 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
5419 gsi_remove (&gsi, true);
5421 new_bb = entry_bb;
5422 if (exit_bb)
5424 exit_succ_e = single_succ_edge (exit_bb);
5425 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
5427 remove_edge_and_dominated_blocks (entry_succ_e);
5429 else
5431 unsigned srcidx, dstidx, num;
5433 /* If the parallel region needs data sent from the parent
5434 function, then the very first statement (except possible
5435 tree profile counter updates) of the parallel body
5436 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
5437 &.OMP_DATA_O is passed as an argument to the child function,
5438 we need to replace it with the argument as seen by the child
5439 function.
5441 In most cases, this will end up being the identity assignment
5442 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
5443 a function call that has been inlined, the original PARM_DECL
5444 .OMP_DATA_I may have been converted into a different local
5445 variable. In which case, we need to keep the assignment. */
5446 if (gimple_omp_taskreg_data_arg (entry_stmt))
5448 basic_block entry_succ_bb = single_succ (entry_bb);
5449 tree arg, narg;
5450 gimple parcopy_stmt = NULL;
5452 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
5454 gimple stmt;
5456 gcc_assert (!gsi_end_p (gsi));
5457 stmt = gsi_stmt (gsi);
5458 if (gimple_code (stmt) != GIMPLE_ASSIGN)
5459 continue;
5461 if (gimple_num_ops (stmt) == 2)
5463 tree arg = gimple_assign_rhs1 (stmt);
5465 /* We're ignore the subcode because we're
5466 effectively doing a STRIP_NOPS. */
5468 if (TREE_CODE (arg) == ADDR_EXPR
5469 && TREE_OPERAND (arg, 0)
5470 == gimple_omp_taskreg_data_arg (entry_stmt))
5472 parcopy_stmt = stmt;
5473 break;
5478 gcc_assert (parcopy_stmt != NULL);
5479 arg = DECL_ARGUMENTS (child_fn);
5481 if (!gimple_in_ssa_p (cfun))
5483 if (gimple_assign_lhs (parcopy_stmt) == arg)
5484 gsi_remove (&gsi, true);
5485 else
5487 /* ?? Is setting the subcode really necessary ?? */
5488 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
5489 gimple_assign_set_rhs1 (parcopy_stmt, arg);
5492 else
5494 /* If we are in ssa form, we must load the value from the default
5495 definition of the argument. That should not be defined now,
5496 since the argument is not used uninitialized. */
5497 gcc_assert (ssa_default_def (cfun, arg) == NULL);
5498 narg = make_ssa_name (arg, gimple_build_nop ());
5499 set_ssa_default_def (cfun, arg, narg);
5500 /* ?? Is setting the subcode really necessary ?? */
5501 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg));
5502 gimple_assign_set_rhs1 (parcopy_stmt, narg);
5503 update_stmt (parcopy_stmt);
5507 /* Declare local variables needed in CHILD_CFUN. */
5508 block = DECL_INITIAL (child_fn);
5509 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
5510 /* The gimplifier could record temporaries in parallel/task block
5511 rather than in containing function's local_decls chain,
5512 which would mean cgraph missed finalizing them. Do it now. */
5513 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
5514 if (TREE_CODE (t) == VAR_DECL
5515 && TREE_STATIC (t)
5516 && !DECL_EXTERNAL (t))
5517 varpool_node::finalize_decl (t);
5518 DECL_SAVED_TREE (child_fn) = NULL;
5519 /* We'll create a CFG for child_fn, so no gimple body is needed. */
5520 gimple_set_body (child_fn, NULL);
5521 TREE_USED (block) = 1;
5523 /* Reset DECL_CONTEXT on function arguments. */
5524 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
5525 DECL_CONTEXT (t) = child_fn;
5527 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
5528 so that it can be moved to the child function. */
5529 gsi = gsi_last_bb (entry_bb);
5530 stmt = gsi_stmt (gsi);
5531 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
5532 || gimple_code (stmt) == GIMPLE_OMP_TASK));
5533 gsi_remove (&gsi, true);
5534 e = split_block (entry_bb, stmt);
5535 entry_bb = e->dest;
5536 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
5538 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
5539 if (exit_bb)
5541 gsi = gsi_last_bb (exit_bb);
5542 gcc_assert (!gsi_end_p (gsi)
5543 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
5544 stmt = gimple_build_return (NULL);
5545 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
5546 gsi_remove (&gsi, true);
5549 /* Move the parallel region into CHILD_CFUN. */
5551 if (gimple_in_ssa_p (cfun))
5553 init_tree_ssa (child_cfun);
5554 init_ssa_operands (child_cfun);
5555 child_cfun->gimple_df->in_ssa_p = true;
5556 block = NULL_TREE;
5558 else
5559 block = gimple_block (entry_stmt);
5561 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
5562 if (exit_bb)
5563 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
5564 /* When the OMP expansion process cannot guarantee an up-to-date
5565 loop tree arrange for the child function to fixup loops. */
5566 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
5567 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
5569 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
5570 num = vec_safe_length (child_cfun->local_decls);
5571 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
5573 t = (*child_cfun->local_decls)[srcidx];
5574 if (DECL_CONTEXT (t) == cfun->decl)
5575 continue;
5576 if (srcidx != dstidx)
5577 (*child_cfun->local_decls)[dstidx] = t;
5578 dstidx++;
5580 if (dstidx != num)
5581 vec_safe_truncate (child_cfun->local_decls, dstidx);
5583 /* Inform the callgraph about the new function. */
5584 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
5585 cgraph_node::add_new_function (child_fn, true);
5587 /* Fix the callgraph edges for child_cfun. Those for cfun will be
5588 fixed in a following pass. */
5589 push_cfun (child_cfun);
5590 if (optimize)
5591 optimize_omp_library_calls (entry_stmt);
5592 cgraph_edge::rebuild_edges ();
5594 /* Some EH regions might become dead, see PR34608. If
5595 pass_cleanup_cfg isn't the first pass to happen with the
5596 new child, these dead EH edges might cause problems.
5597 Clean them up now. */
5598 if (flag_exceptions)
5600 basic_block bb;
5601 bool changed = false;
5603 FOR_EACH_BB_FN (bb, cfun)
5604 changed |= gimple_purge_dead_eh_edges (bb);
5605 if (changed)
5606 cleanup_tree_cfg ();
5608 if (gimple_in_ssa_p (cfun))
5609 update_ssa (TODO_update_ssa);
5610 pop_cfun ();
5613 /* Emit a library call to launch the children threads. */
5614 if (is_cilk_for)
5615 expand_cilk_for_call (new_bb,
5616 as_a <gomp_parallel *> (entry_stmt), ws_args);
5617 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
5618 expand_parallel_call (region, new_bb,
5619 as_a <gomp_parallel *> (entry_stmt), ws_args);
5620 else
5621 expand_task_call (new_bb, as_a <gomp_task *> (entry_stmt));
5622 if (gimple_in_ssa_p (cfun))
5623 update_ssa (TODO_update_ssa_only_virtuals);
5627 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
5628 of the combined collapse > 1 loop constructs, generate code like:
5629 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
5630 if (cond3 is <)
5631 adj = STEP3 - 1;
5632 else
5633 adj = STEP3 + 1;
5634 count3 = (adj + N32 - N31) / STEP3;
5635 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
5636 if (cond2 is <)
5637 adj = STEP2 - 1;
5638 else
5639 adj = STEP2 + 1;
5640 count2 = (adj + N22 - N21) / STEP2;
5641 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
5642 if (cond1 is <)
5643 adj = STEP1 - 1;
5644 else
5645 adj = STEP1 + 1;
5646 count1 = (adj + N12 - N11) / STEP1;
5647 count = count1 * count2 * count3;
5648 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
5649 count = 0;
5650 and set ZERO_ITER_BB to that bb. If this isn't the outermost
5651 of the combined loop constructs, just initialize COUNTS array
5652 from the _looptemp_ clauses. */
5654 /* NOTE: It *could* be better to moosh all of the BBs together,
5655 creating one larger BB with all the computation and the unexpected
5656 jump at the end. I.e.
5658 bool zero3, zero2, zero1, zero;
5660 zero3 = N32 c3 N31;
5661 count3 = (N32 - N31) /[cl] STEP3;
5662 zero2 = N22 c2 N21;
5663 count2 = (N22 - N21) /[cl] STEP2;
5664 zero1 = N12 c1 N11;
5665 count1 = (N12 - N11) /[cl] STEP1;
5666 zero = zero3 || zero2 || zero1;
5667 count = count1 * count2 * count3;
5668 if (__builtin_expect(zero, false)) goto zero_iter_bb;
5670 After all, we expect the zero=false, and thus we expect to have to
5671 evaluate all of the comparison expressions, so short-circuiting
5672 oughtn't be a win. Since the condition isn't protecting a
5673 denominator, we're not concerned about divide-by-zero, so we can
5674 fully evaluate count even if a numerator turned out to be wrong.
5676 It seems like putting this all together would create much better
5677 scheduling opportunities, and less pressure on the chip's branch
5678 predictor. */
5680 static void
5681 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5682 basic_block &entry_bb, tree *counts,
5683 basic_block &zero_iter_bb, int &first_zero_iter,
5684 basic_block &l2_dom_bb)
5686 tree t, type = TREE_TYPE (fd->loop.v);
5687 edge e, ne;
5688 int i;
5690 /* Collapsed loops need work for expansion into SSA form. */
5691 gcc_assert (!gimple_in_ssa_p (cfun));
5693 if (gimple_omp_for_combined_into_p (fd->for_stmt)
5694 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
5696 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5697 isn't supposed to be handled, as the inner loop doesn't
5698 use it. */
5699 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
5700 OMP_CLAUSE__LOOPTEMP_);
5701 gcc_assert (innerc);
5702 for (i = 0; i < fd->collapse; i++)
5704 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5705 OMP_CLAUSE__LOOPTEMP_);
5706 gcc_assert (innerc);
5707 if (i)
5708 counts[i] = OMP_CLAUSE_DECL (innerc);
5709 else
5710 counts[0] = NULL_TREE;
5712 return;
5715 for (i = 0; i < fd->collapse; i++)
5717 tree itype = TREE_TYPE (fd->loops[i].v);
5719 if (SSA_VAR_P (fd->loop.n2)
5720 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
5721 fold_convert (itype, fd->loops[i].n1),
5722 fold_convert (itype, fd->loops[i].n2)))
5723 == NULL_TREE || !integer_onep (t)))
5725 gcond *cond_stmt;
5726 tree n1, n2;
5727 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
5728 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
5729 true, GSI_SAME_STMT);
5730 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
5731 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
5732 true, GSI_SAME_STMT);
5733 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
5734 NULL_TREE, NULL_TREE);
5735 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
5736 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
5737 expand_omp_regimplify_p, NULL, NULL)
5738 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
5739 expand_omp_regimplify_p, NULL, NULL))
5741 *gsi = gsi_for_stmt (cond_stmt);
5742 gimple_regimplify_operands (cond_stmt, gsi);
5744 e = split_block (entry_bb, cond_stmt);
5745 if (zero_iter_bb == NULL)
5747 gassign *assign_stmt;
5748 first_zero_iter = i;
5749 zero_iter_bb = create_empty_bb (entry_bb);
5750 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
5751 *gsi = gsi_after_labels (zero_iter_bb);
5752 assign_stmt = gimple_build_assign (fd->loop.n2,
5753 build_zero_cst (type));
5754 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
5755 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
5756 entry_bb);
5758 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
5759 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
5760 e->flags = EDGE_TRUE_VALUE;
5761 e->probability = REG_BR_PROB_BASE - ne->probability;
5762 if (l2_dom_bb == NULL)
5763 l2_dom_bb = entry_bb;
5764 entry_bb = e->dest;
5765 *gsi = gsi_last_bb (entry_bb);
5768 if (POINTER_TYPE_P (itype))
5769 itype = signed_type_for (itype);
5770 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
5771 ? -1 : 1));
5772 t = fold_build2 (PLUS_EXPR, itype,
5773 fold_convert (itype, fd->loops[i].step), t);
5774 t = fold_build2 (PLUS_EXPR, itype, t,
5775 fold_convert (itype, fd->loops[i].n2));
5776 t = fold_build2 (MINUS_EXPR, itype, t,
5777 fold_convert (itype, fd->loops[i].n1));
5778 /* ?? We could probably use CEIL_DIV_EXPR instead of
5779 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
5780 generate the same code in the end because generically we
5781 don't know that the values involved must be negative for
5782 GT?? */
5783 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
5784 t = fold_build2 (TRUNC_DIV_EXPR, itype,
5785 fold_build1 (NEGATE_EXPR, itype, t),
5786 fold_build1 (NEGATE_EXPR, itype,
5787 fold_convert (itype,
5788 fd->loops[i].step)));
5789 else
5790 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
5791 fold_convert (itype, fd->loops[i].step));
5792 t = fold_convert (type, t);
5793 if (TREE_CODE (t) == INTEGER_CST)
5794 counts[i] = t;
5795 else
5797 counts[i] = create_tmp_reg (type, ".count");
5798 expand_omp_build_assign (gsi, counts[i], t);
5800 if (SSA_VAR_P (fd->loop.n2))
5802 if (i == 0)
5803 t = counts[0];
5804 else
5805 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
5806 expand_omp_build_assign (gsi, fd->loop.n2, t);
5812 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
5813 T = V;
5814 V3 = N31 + (T % count3) * STEP3;
5815 T = T / count3;
5816 V2 = N21 + (T % count2) * STEP2;
5817 T = T / count2;
5818 V1 = N11 + T * STEP1;
5819 if this loop doesn't have an inner loop construct combined with it.
5820 If it does have an inner loop construct combined with it and the
5821 iteration count isn't known constant, store values from counts array
5822 into its _looptemp_ temporaries instead. */
5824 static void
5825 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
5826 tree *counts, gimple inner_stmt, tree startvar)
5828 int i;
5829 if (gimple_omp_for_combined_p (fd->for_stmt))
5831 /* If fd->loop.n2 is constant, then no propagation of the counts
5832 is needed, they are constant. */
5833 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
5834 return;
5836 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
5837 ? gimple_omp_parallel_clauses (inner_stmt)
5838 : gimple_omp_for_clauses (inner_stmt);
5839 /* First two _looptemp_ clauses are for istart/iend, counts[0]
5840 isn't supposed to be handled, as the inner loop doesn't
5841 use it. */
5842 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
5843 gcc_assert (innerc);
5844 for (i = 0; i < fd->collapse; i++)
5846 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
5847 OMP_CLAUSE__LOOPTEMP_);
5848 gcc_assert (innerc);
5849 if (i)
5851 tree tem = OMP_CLAUSE_DECL (innerc);
5852 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
5853 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5854 false, GSI_CONTINUE_LINKING);
5855 gassign *stmt = gimple_build_assign (tem, t);
5856 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5859 return;
5862 tree type = TREE_TYPE (fd->loop.v);
5863 tree tem = create_tmp_reg (type, ".tem");
5864 gassign *stmt = gimple_build_assign (tem, startvar);
5865 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5867 for (i = fd->collapse - 1; i >= 0; i--)
5869 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
5870 itype = vtype;
5871 if (POINTER_TYPE_P (vtype))
5872 itype = signed_type_for (vtype);
5873 if (i != 0)
5874 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
5875 else
5876 t = tem;
5877 t = fold_convert (itype, t);
5878 t = fold_build2 (MULT_EXPR, itype, t,
5879 fold_convert (itype, fd->loops[i].step));
5880 if (POINTER_TYPE_P (vtype))
5881 t = fold_build_pointer_plus (fd->loops[i].n1, t);
5882 else
5883 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
5884 t = force_gimple_operand_gsi (gsi, t,
5885 DECL_P (fd->loops[i].v)
5886 && TREE_ADDRESSABLE (fd->loops[i].v),
5887 NULL_TREE, false,
5888 GSI_CONTINUE_LINKING);
5889 stmt = gimple_build_assign (fd->loops[i].v, t);
5890 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5891 if (i != 0)
5893 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
5894 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
5895 false, GSI_CONTINUE_LINKING);
5896 stmt = gimple_build_assign (tem, t);
5897 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
5903 /* Helper function for expand_omp_for_*. Generate code like:
5904 L10:
5905 V3 += STEP3;
5906 if (V3 cond3 N32) goto BODY_BB; else goto L11;
5907 L11:
5908 V3 = N31;
5909 V2 += STEP2;
5910 if (V2 cond2 N22) goto BODY_BB; else goto L12;
5911 L12:
5912 V2 = N21;
5913 V1 += STEP1;
5914 goto BODY_BB; */
5916 static basic_block
5917 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
5918 basic_block body_bb)
5920 basic_block last_bb, bb, collapse_bb = NULL;
5921 int i;
5922 gimple_stmt_iterator gsi;
5923 edge e;
5924 tree t;
5925 gimple stmt;
5927 last_bb = cont_bb;
5928 for (i = fd->collapse - 1; i >= 0; i--)
5930 tree vtype = TREE_TYPE (fd->loops[i].v);
5932 bb = create_empty_bb (last_bb);
5933 add_bb_to_loop (bb, last_bb->loop_father);
5934 gsi = gsi_start_bb (bb);
5936 if (i < fd->collapse - 1)
5938 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
5939 e->probability = REG_BR_PROB_BASE / 8;
5941 t = fd->loops[i + 1].n1;
5942 t = force_gimple_operand_gsi (&gsi, t,
5943 DECL_P (fd->loops[i + 1].v)
5944 && TREE_ADDRESSABLE (fd->loops[i
5945 + 1].v),
5946 NULL_TREE, false,
5947 GSI_CONTINUE_LINKING);
5948 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
5949 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5951 else
5952 collapse_bb = bb;
5954 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
5956 if (POINTER_TYPE_P (vtype))
5957 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
5958 else
5959 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
5960 t = force_gimple_operand_gsi (&gsi, t,
5961 DECL_P (fd->loops[i].v)
5962 && TREE_ADDRESSABLE (fd->loops[i].v),
5963 NULL_TREE, false, GSI_CONTINUE_LINKING);
5964 stmt = gimple_build_assign (fd->loops[i].v, t);
5965 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5967 if (i > 0)
5969 t = fd->loops[i].n2;
5970 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
5971 false, GSI_CONTINUE_LINKING);
5972 tree v = fd->loops[i].v;
5973 if (DECL_P (v) && TREE_ADDRESSABLE (v))
5974 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
5975 false, GSI_CONTINUE_LINKING);
5976 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
5977 stmt = gimple_build_cond_empty (t);
5978 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
5979 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
5980 e->probability = REG_BR_PROB_BASE * 7 / 8;
5982 else
5983 make_edge (bb, body_bb, EDGE_FALLTHRU);
5984 last_bb = bb;
5987 return collapse_bb;
5991 /* A subroutine of expand_omp_for. Generate code for a parallel
5992 loop with any schedule. Given parameters:
5994 for (V = N1; V cond N2; V += STEP) BODY;
5996 where COND is "<" or ">", we generate pseudocode
5998 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
5999 if (more) goto L0; else goto L3;
6001 V = istart0;
6002 iend = iend0;
6004 BODY;
6005 V += STEP;
6006 if (V cond iend) goto L1; else goto L2;
6008 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6011 If this is a combined omp parallel loop, instead of the call to
6012 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
6013 If this is gimple_omp_for_combined_p loop, then instead of assigning
6014 V and iend in L0 we assign the first two _looptemp_ clause decls of the
6015 inner GIMPLE_OMP_FOR and V += STEP; and
6016 if (V cond iend) goto L1; else goto L2; are removed.
6018 For collapsed loops, given parameters:
6019 collapse(3)
6020 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
6021 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
6022 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
6023 BODY;
6025 we generate pseudocode
6027 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
6028 if (cond3 is <)
6029 adj = STEP3 - 1;
6030 else
6031 adj = STEP3 + 1;
6032 count3 = (adj + N32 - N31) / STEP3;
6033 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
6034 if (cond2 is <)
6035 adj = STEP2 - 1;
6036 else
6037 adj = STEP2 + 1;
6038 count2 = (adj + N22 - N21) / STEP2;
6039 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
6040 if (cond1 is <)
6041 adj = STEP1 - 1;
6042 else
6043 adj = STEP1 + 1;
6044 count1 = (adj + N12 - N11) / STEP1;
6045 count = count1 * count2 * count3;
6046 goto Z1;
6048 count = 0;
6050 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
6051 if (more) goto L0; else goto L3;
6053 V = istart0;
6054 T = V;
6055 V3 = N31 + (T % count3) * STEP3;
6056 T = T / count3;
6057 V2 = N21 + (T % count2) * STEP2;
6058 T = T / count2;
6059 V1 = N11 + T * STEP1;
6060 iend = iend0;
6062 BODY;
6063 V += 1;
6064 if (V < iend) goto L10; else goto L2;
6065 L10:
6066 V3 += STEP3;
6067 if (V3 cond3 N32) goto L1; else goto L11;
6068 L11:
6069 V3 = N31;
6070 V2 += STEP2;
6071 if (V2 cond2 N22) goto L1; else goto L12;
6072 L12:
6073 V2 = N21;
6074 V1 += STEP1;
6075 goto L1;
6077 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
6082 static void
6083 expand_omp_for_generic (struct omp_region *region,
6084 struct omp_for_data *fd,
6085 enum built_in_function start_fn,
6086 enum built_in_function next_fn,
6087 gimple inner_stmt)
6089 tree type, istart0, iend0, iend;
6090 tree t, vmain, vback, bias = NULL_TREE;
6091 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
6092 basic_block l2_bb = NULL, l3_bb = NULL;
6093 gimple_stmt_iterator gsi;
6094 gassign *assign_stmt;
6095 bool in_combined_parallel = is_combined_parallel (region);
6096 bool broken_loop = region->cont == NULL;
6097 edge e, ne;
6098 tree *counts = NULL;
6099 int i;
6101 gcc_assert (!broken_loop || !in_combined_parallel);
6102 gcc_assert (fd->iter_type == long_integer_type_node
6103 || !in_combined_parallel);
6105 type = TREE_TYPE (fd->loop.v);
6106 istart0 = create_tmp_var (fd->iter_type, ".istart0");
6107 iend0 = create_tmp_var (fd->iter_type, ".iend0");
6108 TREE_ADDRESSABLE (istart0) = 1;
6109 TREE_ADDRESSABLE (iend0) = 1;
6111 /* See if we need to bias by LLONG_MIN. */
6112 if (fd->iter_type == long_long_unsigned_type_node
6113 && TREE_CODE (type) == INTEGER_TYPE
6114 && !TYPE_UNSIGNED (type))
6116 tree n1, n2;
6118 if (fd->loop.cond_code == LT_EXPR)
6120 n1 = fd->loop.n1;
6121 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
6123 else
6125 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
6126 n2 = fd->loop.n1;
6128 if (TREE_CODE (n1) != INTEGER_CST
6129 || TREE_CODE (n2) != INTEGER_CST
6130 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
6131 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
6134 entry_bb = region->entry;
6135 cont_bb = region->cont;
6136 collapse_bb = NULL;
6137 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6138 gcc_assert (broken_loop
6139 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
6140 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6141 l1_bb = single_succ (l0_bb);
6142 if (!broken_loop)
6144 l2_bb = create_empty_bb (cont_bb);
6145 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb);
6146 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6148 else
6149 l2_bb = NULL;
6150 l3_bb = BRANCH_EDGE (entry_bb)->dest;
6151 exit_bb = region->exit;
6153 gsi = gsi_last_bb (entry_bb);
6155 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6156 if (fd->collapse > 1)
6158 int first_zero_iter = -1;
6159 basic_block zero_iter_bb = NULL, l2_dom_bb = NULL;
6161 counts = XALLOCAVEC (tree, fd->collapse);
6162 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6163 zero_iter_bb, first_zero_iter,
6164 l2_dom_bb);
6166 if (zero_iter_bb)
6168 /* Some counts[i] vars might be uninitialized if
6169 some loop has zero iterations. But the body shouldn't
6170 be executed in that case, so just avoid uninit warnings. */
6171 for (i = first_zero_iter; i < fd->collapse; i++)
6172 if (SSA_VAR_P (counts[i]))
6173 TREE_NO_WARNING (counts[i]) = 1;
6174 gsi_prev (&gsi);
6175 e = split_block (entry_bb, gsi_stmt (gsi));
6176 entry_bb = e->dest;
6177 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
6178 gsi = gsi_last_bb (entry_bb);
6179 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
6180 get_immediate_dominator (CDI_DOMINATORS,
6181 zero_iter_bb));
6184 if (in_combined_parallel)
6186 /* In a combined parallel loop, emit a call to
6187 GOMP_loop_foo_next. */
6188 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6189 build_fold_addr_expr (istart0),
6190 build_fold_addr_expr (iend0));
6192 else
6194 tree t0, t1, t2, t3, t4;
6195 /* If this is not a combined parallel loop, emit a call to
6196 GOMP_loop_foo_start in ENTRY_BB. */
6197 t4 = build_fold_addr_expr (iend0);
6198 t3 = build_fold_addr_expr (istart0);
6199 t2 = fold_convert (fd->iter_type, fd->loop.step);
6200 t1 = fd->loop.n2;
6201 t0 = fd->loop.n1;
6202 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6204 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6205 OMP_CLAUSE__LOOPTEMP_);
6206 gcc_assert (innerc);
6207 t0 = OMP_CLAUSE_DECL (innerc);
6208 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6209 OMP_CLAUSE__LOOPTEMP_);
6210 gcc_assert (innerc);
6211 t1 = OMP_CLAUSE_DECL (innerc);
6213 if (POINTER_TYPE_P (TREE_TYPE (t0))
6214 && TYPE_PRECISION (TREE_TYPE (t0))
6215 != TYPE_PRECISION (fd->iter_type))
6217 /* Avoid casting pointers to integer of a different size. */
6218 tree itype = signed_type_for (type);
6219 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
6220 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
6222 else
6224 t1 = fold_convert (fd->iter_type, t1);
6225 t0 = fold_convert (fd->iter_type, t0);
6227 if (bias)
6229 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
6230 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
6232 if (fd->iter_type == long_integer_type_node)
6234 if (fd->chunk_size)
6236 t = fold_convert (fd->iter_type, fd->chunk_size);
6237 t = build_call_expr (builtin_decl_explicit (start_fn),
6238 6, t0, t1, t2, t, t3, t4);
6240 else
6241 t = build_call_expr (builtin_decl_explicit (start_fn),
6242 5, t0, t1, t2, t3, t4);
6244 else
6246 tree t5;
6247 tree c_bool_type;
6248 tree bfn_decl;
6250 /* The GOMP_loop_ull_*start functions have additional boolean
6251 argument, true for < loops and false for > loops.
6252 In Fortran, the C bool type can be different from
6253 boolean_type_node. */
6254 bfn_decl = builtin_decl_explicit (start_fn);
6255 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
6256 t5 = build_int_cst (c_bool_type,
6257 fd->loop.cond_code == LT_EXPR ? 1 : 0);
6258 if (fd->chunk_size)
6260 tree bfn_decl = builtin_decl_explicit (start_fn);
6261 t = fold_convert (fd->iter_type, fd->chunk_size);
6262 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
6264 else
6265 t = build_call_expr (builtin_decl_explicit (start_fn),
6266 6, t5, t0, t1, t2, t3, t4);
6269 if (TREE_TYPE (t) != boolean_type_node)
6270 t = fold_build2 (NE_EXPR, boolean_type_node,
6271 t, build_int_cst (TREE_TYPE (t), 0));
6272 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6273 true, GSI_SAME_STMT);
6274 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6276 /* Remove the GIMPLE_OMP_FOR statement. */
6277 gsi_remove (&gsi, true);
6279 /* Iteration setup for sequential loop goes in L0_BB. */
6280 tree startvar = fd->loop.v;
6281 tree endvar = NULL_TREE;
6283 if (gimple_omp_for_combined_p (fd->for_stmt))
6285 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
6286 && gimple_omp_for_kind (inner_stmt)
6287 == GF_OMP_FOR_KIND_SIMD);
6288 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
6289 OMP_CLAUSE__LOOPTEMP_);
6290 gcc_assert (innerc);
6291 startvar = OMP_CLAUSE_DECL (innerc);
6292 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6293 OMP_CLAUSE__LOOPTEMP_);
6294 gcc_assert (innerc);
6295 endvar = OMP_CLAUSE_DECL (innerc);
6298 gsi = gsi_start_bb (l0_bb);
6299 t = istart0;
6300 if (bias)
6301 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6302 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6303 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6304 t = fold_convert (TREE_TYPE (startvar), t);
6305 t = force_gimple_operand_gsi (&gsi, t,
6306 DECL_P (startvar)
6307 && TREE_ADDRESSABLE (startvar),
6308 NULL_TREE, false, GSI_CONTINUE_LINKING);
6309 assign_stmt = gimple_build_assign (startvar, t);
6310 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6312 t = iend0;
6313 if (bias)
6314 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
6315 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
6316 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
6317 t = fold_convert (TREE_TYPE (startvar), t);
6318 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6319 false, GSI_CONTINUE_LINKING);
6320 if (endvar)
6322 assign_stmt = gimple_build_assign (endvar, iend);
6323 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6324 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
6325 assign_stmt = gimple_build_assign (fd->loop.v, iend);
6326 else
6327 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
6328 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6330 if (fd->collapse > 1)
6331 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6333 if (!broken_loop)
6335 /* Code to control the increment and predicate for the sequential
6336 loop goes in the CONT_BB. */
6337 gsi = gsi_last_bb (cont_bb);
6338 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6339 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6340 vmain = gimple_omp_continue_control_use (cont_stmt);
6341 vback = gimple_omp_continue_control_def (cont_stmt);
6343 if (!gimple_omp_for_combined_p (fd->for_stmt))
6345 if (POINTER_TYPE_P (type))
6346 t = fold_build_pointer_plus (vmain, fd->loop.step);
6347 else
6348 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
6349 t = force_gimple_operand_gsi (&gsi, t,
6350 DECL_P (vback)
6351 && TREE_ADDRESSABLE (vback),
6352 NULL_TREE, true, GSI_SAME_STMT);
6353 assign_stmt = gimple_build_assign (vback, t);
6354 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6356 t = build2 (fd->loop.cond_code, boolean_type_node,
6357 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
6358 iend);
6359 gcond *cond_stmt = gimple_build_cond_empty (t);
6360 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6363 /* Remove GIMPLE_OMP_CONTINUE. */
6364 gsi_remove (&gsi, true);
6366 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6367 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
6369 /* Emit code to get the next parallel iteration in L2_BB. */
6370 gsi = gsi_start_bb (l2_bb);
6372 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
6373 build_fold_addr_expr (istart0),
6374 build_fold_addr_expr (iend0));
6375 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6376 false, GSI_CONTINUE_LINKING);
6377 if (TREE_TYPE (t) != boolean_type_node)
6378 t = fold_build2 (NE_EXPR, boolean_type_node,
6379 t, build_int_cst (TREE_TYPE (t), 0));
6380 gcond *cond_stmt = gimple_build_cond_empty (t);
6381 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
6384 /* Add the loop cleanup function. */
6385 gsi = gsi_last_bb (exit_bb);
6386 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6387 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
6388 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6389 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
6390 else
6391 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
6392 gcall *call_stmt = gimple_build_call (t, 0);
6393 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
6394 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
6395 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
6396 gsi_remove (&gsi, true);
6398 /* Connect the new blocks. */
6399 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
6400 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
6402 if (!broken_loop)
6404 gimple_seq phis;
6406 e = find_edge (cont_bb, l3_bb);
6407 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
6409 phis = phi_nodes (l3_bb);
6410 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
6412 gimple phi = gsi_stmt (gsi);
6413 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
6414 PHI_ARG_DEF_FROM_EDGE (phi, e));
6416 remove_edge (e);
6418 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
6419 add_bb_to_loop (l2_bb, cont_bb->loop_father);
6420 e = find_edge (cont_bb, l1_bb);
6421 if (gimple_omp_for_combined_p (fd->for_stmt))
6423 remove_edge (e);
6424 e = NULL;
6426 else if (fd->collapse > 1)
6428 remove_edge (e);
6429 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6431 else
6432 e->flags = EDGE_TRUE_VALUE;
6433 if (e)
6435 e->probability = REG_BR_PROB_BASE * 7 / 8;
6436 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
6438 else
6440 e = find_edge (cont_bb, l2_bb);
6441 e->flags = EDGE_FALLTHRU;
6443 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
6445 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
6446 recompute_dominator (CDI_DOMINATORS, l2_bb));
6447 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
6448 recompute_dominator (CDI_DOMINATORS, l3_bb));
6449 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
6450 recompute_dominator (CDI_DOMINATORS, l0_bb));
6451 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
6452 recompute_dominator (CDI_DOMINATORS, l1_bb));
6454 struct loop *outer_loop = alloc_loop ();
6455 outer_loop->header = l0_bb;
6456 outer_loop->latch = l2_bb;
6457 add_loop (outer_loop, l0_bb->loop_father);
6459 if (!gimple_omp_for_combined_p (fd->for_stmt))
6461 struct loop *loop = alloc_loop ();
6462 loop->header = l1_bb;
6463 /* The loop may have multiple latches. */
6464 add_loop (loop, outer_loop);
6470 /* A subroutine of expand_omp_for. Generate code for a parallel
6471 loop with static schedule and no specified chunk size. Given
6472 parameters:
6474 for (V = N1; V cond N2; V += STEP) BODY;
6476 where COND is "<" or ">", we generate pseudocode
6478 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6479 if (cond is <)
6480 adj = STEP - 1;
6481 else
6482 adj = STEP + 1;
6483 if ((__typeof (V)) -1 > 0 && cond is >)
6484 n = -(adj + N2 - N1) / -STEP;
6485 else
6486 n = (adj + N2 - N1) / STEP;
6487 q = n / nthreads;
6488 tt = n % nthreads;
6489 if (threadid < tt) goto L3; else goto L4;
6491 tt = 0;
6492 q = q + 1;
6494 s0 = q * threadid + tt;
6495 e0 = s0 + q;
6496 V = s0 * STEP + N1;
6497 if (s0 >= e0) goto L2; else goto L0;
6499 e = e0 * STEP + N1;
6501 BODY;
6502 V += STEP;
6503 if (V cond e) goto L1;
6507 static void
6508 expand_omp_for_static_nochunk (struct omp_region *region,
6509 struct omp_for_data *fd,
6510 gimple inner_stmt)
6512 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
6513 tree type, itype, vmain, vback;
6514 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
6515 basic_block body_bb, cont_bb, collapse_bb = NULL;
6516 basic_block fin_bb;
6517 gimple_stmt_iterator gsi;
6518 edge ep;
6519 bool broken_loop = region->cont == NULL;
6520 tree *counts = NULL;
6521 tree n1, n2, step;
6523 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6524 != GF_OMP_FOR_KIND_OACC_LOOP)
6525 || !inner_stmt);
6527 itype = type = TREE_TYPE (fd->loop.v);
6528 if (POINTER_TYPE_P (type))
6529 itype = signed_type_for (type);
6531 entry_bb = region->entry;
6532 cont_bb = region->cont;
6533 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
6534 fin_bb = BRANCH_EDGE (entry_bb)->dest;
6535 gcc_assert (broken_loop
6536 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
6537 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
6538 body_bb = single_succ (seq_start_bb);
6539 if (!broken_loop)
6541 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6542 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6544 exit_bb = region->exit;
6546 /* Iteration space partitioning goes in ENTRY_BB. */
6547 gsi = gsi_last_bb (entry_bb);
6548 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6550 if (fd->collapse > 1)
6552 int first_zero_iter = -1;
6553 basic_block l2_dom_bb = NULL;
6555 counts = XALLOCAVEC (tree, fd->collapse);
6556 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6557 fin_bb, first_zero_iter,
6558 l2_dom_bb);
6559 t = NULL_TREE;
6561 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6562 t = integer_one_node;
6563 else
6564 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6565 fold_convert (type, fd->loop.n1),
6566 fold_convert (type, fd->loop.n2));
6567 if (fd->collapse == 1
6568 && TYPE_UNSIGNED (type)
6569 && (t == NULL_TREE || !integer_onep (t)))
6571 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6572 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6573 true, GSI_SAME_STMT);
6574 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6575 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6576 true, GSI_SAME_STMT);
6577 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6578 NULL_TREE, NULL_TREE);
6579 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6580 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6581 expand_omp_regimplify_p, NULL, NULL)
6582 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6583 expand_omp_regimplify_p, NULL, NULL))
6585 gsi = gsi_for_stmt (cond_stmt);
6586 gimple_regimplify_operands (cond_stmt, &gsi);
6588 ep = split_block (entry_bb, cond_stmt);
6589 ep->flags = EDGE_TRUE_VALUE;
6590 entry_bb = ep->dest;
6591 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6592 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
6593 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
6594 if (gimple_in_ssa_p (cfun))
6596 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6597 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6598 !gsi_end_p (gpi); gsi_next (&gpi))
6600 gphi *phi = gpi.phi ();
6601 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6602 ep, UNKNOWN_LOCATION);
6605 gsi = gsi_last_bb (entry_bb);
6608 switch (gimple_omp_for_kind (fd->for_stmt))
6610 case GF_OMP_FOR_KIND_FOR:
6611 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6612 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6613 break;
6614 case GF_OMP_FOR_KIND_DISTRIBUTE:
6615 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
6616 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
6617 break;
6618 case GF_OMP_FOR_KIND_OACC_LOOP:
6619 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
6620 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
6621 break;
6622 default:
6623 gcc_unreachable ();
6625 nthreads = build_call_expr (nthreads, 0);
6626 nthreads = fold_convert (itype, nthreads);
6627 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
6628 true, GSI_SAME_STMT);
6629 threadid = build_call_expr (threadid, 0);
6630 threadid = fold_convert (itype, threadid);
6631 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
6632 true, GSI_SAME_STMT);
6634 n1 = fd->loop.n1;
6635 n2 = fd->loop.n2;
6636 step = fd->loop.step;
6637 if (gimple_omp_for_combined_into_p (fd->for_stmt))
6639 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
6640 OMP_CLAUSE__LOOPTEMP_);
6641 gcc_assert (innerc);
6642 n1 = OMP_CLAUSE_DECL (innerc);
6643 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6644 OMP_CLAUSE__LOOPTEMP_);
6645 gcc_assert (innerc);
6646 n2 = OMP_CLAUSE_DECL (innerc);
6648 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
6649 true, NULL_TREE, true, GSI_SAME_STMT);
6650 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
6651 true, NULL_TREE, true, GSI_SAME_STMT);
6652 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
6653 true, NULL_TREE, true, GSI_SAME_STMT);
6655 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
6656 t = fold_build2 (PLUS_EXPR, itype, step, t);
6657 t = fold_build2 (PLUS_EXPR, itype, t, n2);
6658 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
6659 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
6660 t = fold_build2 (TRUNC_DIV_EXPR, itype,
6661 fold_build1 (NEGATE_EXPR, itype, t),
6662 fold_build1 (NEGATE_EXPR, itype, step));
6663 else
6664 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
6665 t = fold_convert (itype, t);
6666 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6668 q = create_tmp_reg (itype, "q");
6669 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
6670 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6671 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
6673 tt = create_tmp_reg (itype, "tt");
6674 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
6675 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
6676 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
6678 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
6679 gcond *cond_stmt = gimple_build_cond_empty (t);
6680 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6682 second_bb = split_block (entry_bb, cond_stmt)->dest;
6683 gsi = gsi_last_bb (second_bb);
6684 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6686 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
6687 GSI_SAME_STMT);
6688 gassign *assign_stmt
6689 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
6690 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6692 third_bb = split_block (second_bb, assign_stmt)->dest;
6693 gsi = gsi_last_bb (third_bb);
6694 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6696 t = build2 (MULT_EXPR, itype, q, threadid);
6697 t = build2 (PLUS_EXPR, itype, t, tt);
6698 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6700 t = fold_build2 (PLUS_EXPR, itype, s0, q);
6701 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
6703 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
6704 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6706 /* Remove the GIMPLE_OMP_FOR statement. */
6707 gsi_remove (&gsi, true);
6709 /* Setup code for sequential iteration goes in SEQ_START_BB. */
6710 gsi = gsi_start_bb (seq_start_bb);
6712 tree startvar = fd->loop.v;
6713 tree endvar = NULL_TREE;
6715 if (gimple_omp_for_combined_p (fd->for_stmt))
6717 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
6718 ? gimple_omp_parallel_clauses (inner_stmt)
6719 : gimple_omp_for_clauses (inner_stmt);
6720 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6721 gcc_assert (innerc);
6722 startvar = OMP_CLAUSE_DECL (innerc);
6723 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
6724 OMP_CLAUSE__LOOPTEMP_);
6725 gcc_assert (innerc);
6726 endvar = OMP_CLAUSE_DECL (innerc);
6728 t = fold_convert (itype, s0);
6729 t = fold_build2 (MULT_EXPR, itype, t, step);
6730 if (POINTER_TYPE_P (type))
6731 t = fold_build_pointer_plus (n1, t);
6732 else
6733 t = fold_build2 (PLUS_EXPR, type, t, n1);
6734 t = fold_convert (TREE_TYPE (startvar), t);
6735 t = force_gimple_operand_gsi (&gsi, t,
6736 DECL_P (startvar)
6737 && TREE_ADDRESSABLE (startvar),
6738 NULL_TREE, false, GSI_CONTINUE_LINKING);
6739 assign_stmt = gimple_build_assign (startvar, t);
6740 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6742 t = fold_convert (itype, e0);
6743 t = fold_build2 (MULT_EXPR, itype, t, step);
6744 if (POINTER_TYPE_P (type))
6745 t = fold_build_pointer_plus (n1, t);
6746 else
6747 t = fold_build2 (PLUS_EXPR, type, t, n1);
6748 t = fold_convert (TREE_TYPE (startvar), t);
6749 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6750 false, GSI_CONTINUE_LINKING);
6751 if (endvar)
6753 assign_stmt = gimple_build_assign (endvar, e);
6754 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6755 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
6756 assign_stmt = gimple_build_assign (fd->loop.v, e);
6757 else
6758 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
6759 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
6761 if (fd->collapse > 1)
6762 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
6764 if (!broken_loop)
6766 /* The code controlling the sequential loop replaces the
6767 GIMPLE_OMP_CONTINUE. */
6768 gsi = gsi_last_bb (cont_bb);
6769 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
6770 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
6771 vmain = gimple_omp_continue_control_use (cont_stmt);
6772 vback = gimple_omp_continue_control_def (cont_stmt);
6774 if (!gimple_omp_for_combined_p (fd->for_stmt))
6776 if (POINTER_TYPE_P (type))
6777 t = fold_build_pointer_plus (vmain, step);
6778 else
6779 t = fold_build2 (PLUS_EXPR, type, vmain, step);
6780 t = force_gimple_operand_gsi (&gsi, t,
6781 DECL_P (vback)
6782 && TREE_ADDRESSABLE (vback),
6783 NULL_TREE, true, GSI_SAME_STMT);
6784 assign_stmt = gimple_build_assign (vback, t);
6785 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
6787 t = build2 (fd->loop.cond_code, boolean_type_node,
6788 DECL_P (vback) && TREE_ADDRESSABLE (vback)
6789 ? t : vback, e);
6790 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
6793 /* Remove the GIMPLE_OMP_CONTINUE statement. */
6794 gsi_remove (&gsi, true);
6796 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
6797 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
6800 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
6801 gsi = gsi_last_bb (exit_bb);
6802 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
6804 t = gimple_omp_return_lhs (gsi_stmt (gsi));
6805 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
6806 gcc_checking_assert (t == NULL_TREE);
6807 else
6808 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
6810 gsi_remove (&gsi, true);
6812 /* Connect all the blocks. */
6813 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
6814 ep->probability = REG_BR_PROB_BASE / 4 * 3;
6815 ep = find_edge (entry_bb, second_bb);
6816 ep->flags = EDGE_TRUE_VALUE;
6817 ep->probability = REG_BR_PROB_BASE / 4;
6818 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
6819 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
6821 if (!broken_loop)
6823 ep = find_edge (cont_bb, body_bb);
6824 if (gimple_omp_for_combined_p (fd->for_stmt))
6826 remove_edge (ep);
6827 ep = NULL;
6829 else if (fd->collapse > 1)
6831 remove_edge (ep);
6832 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
6834 else
6835 ep->flags = EDGE_TRUE_VALUE;
6836 find_edge (cont_bb, fin_bb)->flags
6837 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
6840 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
6841 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
6842 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
6844 set_immediate_dominator (CDI_DOMINATORS, body_bb,
6845 recompute_dominator (CDI_DOMINATORS, body_bb));
6846 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
6847 recompute_dominator (CDI_DOMINATORS, fin_bb));
6849 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
6851 struct loop *loop = alloc_loop ();
6852 loop->header = body_bb;
6853 if (collapse_bb == NULL)
6854 loop->latch = cont_bb;
6855 add_loop (loop, body_bb->loop_father);
6860 /* A subroutine of expand_omp_for. Generate code for a parallel
6861 loop with static schedule and a specified chunk size. Given
6862 parameters:
6864 for (V = N1; V cond N2; V += STEP) BODY;
6866 where COND is "<" or ">", we generate pseudocode
6868 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
6869 if (cond is <)
6870 adj = STEP - 1;
6871 else
6872 adj = STEP + 1;
6873 if ((__typeof (V)) -1 > 0 && cond is >)
6874 n = -(adj + N2 - N1) / -STEP;
6875 else
6876 n = (adj + N2 - N1) / STEP;
6877 trip = 0;
6878 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
6879 here so that V is defined
6880 if the loop is not entered
6882 s0 = (trip * nthreads + threadid) * CHUNK;
6883 e0 = min(s0 + CHUNK, n);
6884 if (s0 < n) goto L1; else goto L4;
6886 V = s0 * STEP + N1;
6887 e = e0 * STEP + N1;
6889 BODY;
6890 V += STEP;
6891 if (V cond e) goto L2; else goto L3;
6893 trip += 1;
6894 goto L0;
6898 static void
6899 expand_omp_for_static_chunk (struct omp_region *region,
6900 struct omp_for_data *fd, gimple inner_stmt)
6902 tree n, s0, e0, e, t;
6903 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
6904 tree type, itype, vmain, vback, vextra;
6905 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
6906 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
6907 gimple_stmt_iterator gsi;
6908 edge se;
6909 bool broken_loop = region->cont == NULL;
6910 tree *counts = NULL;
6911 tree n1, n2, step;
6913 gcc_checking_assert ((gimple_omp_for_kind (fd->for_stmt)
6914 != GF_OMP_FOR_KIND_OACC_LOOP)
6915 || !inner_stmt);
6917 itype = type = TREE_TYPE (fd->loop.v);
6918 if (POINTER_TYPE_P (type))
6919 itype = signed_type_for (type);
6921 entry_bb = region->entry;
6922 se = split_block (entry_bb, last_stmt (entry_bb));
6923 entry_bb = se->src;
6924 iter_part_bb = se->dest;
6925 cont_bb = region->cont;
6926 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
6927 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
6928 gcc_assert (broken_loop
6929 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
6930 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
6931 body_bb = single_succ (seq_start_bb);
6932 if (!broken_loop)
6934 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
6935 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
6936 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
6938 exit_bb = region->exit;
6940 /* Trip and adjustment setup goes in ENTRY_BB. */
6941 gsi = gsi_last_bb (entry_bb);
6942 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
6944 if (fd->collapse > 1)
6946 int first_zero_iter = -1;
6947 basic_block l2_dom_bb = NULL;
6949 counts = XALLOCAVEC (tree, fd->collapse);
6950 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
6951 fin_bb, first_zero_iter,
6952 l2_dom_bb);
6953 t = NULL_TREE;
6955 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
6956 t = integer_one_node;
6957 else
6958 t = fold_binary (fd->loop.cond_code, boolean_type_node,
6959 fold_convert (type, fd->loop.n1),
6960 fold_convert (type, fd->loop.n2));
6961 if (fd->collapse == 1
6962 && TYPE_UNSIGNED (type)
6963 && (t == NULL_TREE || !integer_onep (t)))
6965 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
6966 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
6967 true, GSI_SAME_STMT);
6968 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
6969 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
6970 true, GSI_SAME_STMT);
6971 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
6972 NULL_TREE, NULL_TREE);
6973 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
6974 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
6975 expand_omp_regimplify_p, NULL, NULL)
6976 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
6977 expand_omp_regimplify_p, NULL, NULL))
6979 gsi = gsi_for_stmt (cond_stmt);
6980 gimple_regimplify_operands (cond_stmt, &gsi);
6982 se = split_block (entry_bb, cond_stmt);
6983 se->flags = EDGE_TRUE_VALUE;
6984 entry_bb = se->dest;
6985 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
6986 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
6987 se->probability = REG_BR_PROB_BASE / 2000 - 1;
6988 if (gimple_in_ssa_p (cfun))
6990 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
6991 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
6992 !gsi_end_p (gpi); gsi_next (&gpi))
6994 gphi *phi = gpi.phi ();
6995 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
6996 se, UNKNOWN_LOCATION);
6999 gsi = gsi_last_bb (entry_bb);
7002 switch (gimple_omp_for_kind (fd->for_stmt))
7004 case GF_OMP_FOR_KIND_FOR:
7005 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7006 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7007 break;
7008 case GF_OMP_FOR_KIND_DISTRIBUTE:
7009 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
7010 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
7011 break;
7012 case GF_OMP_FOR_KIND_OACC_LOOP:
7013 nthreads = builtin_decl_explicit (BUILT_IN_GOACC_GET_NUM_THREADS);
7014 threadid = builtin_decl_explicit (BUILT_IN_GOACC_GET_THREAD_NUM);
7015 break;
7016 default:
7017 gcc_unreachable ();
7019 nthreads = build_call_expr (nthreads, 0);
7020 nthreads = fold_convert (itype, nthreads);
7021 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
7022 true, GSI_SAME_STMT);
7023 threadid = build_call_expr (threadid, 0);
7024 threadid = fold_convert (itype, threadid);
7025 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
7026 true, GSI_SAME_STMT);
7028 n1 = fd->loop.n1;
7029 n2 = fd->loop.n2;
7030 step = fd->loop.step;
7031 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7033 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7034 OMP_CLAUSE__LOOPTEMP_);
7035 gcc_assert (innerc);
7036 n1 = OMP_CLAUSE_DECL (innerc);
7037 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7038 OMP_CLAUSE__LOOPTEMP_);
7039 gcc_assert (innerc);
7040 n2 = OMP_CLAUSE_DECL (innerc);
7042 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
7043 true, NULL_TREE, true, GSI_SAME_STMT);
7044 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
7045 true, NULL_TREE, true, GSI_SAME_STMT);
7046 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
7047 true, NULL_TREE, true, GSI_SAME_STMT);
7048 fd->chunk_size
7049 = force_gimple_operand_gsi (&gsi, fold_convert (itype, fd->chunk_size),
7050 true, NULL_TREE, true, GSI_SAME_STMT);
7052 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
7053 t = fold_build2 (PLUS_EXPR, itype, step, t);
7054 t = fold_build2 (PLUS_EXPR, itype, t, n2);
7055 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
7056 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
7057 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7058 fold_build1 (NEGATE_EXPR, itype, t),
7059 fold_build1 (NEGATE_EXPR, itype, step));
7060 else
7061 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
7062 t = fold_convert (itype, t);
7063 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7064 true, GSI_SAME_STMT);
7066 trip_var = create_tmp_reg (itype, ".trip");
7067 if (gimple_in_ssa_p (cfun))
7069 trip_init = make_ssa_name (trip_var);
7070 trip_main = make_ssa_name (trip_var);
7071 trip_back = make_ssa_name (trip_var);
7073 else
7075 trip_init = trip_var;
7076 trip_main = trip_var;
7077 trip_back = trip_var;
7080 gassign *assign_stmt
7081 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
7082 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7084 t = fold_build2 (MULT_EXPR, itype, threadid, fd->chunk_size);
7085 t = fold_build2 (MULT_EXPR, itype, t, step);
7086 if (POINTER_TYPE_P (type))
7087 t = fold_build_pointer_plus (n1, t);
7088 else
7089 t = fold_build2 (PLUS_EXPR, type, t, n1);
7090 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7091 true, GSI_SAME_STMT);
7093 /* Remove the GIMPLE_OMP_FOR. */
7094 gsi_remove (&gsi, true);
7096 /* Iteration space partitioning goes in ITER_PART_BB. */
7097 gsi = gsi_last_bb (iter_part_bb);
7099 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
7100 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
7101 t = fold_build2 (MULT_EXPR, itype, t, fd->chunk_size);
7102 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7103 false, GSI_CONTINUE_LINKING);
7105 t = fold_build2 (PLUS_EXPR, itype, s0, fd->chunk_size);
7106 t = fold_build2 (MIN_EXPR, itype, t, n);
7107 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7108 false, GSI_CONTINUE_LINKING);
7110 t = build2 (LT_EXPR, boolean_type_node, s0, n);
7111 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
7113 /* Setup code for sequential iteration goes in SEQ_START_BB. */
7114 gsi = gsi_start_bb (seq_start_bb);
7116 tree startvar = fd->loop.v;
7117 tree endvar = NULL_TREE;
7119 if (gimple_omp_for_combined_p (fd->for_stmt))
7121 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
7122 ? gimple_omp_parallel_clauses (inner_stmt)
7123 : gimple_omp_for_clauses (inner_stmt);
7124 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7125 gcc_assert (innerc);
7126 startvar = OMP_CLAUSE_DECL (innerc);
7127 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7128 OMP_CLAUSE__LOOPTEMP_);
7129 gcc_assert (innerc);
7130 endvar = OMP_CLAUSE_DECL (innerc);
7133 t = fold_convert (itype, s0);
7134 t = fold_build2 (MULT_EXPR, itype, t, step);
7135 if (POINTER_TYPE_P (type))
7136 t = fold_build_pointer_plus (n1, t);
7137 else
7138 t = fold_build2 (PLUS_EXPR, type, t, n1);
7139 t = fold_convert (TREE_TYPE (startvar), t);
7140 t = force_gimple_operand_gsi (&gsi, t,
7141 DECL_P (startvar)
7142 && TREE_ADDRESSABLE (startvar),
7143 NULL_TREE, false, GSI_CONTINUE_LINKING);
7144 assign_stmt = gimple_build_assign (startvar, t);
7145 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7147 t = fold_convert (itype, e0);
7148 t = fold_build2 (MULT_EXPR, itype, t, step);
7149 if (POINTER_TYPE_P (type))
7150 t = fold_build_pointer_plus (n1, t);
7151 else
7152 t = fold_build2 (PLUS_EXPR, type, t, n1);
7153 t = fold_convert (TREE_TYPE (startvar), t);
7154 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7155 false, GSI_CONTINUE_LINKING);
7156 if (endvar)
7158 assign_stmt = gimple_build_assign (endvar, e);
7159 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7160 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
7161 assign_stmt = gimple_build_assign (fd->loop.v, e);
7162 else
7163 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
7164 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7166 if (fd->collapse > 1)
7167 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
7169 if (!broken_loop)
7171 /* The code controlling the sequential loop goes in CONT_BB,
7172 replacing the GIMPLE_OMP_CONTINUE. */
7173 gsi = gsi_last_bb (cont_bb);
7174 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
7175 vmain = gimple_omp_continue_control_use (cont_stmt);
7176 vback = gimple_omp_continue_control_def (cont_stmt);
7178 if (!gimple_omp_for_combined_p (fd->for_stmt))
7180 if (POINTER_TYPE_P (type))
7181 t = fold_build_pointer_plus (vmain, step);
7182 else
7183 t = fold_build2 (PLUS_EXPR, type, vmain, step);
7184 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
7185 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7186 true, GSI_SAME_STMT);
7187 assign_stmt = gimple_build_assign (vback, t);
7188 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
7190 t = build2 (fd->loop.cond_code, boolean_type_node,
7191 DECL_P (vback) && TREE_ADDRESSABLE (vback)
7192 ? t : vback, e);
7193 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
7196 /* Remove GIMPLE_OMP_CONTINUE. */
7197 gsi_remove (&gsi, true);
7199 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
7200 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
7202 /* Trip update code goes into TRIP_UPDATE_BB. */
7203 gsi = gsi_start_bb (trip_update_bb);
7205 t = build_int_cst (itype, 1);
7206 t = build2 (PLUS_EXPR, itype, trip_main, t);
7207 assign_stmt = gimple_build_assign (trip_back, t);
7208 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
7211 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
7212 gsi = gsi_last_bb (exit_bb);
7213 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
7215 t = gimple_omp_return_lhs (gsi_stmt (gsi));
7216 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
7217 gcc_checking_assert (t == NULL_TREE);
7218 else
7219 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
7221 gsi_remove (&gsi, true);
7223 /* Connect the new blocks. */
7224 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
7225 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
7227 if (!broken_loop)
7229 se = find_edge (cont_bb, body_bb);
7230 if (gimple_omp_for_combined_p (fd->for_stmt))
7232 remove_edge (se);
7233 se = NULL;
7235 else if (fd->collapse > 1)
7237 remove_edge (se);
7238 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
7240 else
7241 se->flags = EDGE_TRUE_VALUE;
7242 find_edge (cont_bb, trip_update_bb)->flags
7243 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
7245 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
7248 if (gimple_in_ssa_p (cfun))
7250 gphi_iterator psi;
7251 gphi *phi;
7252 edge re, ene;
7253 edge_var_map *vm;
7254 size_t i;
7256 gcc_assert (fd->collapse == 1 && !broken_loop);
7258 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
7259 remove arguments of the phi nodes in fin_bb. We need to create
7260 appropriate phi nodes in iter_part_bb instead. */
7261 se = single_pred_edge (fin_bb);
7262 re = single_succ_edge (trip_update_bb);
7263 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
7264 ene = single_succ_edge (entry_bb);
7266 psi = gsi_start_phis (fin_bb);
7267 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
7268 gsi_next (&psi), ++i)
7270 gphi *nphi;
7271 source_location locus;
7273 phi = psi.phi ();
7274 t = gimple_phi_result (phi);
7275 gcc_assert (t == redirect_edge_var_map_result (vm));
7276 nphi = create_phi_node (t, iter_part_bb);
7278 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
7279 locus = gimple_phi_arg_location_from_edge (phi, se);
7281 /* A special case -- fd->loop.v is not yet computed in
7282 iter_part_bb, we need to use vextra instead. */
7283 if (t == fd->loop.v)
7284 t = vextra;
7285 add_phi_arg (nphi, t, ene, locus);
7286 locus = redirect_edge_var_map_location (vm);
7287 add_phi_arg (nphi, redirect_edge_var_map_def (vm), re, locus);
7289 gcc_assert (gsi_end_p (psi) && i == head->length ());
7290 redirect_edge_var_map_clear (re);
7291 while (1)
7293 psi = gsi_start_phis (fin_bb);
7294 if (gsi_end_p (psi))
7295 break;
7296 remove_phi_node (&psi, false);
7299 /* Make phi node for trip. */
7300 phi = create_phi_node (trip_main, iter_part_bb);
7301 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
7302 UNKNOWN_LOCATION);
7303 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
7304 UNKNOWN_LOCATION);
7307 if (!broken_loop)
7308 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
7309 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
7310 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
7311 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
7312 recompute_dominator (CDI_DOMINATORS, fin_bb));
7313 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
7314 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
7315 set_immediate_dominator (CDI_DOMINATORS, body_bb,
7316 recompute_dominator (CDI_DOMINATORS, body_bb));
7318 if (!broken_loop)
7320 struct loop *trip_loop = alloc_loop ();
7321 trip_loop->header = iter_part_bb;
7322 trip_loop->latch = trip_update_bb;
7323 add_loop (trip_loop, iter_part_bb->loop_father);
7325 if (!gimple_omp_for_combined_p (fd->for_stmt))
7327 struct loop *loop = alloc_loop ();
7328 loop->header = body_bb;
7329 if (collapse_bb == NULL)
7330 loop->latch = cont_bb;
7331 add_loop (loop, trip_loop);
7336 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
7337 Given parameters:
7338 for (V = N1; V cond N2; V += STEP) BODY;
7340 where COND is "<" or ">" or "!=", we generate pseudocode
7342 for (ind_var = low; ind_var < high; ind_var++)
7344 V = n1 + (ind_var * STEP)
7346 <BODY>
7349 In the above pseudocode, low and high are function parameters of the
7350 child function. In the function below, we are inserting a temp.
7351 variable that will be making a call to two OMP functions that will not be
7352 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
7353 with _Cilk_for). These functions are replaced with low and high
7354 by the function that handles taskreg. */
7357 static void
7358 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
7360 bool broken_loop = region->cont == NULL;
7361 basic_block entry_bb = region->entry;
7362 basic_block cont_bb = region->cont;
7364 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7365 gcc_assert (broken_loop
7366 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7367 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7368 basic_block l1_bb, l2_bb;
7370 if (!broken_loop)
7372 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7373 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7374 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7375 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7377 else
7379 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7380 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7381 l2_bb = single_succ (l1_bb);
7383 basic_block exit_bb = region->exit;
7384 basic_block l2_dom_bb = NULL;
7386 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
7388 /* Below statements until the "tree high_val = ..." are pseudo statements
7389 used to pass information to be used by expand_omp_taskreg.
7390 low_val and high_val will be replaced by the __low and __high
7391 parameter from the child function.
7393 The call_exprs part is a place-holder, it is mainly used
7394 to distinctly identify to the top-level part that this is
7395 where we should put low and high (reasoning given in header
7396 comment). */
7398 tree child_fndecl
7399 = gimple_omp_parallel_child_fn (
7400 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
7401 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
7402 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
7404 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
7405 high_val = t;
7406 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
7407 low_val = t;
7409 gcc_assert (low_val && high_val);
7411 tree type = TREE_TYPE (low_val);
7412 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
7413 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7415 /* Not needed in SSA form right now. */
7416 gcc_assert (!gimple_in_ssa_p (cfun));
7417 if (l2_dom_bb == NULL)
7418 l2_dom_bb = l1_bb;
7420 tree n1 = low_val;
7421 tree n2 = high_val;
7423 gimple stmt = gimple_build_assign (ind_var, n1);
7425 /* Replace the GIMPLE_OMP_FOR statement. */
7426 gsi_replace (&gsi, stmt, true);
7428 if (!broken_loop)
7430 /* Code to control the increment goes in the CONT_BB. */
7431 gsi = gsi_last_bb (cont_bb);
7432 stmt = gsi_stmt (gsi);
7433 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7434 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
7435 build_one_cst (type));
7437 /* Replace GIMPLE_OMP_CONTINUE. */
7438 gsi_replace (&gsi, stmt, true);
7441 /* Emit the condition in L1_BB. */
7442 gsi = gsi_after_labels (l1_bb);
7443 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
7444 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
7445 fd->loop.step);
7446 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
7447 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7448 fd->loop.n1, fold_convert (sizetype, t));
7449 else
7450 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
7451 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
7452 t = fold_convert (TREE_TYPE (fd->loop.v), t);
7453 expand_omp_build_assign (&gsi, fd->loop.v, t);
7455 /* The condition is always '<' since the runtime will fill in the low
7456 and high values. */
7457 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
7458 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
7460 /* Remove GIMPLE_OMP_RETURN. */
7461 gsi = gsi_last_bb (exit_bb);
7462 gsi_remove (&gsi, true);
7464 /* Connect the new blocks. */
7465 remove_edge (FALLTHRU_EDGE (entry_bb));
7467 edge e, ne;
7468 if (!broken_loop)
7470 remove_edge (BRANCH_EDGE (entry_bb));
7471 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7473 e = BRANCH_EDGE (l1_bb);
7474 ne = FALLTHRU_EDGE (l1_bb);
7475 e->flags = EDGE_TRUE_VALUE;
7477 else
7479 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7481 ne = single_succ_edge (l1_bb);
7482 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7485 ne->flags = EDGE_FALSE_VALUE;
7486 e->probability = REG_BR_PROB_BASE * 7 / 8;
7487 ne->probability = REG_BR_PROB_BASE / 8;
7489 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7490 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7491 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7493 if (!broken_loop)
7495 struct loop *loop = alloc_loop ();
7496 loop->header = l1_bb;
7497 loop->latch = cont_bb;
7498 add_loop (loop, l1_bb->loop_father);
7499 loop->safelen = INT_MAX;
7502 /* Pick the correct library function based on the precision of the
7503 induction variable type. */
7504 tree lib_fun = NULL_TREE;
7505 if (TYPE_PRECISION (type) == 32)
7506 lib_fun = cilk_for_32_fndecl;
7507 else if (TYPE_PRECISION (type) == 64)
7508 lib_fun = cilk_for_64_fndecl;
7509 else
7510 gcc_unreachable ();
7512 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
7514 /* WS_ARGS contains the library function flavor to call:
7515 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
7516 user-defined grain value. If the user does not define one, then zero
7517 is passed in by the parser. */
7518 vec_alloc (region->ws_args, 2);
7519 region->ws_args->quick_push (lib_fun);
7520 region->ws_args->quick_push (fd->chunk_size);
7523 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
7524 loop. Given parameters:
7526 for (V = N1; V cond N2; V += STEP) BODY;
7528 where COND is "<" or ">", we generate pseudocode
7530 V = N1;
7531 goto L1;
7533 BODY;
7534 V += STEP;
7536 if (V cond N2) goto L0; else goto L2;
7539 For collapsed loops, given parameters:
7540 collapse(3)
7541 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
7542 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
7543 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
7544 BODY;
7546 we generate pseudocode
7548 if (cond3 is <)
7549 adj = STEP3 - 1;
7550 else
7551 adj = STEP3 + 1;
7552 count3 = (adj + N32 - N31) / STEP3;
7553 if (cond2 is <)
7554 adj = STEP2 - 1;
7555 else
7556 adj = STEP2 + 1;
7557 count2 = (adj + N22 - N21) / STEP2;
7558 if (cond1 is <)
7559 adj = STEP1 - 1;
7560 else
7561 adj = STEP1 + 1;
7562 count1 = (adj + N12 - N11) / STEP1;
7563 count = count1 * count2 * count3;
7564 V = 0;
7565 V1 = N11;
7566 V2 = N21;
7567 V3 = N31;
7568 goto L1;
7570 BODY;
7571 V += 1;
7572 V3 += STEP3;
7573 V2 += (V3 cond3 N32) ? 0 : STEP2;
7574 V3 = (V3 cond3 N32) ? V3 : N31;
7575 V1 += (V2 cond2 N22) ? 0 : STEP1;
7576 V2 = (V2 cond2 N22) ? V2 : N21;
7578 if (V < count) goto L0; else goto L2;
7583 static void
7584 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
7586 tree type, t;
7587 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
7588 gimple_stmt_iterator gsi;
7589 gimple stmt;
7590 gcond *cond_stmt;
7591 bool broken_loop = region->cont == NULL;
7592 edge e, ne;
7593 tree *counts = NULL;
7594 int i;
7595 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7596 OMP_CLAUSE_SAFELEN);
7597 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7598 OMP_CLAUSE__SIMDUID_);
7599 tree n1, n2;
7601 type = TREE_TYPE (fd->loop.v);
7602 entry_bb = region->entry;
7603 cont_bb = region->cont;
7604 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
7605 gcc_assert (broken_loop
7606 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
7607 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
7608 if (!broken_loop)
7610 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
7611 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
7612 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
7613 l2_bb = BRANCH_EDGE (entry_bb)->dest;
7615 else
7617 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
7618 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
7619 l2_bb = single_succ (l1_bb);
7621 exit_bb = region->exit;
7622 l2_dom_bb = NULL;
7624 gsi = gsi_last_bb (entry_bb);
7626 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
7627 /* Not needed in SSA form right now. */
7628 gcc_assert (!gimple_in_ssa_p (cfun));
7629 if (fd->collapse > 1)
7631 int first_zero_iter = -1;
7632 basic_block zero_iter_bb = l2_bb;
7634 counts = XALLOCAVEC (tree, fd->collapse);
7635 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
7636 zero_iter_bb, first_zero_iter,
7637 l2_dom_bb);
7639 if (l2_dom_bb == NULL)
7640 l2_dom_bb = l1_bb;
7642 n1 = fd->loop.n1;
7643 n2 = fd->loop.n2;
7644 if (gimple_omp_for_combined_into_p (fd->for_stmt))
7646 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7647 OMP_CLAUSE__LOOPTEMP_);
7648 gcc_assert (innerc);
7649 n1 = OMP_CLAUSE_DECL (innerc);
7650 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7651 OMP_CLAUSE__LOOPTEMP_);
7652 gcc_assert (innerc);
7653 n2 = OMP_CLAUSE_DECL (innerc);
7654 expand_omp_build_assign (&gsi, fd->loop.v,
7655 fold_convert (type, n1));
7656 if (fd->collapse > 1)
7658 gsi_prev (&gsi);
7659 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
7660 gsi_next (&gsi);
7663 else
7665 expand_omp_build_assign (&gsi, fd->loop.v,
7666 fold_convert (type, fd->loop.n1));
7667 if (fd->collapse > 1)
7668 for (i = 0; i < fd->collapse; i++)
7670 tree itype = TREE_TYPE (fd->loops[i].v);
7671 if (POINTER_TYPE_P (itype))
7672 itype = signed_type_for (itype);
7673 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
7674 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7678 /* Remove the GIMPLE_OMP_FOR statement. */
7679 gsi_remove (&gsi, true);
7681 if (!broken_loop)
7683 /* Code to control the increment goes in the CONT_BB. */
7684 gsi = gsi_last_bb (cont_bb);
7685 stmt = gsi_stmt (gsi);
7686 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
7688 if (POINTER_TYPE_P (type))
7689 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
7690 else
7691 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
7692 expand_omp_build_assign (&gsi, fd->loop.v, t);
7694 if (fd->collapse > 1)
7696 i = fd->collapse - 1;
7697 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7699 t = fold_convert (sizetype, fd->loops[i].step);
7700 t = fold_build_pointer_plus (fd->loops[i].v, t);
7702 else
7704 t = fold_convert (TREE_TYPE (fd->loops[i].v),
7705 fd->loops[i].step);
7706 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7707 fd->loops[i].v, t);
7709 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7711 for (i = fd->collapse - 1; i > 0; i--)
7713 tree itype = TREE_TYPE (fd->loops[i].v);
7714 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
7715 if (POINTER_TYPE_P (itype2))
7716 itype2 = signed_type_for (itype2);
7717 t = build3 (COND_EXPR, itype2,
7718 build2 (fd->loops[i].cond_code, boolean_type_node,
7719 fd->loops[i].v,
7720 fold_convert (itype, fd->loops[i].n2)),
7721 build_int_cst (itype2, 0),
7722 fold_convert (itype2, fd->loops[i - 1].step));
7723 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
7724 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
7725 else
7726 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
7727 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
7729 t = build3 (COND_EXPR, itype,
7730 build2 (fd->loops[i].cond_code, boolean_type_node,
7731 fd->loops[i].v,
7732 fold_convert (itype, fd->loops[i].n2)),
7733 fd->loops[i].v,
7734 fold_convert (itype, fd->loops[i].n1));
7735 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
7739 /* Remove GIMPLE_OMP_CONTINUE. */
7740 gsi_remove (&gsi, true);
7743 /* Emit the condition in L1_BB. */
7744 gsi = gsi_start_bb (l1_bb);
7746 t = fold_convert (type, n2);
7747 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7748 false, GSI_CONTINUE_LINKING);
7749 t = build2 (fd->loop.cond_code, boolean_type_node, fd->loop.v, t);
7750 cond_stmt = gimple_build_cond_empty (t);
7751 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
7752 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
7753 NULL, NULL)
7754 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
7755 NULL, NULL))
7757 gsi = gsi_for_stmt (cond_stmt);
7758 gimple_regimplify_operands (cond_stmt, &gsi);
7761 /* Remove GIMPLE_OMP_RETURN. */
7762 gsi = gsi_last_bb (exit_bb);
7763 gsi_remove (&gsi, true);
7765 /* Connect the new blocks. */
7766 remove_edge (FALLTHRU_EDGE (entry_bb));
7768 if (!broken_loop)
7770 remove_edge (BRANCH_EDGE (entry_bb));
7771 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
7773 e = BRANCH_EDGE (l1_bb);
7774 ne = FALLTHRU_EDGE (l1_bb);
7775 e->flags = EDGE_TRUE_VALUE;
7777 else
7779 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7781 ne = single_succ_edge (l1_bb);
7782 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
7785 ne->flags = EDGE_FALSE_VALUE;
7786 e->probability = REG_BR_PROB_BASE * 7 / 8;
7787 ne->probability = REG_BR_PROB_BASE / 8;
7789 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
7790 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
7791 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
7793 if (!broken_loop)
7795 struct loop *loop = alloc_loop ();
7796 loop->header = l1_bb;
7797 loop->latch = cont_bb;
7798 add_loop (loop, l1_bb->loop_father);
7799 if (safelen == NULL_TREE)
7800 loop->safelen = INT_MAX;
7801 else
7803 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
7804 if (TREE_CODE (safelen) != INTEGER_CST)
7805 loop->safelen = 0;
7806 else if (!tree_fits_uhwi_p (safelen)
7807 || tree_to_uhwi (safelen) > INT_MAX)
7808 loop->safelen = INT_MAX;
7809 else
7810 loop->safelen = tree_to_uhwi (safelen);
7811 if (loop->safelen == 1)
7812 loop->safelen = 0;
7814 if (simduid)
7816 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
7817 cfun->has_simduid_loops = true;
7819 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
7820 the loop. */
7821 if ((flag_tree_loop_vectorize
7822 || (!global_options_set.x_flag_tree_loop_vectorize
7823 && !global_options_set.x_flag_tree_vectorize))
7824 && flag_tree_loop_optimize
7825 && loop->safelen > 1)
7827 loop->force_vectorize = true;
7828 cfun->has_force_vectorize_loops = true;
7834 /* Expand the OMP loop defined by REGION. */
7836 static void
7837 expand_omp_for (struct omp_region *region, gimple inner_stmt)
7839 struct omp_for_data fd;
7840 struct omp_for_data_loop *loops;
7842 loops
7843 = (struct omp_for_data_loop *)
7844 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
7845 * sizeof (struct omp_for_data_loop));
7846 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
7847 &fd, loops);
7848 region->sched_kind = fd.sched_kind;
7850 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
7851 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7852 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
7853 if (region->cont)
7855 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
7856 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7857 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
7859 else
7860 /* If there isn't a continue then this is a degerate case where
7861 the introduction of abnormal edges during lowering will prevent
7862 original loops from being detected. Fix that up. */
7863 loops_state_set (LOOPS_NEED_FIXUP);
7865 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
7866 expand_omp_simd (region, &fd);
7867 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
7868 expand_cilk_for (region, &fd);
7869 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
7870 && !fd.have_ordered)
7872 if (fd.chunk_size == NULL)
7873 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
7874 else
7875 expand_omp_for_static_chunk (region, &fd, inner_stmt);
7877 else
7879 int fn_index, start_ix, next_ix;
7881 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
7882 == GF_OMP_FOR_KIND_FOR);
7883 if (fd.chunk_size == NULL
7884 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
7885 fd.chunk_size = integer_zero_node;
7886 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
7887 fn_index = (fd.sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
7888 ? 3 : fd.sched_kind;
7889 fn_index += fd.have_ordered * 4;
7890 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
7891 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
7892 if (fd.iter_type == long_long_unsigned_type_node)
7894 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
7895 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
7896 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
7897 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
7899 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
7900 (enum built_in_function) next_ix, inner_stmt);
7903 if (gimple_in_ssa_p (cfun))
7904 update_ssa (TODO_update_ssa_only_virtuals);
7908 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
7910 v = GOMP_sections_start (n);
7912 switch (v)
7914 case 0:
7915 goto L2;
7916 case 1:
7917 section 1;
7918 goto L1;
7919 case 2:
7921 case n:
7923 default:
7924 abort ();
7927 v = GOMP_sections_next ();
7928 goto L0;
7930 reduction;
7932 If this is a combined parallel sections, replace the call to
7933 GOMP_sections_start with call to GOMP_sections_next. */
7935 static void
7936 expand_omp_sections (struct omp_region *region)
7938 tree t, u, vin = NULL, vmain, vnext, l2;
7939 unsigned len;
7940 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
7941 gimple_stmt_iterator si, switch_si;
7942 gomp_sections *sections_stmt;
7943 gimple stmt;
7944 gomp_continue *cont;
7945 edge_iterator ei;
7946 edge e;
7947 struct omp_region *inner;
7948 unsigned i, casei;
7949 bool exit_reachable = region->cont != NULL;
7951 gcc_assert (region->exit != NULL);
7952 entry_bb = region->entry;
7953 l0_bb = single_succ (entry_bb);
7954 l1_bb = region->cont;
7955 l2_bb = region->exit;
7956 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
7957 l2 = gimple_block_label (l2_bb);
7958 else
7960 /* This can happen if there are reductions. */
7961 len = EDGE_COUNT (l0_bb->succs);
7962 gcc_assert (len > 0);
7963 e = EDGE_SUCC (l0_bb, len - 1);
7964 si = gsi_last_bb (e->dest);
7965 l2 = NULL_TREE;
7966 if (gsi_end_p (si)
7967 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7968 l2 = gimple_block_label (e->dest);
7969 else
7970 FOR_EACH_EDGE (e, ei, l0_bb->succs)
7972 si = gsi_last_bb (e->dest);
7973 if (gsi_end_p (si)
7974 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
7976 l2 = gimple_block_label (e->dest);
7977 break;
7981 if (exit_reachable)
7982 default_bb = create_empty_bb (l1_bb->prev_bb);
7983 else
7984 default_bb = create_empty_bb (l0_bb);
7986 /* We will build a switch() with enough cases for all the
7987 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
7988 and a default case to abort if something goes wrong. */
7989 len = EDGE_COUNT (l0_bb->succs);
7991 /* Use vec::quick_push on label_vec throughout, since we know the size
7992 in advance. */
7993 auto_vec<tree> label_vec (len);
7995 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
7996 GIMPLE_OMP_SECTIONS statement. */
7997 si = gsi_last_bb (entry_bb);
7998 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
7999 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
8000 vin = gimple_omp_sections_control (sections_stmt);
8001 if (!is_combined_parallel (region))
8003 /* If we are not inside a combined parallel+sections region,
8004 call GOMP_sections_start. */
8005 t = build_int_cst (unsigned_type_node, len - 1);
8006 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
8007 stmt = gimple_build_call (u, 1, t);
8009 else
8011 /* Otherwise, call GOMP_sections_next. */
8012 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8013 stmt = gimple_build_call (u, 0);
8015 gimple_call_set_lhs (stmt, vin);
8016 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8017 gsi_remove (&si, true);
8019 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
8020 L0_BB. */
8021 switch_si = gsi_last_bb (l0_bb);
8022 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
8023 if (exit_reachable)
8025 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
8026 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
8027 vmain = gimple_omp_continue_control_use (cont);
8028 vnext = gimple_omp_continue_control_def (cont);
8030 else
8032 vmain = vin;
8033 vnext = NULL_TREE;
8036 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
8037 label_vec.quick_push (t);
8038 i = 1;
8040 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
8041 for (inner = region->inner, casei = 1;
8042 inner;
8043 inner = inner->next, i++, casei++)
8045 basic_block s_entry_bb, s_exit_bb;
8047 /* Skip optional reduction region. */
8048 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
8050 --i;
8051 --casei;
8052 continue;
8055 s_entry_bb = inner->entry;
8056 s_exit_bb = inner->exit;
8058 t = gimple_block_label (s_entry_bb);
8059 u = build_int_cst (unsigned_type_node, casei);
8060 u = build_case_label (u, NULL, t);
8061 label_vec.quick_push (u);
8063 si = gsi_last_bb (s_entry_bb);
8064 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
8065 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
8066 gsi_remove (&si, true);
8067 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
8069 if (s_exit_bb == NULL)
8070 continue;
8072 si = gsi_last_bb (s_exit_bb);
8073 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8074 gsi_remove (&si, true);
8076 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
8079 /* Error handling code goes in DEFAULT_BB. */
8080 t = gimple_block_label (default_bb);
8081 u = build_case_label (NULL, NULL, t);
8082 make_edge (l0_bb, default_bb, 0);
8083 add_bb_to_loop (default_bb, current_loops->tree_root);
8085 stmt = gimple_build_switch (vmain, u, label_vec);
8086 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
8087 gsi_remove (&switch_si, true);
8089 si = gsi_start_bb (default_bb);
8090 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
8091 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
8093 if (exit_reachable)
8095 tree bfn_decl;
8097 /* Code to get the next section goes in L1_BB. */
8098 si = gsi_last_bb (l1_bb);
8099 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
8101 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
8102 stmt = gimple_build_call (bfn_decl, 0);
8103 gimple_call_set_lhs (stmt, vnext);
8104 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8105 gsi_remove (&si, true);
8107 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
8110 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
8111 si = gsi_last_bb (l2_bb);
8112 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
8113 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
8114 else if (gimple_omp_return_lhs (gsi_stmt (si)))
8115 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
8116 else
8117 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
8118 stmt = gimple_build_call (t, 0);
8119 if (gimple_omp_return_lhs (gsi_stmt (si)))
8120 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
8121 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
8122 gsi_remove (&si, true);
8124 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
8128 /* Expand code for an OpenMP single directive. We've already expanded
8129 much of the code, here we simply place the GOMP_barrier call. */
8131 static void
8132 expand_omp_single (struct omp_region *region)
8134 basic_block entry_bb, exit_bb;
8135 gimple_stmt_iterator si;
8137 entry_bb = region->entry;
8138 exit_bb = region->exit;
8140 si = gsi_last_bb (entry_bb);
8141 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
8142 gsi_remove (&si, true);
8143 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8145 si = gsi_last_bb (exit_bb);
8146 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
8148 tree t = gimple_omp_return_lhs (gsi_stmt (si));
8149 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
8151 gsi_remove (&si, true);
8152 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8156 /* Generic expansion for OpenMP synchronization directives: master,
8157 ordered and critical. All we need to do here is remove the entry
8158 and exit markers for REGION. */
8160 static void
8161 expand_omp_synch (struct omp_region *region)
8163 basic_block entry_bb, exit_bb;
8164 gimple_stmt_iterator si;
8166 entry_bb = region->entry;
8167 exit_bb = region->exit;
8169 si = gsi_last_bb (entry_bb);
8170 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
8171 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
8172 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
8173 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
8174 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
8175 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
8176 gsi_remove (&si, true);
8177 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8179 if (exit_bb)
8181 si = gsi_last_bb (exit_bb);
8182 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
8183 gsi_remove (&si, true);
8184 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
8188 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8189 operation as a normal volatile load. */
8191 static bool
8192 expand_omp_atomic_load (basic_block load_bb, tree addr,
8193 tree loaded_val, int index)
8195 enum built_in_function tmpbase;
8196 gimple_stmt_iterator gsi;
8197 basic_block store_bb;
8198 location_t loc;
8199 gimple stmt;
8200 tree decl, call, type, itype;
8202 gsi = gsi_last_bb (load_bb);
8203 stmt = gsi_stmt (gsi);
8204 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8205 loc = gimple_location (stmt);
8207 /* ??? If the target does not implement atomic_load_optab[mode], and mode
8208 is smaller than word size, then expand_atomic_load assumes that the load
8209 is atomic. We could avoid the builtin entirely in this case. */
8211 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8212 decl = builtin_decl_explicit (tmpbase);
8213 if (decl == NULL_TREE)
8214 return false;
8216 type = TREE_TYPE (loaded_val);
8217 itype = TREE_TYPE (TREE_TYPE (decl));
8219 call = build_call_expr_loc (loc, decl, 2, addr,
8220 build_int_cst (NULL,
8221 gimple_omp_atomic_seq_cst_p (stmt)
8222 ? MEMMODEL_SEQ_CST
8223 : MEMMODEL_RELAXED));
8224 if (!useless_type_conversion_p (type, itype))
8225 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8226 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8228 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8229 gsi_remove (&gsi, true);
8231 store_bb = single_succ (load_bb);
8232 gsi = gsi_last_bb (store_bb);
8233 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8234 gsi_remove (&gsi, true);
8236 if (gimple_in_ssa_p (cfun))
8237 update_ssa (TODO_update_ssa_no_phi);
8239 return true;
8242 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8243 operation as a normal volatile store. */
8245 static bool
8246 expand_omp_atomic_store (basic_block load_bb, tree addr,
8247 tree loaded_val, tree stored_val, int index)
8249 enum built_in_function tmpbase;
8250 gimple_stmt_iterator gsi;
8251 basic_block store_bb = single_succ (load_bb);
8252 location_t loc;
8253 gimple stmt;
8254 tree decl, call, type, itype;
8255 machine_mode imode;
8256 bool exchange;
8258 gsi = gsi_last_bb (load_bb);
8259 stmt = gsi_stmt (gsi);
8260 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
8262 /* If the load value is needed, then this isn't a store but an exchange. */
8263 exchange = gimple_omp_atomic_need_value_p (stmt);
8265 gsi = gsi_last_bb (store_bb);
8266 stmt = gsi_stmt (gsi);
8267 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
8268 loc = gimple_location (stmt);
8270 /* ??? If the target does not implement atomic_store_optab[mode], and mode
8271 is smaller than word size, then expand_atomic_store assumes that the store
8272 is atomic. We could avoid the builtin entirely in this case. */
8274 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
8275 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
8276 decl = builtin_decl_explicit (tmpbase);
8277 if (decl == NULL_TREE)
8278 return false;
8280 type = TREE_TYPE (stored_val);
8282 /* Dig out the type of the function's second argument. */
8283 itype = TREE_TYPE (decl);
8284 itype = TYPE_ARG_TYPES (itype);
8285 itype = TREE_CHAIN (itype);
8286 itype = TREE_VALUE (itype);
8287 imode = TYPE_MODE (itype);
8289 if (exchange && !can_atomic_exchange_p (imode, true))
8290 return false;
8292 if (!useless_type_conversion_p (itype, type))
8293 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
8294 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
8295 build_int_cst (NULL,
8296 gimple_omp_atomic_seq_cst_p (stmt)
8297 ? MEMMODEL_SEQ_CST
8298 : MEMMODEL_RELAXED));
8299 if (exchange)
8301 if (!useless_type_conversion_p (type, itype))
8302 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
8303 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
8306 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8307 gsi_remove (&gsi, true);
8309 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
8310 gsi = gsi_last_bb (load_bb);
8311 gsi_remove (&gsi, true);
8313 if (gimple_in_ssa_p (cfun))
8314 update_ssa (TODO_update_ssa_no_phi);
8316 return true;
8319 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
8320 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
8321 size of the data type, and thus usable to find the index of the builtin
8322 decl. Returns false if the expression is not of the proper form. */
8324 static bool
8325 expand_omp_atomic_fetch_op (basic_block load_bb,
8326 tree addr, tree loaded_val,
8327 tree stored_val, int index)
8329 enum built_in_function oldbase, newbase, tmpbase;
8330 tree decl, itype, call;
8331 tree lhs, rhs;
8332 basic_block store_bb = single_succ (load_bb);
8333 gimple_stmt_iterator gsi;
8334 gimple stmt;
8335 location_t loc;
8336 enum tree_code code;
8337 bool need_old, need_new;
8338 machine_mode imode;
8339 bool seq_cst;
8341 /* We expect to find the following sequences:
8343 load_bb:
8344 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
8346 store_bb:
8347 val = tmp OP something; (or: something OP tmp)
8348 GIMPLE_OMP_STORE (val)
8350 ???FIXME: Allow a more flexible sequence.
8351 Perhaps use data flow to pick the statements.
8355 gsi = gsi_after_labels (store_bb);
8356 stmt = gsi_stmt (gsi);
8357 loc = gimple_location (stmt);
8358 if (!is_gimple_assign (stmt))
8359 return false;
8360 gsi_next (&gsi);
8361 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
8362 return false;
8363 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
8364 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
8365 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
8366 gcc_checking_assert (!need_old || !need_new);
8368 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
8369 return false;
8371 /* Check for one of the supported fetch-op operations. */
8372 code = gimple_assign_rhs_code (stmt);
8373 switch (code)
8375 case PLUS_EXPR:
8376 case POINTER_PLUS_EXPR:
8377 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
8378 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
8379 break;
8380 case MINUS_EXPR:
8381 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
8382 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
8383 break;
8384 case BIT_AND_EXPR:
8385 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
8386 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
8387 break;
8388 case BIT_IOR_EXPR:
8389 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
8390 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
8391 break;
8392 case BIT_XOR_EXPR:
8393 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
8394 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
8395 break;
8396 default:
8397 return false;
8400 /* Make sure the expression is of the proper form. */
8401 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
8402 rhs = gimple_assign_rhs2 (stmt);
8403 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
8404 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
8405 rhs = gimple_assign_rhs1 (stmt);
8406 else
8407 return false;
8409 tmpbase = ((enum built_in_function)
8410 ((need_new ? newbase : oldbase) + index + 1));
8411 decl = builtin_decl_explicit (tmpbase);
8412 if (decl == NULL_TREE)
8413 return false;
8414 itype = TREE_TYPE (TREE_TYPE (decl));
8415 imode = TYPE_MODE (itype);
8417 /* We could test all of the various optabs involved, but the fact of the
8418 matter is that (with the exception of i486 vs i586 and xadd) all targets
8419 that support any atomic operaton optab also implements compare-and-swap.
8420 Let optabs.c take care of expanding any compare-and-swap loop. */
8421 if (!can_compare_and_swap_p (imode, true))
8422 return false;
8424 gsi = gsi_last_bb (load_bb);
8425 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
8427 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
8428 It only requires that the operation happen atomically. Thus we can
8429 use the RELAXED memory model. */
8430 call = build_call_expr_loc (loc, decl, 3, addr,
8431 fold_convert_loc (loc, itype, rhs),
8432 build_int_cst (NULL,
8433 seq_cst ? MEMMODEL_SEQ_CST
8434 : MEMMODEL_RELAXED));
8436 if (need_old || need_new)
8438 lhs = need_old ? loaded_val : stored_val;
8439 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
8440 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
8442 else
8443 call = fold_convert_loc (loc, void_type_node, call);
8444 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
8445 gsi_remove (&gsi, true);
8447 gsi = gsi_last_bb (store_bb);
8448 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
8449 gsi_remove (&gsi, true);
8450 gsi = gsi_last_bb (store_bb);
8451 gsi_remove (&gsi, true);
8453 if (gimple_in_ssa_p (cfun))
8454 update_ssa (TODO_update_ssa_no_phi);
8456 return true;
8459 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8461 oldval = *addr;
8462 repeat:
8463 newval = rhs; // with oldval replacing *addr in rhs
8464 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
8465 if (oldval != newval)
8466 goto repeat;
8468 INDEX is log2 of the size of the data type, and thus usable to find the
8469 index of the builtin decl. */
8471 static bool
8472 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
8473 tree addr, tree loaded_val, tree stored_val,
8474 int index)
8476 tree loadedi, storedi, initial, new_storedi, old_vali;
8477 tree type, itype, cmpxchg, iaddr;
8478 gimple_stmt_iterator si;
8479 basic_block loop_header = single_succ (load_bb);
8480 gimple phi, stmt;
8481 edge e;
8482 enum built_in_function fncode;
8484 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
8485 order to use the RELAXED memory model effectively. */
8486 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
8487 + index + 1);
8488 cmpxchg = builtin_decl_explicit (fncode);
8489 if (cmpxchg == NULL_TREE)
8490 return false;
8491 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8492 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
8494 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
8495 return false;
8497 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
8498 si = gsi_last_bb (load_bb);
8499 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8501 /* For floating-point values, we'll need to view-convert them to integers
8502 so that we can perform the atomic compare and swap. Simplify the
8503 following code by always setting up the "i"ntegral variables. */
8504 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
8506 tree iaddr_val;
8508 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
8509 true));
8510 iaddr_val
8511 = force_gimple_operand_gsi (&si,
8512 fold_convert (TREE_TYPE (iaddr), addr),
8513 false, NULL_TREE, true, GSI_SAME_STMT);
8514 stmt = gimple_build_assign (iaddr, iaddr_val);
8515 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8516 loadedi = create_tmp_var (itype);
8517 if (gimple_in_ssa_p (cfun))
8518 loadedi = make_ssa_name (loadedi);
8520 else
8522 iaddr = addr;
8523 loadedi = loaded_val;
8526 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
8527 tree loaddecl = builtin_decl_explicit (fncode);
8528 if (loaddecl)
8529 initial
8530 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
8531 build_call_expr (loaddecl, 2, iaddr,
8532 build_int_cst (NULL_TREE,
8533 MEMMODEL_RELAXED)));
8534 else
8535 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
8536 build_int_cst (TREE_TYPE (iaddr), 0));
8538 initial
8539 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
8540 GSI_SAME_STMT);
8542 /* Move the value to the LOADEDI temporary. */
8543 if (gimple_in_ssa_p (cfun))
8545 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
8546 phi = create_phi_node (loadedi, loop_header);
8547 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
8548 initial);
8550 else
8551 gsi_insert_before (&si,
8552 gimple_build_assign (loadedi, initial),
8553 GSI_SAME_STMT);
8554 if (loadedi != loaded_val)
8556 gimple_stmt_iterator gsi2;
8557 tree x;
8559 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
8560 gsi2 = gsi_start_bb (loop_header);
8561 if (gimple_in_ssa_p (cfun))
8563 gassign *stmt;
8564 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8565 true, GSI_SAME_STMT);
8566 stmt = gimple_build_assign (loaded_val, x);
8567 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
8569 else
8571 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
8572 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
8573 true, GSI_SAME_STMT);
8576 gsi_remove (&si, true);
8578 si = gsi_last_bb (store_bb);
8579 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8581 if (iaddr == addr)
8582 storedi = stored_val;
8583 else
8584 storedi =
8585 force_gimple_operand_gsi (&si,
8586 build1 (VIEW_CONVERT_EXPR, itype,
8587 stored_val), true, NULL_TREE, true,
8588 GSI_SAME_STMT);
8590 /* Build the compare&swap statement. */
8591 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
8592 new_storedi = force_gimple_operand_gsi (&si,
8593 fold_convert (TREE_TYPE (loadedi),
8594 new_storedi),
8595 true, NULL_TREE,
8596 true, GSI_SAME_STMT);
8598 if (gimple_in_ssa_p (cfun))
8599 old_vali = loadedi;
8600 else
8602 old_vali = create_tmp_var (TREE_TYPE (loadedi));
8603 stmt = gimple_build_assign (old_vali, loadedi);
8604 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8606 stmt = gimple_build_assign (loadedi, new_storedi);
8607 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8610 /* Note that we always perform the comparison as an integer, even for
8611 floating point. This allows the atomic operation to properly
8612 succeed even with NaNs and -0.0. */
8613 stmt = gimple_build_cond_empty
8614 (build2 (NE_EXPR, boolean_type_node,
8615 new_storedi, old_vali));
8616 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8618 /* Update cfg. */
8619 e = single_succ_edge (store_bb);
8620 e->flags &= ~EDGE_FALLTHRU;
8621 e->flags |= EDGE_FALSE_VALUE;
8623 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
8625 /* Copy the new value to loadedi (we already did that before the condition
8626 if we are not in SSA). */
8627 if (gimple_in_ssa_p (cfun))
8629 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
8630 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
8633 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
8634 gsi_remove (&si, true);
8636 struct loop *loop = alloc_loop ();
8637 loop->header = loop_header;
8638 loop->latch = store_bb;
8639 add_loop (loop, loop_header->loop_father);
8641 if (gimple_in_ssa_p (cfun))
8642 update_ssa (TODO_update_ssa_no_phi);
8644 return true;
8647 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
8649 GOMP_atomic_start ();
8650 *addr = rhs;
8651 GOMP_atomic_end ();
8653 The result is not globally atomic, but works so long as all parallel
8654 references are within #pragma omp atomic directives. According to
8655 responses received from omp@openmp.org, appears to be within spec.
8656 Which makes sense, since that's how several other compilers handle
8657 this situation as well.
8658 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
8659 expanding. STORED_VAL is the operand of the matching
8660 GIMPLE_OMP_ATOMIC_STORE.
8662 We replace
8663 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
8664 loaded_val = *addr;
8666 and replace
8667 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
8668 *addr = stored_val;
8671 static bool
8672 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
8673 tree addr, tree loaded_val, tree stored_val)
8675 gimple_stmt_iterator si;
8676 gassign *stmt;
8677 tree t;
8679 si = gsi_last_bb (load_bb);
8680 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
8682 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
8683 t = build_call_expr (t, 0);
8684 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8686 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
8687 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8688 gsi_remove (&si, true);
8690 si = gsi_last_bb (store_bb);
8691 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
8693 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
8694 stored_val);
8695 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
8697 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
8698 t = build_call_expr (t, 0);
8699 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
8700 gsi_remove (&si, true);
8702 if (gimple_in_ssa_p (cfun))
8703 update_ssa (TODO_update_ssa_no_phi);
8704 return true;
8707 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
8708 using expand_omp_atomic_fetch_op. If it failed, we try to
8709 call expand_omp_atomic_pipeline, and if it fails too, the
8710 ultimate fallback is wrapping the operation in a mutex
8711 (expand_omp_atomic_mutex). REGION is the atomic region built
8712 by build_omp_regions_1(). */
8714 static void
8715 expand_omp_atomic (struct omp_region *region)
8717 basic_block load_bb = region->entry, store_bb = region->exit;
8718 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
8719 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
8720 tree loaded_val = gimple_omp_atomic_load_lhs (load);
8721 tree addr = gimple_omp_atomic_load_rhs (load);
8722 tree stored_val = gimple_omp_atomic_store_val (store);
8723 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
8724 HOST_WIDE_INT index;
8726 /* Make sure the type is one of the supported sizes. */
8727 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
8728 index = exact_log2 (index);
8729 if (index >= 0 && index <= 4)
8731 unsigned int align = TYPE_ALIGN_UNIT (type);
8733 /* __sync builtins require strict data alignment. */
8734 if (exact_log2 (align) >= index)
8736 /* Atomic load. */
8737 if (loaded_val == stored_val
8738 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8739 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8740 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8741 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
8742 return;
8744 /* Atomic store. */
8745 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
8746 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
8747 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
8748 && store_bb == single_succ (load_bb)
8749 && first_stmt (store_bb) == store
8750 && expand_omp_atomic_store (load_bb, addr, loaded_val,
8751 stored_val, index))
8752 return;
8754 /* When possible, use specialized atomic update functions. */
8755 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
8756 && store_bb == single_succ (load_bb)
8757 && expand_omp_atomic_fetch_op (load_bb, addr,
8758 loaded_val, stored_val, index))
8759 return;
8761 /* If we don't have specialized __sync builtins, try and implement
8762 as a compare and swap loop. */
8763 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
8764 loaded_val, stored_val, index))
8765 return;
8769 /* The ultimate fallback is wrapping the operation in a mutex. */
8770 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
8774 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
8776 static void
8777 expand_omp_target (struct omp_region *region)
8779 basic_block entry_bb, exit_bb, new_bb;
8780 struct function *child_cfun;
8781 tree child_fn, block, t;
8782 gimple_stmt_iterator gsi;
8783 gomp_target *entry_stmt;
8784 gimple stmt;
8785 edge e;
8786 bool offloaded, data_region;
8788 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
8789 new_bb = region->entry;
8791 offloaded = is_gimple_omp_offloaded (entry_stmt);
8792 switch (gimple_omp_target_kind (entry_stmt))
8794 case GF_OMP_TARGET_KIND_REGION:
8795 case GF_OMP_TARGET_KIND_UPDATE:
8796 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
8797 case GF_OMP_TARGET_KIND_OACC_KERNELS:
8798 case GF_OMP_TARGET_KIND_OACC_UPDATE:
8799 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
8800 data_region = false;
8801 break;
8802 case GF_OMP_TARGET_KIND_DATA:
8803 case GF_OMP_TARGET_KIND_OACC_DATA:
8804 data_region = true;
8805 break;
8806 default:
8807 gcc_unreachable ();
8810 child_fn = NULL_TREE;
8811 child_cfun = NULL;
8812 if (offloaded)
8814 child_fn = gimple_omp_target_child_fn (entry_stmt);
8815 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
8818 /* Supported by expand_omp_taskreg, but not here. */
8819 if (child_cfun != NULL)
8820 gcc_checking_assert (!child_cfun->cfg);
8821 gcc_checking_assert (!gimple_in_ssa_p (cfun));
8823 entry_bb = region->entry;
8824 exit_bb = region->exit;
8826 if (offloaded)
8828 unsigned srcidx, dstidx, num;
8830 /* If the offloading region needs data sent from the parent
8831 function, then the very first statement (except possible
8832 tree profile counter updates) of the offloading body
8833 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
8834 &.OMP_DATA_O is passed as an argument to the child function,
8835 we need to replace it with the argument as seen by the child
8836 function.
8838 In most cases, this will end up being the identity assignment
8839 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
8840 a function call that has been inlined, the original PARM_DECL
8841 .OMP_DATA_I may have been converted into a different local
8842 variable. In which case, we need to keep the assignment. */
8843 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
8844 if (data_arg)
8846 basic_block entry_succ_bb = single_succ (entry_bb);
8847 gimple_stmt_iterator gsi;
8848 tree arg;
8849 gimple tgtcopy_stmt = NULL;
8850 tree sender = TREE_VEC_ELT (data_arg, 0);
8852 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
8854 gcc_assert (!gsi_end_p (gsi));
8855 stmt = gsi_stmt (gsi);
8856 if (gimple_code (stmt) != GIMPLE_ASSIGN)
8857 continue;
8859 if (gimple_num_ops (stmt) == 2)
8861 tree arg = gimple_assign_rhs1 (stmt);
8863 /* We're ignoring the subcode because we're
8864 effectively doing a STRIP_NOPS. */
8866 if (TREE_CODE (arg) == ADDR_EXPR
8867 && TREE_OPERAND (arg, 0) == sender)
8869 tgtcopy_stmt = stmt;
8870 break;
8875 gcc_assert (tgtcopy_stmt != NULL);
8876 arg = DECL_ARGUMENTS (child_fn);
8878 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
8879 gsi_remove (&gsi, true);
8882 /* Declare local variables needed in CHILD_CFUN. */
8883 block = DECL_INITIAL (child_fn);
8884 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
8885 /* The gimplifier could record temporaries in the offloading block
8886 rather than in containing function's local_decls chain,
8887 which would mean cgraph missed finalizing them. Do it now. */
8888 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
8889 if (TREE_CODE (t) == VAR_DECL
8890 && TREE_STATIC (t)
8891 && !DECL_EXTERNAL (t))
8892 varpool_node::finalize_decl (t);
8893 DECL_SAVED_TREE (child_fn) = NULL;
8894 /* We'll create a CFG for child_fn, so no gimple body is needed. */
8895 gimple_set_body (child_fn, NULL);
8896 TREE_USED (block) = 1;
8898 /* Reset DECL_CONTEXT on function arguments. */
8899 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
8900 DECL_CONTEXT (t) = child_fn;
8902 /* Split ENTRY_BB at GIMPLE_*,
8903 so that it can be moved to the child function. */
8904 gsi = gsi_last_bb (entry_bb);
8905 stmt = gsi_stmt (gsi);
8906 gcc_assert (stmt
8907 && gimple_code (stmt) == gimple_code (entry_stmt));
8908 gsi_remove (&gsi, true);
8909 e = split_block (entry_bb, stmt);
8910 entry_bb = e->dest;
8911 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
8913 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
8914 if (exit_bb)
8916 gsi = gsi_last_bb (exit_bb);
8917 gcc_assert (!gsi_end_p (gsi)
8918 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
8919 stmt = gimple_build_return (NULL);
8920 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
8921 gsi_remove (&gsi, true);
8924 /* Move the offloading region into CHILD_CFUN. */
8926 block = gimple_block (entry_stmt);
8928 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
8929 if (exit_bb)
8930 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
8931 /* When the OMP expansion process cannot guarantee an up-to-date
8932 loop tree arrange for the child function to fixup loops. */
8933 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
8934 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
8936 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
8937 num = vec_safe_length (child_cfun->local_decls);
8938 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
8940 t = (*child_cfun->local_decls)[srcidx];
8941 if (DECL_CONTEXT (t) == cfun->decl)
8942 continue;
8943 if (srcidx != dstidx)
8944 (*child_cfun->local_decls)[dstidx] = t;
8945 dstidx++;
8947 if (dstidx != num)
8948 vec_safe_truncate (child_cfun->local_decls, dstidx);
8950 /* Inform the callgraph about the new function. */
8951 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
8952 cgraph_node::add_new_function (child_fn, true);
8954 #ifdef ENABLE_OFFLOADING
8955 /* Add the new function to the offload table. */
8956 vec_safe_push (offload_funcs, child_fn);
8957 #endif
8959 /* Fix the callgraph edges for child_cfun. Those for cfun will be
8960 fixed in a following pass. */
8961 push_cfun (child_cfun);
8962 cgraph_edge::rebuild_edges ();
8964 #ifdef ENABLE_OFFLOADING
8965 /* Prevent IPA from removing child_fn as unreachable, since there are no
8966 refs from the parent function to child_fn in offload LTO mode. */
8967 struct cgraph_node *node = cgraph_node::get (child_fn);
8968 node->mark_force_output ();
8969 #endif
8971 /* Some EH regions might become dead, see PR34608. If
8972 pass_cleanup_cfg isn't the first pass to happen with the
8973 new child, these dead EH edges might cause problems.
8974 Clean them up now. */
8975 if (flag_exceptions)
8977 basic_block bb;
8978 bool changed = false;
8980 FOR_EACH_BB_FN (bb, cfun)
8981 changed |= gimple_purge_dead_eh_edges (bb);
8982 if (changed)
8983 cleanup_tree_cfg ();
8985 pop_cfun ();
8988 /* Emit a library call to launch the offloading region, or do data
8989 transfers. */
8990 tree t1, t2, t3, t4, device, cond, c, clauses;
8991 enum built_in_function start_ix;
8992 location_t clause_loc;
8994 switch (gimple_omp_target_kind (entry_stmt))
8996 case GF_OMP_TARGET_KIND_REGION:
8997 start_ix = BUILT_IN_GOMP_TARGET;
8998 break;
8999 case GF_OMP_TARGET_KIND_DATA:
9000 start_ix = BUILT_IN_GOMP_TARGET_DATA;
9001 break;
9002 case GF_OMP_TARGET_KIND_UPDATE:
9003 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
9004 break;
9005 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9006 start_ix = BUILT_IN_GOACC_PARALLEL;
9007 break;
9008 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9009 start_ix = BUILT_IN_GOACC_KERNELS;
9010 break;
9011 case GF_OMP_TARGET_KIND_OACC_DATA:
9012 start_ix = BUILT_IN_GOACC_DATA_START;
9013 break;
9014 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9015 start_ix = BUILT_IN_GOACC_UPDATE;
9016 break;
9017 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9018 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
9019 break;
9020 default:
9021 gcc_unreachable ();
9024 clauses = gimple_omp_target_clauses (entry_stmt);
9026 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
9027 library choose) and there is no conditional. */
9028 cond = NULL_TREE;
9029 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
9031 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
9032 if (c)
9033 cond = OMP_CLAUSE_IF_EXPR (c);
9035 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
9036 if (c)
9038 /* Even if we pass it to all library function calls, it is currently only
9039 defined/used for the OpenMP target ones. */
9040 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
9041 || start_ix == BUILT_IN_GOMP_TARGET_DATA
9042 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE);
9044 device = OMP_CLAUSE_DEVICE_ID (c);
9045 clause_loc = OMP_CLAUSE_LOCATION (c);
9047 else
9048 clause_loc = gimple_location (entry_stmt);
9050 /* Ensure 'device' is of the correct type. */
9051 device = fold_convert_loc (clause_loc, integer_type_node, device);
9053 /* If we found the clause 'if (cond)', build
9054 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
9055 if (cond)
9057 cond = gimple_boolify (cond);
9059 basic_block cond_bb, then_bb, else_bb;
9060 edge e;
9061 tree tmp_var;
9063 tmp_var = create_tmp_var (TREE_TYPE (device));
9064 if (offloaded)
9065 e = split_block (new_bb, NULL);
9066 else
9068 gsi = gsi_last_bb (new_bb);
9069 gsi_prev (&gsi);
9070 e = split_block (new_bb, gsi_stmt (gsi));
9072 cond_bb = e->src;
9073 new_bb = e->dest;
9074 remove_edge (e);
9076 then_bb = create_empty_bb (cond_bb);
9077 else_bb = create_empty_bb (then_bb);
9078 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
9079 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
9081 stmt = gimple_build_cond_empty (cond);
9082 gsi = gsi_last_bb (cond_bb);
9083 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9085 gsi = gsi_start_bb (then_bb);
9086 stmt = gimple_build_assign (tmp_var, device);
9087 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9089 gsi = gsi_start_bb (else_bb);
9090 stmt = gimple_build_assign (tmp_var,
9091 build_int_cst (integer_type_node,
9092 GOMP_DEVICE_HOST_FALLBACK));
9093 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
9095 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
9096 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
9097 add_bb_to_loop (then_bb, cond_bb->loop_father);
9098 add_bb_to_loop (else_bb, cond_bb->loop_father);
9099 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
9100 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
9102 device = tmp_var;
9105 gsi = gsi_last_bb (new_bb);
9106 t = gimple_omp_target_data_arg (entry_stmt);
9107 if (t == NULL)
9109 t1 = size_zero_node;
9110 t2 = build_zero_cst (ptr_type_node);
9111 t3 = t2;
9112 t4 = t2;
9114 else
9116 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
9117 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
9118 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
9119 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
9120 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
9123 gimple g;
9124 tree offload_table = get_offload_symbol_decl ();
9125 vec<tree> *args;
9126 /* The maximum number used by any start_ix, without varargs. */
9127 unsigned int argcnt = 12;
9129 vec_alloc (args, argcnt);
9130 args->quick_push (device);
9131 if (offloaded)
9132 args->quick_push (build_fold_addr_expr (child_fn));
9133 args->quick_push (build_fold_addr_expr (offload_table));
9134 args->quick_push (t1);
9135 args->quick_push (t2);
9136 args->quick_push (t3);
9137 args->quick_push (t4);
9138 switch (start_ix)
9140 case BUILT_IN_GOACC_DATA_START:
9141 case BUILT_IN_GOMP_TARGET:
9142 case BUILT_IN_GOMP_TARGET_DATA:
9143 case BUILT_IN_GOMP_TARGET_UPDATE:
9144 break;
9145 case BUILT_IN_GOACC_KERNELS:
9146 case BUILT_IN_GOACC_PARALLEL:
9148 tree t_num_gangs, t_num_workers, t_vector_length;
9150 /* Default values for num_gangs, num_workers, and vector_length. */
9151 t_num_gangs = t_num_workers = t_vector_length
9152 = fold_convert_loc (gimple_location (entry_stmt),
9153 integer_type_node, integer_one_node);
9154 /* ..., but if present, use the value specified by the respective
9155 clause, making sure that are of the correct type. */
9156 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_GANGS);
9157 if (c)
9158 t_num_gangs = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9159 integer_type_node,
9160 OMP_CLAUSE_NUM_GANGS_EXPR (c));
9161 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_WORKERS);
9162 if (c)
9163 t_num_workers = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9164 integer_type_node,
9165 OMP_CLAUSE_NUM_WORKERS_EXPR (c));
9166 c = find_omp_clause (clauses, OMP_CLAUSE_VECTOR_LENGTH);
9167 if (c)
9168 t_vector_length = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9169 integer_type_node,
9170 OMP_CLAUSE_VECTOR_LENGTH_EXPR (c));
9171 args->quick_push (t_num_gangs);
9172 args->quick_push (t_num_workers);
9173 args->quick_push (t_vector_length);
9175 /* FALLTHRU */
9176 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
9177 case BUILT_IN_GOACC_UPDATE:
9179 tree t_async;
9180 int t_wait_idx;
9182 /* Default values for t_async. */
9183 t_async = fold_convert_loc (gimple_location (entry_stmt),
9184 integer_type_node,
9185 build_int_cst (integer_type_node,
9186 GOMP_ASYNC_SYNC));
9187 /* ..., but if present, use the value specified by the respective
9188 clause, making sure that is of the correct type. */
9189 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
9190 if (c)
9191 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9192 integer_type_node,
9193 OMP_CLAUSE_ASYNC_EXPR (c));
9195 args->quick_push (t_async);
9196 /* Save the index, and... */
9197 t_wait_idx = args->length ();
9198 /* ... push a default value. */
9199 args->quick_push (fold_convert_loc (gimple_location (entry_stmt),
9200 integer_type_node,
9201 integer_zero_node));
9202 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
9203 if (c)
9205 int n = 0;
9207 for (; c; c = OMP_CLAUSE_CHAIN (c))
9209 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
9211 args->safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
9212 integer_type_node,
9213 OMP_CLAUSE_WAIT_EXPR (c)));
9214 n++;
9218 /* Now that we know the number, replace the default value. */
9219 args->ordered_remove (t_wait_idx);
9220 args->quick_insert (t_wait_idx,
9221 fold_convert_loc (gimple_location (entry_stmt),
9222 integer_type_node,
9223 build_int_cst (integer_type_node, n)));
9226 break;
9227 default:
9228 gcc_unreachable ();
9231 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), *args);
9232 args->release ();
9233 gimple_set_location (g, gimple_location (entry_stmt));
9234 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
9235 if (!offloaded)
9237 g = gsi_stmt (gsi);
9238 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
9239 gsi_remove (&gsi, true);
9241 if (data_region
9242 && region->exit)
9244 gsi = gsi_last_bb (region->exit);
9245 g = gsi_stmt (gsi);
9246 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
9247 gsi_remove (&gsi, true);
9252 /* Expand the parallel region tree rooted at REGION. Expansion
9253 proceeds in depth-first order. Innermost regions are expanded
9254 first. This way, parallel regions that require a new function to
9255 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
9256 internal dependencies in their body. */
9258 static void
9259 expand_omp (struct omp_region *region)
9261 while (region)
9263 location_t saved_location;
9264 gimple inner_stmt = NULL;
9266 /* First, determine whether this is a combined parallel+workshare
9267 region. */
9268 if (region->type == GIMPLE_OMP_PARALLEL)
9269 determine_parallel_type (region);
9271 if (region->type == GIMPLE_OMP_FOR
9272 && gimple_omp_for_combined_p (last_stmt (region->entry)))
9273 inner_stmt = last_stmt (region->inner->entry);
9275 if (region->inner)
9276 expand_omp (region->inner);
9278 saved_location = input_location;
9279 if (gimple_has_location (last_stmt (region->entry)))
9280 input_location = gimple_location (last_stmt (region->entry));
9282 switch (region->type)
9284 case GIMPLE_OMP_PARALLEL:
9285 case GIMPLE_OMP_TASK:
9286 expand_omp_taskreg (region);
9287 break;
9289 case GIMPLE_OMP_FOR:
9290 expand_omp_for (region, inner_stmt);
9291 break;
9293 case GIMPLE_OMP_SECTIONS:
9294 expand_omp_sections (region);
9295 break;
9297 case GIMPLE_OMP_SECTION:
9298 /* Individual omp sections are handled together with their
9299 parent GIMPLE_OMP_SECTIONS region. */
9300 break;
9302 case GIMPLE_OMP_SINGLE:
9303 expand_omp_single (region);
9304 break;
9306 case GIMPLE_OMP_MASTER:
9307 case GIMPLE_OMP_TASKGROUP:
9308 case GIMPLE_OMP_ORDERED:
9309 case GIMPLE_OMP_CRITICAL:
9310 case GIMPLE_OMP_TEAMS:
9311 expand_omp_synch (region);
9312 break;
9314 case GIMPLE_OMP_ATOMIC_LOAD:
9315 expand_omp_atomic (region);
9316 break;
9318 case GIMPLE_OMP_TARGET:
9319 expand_omp_target (region);
9320 break;
9322 default:
9323 gcc_unreachable ();
9326 input_location = saved_location;
9327 region = region->next;
9332 /* Helper for build_omp_regions. Scan the dominator tree starting at
9333 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
9334 true, the function ends once a single tree is built (otherwise, whole
9335 forest of OMP constructs may be built). */
9337 static void
9338 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
9339 bool single_tree)
9341 gimple_stmt_iterator gsi;
9342 gimple stmt;
9343 basic_block son;
9345 gsi = gsi_last_bb (bb);
9346 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
9348 struct omp_region *region;
9349 enum gimple_code code;
9351 stmt = gsi_stmt (gsi);
9352 code = gimple_code (stmt);
9353 if (code == GIMPLE_OMP_RETURN)
9355 /* STMT is the return point out of region PARENT. Mark it
9356 as the exit point and make PARENT the immediately
9357 enclosing region. */
9358 gcc_assert (parent);
9359 region = parent;
9360 region->exit = bb;
9361 parent = parent->outer;
9363 else if (code == GIMPLE_OMP_ATOMIC_STORE)
9365 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
9366 GIMPLE_OMP_RETURN, but matches with
9367 GIMPLE_OMP_ATOMIC_LOAD. */
9368 gcc_assert (parent);
9369 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
9370 region = parent;
9371 region->exit = bb;
9372 parent = parent->outer;
9374 else if (code == GIMPLE_OMP_CONTINUE)
9376 gcc_assert (parent);
9377 parent->cont = bb;
9379 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
9381 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
9382 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
9384 else
9386 region = new_omp_region (bb, code, parent);
9387 /* Otherwise... */
9388 if (code == GIMPLE_OMP_TARGET)
9390 switch (gimple_omp_target_kind (stmt))
9392 case GF_OMP_TARGET_KIND_REGION:
9393 case GF_OMP_TARGET_KIND_DATA:
9394 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
9395 case GF_OMP_TARGET_KIND_OACC_KERNELS:
9396 case GF_OMP_TARGET_KIND_OACC_DATA:
9397 break;
9398 case GF_OMP_TARGET_KIND_UPDATE:
9399 case GF_OMP_TARGET_KIND_OACC_UPDATE:
9400 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
9401 /* ..., other than for those stand-alone directives... */
9402 region = NULL;
9403 break;
9404 default:
9405 gcc_unreachable ();
9408 /* ..., this directive becomes the parent for a new region. */
9409 if (region)
9410 parent = region;
9414 if (single_tree && !parent)
9415 return;
9417 for (son = first_dom_son (CDI_DOMINATORS, bb);
9418 son;
9419 son = next_dom_son (CDI_DOMINATORS, son))
9420 build_omp_regions_1 (son, parent, single_tree);
9423 /* Builds the tree of OMP regions rooted at ROOT, storing it to
9424 root_omp_region. */
9426 static void
9427 build_omp_regions_root (basic_block root)
9429 gcc_assert (root_omp_region == NULL);
9430 build_omp_regions_1 (root, NULL, true);
9431 gcc_assert (root_omp_region != NULL);
9434 /* Expands omp construct (and its subconstructs) starting in HEAD. */
9436 void
9437 omp_expand_local (basic_block head)
9439 build_omp_regions_root (head);
9440 if (dump_file && (dump_flags & TDF_DETAILS))
9442 fprintf (dump_file, "\nOMP region tree\n\n");
9443 dump_omp_region (dump_file, root_omp_region, 0);
9444 fprintf (dump_file, "\n");
9447 remove_exit_barriers (root_omp_region);
9448 expand_omp (root_omp_region);
9450 free_omp_regions ();
9453 /* Scan the CFG and build a tree of OMP regions. Return the root of
9454 the OMP region tree. */
9456 static void
9457 build_omp_regions (void)
9459 gcc_assert (root_omp_region == NULL);
9460 calculate_dominance_info (CDI_DOMINATORS);
9461 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
9464 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
9466 static unsigned int
9467 execute_expand_omp (void)
9469 build_omp_regions ();
9471 if (!root_omp_region)
9472 return 0;
9474 if (dump_file)
9476 fprintf (dump_file, "\nOMP region tree\n\n");
9477 dump_omp_region (dump_file, root_omp_region, 0);
9478 fprintf (dump_file, "\n");
9481 remove_exit_barriers (root_omp_region);
9483 expand_omp (root_omp_region);
9485 cleanup_tree_cfg ();
9487 free_omp_regions ();
9489 return 0;
9492 /* OMP expansion -- the default pass, run before creation of SSA form. */
9494 namespace {
9496 const pass_data pass_data_expand_omp =
9498 GIMPLE_PASS, /* type */
9499 "ompexp", /* name */
9500 OPTGROUP_NONE, /* optinfo_flags */
9501 TV_NONE, /* tv_id */
9502 PROP_gimple_any, /* properties_required */
9503 PROP_gimple_eomp, /* properties_provided */
9504 0, /* properties_destroyed */
9505 0, /* todo_flags_start */
9506 0, /* todo_flags_finish */
9509 class pass_expand_omp : public gimple_opt_pass
9511 public:
9512 pass_expand_omp (gcc::context *ctxt)
9513 : gimple_opt_pass (pass_data_expand_omp, ctxt)
9516 /* opt_pass methods: */
9517 virtual unsigned int execute (function *)
9519 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
9520 || flag_openmp_simd != 0)
9521 && !seen_error ());
9523 /* This pass always runs, to provide PROP_gimple_eomp.
9524 But often, there is nothing to do. */
9525 if (!gate)
9526 return 0;
9528 return execute_expand_omp ();
9531 }; // class pass_expand_omp
9533 } // anon namespace
9535 gimple_opt_pass *
9536 make_pass_expand_omp (gcc::context *ctxt)
9538 return new pass_expand_omp (ctxt);
9541 namespace {
9543 const pass_data pass_data_expand_omp_ssa =
9545 GIMPLE_PASS, /* type */
9546 "ompexpssa", /* name */
9547 OPTGROUP_NONE, /* optinfo_flags */
9548 TV_NONE, /* tv_id */
9549 PROP_cfg | PROP_ssa, /* properties_required */
9550 PROP_gimple_eomp, /* properties_provided */
9551 0, /* properties_destroyed */
9552 0, /* todo_flags_start */
9553 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
9556 class pass_expand_omp_ssa : public gimple_opt_pass
9558 public:
9559 pass_expand_omp_ssa (gcc::context *ctxt)
9560 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
9563 /* opt_pass methods: */
9564 virtual bool gate (function *fun)
9566 return !(fun->curr_properties & PROP_gimple_eomp);
9568 virtual unsigned int execute (function *) { return execute_expand_omp (); }
9570 }; // class pass_expand_omp_ssa
9572 } // anon namespace
9574 gimple_opt_pass *
9575 make_pass_expand_omp_ssa (gcc::context *ctxt)
9577 return new pass_expand_omp_ssa (ctxt);
9580 /* Routines to lower OMP directives into OMP-GIMPLE. */
9582 /* Helper function to preform, potentially COMPLEX_TYPE, operation and
9583 convert it to gimple. */
9584 static void
9585 oacc_gimple_assign (tree dest, tree_code op, tree src, gimple_seq *seq)
9587 gimple stmt;
9589 if (TREE_CODE (TREE_TYPE (dest)) != COMPLEX_TYPE)
9591 stmt = gimple_build_assign (dest, op, dest, src);
9592 gimple_seq_add_stmt (seq, stmt);
9593 return;
9596 tree t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9597 tree rdest = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9598 gimplify_assign (t, rdest, seq);
9599 rdest = t;
9601 t = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9602 tree idest = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (dest)), dest);
9603 gimplify_assign (t, idest, seq);
9604 idest = t;
9606 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9607 tree rsrc = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9608 gimplify_assign (t, rsrc, seq);
9609 rsrc = t;
9611 t = create_tmp_var (TREE_TYPE (TREE_TYPE (src)));
9612 tree isrc = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (src)), src);
9613 gimplify_assign (t, isrc, seq);
9614 isrc = t;
9616 tree r = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9617 tree i = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9618 tree result;
9620 if (op == PLUS_EXPR)
9622 stmt = gimple_build_assign (r, op, rdest, rsrc);
9623 gimple_seq_add_stmt (seq, stmt);
9625 stmt = gimple_build_assign (i, op, idest, isrc);
9626 gimple_seq_add_stmt (seq, stmt);
9628 else if (op == MULT_EXPR)
9630 /* Let x = a + ib = dest, y = c + id = src.
9631 x * y = (ac - bd) + i(ad + bc) */
9632 tree ac = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9633 tree bd = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9634 tree ad = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9635 tree bc = create_tmp_var (TREE_TYPE (TREE_TYPE (dest)));
9637 stmt = gimple_build_assign (ac, MULT_EXPR, rdest, rsrc);
9638 gimple_seq_add_stmt (seq, stmt);
9640 stmt = gimple_build_assign (bd, MULT_EXPR, idest, isrc);
9641 gimple_seq_add_stmt (seq, stmt);
9643 stmt = gimple_build_assign (r, MINUS_EXPR, ac, bd);
9644 gimple_seq_add_stmt (seq, stmt);
9646 stmt = gimple_build_assign (ad, MULT_EXPR, rdest, isrc);
9647 gimple_seq_add_stmt (seq, stmt);
9649 stmt = gimple_build_assign (bd, MULT_EXPR, idest, rsrc);
9650 gimple_seq_add_stmt (seq, stmt);
9652 stmt = gimple_build_assign (i, PLUS_EXPR, ad, bc);
9653 gimple_seq_add_stmt (seq, stmt);
9655 else
9656 gcc_unreachable ();
9658 result = build2 (COMPLEX_EXPR, TREE_TYPE (dest), r, i);
9659 gimplify_assign (dest, result, seq);
9662 /* Helper function to initialize local data for the reduction arrays.
9663 The reduction arrays need to be placed inside the calling function
9664 for accelerators, or else the host won't be able to preform the final
9665 reduction. */
9667 static void
9668 oacc_initialize_reduction_data (tree clauses, tree nthreads,
9669 gimple_seq *stmt_seqp, omp_context *ctx)
9671 tree c, t, oc;
9672 gimple stmt;
9673 omp_context *octx;
9675 /* Find the innermost OpenACC parallel context. */
9676 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET
9677 && (gimple_omp_target_kind (ctx->stmt)
9678 == GF_OMP_TARGET_KIND_OACC_PARALLEL))
9679 octx = ctx;
9680 else
9681 octx = ctx->outer;
9682 gcc_checking_assert (gimple_code (octx->stmt) == GIMPLE_OMP_TARGET
9683 && (gimple_omp_target_kind (octx->stmt)
9684 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
9686 /* Extract the clauses. */
9687 oc = gimple_omp_target_clauses (octx->stmt);
9689 /* Find the last outer clause. */
9690 for (; oc && OMP_CLAUSE_CHAIN (oc); oc = OMP_CLAUSE_CHAIN (oc))
9693 /* Allocate arrays for each reduction variable. */
9694 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9696 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9697 continue;
9699 tree var = OMP_CLAUSE_DECL (c);
9700 tree type = get_base_type (var);
9701 tree array = lookup_oacc_reduction (oacc_get_reduction_array_id (var),
9702 ctx);
9703 tree size, call;
9705 /* Calculate size of the reduction array. */
9706 t = create_tmp_var (TREE_TYPE (nthreads));
9707 stmt = gimple_build_assign (t, MULT_EXPR, nthreads,
9708 fold_convert (TREE_TYPE (nthreads),
9709 TYPE_SIZE_UNIT (type)));
9710 gimple_seq_add_stmt (stmt_seqp, stmt);
9712 size = create_tmp_var (sizetype);
9713 gimplify_assign (size, fold_build1 (NOP_EXPR, sizetype, t), stmt_seqp);
9715 /* Now allocate memory for it. */
9716 call = unshare_expr (builtin_decl_explicit (BUILT_IN_ALLOCA));
9717 stmt = gimple_build_call (call, 1, size);
9718 gimple_call_set_lhs (stmt, array);
9719 gimple_seq_add_stmt (stmt_seqp, stmt);
9721 /* Map this array into the accelerator. */
9723 /* Add the reduction array to the list of clauses. */
9724 tree x = array;
9725 t = build_omp_clause (gimple_location (ctx->stmt), OMP_CLAUSE_MAP);
9726 OMP_CLAUSE_SET_MAP_KIND (t, GOMP_MAP_FORCE_FROM);
9727 OMP_CLAUSE_DECL (t) = x;
9728 OMP_CLAUSE_CHAIN (t) = NULL;
9729 if (oc)
9730 OMP_CLAUSE_CHAIN (oc) = t;
9731 else
9732 gimple_omp_target_set_clauses (as_a <gomp_target *> (octx->stmt), t);
9733 OMP_CLAUSE_SIZE (t) = size;
9734 oc = t;
9738 /* Helper function to process the array of partial reductions. Nthreads
9739 indicates the number of threads. Unfortunately, GOACC_GET_NUM_THREADS
9740 cannot be used here, because nthreads on the host may be different than
9741 on the accelerator. */
9743 static void
9744 oacc_finalize_reduction_data (tree clauses, tree nthreads,
9745 gimple_seq *stmt_seqp, omp_context *ctx)
9747 tree c, x, var, array, loop_header, loop_body, loop_exit, type;
9748 gimple stmt;
9750 /* Create for loop.
9752 let var = the original reduction variable
9753 let array = reduction variable array
9755 for (i = 0; i < nthreads; i++)
9756 var op= array[i]
9759 loop_header = create_artificial_label (UNKNOWN_LOCATION);
9760 loop_body = create_artificial_label (UNKNOWN_LOCATION);
9761 loop_exit = create_artificial_label (UNKNOWN_LOCATION);
9763 /* Create and initialize an index variable. */
9764 tree ix = create_tmp_var (sizetype);
9765 gimplify_assign (ix, fold_build1 (NOP_EXPR, sizetype, integer_zero_node),
9766 stmt_seqp);
9768 /* Insert the loop header label here. */
9769 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_header));
9771 /* Exit loop if ix >= nthreads. */
9772 x = create_tmp_var (sizetype);
9773 gimplify_assign (x, fold_build1 (NOP_EXPR, sizetype, nthreads), stmt_seqp);
9774 stmt = gimple_build_cond (GE_EXPR, ix, x, loop_exit, loop_body);
9775 gimple_seq_add_stmt (stmt_seqp, stmt);
9777 /* Insert the loop body label here. */
9778 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_body));
9780 /* Collapse each reduction array, one element at a time. */
9781 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9783 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
9784 continue;
9786 tree_code reduction_code = OMP_CLAUSE_REDUCTION_CODE (c);
9788 /* reduction(-:var) sums up the partial results, so it acts
9789 identically to reduction(+:var). */
9790 if (reduction_code == MINUS_EXPR)
9791 reduction_code = PLUS_EXPR;
9793 /* Set up reduction variable var. */
9794 var = OMP_CLAUSE_DECL (c);
9795 type = get_base_type (var);
9796 array = lookup_oacc_reduction (oacc_get_reduction_array_id
9797 (OMP_CLAUSE_DECL (c)), ctx);
9799 /* Calculate the array offset. */
9800 tree offset = create_tmp_var (sizetype);
9801 gimplify_assign (offset, TYPE_SIZE_UNIT (type), stmt_seqp);
9802 stmt = gimple_build_assign (offset, MULT_EXPR, offset, ix);
9803 gimple_seq_add_stmt (stmt_seqp, stmt);
9805 tree ptr = create_tmp_var (TREE_TYPE (array));
9806 stmt = gimple_build_assign (ptr, POINTER_PLUS_EXPR, array, offset);
9807 gimple_seq_add_stmt (stmt_seqp, stmt);
9809 /* Extract array[ix] into mem. */
9810 tree mem = create_tmp_var (type);
9811 gimplify_assign (mem, build_simple_mem_ref (ptr), stmt_seqp);
9813 /* Find the original reduction variable. */
9814 if (is_reference (var))
9815 var = build_simple_mem_ref (var);
9817 tree t = create_tmp_var (type);
9819 x = lang_hooks.decls.omp_clause_assign_op (c, t, var);
9820 gimplify_and_add (unshare_expr(x), stmt_seqp);
9822 /* var = var op mem */
9823 switch (OMP_CLAUSE_REDUCTION_CODE (c))
9825 case TRUTH_ANDIF_EXPR:
9826 case TRUTH_ORIF_EXPR:
9827 t = fold_build2 (OMP_CLAUSE_REDUCTION_CODE (c), integer_type_node,
9828 t, mem);
9829 gimplify_and_add (t, stmt_seqp);
9830 break;
9831 default:
9832 /* The lhs isn't a gimple_reg when var is COMPLEX_TYPE. */
9833 oacc_gimple_assign (t, OMP_CLAUSE_REDUCTION_CODE (c), mem,
9834 stmt_seqp);
9837 t = fold_build1 (NOP_EXPR, TREE_TYPE (var), t);
9838 x = lang_hooks.decls.omp_clause_assign_op (c, var, t);
9839 gimplify_and_add (unshare_expr(x), stmt_seqp);
9842 /* Increment the induction variable. */
9843 tree one = fold_build1 (NOP_EXPR, sizetype, integer_one_node);
9844 stmt = gimple_build_assign (ix, PLUS_EXPR, ix, one);
9845 gimple_seq_add_stmt (stmt_seqp, stmt);
9847 /* Go back to the top of the loop. */
9848 gimple_seq_add_stmt (stmt_seqp, gimple_build_goto (loop_header));
9850 /* Place the loop exit label here. */
9851 gimple_seq_add_stmt (stmt_seqp, gimple_build_label (loop_exit));
9854 /* Scan through all of the gimple stmts searching for an OMP_FOR_EXPR, and
9855 scan that for reductions. */
9857 static void
9858 oacc_process_reduction_data (gimple_seq *body, gimple_seq *in_stmt_seqp,
9859 gimple_seq *out_stmt_seqp, omp_context *ctx)
9861 gimple_stmt_iterator gsi;
9862 gimple_seq inner = NULL;
9864 /* A collapse clause may have inserted a new bind block. */
9865 gsi = gsi_start (*body);
9866 while (!gsi_end_p (gsi))
9868 gimple stmt = gsi_stmt (gsi);
9869 if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
9871 inner = gimple_bind_body (bind_stmt);
9872 body = &inner;
9873 gsi = gsi_start (*body);
9875 else if (dyn_cast <gomp_for *> (stmt))
9876 break;
9877 else
9878 gsi_next (&gsi);
9881 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
9883 tree clauses, nthreads, t, c, acc_device, acc_device_host, call,
9884 enter, exit;
9885 bool reduction_found = false;
9887 gimple stmt = gsi_stmt (gsi);
9889 switch (gimple_code (stmt))
9891 case GIMPLE_OMP_FOR:
9892 clauses = gimple_omp_for_clauses (stmt);
9894 /* Search for a reduction clause. */
9895 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
9896 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
9898 reduction_found = true;
9899 break;
9902 if (!reduction_found)
9903 break;
9905 ctx = maybe_lookup_ctx (stmt);
9906 t = NULL_TREE;
9908 /* Extract the number of threads. */
9909 nthreads = create_tmp_var (sizetype);
9910 t = oacc_max_threads (ctx);
9911 gimplify_assign (nthreads, t, in_stmt_seqp);
9913 /* Determine if this is kernel will be executed on the host. */
9914 call = builtin_decl_explicit (BUILT_IN_ACC_GET_DEVICE_TYPE);
9915 acc_device = create_tmp_var (integer_type_node, ".acc_device_type");
9916 stmt = gimple_build_call (call, 0);
9917 gimple_call_set_lhs (stmt, acc_device);
9918 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9920 /* Set nthreads = 1 for ACC_DEVICE_TYPE=host. */
9921 acc_device_host = create_tmp_var (integer_type_node,
9922 ".acc_device_host");
9923 gimplify_assign (acc_device_host,
9924 build_int_cst (integer_type_node,
9925 GOMP_DEVICE_HOST),
9926 in_stmt_seqp);
9928 enter = create_artificial_label (UNKNOWN_LOCATION);
9929 exit = create_artificial_label (UNKNOWN_LOCATION);
9931 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9932 enter, exit);
9933 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9934 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9935 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9936 integer_one_node),
9937 in_stmt_seqp);
9938 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9940 /* Also, set nthreads = 1 for ACC_DEVICE_TYPE=host_nonshm. */
9941 gimplify_assign (acc_device_host,
9942 build_int_cst (integer_type_node,
9943 GOMP_DEVICE_HOST_NONSHM),
9944 in_stmt_seqp);
9946 enter = create_artificial_label (UNKNOWN_LOCATION);
9947 exit = create_artificial_label (UNKNOWN_LOCATION);
9949 stmt = gimple_build_cond (EQ_EXPR, acc_device, acc_device_host,
9950 enter, exit);
9951 gimple_seq_add_stmt (in_stmt_seqp, stmt);
9952 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (enter));
9953 gimplify_assign (nthreads, fold_build1 (NOP_EXPR, sizetype,
9954 integer_one_node),
9955 in_stmt_seqp);
9956 gimple_seq_add_stmt (in_stmt_seqp, gimple_build_label (exit));
9958 oacc_initialize_reduction_data (clauses, nthreads, in_stmt_seqp,
9959 ctx);
9960 oacc_finalize_reduction_data (clauses, nthreads, out_stmt_seqp, ctx);
9961 break;
9962 default:
9963 // Scan for other directives which support reduction here.
9964 break;
9969 /* If ctx is a worksharing context inside of a cancellable parallel
9970 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
9971 and conditional branch to parallel's cancel_label to handle
9972 cancellation in the implicit barrier. */
9974 static void
9975 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
9977 gimple omp_return = gimple_seq_last_stmt (*body);
9978 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
9979 if (gimple_omp_return_nowait_p (omp_return))
9980 return;
9981 if (ctx->outer
9982 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
9983 && ctx->outer->cancellable)
9985 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
9986 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
9987 tree lhs = create_tmp_var (c_bool_type);
9988 gimple_omp_return_set_lhs (omp_return, lhs);
9989 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
9990 gimple g = gimple_build_cond (NE_EXPR, lhs,
9991 fold_convert (c_bool_type,
9992 boolean_false_node),
9993 ctx->outer->cancel_label, fallthru_label);
9994 gimple_seq_add_stmt (body, g);
9995 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
9999 /* Lower the OpenMP sections directive in the current statement in GSI_P.
10000 CTX is the enclosing OMP context for the current statement. */
10002 static void
10003 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10005 tree block, control;
10006 gimple_stmt_iterator tgsi;
10007 gomp_sections *stmt;
10008 gimple t;
10009 gbind *new_stmt, *bind;
10010 gimple_seq ilist, dlist, olist, new_body;
10012 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
10014 push_gimplify_context ();
10016 dlist = NULL;
10017 ilist = NULL;
10018 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
10019 &ilist, &dlist, ctx, NULL);
10021 new_body = gimple_omp_body (stmt);
10022 gimple_omp_set_body (stmt, NULL);
10023 tgsi = gsi_start (new_body);
10024 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
10026 omp_context *sctx;
10027 gimple sec_start;
10029 sec_start = gsi_stmt (tgsi);
10030 sctx = maybe_lookup_ctx (sec_start);
10031 gcc_assert (sctx);
10033 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
10034 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
10035 GSI_CONTINUE_LINKING);
10036 gimple_omp_set_body (sec_start, NULL);
10038 if (gsi_one_before_end_p (tgsi))
10040 gimple_seq l = NULL;
10041 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
10042 &l, ctx);
10043 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
10044 gimple_omp_section_set_last (sec_start);
10047 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
10048 GSI_CONTINUE_LINKING);
10051 block = make_node (BLOCK);
10052 bind = gimple_build_bind (NULL, new_body, block);
10054 olist = NULL;
10055 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
10057 block = make_node (BLOCK);
10058 new_stmt = gimple_build_bind (NULL, NULL, block);
10059 gsi_replace (gsi_p, new_stmt, true);
10061 pop_gimplify_context (new_stmt);
10062 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10063 BLOCK_VARS (block) = gimple_bind_vars (bind);
10064 if (BLOCK_VARS (block))
10065 TREE_USED (block) = 1;
10067 new_body = NULL;
10068 gimple_seq_add_seq (&new_body, ilist);
10069 gimple_seq_add_stmt (&new_body, stmt);
10070 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
10071 gimple_seq_add_stmt (&new_body, bind);
10073 control = create_tmp_var (unsigned_type_node, ".section");
10074 t = gimple_build_omp_continue (control, control);
10075 gimple_omp_sections_set_control (stmt, control);
10076 gimple_seq_add_stmt (&new_body, t);
10078 gimple_seq_add_seq (&new_body, olist);
10079 if (ctx->cancellable)
10080 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
10081 gimple_seq_add_seq (&new_body, dlist);
10083 new_body = maybe_catch_exception (new_body);
10085 t = gimple_build_omp_return
10086 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
10087 OMP_CLAUSE_NOWAIT));
10088 gimple_seq_add_stmt (&new_body, t);
10089 maybe_add_implicit_barrier_cancel (ctx, &new_body);
10091 gimple_bind_set_body (new_stmt, new_body);
10095 /* A subroutine of lower_omp_single. Expand the simple form of
10096 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
10098 if (GOMP_single_start ())
10099 BODY;
10100 [ GOMP_barrier (); ] -> unless 'nowait' is present.
10102 FIXME. It may be better to delay expanding the logic of this until
10103 pass_expand_omp. The expanded logic may make the job more difficult
10104 to a synchronization analysis pass. */
10106 static void
10107 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
10109 location_t loc = gimple_location (single_stmt);
10110 tree tlabel = create_artificial_label (loc);
10111 tree flabel = create_artificial_label (loc);
10112 gimple call, cond;
10113 tree lhs, decl;
10115 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
10116 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
10117 call = gimple_build_call (decl, 0);
10118 gimple_call_set_lhs (call, lhs);
10119 gimple_seq_add_stmt (pre_p, call);
10121 cond = gimple_build_cond (EQ_EXPR, lhs,
10122 fold_convert_loc (loc, TREE_TYPE (lhs),
10123 boolean_true_node),
10124 tlabel, flabel);
10125 gimple_seq_add_stmt (pre_p, cond);
10126 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
10127 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10128 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
10132 /* A subroutine of lower_omp_single. Expand the simple form of
10133 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
10135 #pragma omp single copyprivate (a, b, c)
10137 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
10140 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
10142 BODY;
10143 copyout.a = a;
10144 copyout.b = b;
10145 copyout.c = c;
10146 GOMP_single_copy_end (&copyout);
10148 else
10150 a = copyout_p->a;
10151 b = copyout_p->b;
10152 c = copyout_p->c;
10154 GOMP_barrier ();
10157 FIXME. It may be better to delay expanding the logic of this until
10158 pass_expand_omp. The expanded logic may make the job more difficult
10159 to a synchronization analysis pass. */
10161 static void
10162 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
10163 omp_context *ctx)
10165 tree ptr_type, t, l0, l1, l2, bfn_decl;
10166 gimple_seq copyin_seq;
10167 location_t loc = gimple_location (single_stmt);
10169 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
10171 ptr_type = build_pointer_type (ctx->record_type);
10172 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
10174 l0 = create_artificial_label (loc);
10175 l1 = create_artificial_label (loc);
10176 l2 = create_artificial_label (loc);
10178 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
10179 t = build_call_expr_loc (loc, bfn_decl, 0);
10180 t = fold_convert_loc (loc, ptr_type, t);
10181 gimplify_assign (ctx->receiver_decl, t, pre_p);
10183 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
10184 build_int_cst (ptr_type, 0));
10185 t = build3 (COND_EXPR, void_type_node, t,
10186 build_and_jump (&l0), build_and_jump (&l1));
10187 gimplify_and_add (t, pre_p);
10189 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
10191 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
10193 copyin_seq = NULL;
10194 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
10195 &copyin_seq, ctx);
10197 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
10198 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
10199 t = build_call_expr_loc (loc, bfn_decl, 1, t);
10200 gimplify_and_add (t, pre_p);
10202 t = build_and_jump (&l2);
10203 gimplify_and_add (t, pre_p);
10205 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
10207 gimple_seq_add_seq (pre_p, copyin_seq);
10209 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
10213 /* Expand code for an OpenMP single directive. */
10215 static void
10216 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10218 tree block;
10219 gimple t;
10220 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
10221 gbind *bind;
10222 gimple_seq bind_body, bind_body_tail = NULL, dlist;
10224 push_gimplify_context ();
10226 block = make_node (BLOCK);
10227 bind = gimple_build_bind (NULL, NULL, block);
10228 gsi_replace (gsi_p, bind, true);
10229 bind_body = NULL;
10230 dlist = NULL;
10231 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
10232 &bind_body, &dlist, ctx, NULL);
10233 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
10235 gimple_seq_add_stmt (&bind_body, single_stmt);
10237 if (ctx->record_type)
10238 lower_omp_single_copy (single_stmt, &bind_body, ctx);
10239 else
10240 lower_omp_single_simple (single_stmt, &bind_body);
10242 gimple_omp_set_body (single_stmt, NULL);
10244 gimple_seq_add_seq (&bind_body, dlist);
10246 bind_body = maybe_catch_exception (bind_body);
10248 t = gimple_build_omp_return
10249 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
10250 OMP_CLAUSE_NOWAIT));
10251 gimple_seq_add_stmt (&bind_body_tail, t);
10252 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
10253 if (ctx->record_type)
10255 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
10256 tree clobber = build_constructor (ctx->record_type, NULL);
10257 TREE_THIS_VOLATILE (clobber) = 1;
10258 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
10259 clobber), GSI_SAME_STMT);
10261 gimple_seq_add_seq (&bind_body, bind_body_tail);
10262 gimple_bind_set_body (bind, bind_body);
10264 pop_gimplify_context (bind);
10266 gimple_bind_append_vars (bind, ctx->block_vars);
10267 BLOCK_VARS (block) = ctx->block_vars;
10268 if (BLOCK_VARS (block))
10269 TREE_USED (block) = 1;
10273 /* Expand code for an OpenMP master directive. */
10275 static void
10276 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10278 tree block, lab = NULL, x, bfn_decl;
10279 gimple stmt = gsi_stmt (*gsi_p);
10280 gbind *bind;
10281 location_t loc = gimple_location (stmt);
10282 gimple_seq tseq;
10284 push_gimplify_context ();
10286 block = make_node (BLOCK);
10287 bind = gimple_build_bind (NULL, NULL, block);
10288 gsi_replace (gsi_p, bind, true);
10289 gimple_bind_add_stmt (bind, stmt);
10291 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
10292 x = build_call_expr_loc (loc, bfn_decl, 0);
10293 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
10294 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
10295 tseq = NULL;
10296 gimplify_and_add (x, &tseq);
10297 gimple_bind_add_seq (bind, tseq);
10299 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10300 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10301 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10302 gimple_omp_set_body (stmt, NULL);
10304 gimple_bind_add_stmt (bind, gimple_build_label (lab));
10306 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10308 pop_gimplify_context (bind);
10310 gimple_bind_append_vars (bind, ctx->block_vars);
10311 BLOCK_VARS (block) = ctx->block_vars;
10315 /* Expand code for an OpenMP taskgroup directive. */
10317 static void
10318 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10320 gimple stmt = gsi_stmt (*gsi_p);
10321 gcall *x;
10322 gbind *bind;
10323 tree block = make_node (BLOCK);
10325 bind = gimple_build_bind (NULL, NULL, block);
10326 gsi_replace (gsi_p, bind, true);
10327 gimple_bind_add_stmt (bind, stmt);
10329 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
10331 gimple_bind_add_stmt (bind, x);
10333 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10334 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10335 gimple_omp_set_body (stmt, NULL);
10337 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10339 gimple_bind_append_vars (bind, ctx->block_vars);
10340 BLOCK_VARS (block) = ctx->block_vars;
10344 /* Expand code for an OpenMP ordered directive. */
10346 static void
10347 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10349 tree block;
10350 gimple stmt = gsi_stmt (*gsi_p);
10351 gcall *x;
10352 gbind *bind;
10354 push_gimplify_context ();
10356 block = make_node (BLOCK);
10357 bind = gimple_build_bind (NULL, NULL, block);
10358 gsi_replace (gsi_p, bind, true);
10359 gimple_bind_add_stmt (bind, stmt);
10361 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
10363 gimple_bind_add_stmt (bind, x);
10365 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10366 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10367 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10368 gimple_omp_set_body (stmt, NULL);
10370 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END), 0);
10371 gimple_bind_add_stmt (bind, x);
10373 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10375 pop_gimplify_context (bind);
10377 gimple_bind_append_vars (bind, ctx->block_vars);
10378 BLOCK_VARS (block) = gimple_bind_vars (bind);
10382 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
10383 substitution of a couple of function calls. But in the NAMED case,
10384 requires that languages coordinate a symbol name. It is therefore
10385 best put here in common code. */
10387 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
10389 static void
10390 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10392 tree block;
10393 tree name, lock, unlock;
10394 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
10395 gbind *bind;
10396 location_t loc = gimple_location (stmt);
10397 gimple_seq tbody;
10399 name = gimple_omp_critical_name (stmt);
10400 if (name)
10402 tree decl;
10404 if (!critical_name_mutexes)
10405 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
10407 tree *n = critical_name_mutexes->get (name);
10408 if (n == NULL)
10410 char *new_str;
10412 decl = create_tmp_var_raw (ptr_type_node);
10414 new_str = ACONCAT ((".gomp_critical_user_",
10415 IDENTIFIER_POINTER (name), NULL));
10416 DECL_NAME (decl) = get_identifier (new_str);
10417 TREE_PUBLIC (decl) = 1;
10418 TREE_STATIC (decl) = 1;
10419 DECL_COMMON (decl) = 1;
10420 DECL_ARTIFICIAL (decl) = 1;
10421 DECL_IGNORED_P (decl) = 1;
10423 varpool_node::finalize_decl (decl);
10425 critical_name_mutexes->put (name, decl);
10427 else
10428 decl = *n;
10430 /* If '#pragma omp critical' is inside offloaded region or
10431 inside function marked as offloadable, the symbol must be
10432 marked as offloadable too. */
10433 omp_context *octx;
10434 if (cgraph_node::get (current_function_decl)->offloadable)
10435 varpool_node::get_create (decl)->offloadable = 1;
10436 else
10437 for (octx = ctx->outer; octx; octx = octx->outer)
10438 if (is_gimple_omp_offloaded (octx->stmt))
10440 varpool_node::get_create (decl)->offloadable = 1;
10441 break;
10444 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
10445 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
10447 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
10448 unlock = build_call_expr_loc (loc, unlock, 1,
10449 build_fold_addr_expr_loc (loc, decl));
10451 else
10453 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
10454 lock = build_call_expr_loc (loc, lock, 0);
10456 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
10457 unlock = build_call_expr_loc (loc, unlock, 0);
10460 push_gimplify_context ();
10462 block = make_node (BLOCK);
10463 bind = gimple_build_bind (NULL, NULL, block);
10464 gsi_replace (gsi_p, bind, true);
10465 gimple_bind_add_stmt (bind, stmt);
10467 tbody = gimple_bind_body (bind);
10468 gimplify_and_add (lock, &tbody);
10469 gimple_bind_set_body (bind, tbody);
10471 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10472 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
10473 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
10474 gimple_omp_set_body (stmt, NULL);
10476 tbody = gimple_bind_body (bind);
10477 gimplify_and_add (unlock, &tbody);
10478 gimple_bind_set_body (bind, tbody);
10480 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
10482 pop_gimplify_context (bind);
10483 gimple_bind_append_vars (bind, ctx->block_vars);
10484 BLOCK_VARS (block) = gimple_bind_vars (bind);
10488 /* A subroutine of lower_omp_for. Generate code to emit the predicate
10489 for a lastprivate clause. Given a loop control predicate of (V
10490 cond N2), we gate the clause on (!(V cond N2)). The lowered form
10491 is appended to *DLIST, iterator initialization is appended to
10492 *BODY_P. */
10494 static void
10495 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
10496 gimple_seq *dlist, struct omp_context *ctx)
10498 tree clauses, cond, vinit;
10499 enum tree_code cond_code;
10500 gimple_seq stmts;
10502 cond_code = fd->loop.cond_code;
10503 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
10505 /* When possible, use a strict equality expression. This can let VRP
10506 type optimizations deduce the value and remove a copy. */
10507 if (tree_fits_shwi_p (fd->loop.step))
10509 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
10510 if (step == 1 || step == -1)
10511 cond_code = EQ_EXPR;
10514 cond = build2 (cond_code, boolean_type_node, fd->loop.v, fd->loop.n2);
10516 clauses = gimple_omp_for_clauses (fd->for_stmt);
10517 stmts = NULL;
10518 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
10519 if (!gimple_seq_empty_p (stmts))
10521 gimple_seq_add_seq (&stmts, *dlist);
10522 *dlist = stmts;
10524 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
10525 vinit = fd->loop.n1;
10526 if (cond_code == EQ_EXPR
10527 && tree_fits_shwi_p (fd->loop.n2)
10528 && ! integer_zerop (fd->loop.n2))
10529 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
10530 else
10531 vinit = unshare_expr (vinit);
10533 /* Initialize the iterator variable, so that threads that don't execute
10534 any iterations don't execute the lastprivate clauses by accident. */
10535 gimplify_assign (fd->loop.v, vinit, body_p);
10540 /* Lower code for an OMP loop directive. */
10542 static void
10543 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
10545 tree *rhs_p, block;
10546 struct omp_for_data fd, *fdp = NULL;
10547 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
10548 gbind *new_stmt;
10549 gimple_seq omp_for_body, body, dlist;
10550 size_t i;
10552 push_gimplify_context ();
10554 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
10556 block = make_node (BLOCK);
10557 new_stmt = gimple_build_bind (NULL, NULL, block);
10558 /* Replace at gsi right away, so that 'stmt' is no member
10559 of a sequence anymore as we're going to add to to a different
10560 one below. */
10561 gsi_replace (gsi_p, new_stmt, true);
10563 /* Move declaration of temporaries in the loop body before we make
10564 it go away. */
10565 omp_for_body = gimple_omp_body (stmt);
10566 if (!gimple_seq_empty_p (omp_for_body)
10567 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
10569 gbind *inner_bind
10570 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
10571 tree vars = gimple_bind_vars (inner_bind);
10572 gimple_bind_append_vars (new_stmt, vars);
10573 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
10574 keep them on the inner_bind and it's block. */
10575 gimple_bind_set_vars (inner_bind, NULL_TREE);
10576 if (gimple_bind_block (inner_bind))
10577 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
10580 if (gimple_omp_for_combined_into_p (stmt))
10582 extract_omp_for_data (stmt, &fd, NULL);
10583 fdp = &fd;
10585 /* We need two temporaries with fd.loop.v type (istart/iend)
10586 and then (fd.collapse - 1) temporaries with the same
10587 type for count2 ... countN-1 vars if not constant. */
10588 size_t count = 2;
10589 tree type = fd.iter_type;
10590 if (fd.collapse > 1
10591 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
10592 count += fd.collapse - 1;
10593 bool parallel_for = gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR;
10594 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
10595 tree clauses = *pc;
10596 if (parallel_for)
10597 outerc
10598 = find_omp_clause (gimple_omp_parallel_clauses (ctx->outer->stmt),
10599 OMP_CLAUSE__LOOPTEMP_);
10600 for (i = 0; i < count; i++)
10602 tree temp;
10603 if (parallel_for)
10605 gcc_assert (outerc);
10606 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
10607 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
10608 OMP_CLAUSE__LOOPTEMP_);
10610 else
10612 temp = create_tmp_var (type);
10613 insert_decl_map (&ctx->outer->cb, temp, temp);
10615 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
10616 OMP_CLAUSE_DECL (*pc) = temp;
10617 pc = &OMP_CLAUSE_CHAIN (*pc);
10619 *pc = clauses;
10622 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
10623 dlist = NULL;
10624 body = NULL;
10625 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
10626 fdp);
10627 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
10629 lower_omp (gimple_omp_body_ptr (stmt), ctx);
10631 /* Lower the header expressions. At this point, we can assume that
10632 the header is of the form:
10634 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
10636 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
10637 using the .omp_data_s mapping, if needed. */
10638 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
10640 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
10641 if (!is_gimple_min_invariant (*rhs_p))
10642 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10644 rhs_p = gimple_omp_for_final_ptr (stmt, i);
10645 if (!is_gimple_min_invariant (*rhs_p))
10646 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10648 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
10649 if (!is_gimple_min_invariant (*rhs_p))
10650 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
10653 /* Once lowered, extract the bounds and clauses. */
10654 extract_omp_for_data (stmt, &fd, NULL);
10656 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
10658 gimple_seq_add_stmt (&body, stmt);
10659 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
10661 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
10662 fd.loop.v));
10664 /* After the loop, add exit clauses. */
10665 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
10667 if (ctx->cancellable)
10668 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
10670 gimple_seq_add_seq (&body, dlist);
10672 body = maybe_catch_exception (body);
10674 /* Region exit marker goes at the end of the loop body. */
10675 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
10676 maybe_add_implicit_barrier_cancel (ctx, &body);
10677 pop_gimplify_context (new_stmt);
10679 gimple_bind_append_vars (new_stmt, ctx->block_vars);
10680 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
10681 if (BLOCK_VARS (block))
10682 TREE_USED (block) = 1;
10684 gimple_bind_set_body (new_stmt, body);
10685 gimple_omp_set_body (stmt, NULL);
10686 gimple_omp_for_set_pre_body (stmt, NULL);
10689 /* Callback for walk_stmts. Check if the current statement only contains
10690 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
10692 static tree
10693 check_combined_parallel (gimple_stmt_iterator *gsi_p,
10694 bool *handled_ops_p,
10695 struct walk_stmt_info *wi)
10697 int *info = (int *) wi->info;
10698 gimple stmt = gsi_stmt (*gsi_p);
10700 *handled_ops_p = true;
10701 switch (gimple_code (stmt))
10703 WALK_SUBSTMTS;
10705 case GIMPLE_OMP_FOR:
10706 case GIMPLE_OMP_SECTIONS:
10707 *info = *info == 0 ? 1 : -1;
10708 break;
10709 default:
10710 *info = -1;
10711 break;
10713 return NULL;
10716 struct omp_taskcopy_context
10718 /* This field must be at the beginning, as we do "inheritance": Some
10719 callback functions for tree-inline.c (e.g., omp_copy_decl)
10720 receive a copy_body_data pointer that is up-casted to an
10721 omp_context pointer. */
10722 copy_body_data cb;
10723 omp_context *ctx;
10726 static tree
10727 task_copyfn_copy_decl (tree var, copy_body_data *cb)
10729 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
10731 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
10732 return create_tmp_var (TREE_TYPE (var));
10734 return var;
10737 static tree
10738 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
10740 tree name, new_fields = NULL, type, f;
10742 type = lang_hooks.types.make_type (RECORD_TYPE);
10743 name = DECL_NAME (TYPE_NAME (orig_type));
10744 name = build_decl (gimple_location (tcctx->ctx->stmt),
10745 TYPE_DECL, name, type);
10746 TYPE_NAME (type) = name;
10748 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
10750 tree new_f = copy_node (f);
10751 DECL_CONTEXT (new_f) = type;
10752 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
10753 TREE_CHAIN (new_f) = new_fields;
10754 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10755 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
10756 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
10757 &tcctx->cb, NULL);
10758 new_fields = new_f;
10759 tcctx->cb.decl_map->put (f, new_f);
10761 TYPE_FIELDS (type) = nreverse (new_fields);
10762 layout_type (type);
10763 return type;
10766 /* Create task copyfn. */
10768 static void
10769 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
10771 struct function *child_cfun;
10772 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
10773 tree record_type, srecord_type, bind, list;
10774 bool record_needs_remap = false, srecord_needs_remap = false;
10775 splay_tree_node n;
10776 struct omp_taskcopy_context tcctx;
10777 location_t loc = gimple_location (task_stmt);
10779 child_fn = gimple_omp_task_copy_fn (task_stmt);
10780 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
10781 gcc_assert (child_cfun->cfg == NULL);
10782 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
10784 /* Reset DECL_CONTEXT on function arguments. */
10785 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
10786 DECL_CONTEXT (t) = child_fn;
10788 /* Populate the function. */
10789 push_gimplify_context ();
10790 push_cfun (child_cfun);
10792 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
10793 TREE_SIDE_EFFECTS (bind) = 1;
10794 list = NULL;
10795 DECL_SAVED_TREE (child_fn) = bind;
10796 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
10798 /* Remap src and dst argument types if needed. */
10799 record_type = ctx->record_type;
10800 srecord_type = ctx->srecord_type;
10801 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
10802 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10804 record_needs_remap = true;
10805 break;
10807 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
10808 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
10810 srecord_needs_remap = true;
10811 break;
10814 if (record_needs_remap || srecord_needs_remap)
10816 memset (&tcctx, '\0', sizeof (tcctx));
10817 tcctx.cb.src_fn = ctx->cb.src_fn;
10818 tcctx.cb.dst_fn = child_fn;
10819 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
10820 gcc_checking_assert (tcctx.cb.src_node);
10821 tcctx.cb.dst_node = tcctx.cb.src_node;
10822 tcctx.cb.src_cfun = ctx->cb.src_cfun;
10823 tcctx.cb.copy_decl = task_copyfn_copy_decl;
10824 tcctx.cb.eh_lp_nr = 0;
10825 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
10826 tcctx.cb.decl_map = new hash_map<tree, tree>;
10827 tcctx.ctx = ctx;
10829 if (record_needs_remap)
10830 record_type = task_copyfn_remap_type (&tcctx, record_type);
10831 if (srecord_needs_remap)
10832 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
10834 else
10835 tcctx.cb.decl_map = NULL;
10837 arg = DECL_ARGUMENTS (child_fn);
10838 TREE_TYPE (arg) = build_pointer_type (record_type);
10839 sarg = DECL_CHAIN (arg);
10840 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
10842 /* First pass: initialize temporaries used in record_type and srecord_type
10843 sizes and field offsets. */
10844 if (tcctx.cb.decl_map)
10845 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10846 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10848 tree *p;
10850 decl = OMP_CLAUSE_DECL (c);
10851 p = tcctx.cb.decl_map->get (decl);
10852 if (p == NULL)
10853 continue;
10854 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10855 sf = (tree) n->value;
10856 sf = *tcctx.cb.decl_map->get (sf);
10857 src = build_simple_mem_ref_loc (loc, sarg);
10858 src = omp_build_component_ref (src, sf);
10859 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
10860 append_to_statement_list (t, &list);
10863 /* Second pass: copy shared var pointers and copy construct non-VLA
10864 firstprivate vars. */
10865 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10866 switch (OMP_CLAUSE_CODE (c))
10868 case OMP_CLAUSE_SHARED:
10869 decl = OMP_CLAUSE_DECL (c);
10870 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10871 if (n == NULL)
10872 break;
10873 f = (tree) n->value;
10874 if (tcctx.cb.decl_map)
10875 f = *tcctx.cb.decl_map->get (f);
10876 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10877 sf = (tree) n->value;
10878 if (tcctx.cb.decl_map)
10879 sf = *tcctx.cb.decl_map->get (sf);
10880 src = build_simple_mem_ref_loc (loc, sarg);
10881 src = omp_build_component_ref (src, sf);
10882 dst = build_simple_mem_ref_loc (loc, arg);
10883 dst = omp_build_component_ref (dst, f);
10884 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10885 append_to_statement_list (t, &list);
10886 break;
10887 case OMP_CLAUSE_FIRSTPRIVATE:
10888 decl = OMP_CLAUSE_DECL (c);
10889 if (is_variable_sized (decl))
10890 break;
10891 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10892 if (n == NULL)
10893 break;
10894 f = (tree) n->value;
10895 if (tcctx.cb.decl_map)
10896 f = *tcctx.cb.decl_map->get (f);
10897 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10898 if (n != NULL)
10900 sf = (tree) n->value;
10901 if (tcctx.cb.decl_map)
10902 sf = *tcctx.cb.decl_map->get (sf);
10903 src = build_simple_mem_ref_loc (loc, sarg);
10904 src = omp_build_component_ref (src, sf);
10905 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
10906 src = build_simple_mem_ref_loc (loc, src);
10908 else
10909 src = decl;
10910 dst = build_simple_mem_ref_loc (loc, arg);
10911 dst = omp_build_component_ref (dst, f);
10912 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10913 append_to_statement_list (t, &list);
10914 break;
10915 case OMP_CLAUSE_PRIVATE:
10916 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
10917 break;
10918 decl = OMP_CLAUSE_DECL (c);
10919 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10920 f = (tree) n->value;
10921 if (tcctx.cb.decl_map)
10922 f = *tcctx.cb.decl_map->get (f);
10923 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
10924 if (n != NULL)
10926 sf = (tree) n->value;
10927 if (tcctx.cb.decl_map)
10928 sf = *tcctx.cb.decl_map->get (sf);
10929 src = build_simple_mem_ref_loc (loc, sarg);
10930 src = omp_build_component_ref (src, sf);
10931 if (use_pointer_for_field (decl, NULL))
10932 src = build_simple_mem_ref_loc (loc, src);
10934 else
10935 src = decl;
10936 dst = build_simple_mem_ref_loc (loc, arg);
10937 dst = omp_build_component_ref (dst, f);
10938 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
10939 append_to_statement_list (t, &list);
10940 break;
10941 default:
10942 break;
10945 /* Last pass: handle VLA firstprivates. */
10946 if (tcctx.cb.decl_map)
10947 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
10948 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
10950 tree ind, ptr, df;
10952 decl = OMP_CLAUSE_DECL (c);
10953 if (!is_variable_sized (decl))
10954 continue;
10955 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
10956 if (n == NULL)
10957 continue;
10958 f = (tree) n->value;
10959 f = *tcctx.cb.decl_map->get (f);
10960 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
10961 ind = DECL_VALUE_EXPR (decl);
10962 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
10963 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
10964 n = splay_tree_lookup (ctx->sfield_map,
10965 (splay_tree_key) TREE_OPERAND (ind, 0));
10966 sf = (tree) n->value;
10967 sf = *tcctx.cb.decl_map->get (sf);
10968 src = build_simple_mem_ref_loc (loc, sarg);
10969 src = omp_build_component_ref (src, sf);
10970 src = build_simple_mem_ref_loc (loc, src);
10971 dst = build_simple_mem_ref_loc (loc, arg);
10972 dst = omp_build_component_ref (dst, f);
10973 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
10974 append_to_statement_list (t, &list);
10975 n = splay_tree_lookup (ctx->field_map,
10976 (splay_tree_key) TREE_OPERAND (ind, 0));
10977 df = (tree) n->value;
10978 df = *tcctx.cb.decl_map->get (df);
10979 ptr = build_simple_mem_ref_loc (loc, arg);
10980 ptr = omp_build_component_ref (ptr, df);
10981 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
10982 build_fold_addr_expr_loc (loc, dst));
10983 append_to_statement_list (t, &list);
10986 t = build1 (RETURN_EXPR, void_type_node, NULL);
10987 append_to_statement_list (t, &list);
10989 if (tcctx.cb.decl_map)
10990 delete tcctx.cb.decl_map;
10991 pop_gimplify_context (NULL);
10992 BIND_EXPR_BODY (bind) = list;
10993 pop_cfun ();
10996 static void
10997 lower_depend_clauses (gimple stmt, gimple_seq *iseq, gimple_seq *oseq)
10999 tree c, clauses;
11000 gimple g;
11001 size_t n_in = 0, n_out = 0, idx = 2, i;
11003 clauses = find_omp_clause (gimple_omp_task_clauses (stmt),
11004 OMP_CLAUSE_DEPEND);
11005 gcc_assert (clauses);
11006 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11007 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
11008 switch (OMP_CLAUSE_DEPEND_KIND (c))
11010 case OMP_CLAUSE_DEPEND_IN:
11011 n_in++;
11012 break;
11013 case OMP_CLAUSE_DEPEND_OUT:
11014 case OMP_CLAUSE_DEPEND_INOUT:
11015 n_out++;
11016 break;
11017 default:
11018 gcc_unreachable ();
11020 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
11021 tree array = create_tmp_var (type);
11022 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
11023 NULL_TREE);
11024 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
11025 gimple_seq_add_stmt (iseq, g);
11026 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
11027 NULL_TREE);
11028 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
11029 gimple_seq_add_stmt (iseq, g);
11030 for (i = 0; i < 2; i++)
11032 if ((i ? n_in : n_out) == 0)
11033 continue;
11034 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
11035 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
11036 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
11038 tree t = OMP_CLAUSE_DECL (c);
11039 t = fold_convert (ptr_type_node, t);
11040 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
11041 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
11042 NULL_TREE, NULL_TREE);
11043 g = gimple_build_assign (r, t);
11044 gimple_seq_add_stmt (iseq, g);
11047 tree *p = gimple_omp_task_clauses_ptr (stmt);
11048 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
11049 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
11050 OMP_CLAUSE_CHAIN (c) = *p;
11051 *p = c;
11052 tree clobber = build_constructor (type, NULL);
11053 TREE_THIS_VOLATILE (clobber) = 1;
11054 g = gimple_build_assign (array, clobber);
11055 gimple_seq_add_stmt (oseq, g);
11058 /* Lower the OpenMP parallel or task directive in the current statement
11059 in GSI_P. CTX holds context information for the directive. */
11061 static void
11062 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11064 tree clauses;
11065 tree child_fn, t;
11066 gimple stmt = gsi_stmt (*gsi_p);
11067 gbind *par_bind, *bind, *dep_bind = NULL;
11068 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
11069 location_t loc = gimple_location (stmt);
11071 clauses = gimple_omp_taskreg_clauses (stmt);
11072 par_bind
11073 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
11074 par_body = gimple_bind_body (par_bind);
11075 child_fn = ctx->cb.dst_fn;
11076 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
11077 && !gimple_omp_parallel_combined_p (stmt))
11079 struct walk_stmt_info wi;
11080 int ws_num = 0;
11082 memset (&wi, 0, sizeof (wi));
11083 wi.info = &ws_num;
11084 wi.val_only = true;
11085 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
11086 if (ws_num == 1)
11087 gimple_omp_parallel_set_combined_p (stmt, true);
11089 gimple_seq dep_ilist = NULL;
11090 gimple_seq dep_olist = NULL;
11091 if (gimple_code (stmt) == GIMPLE_OMP_TASK
11092 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
11094 push_gimplify_context ();
11095 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
11096 lower_depend_clauses (stmt, &dep_ilist, &dep_olist);
11099 if (ctx->srecord_type)
11100 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
11102 push_gimplify_context ();
11104 par_olist = NULL;
11105 par_ilist = NULL;
11106 par_rlist = NULL;
11107 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
11108 lower_omp (&par_body, ctx);
11109 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
11110 lower_reduction_clauses (clauses, &par_rlist, ctx);
11112 /* Declare all the variables created by mapping and the variables
11113 declared in the scope of the parallel body. */
11114 record_vars_into (ctx->block_vars, child_fn);
11115 record_vars_into (gimple_bind_vars (par_bind), child_fn);
11117 if (ctx->record_type)
11119 ctx->sender_decl
11120 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
11121 : ctx->record_type, ".omp_data_o");
11122 DECL_NAMELESS (ctx->sender_decl) = 1;
11123 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11124 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
11127 olist = NULL;
11128 ilist = NULL;
11129 lower_send_clauses (clauses, &ilist, &olist, ctx);
11130 lower_send_shared_vars (&ilist, &olist, ctx);
11132 if (ctx->record_type)
11134 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
11135 TREE_THIS_VOLATILE (clobber) = 1;
11136 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11137 clobber));
11140 /* Once all the expansions are done, sequence all the different
11141 fragments inside gimple_omp_body. */
11143 new_body = NULL;
11145 if (ctx->record_type)
11147 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11148 /* fixup_child_record_type might have changed receiver_decl's type. */
11149 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11150 gimple_seq_add_stmt (&new_body,
11151 gimple_build_assign (ctx->receiver_decl, t));
11154 gimple_seq_add_seq (&new_body, par_ilist);
11155 gimple_seq_add_seq (&new_body, par_body);
11156 gimple_seq_add_seq (&new_body, par_rlist);
11157 if (ctx->cancellable)
11158 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
11159 gimple_seq_add_seq (&new_body, par_olist);
11160 new_body = maybe_catch_exception (new_body);
11161 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11162 gimple_omp_set_body (stmt, new_body);
11164 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
11165 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
11166 gimple_bind_add_seq (bind, ilist);
11167 gimple_bind_add_stmt (bind, stmt);
11168 gimple_bind_add_seq (bind, olist);
11170 pop_gimplify_context (NULL);
11172 if (dep_bind)
11174 gimple_bind_add_seq (dep_bind, dep_ilist);
11175 gimple_bind_add_stmt (dep_bind, bind);
11176 gimple_bind_add_seq (dep_bind, dep_olist);
11177 pop_gimplify_context (dep_bind);
11181 /* Lower the GIMPLE_OMP_TARGET in the current statement
11182 in GSI_P. CTX holds context information for the directive. */
11184 static void
11185 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11187 tree clauses;
11188 tree child_fn, t, c;
11189 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
11190 gbind *tgt_bind, *bind;
11191 gimple_seq tgt_body, olist, ilist, orlist, irlist, new_body;
11192 location_t loc = gimple_location (stmt);
11193 bool offloaded, data_region;
11194 unsigned int map_cnt = 0;
11196 offloaded = is_gimple_omp_offloaded (stmt);
11197 switch (gimple_omp_target_kind (stmt))
11199 case GF_OMP_TARGET_KIND_REGION:
11200 case GF_OMP_TARGET_KIND_UPDATE:
11201 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
11202 case GF_OMP_TARGET_KIND_OACC_KERNELS:
11203 case GF_OMP_TARGET_KIND_OACC_UPDATE:
11204 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
11205 data_region = false;
11206 break;
11207 case GF_OMP_TARGET_KIND_DATA:
11208 case GF_OMP_TARGET_KIND_OACC_DATA:
11209 data_region = true;
11210 break;
11211 default:
11212 gcc_unreachable ();
11215 clauses = gimple_omp_target_clauses (stmt);
11217 tgt_bind = NULL;
11218 tgt_body = NULL;
11219 if (offloaded)
11221 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
11222 tgt_body = gimple_bind_body (tgt_bind);
11224 else if (data_region)
11225 tgt_body = gimple_omp_body (stmt);
11226 child_fn = ctx->cb.dst_fn;
11228 push_gimplify_context ();
11230 irlist = NULL;
11231 orlist = NULL;
11232 if (offloaded
11233 && is_gimple_omp_oacc (stmt))
11234 oacc_process_reduction_data (&tgt_body, &irlist, &orlist, ctx);
11236 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11237 switch (OMP_CLAUSE_CODE (c))
11239 tree var, x;
11241 default:
11242 break;
11243 case OMP_CLAUSE_MAP:
11244 #ifdef ENABLE_CHECKING
11245 /* First check what we're prepared to handle in the following. */
11246 switch (OMP_CLAUSE_MAP_KIND (c))
11248 case GOMP_MAP_ALLOC:
11249 case GOMP_MAP_TO:
11250 case GOMP_MAP_FROM:
11251 case GOMP_MAP_TOFROM:
11252 case GOMP_MAP_POINTER:
11253 case GOMP_MAP_TO_PSET:
11254 break;
11255 case GOMP_MAP_FORCE_ALLOC:
11256 case GOMP_MAP_FORCE_TO:
11257 case GOMP_MAP_FORCE_FROM:
11258 case GOMP_MAP_FORCE_TOFROM:
11259 case GOMP_MAP_FORCE_PRESENT:
11260 case GOMP_MAP_FORCE_DEALLOC:
11261 case GOMP_MAP_FORCE_DEVICEPTR:
11262 gcc_assert (is_gimple_omp_oacc (stmt));
11263 break;
11264 default:
11265 gcc_unreachable ();
11267 #endif
11268 /* FALLTHRU */
11269 case OMP_CLAUSE_TO:
11270 case OMP_CLAUSE_FROM:
11271 var = OMP_CLAUSE_DECL (c);
11272 if (!DECL_P (var))
11274 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
11275 || !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11276 map_cnt++;
11277 continue;
11280 if (DECL_SIZE (var)
11281 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
11283 tree var2 = DECL_VALUE_EXPR (var);
11284 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
11285 var2 = TREE_OPERAND (var2, 0);
11286 gcc_assert (DECL_P (var2));
11287 var = var2;
11290 if (!maybe_lookup_field (var, ctx))
11291 continue;
11293 if (offloaded)
11295 x = build_receiver_ref (var, true, ctx);
11296 tree new_var = lookup_decl (var, ctx);
11297 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11298 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11299 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
11300 x = build_simple_mem_ref (x);
11301 SET_DECL_VALUE_EXPR (new_var, x);
11302 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
11304 map_cnt++;
11307 if (offloaded)
11309 target_nesting_level++;
11310 lower_omp (&tgt_body, ctx);
11311 target_nesting_level--;
11313 else if (data_region)
11314 lower_omp (&tgt_body, ctx);
11316 if (offloaded)
11318 /* Declare all the variables created by mapping and the variables
11319 declared in the scope of the target body. */
11320 record_vars_into (ctx->block_vars, child_fn);
11321 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
11324 olist = NULL;
11325 ilist = NULL;
11326 if (ctx->record_type)
11328 ctx->sender_decl
11329 = create_tmp_var (ctx->record_type, ".omp_data_arr");
11330 DECL_NAMELESS (ctx->sender_decl) = 1;
11331 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
11332 t = make_tree_vec (3);
11333 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
11334 TREE_VEC_ELT (t, 1)
11335 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
11336 ".omp_data_sizes");
11337 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
11338 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
11339 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
11340 tree tkind_type;
11341 int talign_shift;
11342 if (is_gimple_omp_oacc (stmt))
11344 tkind_type = short_unsigned_type_node;
11345 talign_shift = 8;
11347 else
11349 tkind_type = unsigned_char_type_node;
11350 talign_shift = 3;
11352 TREE_VEC_ELT (t, 2)
11353 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
11354 ".omp_data_kinds");
11355 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
11356 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
11357 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
11358 gimple_omp_target_set_data_arg (stmt, t);
11360 vec<constructor_elt, va_gc> *vsize;
11361 vec<constructor_elt, va_gc> *vkind;
11362 vec_alloc (vsize, map_cnt);
11363 vec_alloc (vkind, map_cnt);
11364 unsigned int map_idx = 0;
11366 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
11367 switch (OMP_CLAUSE_CODE (c))
11369 tree ovar, nc;
11371 default:
11372 break;
11373 case OMP_CLAUSE_MAP:
11374 case OMP_CLAUSE_TO:
11375 case OMP_CLAUSE_FROM:
11376 nc = c;
11377 ovar = OMP_CLAUSE_DECL (c);
11378 if (!DECL_P (ovar))
11380 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11381 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
11383 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
11384 == get_base_address (ovar));
11385 nc = OMP_CLAUSE_CHAIN (c);
11386 ovar = OMP_CLAUSE_DECL (nc);
11388 else
11390 tree x = build_sender_ref (ovar, ctx);
11391 tree v
11392 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
11393 gimplify_assign (x, v, &ilist);
11394 nc = NULL_TREE;
11397 else
11399 if (DECL_SIZE (ovar)
11400 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
11402 tree ovar2 = DECL_VALUE_EXPR (ovar);
11403 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
11404 ovar2 = TREE_OPERAND (ovar2, 0);
11405 gcc_assert (DECL_P (ovar2));
11406 ovar = ovar2;
11408 if (!maybe_lookup_field (ovar, ctx))
11409 continue;
11412 unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
11413 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
11414 talign = DECL_ALIGN_UNIT (ovar);
11415 if (nc)
11417 tree var = lookup_decl_in_outer_ctx (ovar, ctx);
11418 tree x = build_sender_ref (ovar, ctx);
11419 if (maybe_lookup_oacc_reduction (var, ctx))
11421 gcc_checking_assert (offloaded
11422 && is_gimple_omp_oacc (stmt));
11423 gimplify_assign (x, var, &ilist);
11425 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
11426 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
11427 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
11428 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
11430 gcc_assert (offloaded);
11431 tree avar
11432 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
11433 mark_addressable (avar);
11434 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
11435 talign = DECL_ALIGN_UNIT (avar);
11436 avar = build_fold_addr_expr (avar);
11437 gimplify_assign (x, avar, &ilist);
11439 else if (is_gimple_reg (var))
11441 gcc_assert (offloaded);
11442 tree avar = create_tmp_var (TREE_TYPE (var));
11443 mark_addressable (avar);
11444 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
11445 if (GOMP_MAP_COPY_TO_P (map_kind)
11446 || map_kind == GOMP_MAP_POINTER
11447 || map_kind == GOMP_MAP_TO_PSET
11448 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11449 gimplify_assign (avar, var, &ilist);
11450 avar = build_fold_addr_expr (avar);
11451 gimplify_assign (x, avar, &ilist);
11452 if ((GOMP_MAP_COPY_FROM_P (map_kind)
11453 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
11454 && !TYPE_READONLY (TREE_TYPE (var)))
11456 x = build_sender_ref (ovar, ctx);
11457 x = build_simple_mem_ref (x);
11458 gimplify_assign (var, x, &olist);
11461 else
11463 var = build_fold_addr_expr (var);
11464 gimplify_assign (x, var, &ilist);
11467 tree s = OMP_CLAUSE_SIZE (c);
11468 if (s == NULL_TREE)
11469 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
11470 s = fold_convert (size_type_node, s);
11471 tree purpose = size_int (map_idx++);
11472 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
11473 if (TREE_CODE (s) != INTEGER_CST)
11474 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
11476 unsigned HOST_WIDE_INT tkind;
11477 switch (OMP_CLAUSE_CODE (c))
11479 case OMP_CLAUSE_MAP:
11480 tkind = OMP_CLAUSE_MAP_KIND (c);
11481 break;
11482 case OMP_CLAUSE_TO:
11483 tkind = GOMP_MAP_TO;
11484 break;
11485 case OMP_CLAUSE_FROM:
11486 tkind = GOMP_MAP_FROM;
11487 break;
11488 default:
11489 gcc_unreachable ();
11491 gcc_checking_assert (tkind
11492 < (HOST_WIDE_INT_C (1U) << talign_shift));
11493 talign = ceil_log2 (talign);
11494 tkind |= talign << talign_shift;
11495 gcc_checking_assert (tkind
11496 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
11497 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
11498 build_int_cstu (tkind_type, tkind));
11499 if (nc && nc != c)
11500 c = nc;
11503 gcc_assert (map_idx == map_cnt);
11505 DECL_INITIAL (TREE_VEC_ELT (t, 1))
11506 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
11507 DECL_INITIAL (TREE_VEC_ELT (t, 2))
11508 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
11509 if (!TREE_STATIC (TREE_VEC_ELT (t, 1)))
11511 gimple_seq initlist = NULL;
11512 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
11513 TREE_VEC_ELT (t, 1)),
11514 &initlist, true, NULL_TREE);
11515 gimple_seq_add_seq (&ilist, initlist);
11517 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)),
11518 NULL);
11519 TREE_THIS_VOLATILE (clobber) = 1;
11520 gimple_seq_add_stmt (&olist,
11521 gimple_build_assign (TREE_VEC_ELT (t, 1),
11522 clobber));
11525 tree clobber = build_constructor (ctx->record_type, NULL);
11526 TREE_THIS_VOLATILE (clobber) = 1;
11527 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
11528 clobber));
11531 /* Once all the expansions are done, sequence all the different
11532 fragments inside gimple_omp_body. */
11534 new_body = NULL;
11536 if (offloaded
11537 && ctx->record_type)
11539 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
11540 /* fixup_child_record_type might have changed receiver_decl's type. */
11541 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
11542 gimple_seq_add_stmt (&new_body,
11543 gimple_build_assign (ctx->receiver_decl, t));
11546 if (offloaded)
11548 gimple_seq_add_seq (&new_body, tgt_body);
11549 new_body = maybe_catch_exception (new_body);
11551 else if (data_region)
11552 new_body = tgt_body;
11553 if (offloaded || data_region)
11555 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
11556 gimple_omp_set_body (stmt, new_body);
11559 bind = gimple_build_bind (NULL, NULL,
11560 tgt_bind ? gimple_bind_block (tgt_bind)
11561 : NULL_TREE);
11562 gsi_replace (gsi_p, bind, true);
11563 gimple_bind_add_seq (bind, irlist);
11564 gimple_bind_add_seq (bind, ilist);
11565 gimple_bind_add_stmt (bind, stmt);
11566 gimple_bind_add_seq (bind, olist);
11567 gimple_bind_add_seq (bind, orlist);
11569 pop_gimplify_context (NULL);
11572 /* Expand code for an OpenMP teams directive. */
11574 static void
11575 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11577 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
11578 push_gimplify_context ();
11580 tree block = make_node (BLOCK);
11581 gbind *bind = gimple_build_bind (NULL, NULL, block);
11582 gsi_replace (gsi_p, bind, true);
11583 gimple_seq bind_body = NULL;
11584 gimple_seq dlist = NULL;
11585 gimple_seq olist = NULL;
11587 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11588 OMP_CLAUSE_NUM_TEAMS);
11589 if (num_teams == NULL_TREE)
11590 num_teams = build_int_cst (unsigned_type_node, 0);
11591 else
11593 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
11594 num_teams = fold_convert (unsigned_type_node, num_teams);
11595 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
11597 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
11598 OMP_CLAUSE_THREAD_LIMIT);
11599 if (thread_limit == NULL_TREE)
11600 thread_limit = build_int_cst (unsigned_type_node, 0);
11601 else
11603 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
11604 thread_limit = fold_convert (unsigned_type_node, thread_limit);
11605 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
11606 fb_rvalue);
11609 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
11610 &bind_body, &dlist, ctx, NULL);
11611 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
11612 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
11613 gimple_seq_add_stmt (&bind_body, teams_stmt);
11615 location_t loc = gimple_location (teams_stmt);
11616 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
11617 gimple call = gimple_build_call (decl, 2, num_teams, thread_limit);
11618 gimple_set_location (call, loc);
11619 gimple_seq_add_stmt (&bind_body, call);
11621 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
11622 gimple_omp_set_body (teams_stmt, NULL);
11623 gimple_seq_add_seq (&bind_body, olist);
11624 gimple_seq_add_seq (&bind_body, dlist);
11625 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
11626 gimple_bind_set_body (bind, bind_body);
11628 pop_gimplify_context (bind);
11630 gimple_bind_append_vars (bind, ctx->block_vars);
11631 BLOCK_VARS (block) = ctx->block_vars;
11632 if (BLOCK_VARS (block))
11633 TREE_USED (block) = 1;
11637 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
11638 regimplified. If DATA is non-NULL, lower_omp_1 is outside
11639 of OMP context, but with task_shared_vars set. */
11641 static tree
11642 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
11643 void *data)
11645 tree t = *tp;
11647 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
11648 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
11649 return t;
11651 if (task_shared_vars
11652 && DECL_P (t)
11653 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
11654 return t;
11656 /* If a global variable has been privatized, TREE_CONSTANT on
11657 ADDR_EXPR might be wrong. */
11658 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
11659 recompute_tree_invariant_for_addr_expr (t);
11661 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
11662 return NULL_TREE;
11665 static void
11666 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
11668 gimple stmt = gsi_stmt (*gsi_p);
11669 struct walk_stmt_info wi;
11670 gcall *call_stmt;
11672 if (gimple_has_location (stmt))
11673 input_location = gimple_location (stmt);
11675 if (task_shared_vars)
11676 memset (&wi, '\0', sizeof (wi));
11678 /* If we have issued syntax errors, avoid doing any heavy lifting.
11679 Just replace the OMP directives with a NOP to avoid
11680 confusing RTL expansion. */
11681 if (seen_error () && is_gimple_omp (stmt))
11683 gsi_replace (gsi_p, gimple_build_nop (), true);
11684 return;
11687 switch (gimple_code (stmt))
11689 case GIMPLE_COND:
11691 gcond *cond_stmt = as_a <gcond *> (stmt);
11692 if ((ctx || task_shared_vars)
11693 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
11694 lower_omp_regimplify_p,
11695 ctx ? NULL : &wi, NULL)
11696 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
11697 lower_omp_regimplify_p,
11698 ctx ? NULL : &wi, NULL)))
11699 gimple_regimplify_operands (cond_stmt, gsi_p);
11701 break;
11702 case GIMPLE_CATCH:
11703 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
11704 break;
11705 case GIMPLE_EH_FILTER:
11706 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
11707 break;
11708 case GIMPLE_TRY:
11709 lower_omp (gimple_try_eval_ptr (stmt), ctx);
11710 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
11711 break;
11712 case GIMPLE_TRANSACTION:
11713 lower_omp (gimple_transaction_body_ptr (
11714 as_a <gtransaction *> (stmt)),
11715 ctx);
11716 break;
11717 case GIMPLE_BIND:
11718 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
11719 break;
11720 case GIMPLE_OMP_PARALLEL:
11721 case GIMPLE_OMP_TASK:
11722 ctx = maybe_lookup_ctx (stmt);
11723 gcc_assert (ctx);
11724 if (ctx->cancellable)
11725 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11726 lower_omp_taskreg (gsi_p, ctx);
11727 break;
11728 case GIMPLE_OMP_FOR:
11729 ctx = maybe_lookup_ctx (stmt);
11730 gcc_assert (ctx);
11731 if (ctx->cancellable)
11732 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11733 lower_omp_for (gsi_p, ctx);
11734 break;
11735 case GIMPLE_OMP_SECTIONS:
11736 ctx = maybe_lookup_ctx (stmt);
11737 gcc_assert (ctx);
11738 if (ctx->cancellable)
11739 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
11740 lower_omp_sections (gsi_p, ctx);
11741 break;
11742 case GIMPLE_OMP_SINGLE:
11743 ctx = maybe_lookup_ctx (stmt);
11744 gcc_assert (ctx);
11745 lower_omp_single (gsi_p, ctx);
11746 break;
11747 case GIMPLE_OMP_MASTER:
11748 ctx = maybe_lookup_ctx (stmt);
11749 gcc_assert (ctx);
11750 lower_omp_master (gsi_p, ctx);
11751 break;
11752 case GIMPLE_OMP_TASKGROUP:
11753 ctx = maybe_lookup_ctx (stmt);
11754 gcc_assert (ctx);
11755 lower_omp_taskgroup (gsi_p, ctx);
11756 break;
11757 case GIMPLE_OMP_ORDERED:
11758 ctx = maybe_lookup_ctx (stmt);
11759 gcc_assert (ctx);
11760 lower_omp_ordered (gsi_p, ctx);
11761 break;
11762 case GIMPLE_OMP_CRITICAL:
11763 ctx = maybe_lookup_ctx (stmt);
11764 gcc_assert (ctx);
11765 lower_omp_critical (gsi_p, ctx);
11766 break;
11767 case GIMPLE_OMP_ATOMIC_LOAD:
11768 if ((ctx || task_shared_vars)
11769 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
11770 as_a <gomp_atomic_load *> (stmt)),
11771 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
11772 gimple_regimplify_operands (stmt, gsi_p);
11773 break;
11774 case GIMPLE_OMP_TARGET:
11775 ctx = maybe_lookup_ctx (stmt);
11776 gcc_assert (ctx);
11777 lower_omp_target (gsi_p, ctx);
11778 break;
11779 case GIMPLE_OMP_TEAMS:
11780 ctx = maybe_lookup_ctx (stmt);
11781 gcc_assert (ctx);
11782 lower_omp_teams (gsi_p, ctx);
11783 break;
11784 case GIMPLE_CALL:
11785 tree fndecl;
11786 call_stmt = as_a <gcall *> (stmt);
11787 fndecl = gimple_call_fndecl (call_stmt);
11788 if (fndecl
11789 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
11790 switch (DECL_FUNCTION_CODE (fndecl))
11792 case BUILT_IN_GOMP_BARRIER:
11793 if (ctx == NULL)
11794 break;
11795 /* FALLTHRU */
11796 case BUILT_IN_GOMP_CANCEL:
11797 case BUILT_IN_GOMP_CANCELLATION_POINT:
11798 omp_context *cctx;
11799 cctx = ctx;
11800 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
11801 cctx = cctx->outer;
11802 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
11803 if (!cctx->cancellable)
11805 if (DECL_FUNCTION_CODE (fndecl)
11806 == BUILT_IN_GOMP_CANCELLATION_POINT)
11808 stmt = gimple_build_nop ();
11809 gsi_replace (gsi_p, stmt, false);
11811 break;
11813 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
11815 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
11816 gimple_call_set_fndecl (call_stmt, fndecl);
11817 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
11819 tree lhs;
11820 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
11821 gimple_call_set_lhs (call_stmt, lhs);
11822 tree fallthru_label;
11823 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
11824 gimple g;
11825 g = gimple_build_label (fallthru_label);
11826 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11827 g = gimple_build_cond (NE_EXPR, lhs,
11828 fold_convert (TREE_TYPE (lhs),
11829 boolean_false_node),
11830 cctx->cancel_label, fallthru_label);
11831 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
11832 break;
11833 default:
11834 break;
11836 /* FALLTHRU */
11837 default:
11838 if ((ctx || task_shared_vars)
11839 && walk_gimple_op (stmt, lower_omp_regimplify_p,
11840 ctx ? NULL : &wi))
11842 /* Just remove clobbers, this should happen only if we have
11843 "privatized" local addressable variables in SIMD regions,
11844 the clobber isn't needed in that case and gimplifying address
11845 of the ARRAY_REF into a pointer and creating MEM_REF based
11846 clobber would create worse code than we get with the clobber
11847 dropped. */
11848 if (gimple_clobber_p (stmt))
11850 gsi_replace (gsi_p, gimple_build_nop (), true);
11851 break;
11853 gimple_regimplify_operands (stmt, gsi_p);
11855 break;
11859 static void
11860 lower_omp (gimple_seq *body, omp_context *ctx)
11862 location_t saved_location = input_location;
11863 gimple_stmt_iterator gsi;
11864 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11865 lower_omp_1 (&gsi, ctx);
11866 /* During gimplification, we haven't folded statments inside offloading
11867 regions (gimplify.c:maybe_fold_stmt); do that now. */
11868 if (target_nesting_level)
11869 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
11870 fold_stmt (&gsi);
11871 input_location = saved_location;
11874 /* Main entry point. */
11876 static unsigned int
11877 execute_lower_omp (void)
11879 gimple_seq body;
11880 int i;
11881 omp_context *ctx;
11883 /* This pass always runs, to provide PROP_gimple_lomp.
11884 But often, there is nothing to do. */
11885 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
11886 && flag_openmp_simd == 0)
11887 return 0;
11889 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
11890 delete_omp_context);
11892 body = gimple_body (current_function_decl);
11893 scan_omp (&body, NULL);
11894 gcc_assert (taskreg_nesting_level == 0);
11895 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
11896 finish_taskreg_scan (ctx);
11897 taskreg_contexts.release ();
11899 if (all_contexts->root)
11901 if (task_shared_vars)
11902 push_gimplify_context ();
11903 lower_omp (&body, NULL);
11904 if (task_shared_vars)
11905 pop_gimplify_context (NULL);
11908 if (all_contexts)
11910 splay_tree_delete (all_contexts);
11911 all_contexts = NULL;
11913 BITMAP_FREE (task_shared_vars);
11914 return 0;
11917 namespace {
11919 const pass_data pass_data_lower_omp =
11921 GIMPLE_PASS, /* type */
11922 "omplower", /* name */
11923 OPTGROUP_NONE, /* optinfo_flags */
11924 TV_NONE, /* tv_id */
11925 PROP_gimple_any, /* properties_required */
11926 PROP_gimple_lomp, /* properties_provided */
11927 0, /* properties_destroyed */
11928 0, /* todo_flags_start */
11929 0, /* todo_flags_finish */
11932 class pass_lower_omp : public gimple_opt_pass
11934 public:
11935 pass_lower_omp (gcc::context *ctxt)
11936 : gimple_opt_pass (pass_data_lower_omp, ctxt)
11939 /* opt_pass methods: */
11940 virtual unsigned int execute (function *) { return execute_lower_omp (); }
11942 }; // class pass_lower_omp
11944 } // anon namespace
11946 gimple_opt_pass *
11947 make_pass_lower_omp (gcc::context *ctxt)
11949 return new pass_lower_omp (ctxt);
11952 /* The following is a utility to diagnose structured block violations.
11953 It is not part of the "omplower" pass, as that's invoked too late. It
11954 should be invoked by the respective front ends after gimplification. */
11956 static splay_tree all_labels;
11958 /* Check for mismatched contexts and generate an error if needed. Return
11959 true if an error is detected. */
11961 static bool
11962 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
11963 gimple branch_ctx, gimple label_ctx)
11965 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
11966 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
11968 if (label_ctx == branch_ctx)
11969 return false;
11971 const char* kind = NULL;
11973 if (flag_cilkplus)
11975 if ((branch_ctx
11976 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
11977 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
11978 || (label_ctx
11979 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
11980 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
11981 kind = "Cilk Plus";
11983 if (flag_openacc)
11985 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
11986 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
11988 gcc_checking_assert (kind == NULL);
11989 kind = "OpenACC";
11992 if (kind == NULL)
11994 gcc_checking_assert (flag_openmp);
11995 kind = "OpenMP";
11999 Previously we kept track of the label's entire context in diagnose_sb_[12]
12000 so we could traverse it and issue a correct "exit" or "enter" error
12001 message upon a structured block violation.
12003 We built the context by building a list with tree_cons'ing, but there is
12004 no easy counterpart in gimple tuples. It seems like far too much work
12005 for issuing exit/enter error messages. If someone really misses the
12006 distinct error message... patches welcome.
12009 #if 0
12010 /* Try to avoid confusing the user by producing and error message
12011 with correct "exit" or "enter" verbiage. We prefer "exit"
12012 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
12013 if (branch_ctx == NULL)
12014 exit_p = false;
12015 else
12017 while (label_ctx)
12019 if (TREE_VALUE (label_ctx) == branch_ctx)
12021 exit_p = false;
12022 break;
12024 label_ctx = TREE_CHAIN (label_ctx);
12028 if (exit_p)
12029 error ("invalid exit from %s structured block", kind);
12030 else
12031 error ("invalid entry to %s structured block", kind);
12032 #endif
12034 /* If it's obvious we have an invalid entry, be specific about the error. */
12035 if (branch_ctx == NULL)
12036 error ("invalid entry to %s structured block", kind);
12037 else
12039 /* Otherwise, be vague and lazy, but efficient. */
12040 error ("invalid branch to/from %s structured block", kind);
12043 gsi_replace (gsi_p, gimple_build_nop (), false);
12044 return true;
12047 /* Pass 1: Create a minimal tree of structured blocks, and record
12048 where each label is found. */
12050 static tree
12051 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12052 struct walk_stmt_info *wi)
12054 gimple context = (gimple) wi->info;
12055 gimple inner_context;
12056 gimple stmt = gsi_stmt (*gsi_p);
12058 *handled_ops_p = true;
12060 switch (gimple_code (stmt))
12062 WALK_SUBSTMTS;
12064 case GIMPLE_OMP_PARALLEL:
12065 case GIMPLE_OMP_TASK:
12066 case GIMPLE_OMP_SECTIONS:
12067 case GIMPLE_OMP_SINGLE:
12068 case GIMPLE_OMP_SECTION:
12069 case GIMPLE_OMP_MASTER:
12070 case GIMPLE_OMP_ORDERED:
12071 case GIMPLE_OMP_CRITICAL:
12072 case GIMPLE_OMP_TARGET:
12073 case GIMPLE_OMP_TEAMS:
12074 case GIMPLE_OMP_TASKGROUP:
12075 /* The minimal context here is just the current OMP construct. */
12076 inner_context = stmt;
12077 wi->info = inner_context;
12078 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12079 wi->info = context;
12080 break;
12082 case GIMPLE_OMP_FOR:
12083 inner_context = stmt;
12084 wi->info = inner_context;
12085 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12086 walk them. */
12087 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
12088 diagnose_sb_1, NULL, wi);
12089 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
12090 wi->info = context;
12091 break;
12093 case GIMPLE_LABEL:
12094 splay_tree_insert (all_labels,
12095 (splay_tree_key) gimple_label_label (
12096 as_a <glabel *> (stmt)),
12097 (splay_tree_value) context);
12098 break;
12100 default:
12101 break;
12104 return NULL_TREE;
12107 /* Pass 2: Check each branch and see if its context differs from that of
12108 the destination label's context. */
12110 static tree
12111 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
12112 struct walk_stmt_info *wi)
12114 gimple context = (gimple) wi->info;
12115 splay_tree_node n;
12116 gimple stmt = gsi_stmt (*gsi_p);
12118 *handled_ops_p = true;
12120 switch (gimple_code (stmt))
12122 WALK_SUBSTMTS;
12124 case GIMPLE_OMP_PARALLEL:
12125 case GIMPLE_OMP_TASK:
12126 case GIMPLE_OMP_SECTIONS:
12127 case GIMPLE_OMP_SINGLE:
12128 case GIMPLE_OMP_SECTION:
12129 case GIMPLE_OMP_MASTER:
12130 case GIMPLE_OMP_ORDERED:
12131 case GIMPLE_OMP_CRITICAL:
12132 case GIMPLE_OMP_TARGET:
12133 case GIMPLE_OMP_TEAMS:
12134 case GIMPLE_OMP_TASKGROUP:
12135 wi->info = stmt;
12136 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12137 wi->info = context;
12138 break;
12140 case GIMPLE_OMP_FOR:
12141 wi->info = stmt;
12142 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
12143 walk them. */
12144 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
12145 diagnose_sb_2, NULL, wi);
12146 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
12147 wi->info = context;
12148 break;
12150 case GIMPLE_COND:
12152 gcond *cond_stmt = as_a <gcond *> (stmt);
12153 tree lab = gimple_cond_true_label (cond_stmt);
12154 if (lab)
12156 n = splay_tree_lookup (all_labels,
12157 (splay_tree_key) lab);
12158 diagnose_sb_0 (gsi_p, context,
12159 n ? (gimple) n->value : NULL);
12161 lab = gimple_cond_false_label (cond_stmt);
12162 if (lab)
12164 n = splay_tree_lookup (all_labels,
12165 (splay_tree_key) lab);
12166 diagnose_sb_0 (gsi_p, context,
12167 n ? (gimple) n->value : NULL);
12170 break;
12172 case GIMPLE_GOTO:
12174 tree lab = gimple_goto_dest (stmt);
12175 if (TREE_CODE (lab) != LABEL_DECL)
12176 break;
12178 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12179 diagnose_sb_0 (gsi_p, context, n ? (gimple) n->value : NULL);
12181 break;
12183 case GIMPLE_SWITCH:
12185 gswitch *switch_stmt = as_a <gswitch *> (stmt);
12186 unsigned int i;
12187 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
12189 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
12190 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
12191 if (n && diagnose_sb_0 (gsi_p, context, (gimple) n->value))
12192 break;
12195 break;
12197 case GIMPLE_RETURN:
12198 diagnose_sb_0 (gsi_p, context, NULL);
12199 break;
12201 default:
12202 break;
12205 return NULL_TREE;
12208 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
12209 GIMPLE_* codes. */
12210 bool
12211 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
12212 int *region_idx)
12214 gimple last = last_stmt (bb);
12215 enum gimple_code code = gimple_code (last);
12216 struct omp_region *cur_region = *region;
12217 bool fallthru = false;
12219 switch (code)
12221 case GIMPLE_OMP_PARALLEL:
12222 case GIMPLE_OMP_TASK:
12223 case GIMPLE_OMP_FOR:
12224 case GIMPLE_OMP_SINGLE:
12225 case GIMPLE_OMP_TEAMS:
12226 case GIMPLE_OMP_MASTER:
12227 case GIMPLE_OMP_TASKGROUP:
12228 case GIMPLE_OMP_ORDERED:
12229 case GIMPLE_OMP_CRITICAL:
12230 case GIMPLE_OMP_SECTION:
12231 cur_region = new_omp_region (bb, code, cur_region);
12232 fallthru = true;
12233 break;
12235 case GIMPLE_OMP_TARGET:
12236 cur_region = new_omp_region (bb, code, cur_region);
12237 fallthru = true;
12238 switch (gimple_omp_target_kind (last))
12240 case GF_OMP_TARGET_KIND_REGION:
12241 case GF_OMP_TARGET_KIND_DATA:
12242 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12243 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12244 case GF_OMP_TARGET_KIND_OACC_DATA:
12245 break;
12246 case GF_OMP_TARGET_KIND_UPDATE:
12247 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12248 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12249 cur_region = cur_region->outer;
12250 break;
12251 default:
12252 gcc_unreachable ();
12254 break;
12256 case GIMPLE_OMP_SECTIONS:
12257 cur_region = new_omp_region (bb, code, cur_region);
12258 fallthru = true;
12259 break;
12261 case GIMPLE_OMP_SECTIONS_SWITCH:
12262 fallthru = false;
12263 break;
12265 case GIMPLE_OMP_ATOMIC_LOAD:
12266 case GIMPLE_OMP_ATOMIC_STORE:
12267 fallthru = true;
12268 break;
12270 case GIMPLE_OMP_RETURN:
12271 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
12272 somewhere other than the next block. This will be
12273 created later. */
12274 cur_region->exit = bb;
12275 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
12276 cur_region = cur_region->outer;
12277 break;
12279 case GIMPLE_OMP_CONTINUE:
12280 cur_region->cont = bb;
12281 switch (cur_region->type)
12283 case GIMPLE_OMP_FOR:
12284 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
12285 succs edges as abnormal to prevent splitting
12286 them. */
12287 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
12288 /* Make the loopback edge. */
12289 make_edge (bb, single_succ (cur_region->entry),
12290 EDGE_ABNORMAL);
12292 /* Create an edge from GIMPLE_OMP_FOR to exit, which
12293 corresponds to the case that the body of the loop
12294 is not executed at all. */
12295 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
12296 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
12297 fallthru = false;
12298 break;
12300 case GIMPLE_OMP_SECTIONS:
12301 /* Wire up the edges into and out of the nested sections. */
12303 basic_block switch_bb = single_succ (cur_region->entry);
12305 struct omp_region *i;
12306 for (i = cur_region->inner; i ; i = i->next)
12308 gcc_assert (i->type == GIMPLE_OMP_SECTION);
12309 make_edge (switch_bb, i->entry, 0);
12310 make_edge (i->exit, bb, EDGE_FALLTHRU);
12313 /* Make the loopback edge to the block with
12314 GIMPLE_OMP_SECTIONS_SWITCH. */
12315 make_edge (bb, switch_bb, 0);
12317 /* Make the edge from the switch to exit. */
12318 make_edge (switch_bb, bb->next_bb, 0);
12319 fallthru = false;
12321 break;
12323 default:
12324 gcc_unreachable ();
12326 break;
12328 default:
12329 gcc_unreachable ();
12332 if (*region != cur_region)
12334 *region = cur_region;
12335 if (cur_region)
12336 *region_idx = cur_region->entry->index;
12337 else
12338 *region_idx = 0;
12341 return fallthru;
12344 static unsigned int
12345 diagnose_omp_structured_block_errors (void)
12347 struct walk_stmt_info wi;
12348 gimple_seq body = gimple_body (current_function_decl);
12350 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
12352 memset (&wi, 0, sizeof (wi));
12353 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
12355 memset (&wi, 0, sizeof (wi));
12356 wi.want_locations = true;
12357 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
12359 gimple_set_body (current_function_decl, body);
12361 splay_tree_delete (all_labels);
12362 all_labels = NULL;
12364 return 0;
12367 namespace {
12369 const pass_data pass_data_diagnose_omp_blocks =
12371 GIMPLE_PASS, /* type */
12372 "*diagnose_omp_blocks", /* name */
12373 OPTGROUP_NONE, /* optinfo_flags */
12374 TV_NONE, /* tv_id */
12375 PROP_gimple_any, /* properties_required */
12376 0, /* properties_provided */
12377 0, /* properties_destroyed */
12378 0, /* todo_flags_start */
12379 0, /* todo_flags_finish */
12382 class pass_diagnose_omp_blocks : public gimple_opt_pass
12384 public:
12385 pass_diagnose_omp_blocks (gcc::context *ctxt)
12386 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
12389 /* opt_pass methods: */
12390 virtual bool gate (function *)
12392 return flag_cilkplus || flag_openacc || flag_openmp;
12394 virtual unsigned int execute (function *)
12396 return diagnose_omp_structured_block_errors ();
12399 }; // class pass_diagnose_omp_blocks
12401 } // anon namespace
12403 gimple_opt_pass *
12404 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
12406 return new pass_diagnose_omp_blocks (ctxt);
12409 /* SIMD clone supporting code. */
12411 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
12412 of arguments to reserve space for. */
12414 static struct cgraph_simd_clone *
12415 simd_clone_struct_alloc (int nargs)
12417 struct cgraph_simd_clone *clone_info;
12418 size_t len = (sizeof (struct cgraph_simd_clone)
12419 + nargs * sizeof (struct cgraph_simd_clone_arg));
12420 clone_info = (struct cgraph_simd_clone *)
12421 ggc_internal_cleared_alloc (len);
12422 return clone_info;
12425 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
12427 static inline void
12428 simd_clone_struct_copy (struct cgraph_simd_clone *to,
12429 struct cgraph_simd_clone *from)
12431 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
12432 + ((from->nargs - from->inbranch)
12433 * sizeof (struct cgraph_simd_clone_arg))));
12436 /* Return vector of parameter types of function FNDECL. This uses
12437 TYPE_ARG_TYPES if available, otherwise falls back to types of
12438 DECL_ARGUMENTS types. */
12440 vec<tree>
12441 simd_clone_vector_of_formal_parm_types (tree fndecl)
12443 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
12444 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
12445 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
12446 unsigned int i;
12447 tree arg;
12448 FOR_EACH_VEC_ELT (args, i, arg)
12449 args[i] = TREE_TYPE (args[i]);
12450 return args;
12453 /* Given a simd function in NODE, extract the simd specific
12454 information from the OMP clauses passed in CLAUSES, and return
12455 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
12456 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
12457 otherwise set to FALSE. */
12459 static struct cgraph_simd_clone *
12460 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
12461 bool *inbranch_specified)
12463 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
12464 tree t;
12465 int n;
12466 *inbranch_specified = false;
12468 n = args.length ();
12469 if (n > 0 && args.last () == void_type_node)
12470 n--;
12472 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
12473 be cloned have a distinctive artificial label in addition to "omp
12474 declare simd". */
12475 bool cilk_clone
12476 = (flag_cilkplus
12477 && lookup_attribute ("cilk simd function",
12478 DECL_ATTRIBUTES (node->decl)));
12480 /* Allocate one more than needed just in case this is an in-branch
12481 clone which will require a mask argument. */
12482 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
12483 clone_info->nargs = n;
12484 clone_info->cilk_elemental = cilk_clone;
12486 if (!clauses)
12488 args.release ();
12489 return clone_info;
12491 clauses = TREE_VALUE (clauses);
12492 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
12493 return clone_info;
12495 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
12497 switch (OMP_CLAUSE_CODE (t))
12499 case OMP_CLAUSE_INBRANCH:
12500 clone_info->inbranch = 1;
12501 *inbranch_specified = true;
12502 break;
12503 case OMP_CLAUSE_NOTINBRANCH:
12504 clone_info->inbranch = 0;
12505 *inbranch_specified = true;
12506 break;
12507 case OMP_CLAUSE_SIMDLEN:
12508 clone_info->simdlen
12509 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
12510 break;
12511 case OMP_CLAUSE_LINEAR:
12513 tree decl = OMP_CLAUSE_DECL (t);
12514 tree step = OMP_CLAUSE_LINEAR_STEP (t);
12515 int argno = TREE_INT_CST_LOW (decl);
12516 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
12518 clone_info->args[argno].arg_type
12519 = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
12520 clone_info->args[argno].linear_step = tree_to_shwi (step);
12521 gcc_assert (clone_info->args[argno].linear_step >= 0
12522 && clone_info->args[argno].linear_step < n);
12524 else
12526 if (POINTER_TYPE_P (args[argno]))
12527 step = fold_convert (ssizetype, step);
12528 if (!tree_fits_shwi_p (step))
12530 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12531 "ignoring large linear step");
12532 args.release ();
12533 return NULL;
12535 else if (integer_zerop (step))
12537 warning_at (OMP_CLAUSE_LOCATION (t), 0,
12538 "ignoring zero linear step");
12539 args.release ();
12540 return NULL;
12542 else
12544 clone_info->args[argno].arg_type
12545 = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
12546 clone_info->args[argno].linear_step = tree_to_shwi (step);
12549 break;
12551 case OMP_CLAUSE_UNIFORM:
12553 tree decl = OMP_CLAUSE_DECL (t);
12554 int argno = tree_to_uhwi (decl);
12555 clone_info->args[argno].arg_type
12556 = SIMD_CLONE_ARG_TYPE_UNIFORM;
12557 break;
12559 case OMP_CLAUSE_ALIGNED:
12561 tree decl = OMP_CLAUSE_DECL (t);
12562 int argno = tree_to_uhwi (decl);
12563 clone_info->args[argno].alignment
12564 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
12565 break;
12567 default:
12568 break;
12571 args.release ();
12572 return clone_info;
12575 /* Given a SIMD clone in NODE, calculate the characteristic data
12576 type and return the coresponding type. The characteristic data
12577 type is computed as described in the Intel Vector ABI. */
12579 static tree
12580 simd_clone_compute_base_data_type (struct cgraph_node *node,
12581 struct cgraph_simd_clone *clone_info)
12583 tree type = integer_type_node;
12584 tree fndecl = node->decl;
12586 /* a) For non-void function, the characteristic data type is the
12587 return type. */
12588 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
12589 type = TREE_TYPE (TREE_TYPE (fndecl));
12591 /* b) If the function has any non-uniform, non-linear parameters,
12592 then the characteristic data type is the type of the first
12593 such parameter. */
12594 else
12596 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
12597 for (unsigned int i = 0; i < clone_info->nargs; ++i)
12598 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
12600 type = map[i];
12601 break;
12603 map.release ();
12606 /* c) If the characteristic data type determined by a) or b) above
12607 is struct, union, or class type which is pass-by-value (except
12608 for the type that maps to the built-in complex data type), the
12609 characteristic data type is int. */
12610 if (RECORD_OR_UNION_TYPE_P (type)
12611 && !aggregate_value_p (type, NULL)
12612 && TREE_CODE (type) != COMPLEX_TYPE)
12613 return integer_type_node;
12615 /* d) If none of the above three classes is applicable, the
12616 characteristic data type is int. */
12618 return type;
12620 /* e) For Intel Xeon Phi native and offload compilation, if the
12621 resulting characteristic data type is 8-bit or 16-bit integer
12622 data type, the characteristic data type is int. */
12623 /* Well, we don't handle Xeon Phi yet. */
12626 static tree
12627 simd_clone_mangle (struct cgraph_node *node,
12628 struct cgraph_simd_clone *clone_info)
12630 char vecsize_mangle = clone_info->vecsize_mangle;
12631 char mask = clone_info->inbranch ? 'M' : 'N';
12632 unsigned int simdlen = clone_info->simdlen;
12633 unsigned int n;
12634 pretty_printer pp;
12636 gcc_assert (vecsize_mangle && simdlen);
12638 pp_string (&pp, "_ZGV");
12639 pp_character (&pp, vecsize_mangle);
12640 pp_character (&pp, mask);
12641 pp_decimal_int (&pp, simdlen);
12643 for (n = 0; n < clone_info->nargs; ++n)
12645 struct cgraph_simd_clone_arg arg = clone_info->args[n];
12647 if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM)
12648 pp_character (&pp, 'u');
12649 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
12651 gcc_assert (arg.linear_step != 0);
12652 pp_character (&pp, 'l');
12653 if (arg.linear_step > 1)
12654 pp_unsigned_wide_integer (&pp, arg.linear_step);
12655 else if (arg.linear_step < 0)
12657 pp_character (&pp, 'n');
12658 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
12659 arg.linear_step));
12662 else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
12664 pp_character (&pp, 's');
12665 pp_unsigned_wide_integer (&pp, arg.linear_step);
12667 else
12668 pp_character (&pp, 'v');
12669 if (arg.alignment)
12671 pp_character (&pp, 'a');
12672 pp_decimal_int (&pp, arg.alignment);
12676 pp_underscore (&pp);
12677 pp_string (&pp,
12678 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)));
12679 const char *str = pp_formatted_text (&pp);
12681 /* If there already is a SIMD clone with the same mangled name, don't
12682 add another one. This can happen e.g. for
12683 #pragma omp declare simd
12684 #pragma omp declare simd simdlen(8)
12685 int foo (int, int);
12686 if the simdlen is assumed to be 8 for the first one, etc. */
12687 for (struct cgraph_node *clone = node->simd_clones; clone;
12688 clone = clone->simdclone->next_clone)
12689 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
12690 str) == 0)
12691 return NULL_TREE;
12693 return get_identifier (str);
12696 /* Create a simd clone of OLD_NODE and return it. */
12698 static struct cgraph_node *
12699 simd_clone_create (struct cgraph_node *old_node)
12701 struct cgraph_node *new_node;
12702 if (old_node->definition)
12704 if (!old_node->has_gimple_body_p ())
12705 return NULL;
12706 old_node->get_body ();
12707 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
12708 false, NULL, NULL,
12709 "simdclone");
12711 else
12713 tree old_decl = old_node->decl;
12714 tree new_decl = copy_node (old_node->decl);
12715 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
12716 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
12717 SET_DECL_RTL (new_decl, NULL);
12718 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
12719 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
12720 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
12721 symtab->call_cgraph_insertion_hooks (new_node);
12723 if (new_node == NULL)
12724 return new_node;
12726 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
12728 /* The function cgraph_function_versioning () will force the new
12729 symbol local. Undo this, and inherit external visability from
12730 the old node. */
12731 new_node->local.local = old_node->local.local;
12732 new_node->externally_visible = old_node->externally_visible;
12734 return new_node;
12737 /* Adjust the return type of the given function to its appropriate
12738 vector counterpart. Returns a simd array to be used throughout the
12739 function as a return value. */
12741 static tree
12742 simd_clone_adjust_return_type (struct cgraph_node *node)
12744 tree fndecl = node->decl;
12745 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
12746 unsigned int veclen;
12747 tree t;
12749 /* Adjust the function return type. */
12750 if (orig_rettype == void_type_node)
12751 return NULL_TREE;
12752 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
12753 t = TREE_TYPE (TREE_TYPE (fndecl));
12754 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
12755 veclen = node->simdclone->vecsize_int;
12756 else
12757 veclen = node->simdclone->vecsize_float;
12758 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
12759 if (veclen > node->simdclone->simdlen)
12760 veclen = node->simdclone->simdlen;
12761 if (POINTER_TYPE_P (t))
12762 t = pointer_sized_int_node;
12763 if (veclen == node->simdclone->simdlen)
12764 t = build_vector_type (t, node->simdclone->simdlen);
12765 else
12767 t = build_vector_type (t, veclen);
12768 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
12770 TREE_TYPE (TREE_TYPE (fndecl)) = t;
12771 if (!node->definition)
12772 return NULL_TREE;
12774 t = DECL_RESULT (fndecl);
12775 /* Adjust the DECL_RESULT. */
12776 gcc_assert (TREE_TYPE (t) != void_type_node);
12777 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
12778 relayout_decl (t);
12780 tree atype = build_array_type_nelts (orig_rettype,
12781 node->simdclone->simdlen);
12782 if (veclen != node->simdclone->simdlen)
12783 return build1 (VIEW_CONVERT_EXPR, atype, t);
12785 /* Set up a SIMD array to use as the return value. */
12786 tree retval = create_tmp_var_raw (atype, "retval");
12787 gimple_add_tmp_var (retval);
12788 return retval;
12791 /* Each vector argument has a corresponding array to be used locally
12792 as part of the eventual loop. Create such temporary array and
12793 return it.
12795 PREFIX is the prefix to be used for the temporary.
12797 TYPE is the inner element type.
12799 SIMDLEN is the number of elements. */
12801 static tree
12802 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
12804 tree atype = build_array_type_nelts (type, simdlen);
12805 tree avar = create_tmp_var_raw (atype, prefix);
12806 gimple_add_tmp_var (avar);
12807 return avar;
12810 /* Modify the function argument types to their corresponding vector
12811 counterparts if appropriate. Also, create one array for each simd
12812 argument to be used locally when using the function arguments as
12813 part of the loop.
12815 NODE is the function whose arguments are to be adjusted.
12817 Returns an adjustment vector that will be filled describing how the
12818 argument types will be adjusted. */
12820 static ipa_parm_adjustment_vec
12821 simd_clone_adjust_argument_types (struct cgraph_node *node)
12823 vec<tree> args;
12824 ipa_parm_adjustment_vec adjustments;
12826 if (node->definition)
12827 args = ipa_get_vector_of_formal_parms (node->decl);
12828 else
12829 args = simd_clone_vector_of_formal_parm_types (node->decl);
12830 adjustments.create (args.length ());
12831 unsigned i, j, veclen;
12832 struct ipa_parm_adjustment adj;
12833 for (i = 0; i < node->simdclone->nargs; ++i)
12835 memset (&adj, 0, sizeof (adj));
12836 tree parm = args[i];
12837 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
12838 adj.base_index = i;
12839 adj.base = parm;
12841 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
12842 node->simdclone->args[i].orig_type = parm_type;
12844 if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR)
12846 /* No adjustment necessary for scalar arguments. */
12847 adj.op = IPA_PARM_OP_COPY;
12849 else
12851 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
12852 veclen = node->simdclone->vecsize_int;
12853 else
12854 veclen = node->simdclone->vecsize_float;
12855 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
12856 if (veclen > node->simdclone->simdlen)
12857 veclen = node->simdclone->simdlen;
12858 adj.arg_prefix = "simd";
12859 if (POINTER_TYPE_P (parm_type))
12860 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12861 else
12862 adj.type = build_vector_type (parm_type, veclen);
12863 node->simdclone->args[i].vector_type = adj.type;
12864 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12866 adjustments.safe_push (adj);
12867 if (j == veclen)
12869 memset (&adj, 0, sizeof (adj));
12870 adj.op = IPA_PARM_OP_NEW;
12871 adj.arg_prefix = "simd";
12872 adj.base_index = i;
12873 adj.type = node->simdclone->args[i].vector_type;
12877 if (node->definition)
12878 node->simdclone->args[i].simd_array
12879 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
12880 parm_type, node->simdclone->simdlen);
12882 adjustments.safe_push (adj);
12885 if (node->simdclone->inbranch)
12887 tree base_type
12888 = simd_clone_compute_base_data_type (node->simdclone->origin,
12889 node->simdclone);
12891 memset (&adj, 0, sizeof (adj));
12892 adj.op = IPA_PARM_OP_NEW;
12893 adj.arg_prefix = "mask";
12895 adj.base_index = i;
12896 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
12897 veclen = node->simdclone->vecsize_int;
12898 else
12899 veclen = node->simdclone->vecsize_float;
12900 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
12901 if (veclen > node->simdclone->simdlen)
12902 veclen = node->simdclone->simdlen;
12903 if (POINTER_TYPE_P (base_type))
12904 adj.type = build_vector_type (pointer_sized_int_node, veclen);
12905 else
12906 adj.type = build_vector_type (base_type, veclen);
12907 adjustments.safe_push (adj);
12909 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
12910 adjustments.safe_push (adj);
12912 /* We have previously allocated one extra entry for the mask. Use
12913 it and fill it. */
12914 struct cgraph_simd_clone *sc = node->simdclone;
12915 sc->nargs++;
12916 if (node->definition)
12918 sc->args[i].orig_arg
12919 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
12920 sc->args[i].simd_array
12921 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
12923 sc->args[i].orig_type = base_type;
12924 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
12927 if (node->definition)
12928 ipa_modify_formal_parameters (node->decl, adjustments);
12929 else
12931 tree new_arg_types = NULL_TREE, new_reversed;
12932 bool last_parm_void = false;
12933 if (args.length () > 0 && args.last () == void_type_node)
12934 last_parm_void = true;
12936 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
12937 j = adjustments.length ();
12938 for (i = 0; i < j; i++)
12940 struct ipa_parm_adjustment *adj = &adjustments[i];
12941 tree ptype;
12942 if (adj->op == IPA_PARM_OP_COPY)
12943 ptype = args[adj->base_index];
12944 else
12945 ptype = adj->type;
12946 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
12948 new_reversed = nreverse (new_arg_types);
12949 if (last_parm_void)
12951 if (new_reversed)
12952 TREE_CHAIN (new_arg_types) = void_list_node;
12953 else
12954 new_reversed = void_list_node;
12957 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
12958 TYPE_ARG_TYPES (new_type) = new_reversed;
12959 TREE_TYPE (node->decl) = new_type;
12961 adjustments.release ();
12963 args.release ();
12964 return adjustments;
12967 /* Initialize and copy the function arguments in NODE to their
12968 corresponding local simd arrays. Returns a fresh gimple_seq with
12969 the instruction sequence generated. */
12971 static gimple_seq
12972 simd_clone_init_simd_arrays (struct cgraph_node *node,
12973 ipa_parm_adjustment_vec adjustments)
12975 gimple_seq seq = NULL;
12976 unsigned i = 0, j = 0, k;
12978 for (tree arg = DECL_ARGUMENTS (node->decl);
12979 arg;
12980 arg = DECL_CHAIN (arg), i++, j++)
12982 if (adjustments[j].op == IPA_PARM_OP_COPY)
12983 continue;
12985 node->simdclone->args[i].vector_arg = arg;
12987 tree array = node->simdclone->args[i].simd_array;
12988 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
12990 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
12991 tree ptr = build_fold_addr_expr (array);
12992 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
12993 build_int_cst (ptype, 0));
12994 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
12995 gimplify_and_add (t, &seq);
12997 else
12999 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
13000 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
13001 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
13003 tree ptr = build_fold_addr_expr (array);
13004 int elemsize;
13005 if (k)
13007 arg = DECL_CHAIN (arg);
13008 j++;
13010 elemsize
13011 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
13012 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
13013 build_int_cst (ptype, k * elemsize));
13014 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
13015 gimplify_and_add (t, &seq);
13019 return seq;
13022 /* Callback info for ipa_simd_modify_stmt_ops below. */
13024 struct modify_stmt_info {
13025 ipa_parm_adjustment_vec adjustments;
13026 gimple stmt;
13027 /* True if the parent statement was modified by
13028 ipa_simd_modify_stmt_ops. */
13029 bool modified;
13032 /* Callback for walk_gimple_op.
13034 Adjust operands from a given statement as specified in the
13035 adjustments vector in the callback data. */
13037 static tree
13038 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
13040 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13041 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
13042 tree *orig_tp = tp;
13043 if (TREE_CODE (*tp) == ADDR_EXPR)
13044 tp = &TREE_OPERAND (*tp, 0);
13045 struct ipa_parm_adjustment *cand = NULL;
13046 if (TREE_CODE (*tp) == PARM_DECL)
13047 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
13048 else
13050 if (TYPE_P (*tp))
13051 *walk_subtrees = 0;
13054 tree repl = NULL_TREE;
13055 if (cand)
13056 repl = unshare_expr (cand->new_decl);
13057 else
13059 if (tp != orig_tp)
13061 *walk_subtrees = 0;
13062 bool modified = info->modified;
13063 info->modified = false;
13064 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
13065 if (!info->modified)
13067 info->modified = modified;
13068 return NULL_TREE;
13070 info->modified = modified;
13071 repl = *tp;
13073 else
13074 return NULL_TREE;
13077 if (tp != orig_tp)
13079 repl = build_fold_addr_expr (repl);
13080 gimple stmt;
13081 if (is_gimple_debug (info->stmt))
13083 tree vexpr = make_node (DEBUG_EXPR_DECL);
13084 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
13085 DECL_ARTIFICIAL (vexpr) = 1;
13086 TREE_TYPE (vexpr) = TREE_TYPE (repl);
13087 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
13088 repl = vexpr;
13090 else
13092 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
13093 repl = gimple_assign_lhs (stmt);
13095 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
13096 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13097 *orig_tp = repl;
13099 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
13101 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
13102 *tp = vce;
13104 else
13105 *tp = repl;
13107 info->modified = true;
13108 return NULL_TREE;
13111 /* Traverse the function body and perform all modifications as
13112 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
13113 modified such that the replacement/reduction value will now be an
13114 offset into the corresponding simd_array.
13116 This function will replace all function argument uses with their
13117 corresponding simd array elements, and ajust the return values
13118 accordingly. */
13120 static void
13121 ipa_simd_modify_function_body (struct cgraph_node *node,
13122 ipa_parm_adjustment_vec adjustments,
13123 tree retval_array, tree iter)
13125 basic_block bb;
13126 unsigned int i, j, l;
13128 /* Re-use the adjustments array, but this time use it to replace
13129 every function argument use to an offset into the corresponding
13130 simd_array. */
13131 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
13133 if (!node->simdclone->args[i].vector_arg)
13134 continue;
13136 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
13137 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
13138 adjustments[j].new_decl
13139 = build4 (ARRAY_REF,
13140 basetype,
13141 node->simdclone->args[i].simd_array,
13142 iter,
13143 NULL_TREE, NULL_TREE);
13144 if (adjustments[j].op == IPA_PARM_OP_NONE
13145 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
13146 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
13149 l = adjustments.length ();
13150 for (i = 1; i < num_ssa_names; i++)
13152 tree name = ssa_name (i);
13153 if (name
13154 && SSA_NAME_VAR (name)
13155 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
13157 for (j = 0; j < l; j++)
13158 if (SSA_NAME_VAR (name) == adjustments[j].base
13159 && adjustments[j].new_decl)
13161 tree base_var;
13162 if (adjustments[j].new_ssa_base == NULL_TREE)
13164 base_var
13165 = copy_var_decl (adjustments[j].base,
13166 DECL_NAME (adjustments[j].base),
13167 TREE_TYPE (adjustments[j].base));
13168 adjustments[j].new_ssa_base = base_var;
13170 else
13171 base_var = adjustments[j].new_ssa_base;
13172 if (SSA_NAME_IS_DEFAULT_DEF (name))
13174 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13175 gimple_stmt_iterator gsi = gsi_after_labels (bb);
13176 tree new_decl = unshare_expr (adjustments[j].new_decl);
13177 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
13178 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13179 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
13180 gimple stmt = gimple_build_assign (name, new_decl);
13181 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
13183 else
13184 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
13189 struct modify_stmt_info info;
13190 info.adjustments = adjustments;
13192 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
13194 gimple_stmt_iterator gsi;
13196 gsi = gsi_start_bb (bb);
13197 while (!gsi_end_p (gsi))
13199 gimple stmt = gsi_stmt (gsi);
13200 info.stmt = stmt;
13201 struct walk_stmt_info wi;
13203 memset (&wi, 0, sizeof (wi));
13204 info.modified = false;
13205 wi.info = &info;
13206 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
13208 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
13210 tree retval = gimple_return_retval (return_stmt);
13211 if (!retval)
13213 gsi_remove (&gsi, true);
13214 continue;
13217 /* Replace `return foo' with `retval_array[iter] = foo'. */
13218 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
13219 retval_array, iter, NULL, NULL);
13220 stmt = gimple_build_assign (ref, retval);
13221 gsi_replace (&gsi, stmt, true);
13222 info.modified = true;
13225 if (info.modified)
13227 update_stmt (stmt);
13228 if (maybe_clean_eh_stmt (stmt))
13229 gimple_purge_dead_eh_edges (gimple_bb (stmt));
13231 gsi_next (&gsi);
13236 /* Adjust the argument types in NODE to their appropriate vector
13237 counterparts. */
13239 static void
13240 simd_clone_adjust (struct cgraph_node *node)
13242 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
13244 targetm.simd_clone.adjust (node);
13246 tree retval = simd_clone_adjust_return_type (node);
13247 ipa_parm_adjustment_vec adjustments
13248 = simd_clone_adjust_argument_types (node);
13250 push_gimplify_context ();
13252 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
13254 /* Adjust all uses of vector arguments accordingly. Adjust all
13255 return values accordingly. */
13256 tree iter = create_tmp_var (unsigned_type_node, "iter");
13257 tree iter1 = make_ssa_name (iter);
13258 tree iter2 = make_ssa_name (iter);
13259 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
13261 /* Initialize the iteration variable. */
13262 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13263 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
13264 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
13265 /* Insert the SIMD array and iv initialization at function
13266 entry. */
13267 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
13269 pop_gimplify_context (NULL);
13271 /* Create a new BB right before the original exit BB, to hold the
13272 iteration increment and the condition/branch. */
13273 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
13274 basic_block incr_bb = create_empty_bb (orig_exit);
13275 add_bb_to_loop (incr_bb, body_bb->loop_father);
13276 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
13277 flag. Set it now to be a FALLTHRU_EDGE. */
13278 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
13279 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
13280 for (unsigned i = 0;
13281 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
13283 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
13284 redirect_edge_succ (e, incr_bb);
13286 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
13287 e->probability = REG_BR_PROB_BASE;
13288 gsi = gsi_last_bb (incr_bb);
13289 gimple g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
13290 build_int_cst (unsigned_type_node, 1));
13291 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13293 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
13294 struct loop *loop = alloc_loop ();
13295 cfun->has_force_vectorize_loops = true;
13296 loop->safelen = node->simdclone->simdlen;
13297 loop->force_vectorize = true;
13298 loop->header = body_bb;
13300 /* Branch around the body if the mask applies. */
13301 if (node->simdclone->inbranch)
13303 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
13304 tree mask_array
13305 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
13306 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
13307 tree aref = build4 (ARRAY_REF,
13308 TREE_TYPE (TREE_TYPE (mask_array)),
13309 mask_array, iter1,
13310 NULL, NULL);
13311 g = gimple_build_assign (mask, aref);
13312 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13313 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
13314 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
13316 aref = build1 (VIEW_CONVERT_EXPR,
13317 build_nonstandard_integer_type (bitsize, 0), mask);
13318 mask = make_ssa_name (TREE_TYPE (aref));
13319 g = gimple_build_assign (mask, aref);
13320 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13323 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
13324 NULL, NULL);
13325 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13326 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
13327 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
13330 /* Generate the condition. */
13331 g = gimple_build_cond (LT_EXPR,
13332 iter2,
13333 build_int_cst (unsigned_type_node,
13334 node->simdclone->simdlen),
13335 NULL, NULL);
13336 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13337 e = split_block (incr_bb, gsi_stmt (gsi));
13338 basic_block latch_bb = e->dest;
13339 basic_block new_exit_bb;
13340 new_exit_bb = split_block (latch_bb, NULL)->dest;
13341 loop->latch = latch_bb;
13343 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
13345 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
13346 /* The successor of incr_bb is already pointing to latch_bb; just
13347 change the flags.
13348 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
13349 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
13351 gphi *phi = create_phi_node (iter1, body_bb);
13352 edge preheader_edge = find_edge (entry_bb, body_bb);
13353 edge latch_edge = single_succ_edge (latch_bb);
13354 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
13355 UNKNOWN_LOCATION);
13356 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13358 /* Generate the new return. */
13359 gsi = gsi_last_bb (new_exit_bb);
13360 if (retval
13361 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
13362 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
13363 retval = TREE_OPERAND (retval, 0);
13364 else if (retval)
13366 retval = build1 (VIEW_CONVERT_EXPR,
13367 TREE_TYPE (TREE_TYPE (node->decl)),
13368 retval);
13369 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
13370 false, GSI_CONTINUE_LINKING);
13372 g = gimple_build_return (retval);
13373 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
13375 /* Handle aligned clauses by replacing default defs of the aligned
13376 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
13377 lhs. Handle linear by adding PHIs. */
13378 for (unsigned i = 0; i < node->simdclone->nargs; i++)
13379 if (node->simdclone->args[i].alignment
13380 && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
13381 && (node->simdclone->args[i].alignment
13382 & (node->simdclone->args[i].alignment - 1)) == 0
13383 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
13384 == POINTER_TYPE)
13386 unsigned int alignment = node->simdclone->args[i].alignment;
13387 tree orig_arg = node->simdclone->args[i].orig_arg;
13388 tree def = ssa_default_def (cfun, orig_arg);
13389 if (def && !has_zero_uses (def))
13391 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
13392 gimple_seq seq = NULL;
13393 bool need_cvt = false;
13394 gcall *call
13395 = gimple_build_call (fn, 2, def, size_int (alignment));
13396 g = call;
13397 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
13398 ptr_type_node))
13399 need_cvt = true;
13400 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
13401 gimple_call_set_lhs (g, t);
13402 gimple_seq_add_stmt_without_update (&seq, g);
13403 if (need_cvt)
13405 t = make_ssa_name (orig_arg);
13406 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
13407 gimple_seq_add_stmt_without_update (&seq, g);
13409 gsi_insert_seq_on_edge_immediate
13410 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
13412 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
13413 int freq = compute_call_stmt_bb_frequency (current_function_decl,
13414 entry_bb);
13415 node->create_edge (cgraph_node::get_create (fn),
13416 call, entry_bb->count, freq);
13418 imm_use_iterator iter;
13419 use_operand_p use_p;
13420 gimple use_stmt;
13421 tree repl = gimple_get_lhs (g);
13422 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13423 if (is_gimple_debug (use_stmt) || use_stmt == call)
13424 continue;
13425 else
13426 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13427 SET_USE (use_p, repl);
13430 else if (node->simdclone->args[i].arg_type
13431 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
13433 tree orig_arg = node->simdclone->args[i].orig_arg;
13434 tree def = ssa_default_def (cfun, orig_arg);
13435 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13436 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
13437 if (def && !has_zero_uses (def))
13439 iter1 = make_ssa_name (orig_arg);
13440 iter2 = make_ssa_name (orig_arg);
13441 phi = create_phi_node (iter1, body_bb);
13442 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
13443 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
13444 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13445 ? PLUS_EXPR : POINTER_PLUS_EXPR;
13446 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
13447 ? TREE_TYPE (orig_arg) : sizetype;
13448 tree addcst
13449 = build_int_cst (addtype, node->simdclone->args[i].linear_step);
13450 g = gimple_build_assign (iter2, code, iter1, addcst);
13451 gsi = gsi_last_bb (incr_bb);
13452 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13454 imm_use_iterator iter;
13455 use_operand_p use_p;
13456 gimple use_stmt;
13457 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
13458 if (use_stmt == phi)
13459 continue;
13460 else
13461 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
13462 SET_USE (use_p, iter1);
13466 calculate_dominance_info (CDI_DOMINATORS);
13467 add_loop (loop, loop->header->loop_father);
13468 update_ssa (TODO_update_ssa);
13470 pop_cfun ();
13473 /* If the function in NODE is tagged as an elemental SIMD function,
13474 create the appropriate SIMD clones. */
13476 static void
13477 expand_simd_clones (struct cgraph_node *node)
13479 tree attr = lookup_attribute ("omp declare simd",
13480 DECL_ATTRIBUTES (node->decl));
13481 if (attr == NULL_TREE
13482 || node->global.inlined_to
13483 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
13484 return;
13486 /* Ignore
13487 #pragma omp declare simd
13488 extern int foo ();
13489 in C, there we don't know the argument types at all. */
13490 if (!node->definition
13491 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
13492 return;
13496 /* Start with parsing the "omp declare simd" attribute(s). */
13497 bool inbranch_clause_specified;
13498 struct cgraph_simd_clone *clone_info
13499 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
13500 &inbranch_clause_specified);
13501 if (clone_info == NULL)
13502 continue;
13504 int orig_simdlen = clone_info->simdlen;
13505 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
13506 /* The target can return 0 (no simd clones should be created),
13507 1 (just one ISA of simd clones should be created) or higher
13508 count of ISA variants. In that case, clone_info is initialized
13509 for the first ISA variant. */
13510 int count
13511 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
13512 base_type, 0);
13513 if (count == 0)
13514 continue;
13516 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
13517 also create one inbranch and one !inbranch clone of it. */
13518 for (int i = 0; i < count * 2; i++)
13520 struct cgraph_simd_clone *clone = clone_info;
13521 if (inbranch_clause_specified && (i & 1) != 0)
13522 continue;
13524 if (i != 0)
13526 clone = simd_clone_struct_alloc (clone_info->nargs
13527 + ((i & 1) != 0));
13528 simd_clone_struct_copy (clone, clone_info);
13529 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
13530 and simd_clone_adjust_argument_types did to the first
13531 clone's info. */
13532 clone->nargs -= clone_info->inbranch;
13533 clone->simdlen = orig_simdlen;
13534 /* And call the target hook again to get the right ISA. */
13535 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
13536 base_type,
13537 i / 2);
13538 if ((i & 1) != 0)
13539 clone->inbranch = 1;
13542 /* simd_clone_mangle might fail if such a clone has been created
13543 already. */
13544 tree id = simd_clone_mangle (node, clone);
13545 if (id == NULL_TREE)
13546 continue;
13548 /* Only when we are sure we want to create the clone actually
13549 clone the function (or definitions) or create another
13550 extern FUNCTION_DECL (for prototypes without definitions). */
13551 struct cgraph_node *n = simd_clone_create (node);
13552 if (n == NULL)
13553 continue;
13555 n->simdclone = clone;
13556 clone->origin = node;
13557 clone->next_clone = NULL;
13558 if (node->simd_clones == NULL)
13560 clone->prev_clone = n;
13561 node->simd_clones = n;
13563 else
13565 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
13566 clone->prev_clone->simdclone->next_clone = n;
13567 node->simd_clones->simdclone->prev_clone = n;
13569 symtab->change_decl_assembler_name (n->decl, id);
13570 /* And finally adjust the return type, parameters and for
13571 definitions also function body. */
13572 if (node->definition)
13573 simd_clone_adjust (n);
13574 else
13576 simd_clone_adjust_return_type (n);
13577 simd_clone_adjust_argument_types (n);
13581 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
13584 /* Entry point for IPA simd clone creation pass. */
13586 static unsigned int
13587 ipa_omp_simd_clone (void)
13589 struct cgraph_node *node;
13590 FOR_EACH_FUNCTION (node)
13591 expand_simd_clones (node);
13592 return 0;
13595 namespace {
13597 const pass_data pass_data_omp_simd_clone =
13599 SIMPLE_IPA_PASS, /* type */
13600 "simdclone", /* name */
13601 OPTGROUP_NONE, /* optinfo_flags */
13602 TV_NONE, /* tv_id */
13603 ( PROP_ssa | PROP_cfg ), /* properties_required */
13604 0, /* properties_provided */
13605 0, /* properties_destroyed */
13606 0, /* todo_flags_start */
13607 0, /* todo_flags_finish */
13610 class pass_omp_simd_clone : public simple_ipa_opt_pass
13612 public:
13613 pass_omp_simd_clone(gcc::context *ctxt)
13614 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
13617 /* opt_pass methods: */
13618 virtual bool gate (function *);
13619 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
13622 bool
13623 pass_omp_simd_clone::gate (function *)
13625 return ((flag_openmp || flag_openmp_simd
13626 || flag_cilkplus
13627 || (in_lto_p && !flag_wpa))
13628 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
13631 } // anon namespace
13633 simple_ipa_opt_pass *
13634 make_pass_omp_simd_clone (gcc::context *ctxt)
13636 return new pass_omp_simd_clone (ctxt);
13639 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
13640 adds their addresses and sizes to constructor-vector V_CTOR. */
13641 static void
13642 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
13643 vec<constructor_elt, va_gc> *v_ctor)
13645 unsigned len = vec_safe_length (v_decls);
13646 for (unsigned i = 0; i < len; i++)
13648 tree it = (*v_decls)[i];
13649 bool is_function = TREE_CODE (it) != VAR_DECL;
13651 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
13652 if (!is_function)
13653 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
13654 fold_convert (const_ptr_type_node,
13655 DECL_SIZE_UNIT (it)));
13659 /* Create new symbols containing (address, size) pairs for global variables,
13660 marked with "omp declare target" attribute, as well as addresses for the
13661 functions, which are outlined offloading regions. */
13662 void
13663 omp_finish_file (void)
13665 unsigned num_funcs = vec_safe_length (offload_funcs);
13666 unsigned num_vars = vec_safe_length (offload_vars);
13668 if (num_funcs == 0 && num_vars == 0)
13669 return;
13671 if (targetm_common.have_named_sections)
13673 vec<constructor_elt, va_gc> *v_f, *v_v;
13674 vec_alloc (v_f, num_funcs);
13675 vec_alloc (v_v, num_vars * 2);
13677 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
13678 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
13680 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
13681 num_vars * 2);
13682 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
13683 num_funcs);
13684 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13685 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
13686 tree ctor_v = build_constructor (vars_decl_type, v_v);
13687 tree ctor_f = build_constructor (funcs_decl_type, v_f);
13688 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
13689 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
13690 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13691 get_identifier (".offload_func_table"),
13692 funcs_decl_type);
13693 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13694 get_identifier (".offload_var_table"),
13695 vars_decl_type);
13696 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
13697 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
13698 otherwise a joint table in a binary will contain padding between
13699 tables from multiple object files. */
13700 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
13701 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
13702 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
13703 DECL_INITIAL (funcs_decl) = ctor_f;
13704 DECL_INITIAL (vars_decl) = ctor_v;
13705 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
13706 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
13708 varpool_node::finalize_decl (vars_decl);
13709 varpool_node::finalize_decl (funcs_decl);
13711 else
13713 for (unsigned i = 0; i < num_funcs; i++)
13715 tree it = (*offload_funcs)[i];
13716 targetm.record_offload_symbol (it);
13718 for (unsigned i = 0; i < num_vars; i++)
13720 tree it = (*offload_vars)[i];
13721 targetm.record_offload_symbol (it);
13726 #include "gt-omp-low.h"