gen-pass-instances.awk: Remove unused var in handle_line
[gcc.git] / gcc / omp-low.c
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.
4
5 Contributed by Diego Novillo <dnovillo@redhat.com>
6
7 Copyright (C) 2005-2015 Free Software Foundation, Inc.
8
9 This file is part of GCC.
10
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.
15
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.
20
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/>. */
24
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "backend.h"
29 #include "target.h"
30 #include "rtl.h"
31 #include "tree.h"
32 #include "gimple.h"
33 #include "cfghooks.h"
34 #include "alloc-pool.h"
35 #include "tree-pass.h"
36 #include "ssa.h"
37 #include "expmed.h"
38 #include "optabs.h"
39 #include "emit-rtl.h"
40 #include "cgraph.h"
41 #include "pretty-print.h"
42 #include "diagnostic-core.h"
43 #include "alias.h"
44 #include "fold-const.h"
45 #include "stor-layout.h"
46 #include "cfganal.h"
47 #include "internal-fn.h"
48 #include "gimple-fold.h"
49 #include "gimplify.h"
50 #include "gimple-iterator.h"
51 #include "gimplify-me.h"
52 #include "gimple-walk.h"
53 #include "tree-iterator.h"
54 #include "tree-inline.h"
55 #include "langhooks.h"
56 #include "tree-cfg.h"
57 #include "tree-into-ssa.h"
58 #include "flags.h"
59 #include "dojump.h"
60 #include "explow.h"
61 #include "calls.h"
62 #include "varasm.h"
63 #include "stmt.h"
64 #include "expr.h"
65 #include "tree-dfa.h"
66 #include "tree-ssa.h"
67 #include "except.h"
68 #include "splay-tree.h"
69 #include "cfgloop.h"
70 #include "common/common-target.h"
71 #include "omp-low.h"
72 #include "gimple-low.h"
73 #include "tree-cfgcleanup.h"
74 #include "symbol-summary.h"
75 #include "ipa-prop.h"
76 #include "tree-nested.h"
77 #include "tree-eh.h"
78 #include "cilk.h"
79 #include "context.h"
80 #include "lto-section-names.h"
81 #include "gomp-constants.h"
82 #include "gimple-pretty-print.h"
83
84 /* Lowering of OMP parallel and workshare constructs proceeds in two
85 phases. The first phase scans the function looking for OMP statements
86 and then for variables that must be replaced to satisfy data sharing
87 clauses. The second phase expands code for the constructs, as well as
88 re-gimplifying things when variables have been replaced with complex
89 expressions.
90
91 Final code generation is done by pass_expand_omp. The flowgraph is
92 scanned for regions which are then moved to a new
93 function, to be invoked by the thread library, or offloaded. */
94
95 /* OMP region information. Every parallel and workshare
96 directive is enclosed between two markers, the OMP_* directive
97 and a corresponding GIMPLE_OMP_RETURN statement. */
98
99 struct omp_region
100 {
101 /* The enclosing region. */
102 struct omp_region *outer;
103
104 /* First child region. */
105 struct omp_region *inner;
106
107 /* Next peer region. */
108 struct omp_region *next;
109
110 /* Block containing the omp directive as its last stmt. */
111 basic_block entry;
112
113 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
114 basic_block exit;
115
116 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
117 basic_block cont;
118
119 /* If this is a combined parallel+workshare region, this is a list
120 of additional arguments needed by the combined parallel+workshare
121 library call. */
122 vec<tree, va_gc> *ws_args;
123
124 /* The code for the omp directive of this region. */
125 enum gimple_code type;
126
127 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
128 enum omp_clause_schedule_kind sched_kind;
129
130 /* Schedule modifiers. */
131 unsigned char sched_modifiers;
132
133 /* True if this is a combined parallel+workshare region. */
134 bool is_combined_parallel;
135
136 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
137 a depend clause. */
138 gomp_ordered *ord_stmt;
139 };
140
141 /* Context structure. Used to store information about each parallel
142 directive in the code. */
143
144 struct omp_context
145 {
146 /* This field must be at the beginning, as we do "inheritance": Some
147 callback functions for tree-inline.c (e.g., omp_copy_decl)
148 receive a copy_body_data pointer that is up-casted to an
149 omp_context pointer. */
150 copy_body_data cb;
151
152 /* The tree of contexts corresponding to the encountered constructs. */
153 struct omp_context *outer;
154 gimple *stmt;
155
156 /* Map variables to fields in a structure that allows communication
157 between sending and receiving threads. */
158 splay_tree field_map;
159 tree record_type;
160 tree sender_decl;
161 tree receiver_decl;
162
163 /* These are used just by task contexts, if task firstprivate fn is
164 needed. srecord_type is used to communicate from the thread
165 that encountered the task construct to task firstprivate fn,
166 record_type is allocated by GOMP_task, initialized by task firstprivate
167 fn and passed to the task body fn. */
168 splay_tree sfield_map;
169 tree srecord_type;
170
171 /* A chain of variables to add to the top-level block surrounding the
172 construct. In the case of a parallel, this is in the child function. */
173 tree block_vars;
174
175 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
176 barriers should jump to during omplower pass. */
177 tree cancel_label;
178
179 /* What to do with variables with implicitly determined sharing
180 attributes. */
181 enum omp_clause_default_kind default_kind;
182
183 /* Nesting depth of this context. Used to beautify error messages re
184 invalid gotos. The outermost ctx is depth 1, with depth 0 being
185 reserved for the main body of the function. */
186 int depth;
187
188 /* True if this parallel directive is nested within another. */
189 bool is_nested;
190
191 /* True if this construct can be cancelled. */
192 bool cancellable;
193 };
194
195 /* A structure holding the elements of:
196 for (V = N1; V cond N2; V += STEP) [...] */
197
198 struct omp_for_data_loop
199 {
200 tree v, n1, n2, step;
201 enum tree_code cond_code;
202 };
203
204 /* A structure describing the main elements of a parallel loop. */
205
206 struct omp_for_data
207 {
208 struct omp_for_data_loop loop;
209 tree chunk_size;
210 gomp_for *for_stmt;
211 tree pre, iter_type;
212 int collapse;
213 int ordered;
214 bool have_nowait, have_ordered, simd_schedule;
215 unsigned char sched_modifiers;
216 enum omp_clause_schedule_kind sched_kind;
217 struct omp_for_data_loop *loops;
218 };
219
220 /* Describe the OpenACC looping structure of a function. The entire
221 function is held in a 'NULL' loop. */
222
223 struct oacc_loop
224 {
225 oacc_loop *parent; /* Containing loop. */
226
227 oacc_loop *child; /* First inner loop. */
228
229 oacc_loop *sibling; /* Next loop within same parent. */
230
231 location_t loc; /* Location of the loop start. */
232
233 gcall *marker; /* Initial head marker. */
234
235 gcall *heads[GOMP_DIM_MAX]; /* Head marker functions. */
236 gcall *tails[GOMP_DIM_MAX]; /* Tail marker functions. */
237
238 tree routine; /* Pseudo-loop enclosing a routine. */
239
240 unsigned mask; /* Partitioning mask. */
241 unsigned flags; /* Partitioning flags. */
242 tree chunk_size; /* Chunk size. */
243 gcall *head_end; /* Final marker of head sequence. */
244 };
245
246 /* Flags for an OpenACC loop. */
247
248 enum oacc_loop_flags {
249 OLF_SEQ = 1u << 0, /* Explicitly sequential */
250 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
251 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
252 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
253
254 /* Explicitly specified loop axes. */
255 OLF_DIM_BASE = 4,
256 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
257 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
258 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
259
260 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
261 };
262
263
264 static splay_tree all_contexts;
265 static int taskreg_nesting_level;
266 static int target_nesting_level;
267 static struct omp_region *root_omp_region;
268 static bitmap task_shared_vars;
269 static vec<omp_context *> taskreg_contexts;
270 static bool omp_any_child_fn_dumped;
271
272 static void scan_omp (gimple_seq *, omp_context *);
273 static tree scan_omp_1_op (tree *, int *, void *);
274 static gphi *find_phi_with_arg_on_edge (tree, edge);
275
276 #define WALK_SUBSTMTS \
277 case GIMPLE_BIND: \
278 case GIMPLE_TRY: \
279 case GIMPLE_CATCH: \
280 case GIMPLE_EH_FILTER: \
281 case GIMPLE_TRANSACTION: \
282 /* The sub-statements for these should be walked. */ \
283 *handled_ops_p = false; \
284 break;
285
286 /* Return true if CTX corresponds to an oacc parallel region. */
287
288 static bool
289 is_oacc_parallel (omp_context *ctx)
290 {
291 enum gimple_code outer_type = gimple_code (ctx->stmt);
292 return ((outer_type == GIMPLE_OMP_TARGET)
293 && (gimple_omp_target_kind (ctx->stmt)
294 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
295 }
296
297 /* Return true if CTX corresponds to an oacc kernels region. */
298
299 static bool
300 is_oacc_kernels (omp_context *ctx)
301 {
302 enum gimple_code outer_type = gimple_code (ctx->stmt);
303 return ((outer_type == GIMPLE_OMP_TARGET)
304 && (gimple_omp_target_kind (ctx->stmt)
305 == GF_OMP_TARGET_KIND_OACC_KERNELS));
306 }
307
308 /* If DECL is the artificial dummy VAR_DECL created for non-static
309 data member privatization, return the underlying "this" parameter,
310 otherwise return NULL. */
311
312 tree
313 omp_member_access_dummy_var (tree decl)
314 {
315 if (!VAR_P (decl)
316 || !DECL_ARTIFICIAL (decl)
317 || !DECL_IGNORED_P (decl)
318 || !DECL_HAS_VALUE_EXPR_P (decl)
319 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
320 return NULL_TREE;
321
322 tree v = DECL_VALUE_EXPR (decl);
323 if (TREE_CODE (v) != COMPONENT_REF)
324 return NULL_TREE;
325
326 while (1)
327 switch (TREE_CODE (v))
328 {
329 case COMPONENT_REF:
330 case MEM_REF:
331 case INDIRECT_REF:
332 CASE_CONVERT:
333 case POINTER_PLUS_EXPR:
334 v = TREE_OPERAND (v, 0);
335 continue;
336 case PARM_DECL:
337 if (DECL_CONTEXT (v) == current_function_decl
338 && DECL_ARTIFICIAL (v)
339 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
340 return v;
341 return NULL_TREE;
342 default:
343 return NULL_TREE;
344 }
345 }
346
347 /* Helper for unshare_and_remap, called through walk_tree. */
348
349 static tree
350 unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
351 {
352 tree *pair = (tree *) data;
353 if (*tp == pair[0])
354 {
355 *tp = unshare_expr (pair[1]);
356 *walk_subtrees = 0;
357 }
358 else if (IS_TYPE_OR_DECL_P (*tp))
359 *walk_subtrees = 0;
360 return NULL_TREE;
361 }
362
363 /* Return unshare_expr (X) with all occurrences of FROM
364 replaced with TO. */
365
366 static tree
367 unshare_and_remap (tree x, tree from, tree to)
368 {
369 tree pair[2] = { from, to };
370 x = unshare_expr (x);
371 walk_tree (&x, unshare_and_remap_1, pair, NULL);
372 return x;
373 }
374
375 /* Holds offload tables with decls. */
376 vec<tree, va_gc> *offload_funcs, *offload_vars;
377
378 /* Convenience function for calling scan_omp_1_op on tree operands. */
379
380 static inline tree
381 scan_omp_op (tree *tp, omp_context *ctx)
382 {
383 struct walk_stmt_info wi;
384
385 memset (&wi, 0, sizeof (wi));
386 wi.info = ctx;
387 wi.want_locations = true;
388
389 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
390 }
391
392 static void lower_omp (gimple_seq *, omp_context *);
393 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
394 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
395
396 /* Find an OMP clause of type KIND within CLAUSES. */
397
398 tree
399 find_omp_clause (tree clauses, enum omp_clause_code kind)
400 {
401 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
402 if (OMP_CLAUSE_CODE (clauses) == kind)
403 return clauses;
404
405 return NULL_TREE;
406 }
407
408 /* Return true if CTX is for an omp parallel. */
409
410 static inline bool
411 is_parallel_ctx (omp_context *ctx)
412 {
413 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
414 }
415
416
417 /* Return true if CTX is for an omp task. */
418
419 static inline bool
420 is_task_ctx (omp_context *ctx)
421 {
422 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
423 }
424
425
426 /* Return true if CTX is for an omp taskloop. */
427
428 static inline bool
429 is_taskloop_ctx (omp_context *ctx)
430 {
431 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
432 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
433 }
434
435
436 /* Return true if CTX is for an omp parallel or omp task. */
437
438 static inline bool
439 is_taskreg_ctx (omp_context *ctx)
440 {
441 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
442 }
443
444
445 /* Return true if REGION is a combined parallel+workshare region. */
446
447 static inline bool
448 is_combined_parallel (struct omp_region *region)
449 {
450 return region->is_combined_parallel;
451 }
452
453
454 /* Extract the header elements of parallel loop FOR_STMT and store
455 them into *FD. */
456
457 static void
458 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
459 struct omp_for_data_loop *loops)
460 {
461 tree t, var, *collapse_iter, *collapse_count;
462 tree count = NULL_TREE, iter_type = long_integer_type_node;
463 struct omp_for_data_loop *loop;
464 int i;
465 struct omp_for_data_loop dummy_loop;
466 location_t loc = gimple_location (for_stmt);
467 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
468 bool distribute = gimple_omp_for_kind (for_stmt)
469 == GF_OMP_FOR_KIND_DISTRIBUTE;
470 bool taskloop = gimple_omp_for_kind (for_stmt)
471 == GF_OMP_FOR_KIND_TASKLOOP;
472 tree iterv, countv;
473
474 fd->for_stmt = for_stmt;
475 fd->pre = NULL;
476 if (gimple_omp_for_collapse (for_stmt) > 1)
477 fd->loops = loops;
478 else
479 fd->loops = &fd->loop;
480
481 fd->have_nowait = distribute || simd;
482 fd->have_ordered = false;
483 fd->collapse = 1;
484 fd->ordered = 0;
485 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
486 fd->sched_modifiers = 0;
487 fd->chunk_size = NULL_TREE;
488 fd->simd_schedule = false;
489 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
490 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
491 collapse_iter = NULL;
492 collapse_count = NULL;
493
494 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
495 switch (OMP_CLAUSE_CODE (t))
496 {
497 case OMP_CLAUSE_NOWAIT:
498 fd->have_nowait = true;
499 break;
500 case OMP_CLAUSE_ORDERED:
501 fd->have_ordered = true;
502 if (OMP_CLAUSE_ORDERED_EXPR (t))
503 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
504 break;
505 case OMP_CLAUSE_SCHEDULE:
506 gcc_assert (!distribute && !taskloop);
507 fd->sched_kind
508 = (enum omp_clause_schedule_kind)
509 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
510 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
511 & ~OMP_CLAUSE_SCHEDULE_MASK);
512 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
513 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
514 break;
515 case OMP_CLAUSE_DIST_SCHEDULE:
516 gcc_assert (distribute);
517 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
518 break;
519 case OMP_CLAUSE_COLLAPSE:
520 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
521 if (fd->collapse > 1)
522 {
523 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
524 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
525 }
526 break;
527 default:
528 break;
529 }
530 if (fd->ordered && fd->collapse == 1 && loops != NULL)
531 {
532 fd->loops = loops;
533 iterv = NULL_TREE;
534 countv = NULL_TREE;
535 collapse_iter = &iterv;
536 collapse_count = &countv;
537 }
538
539 /* FIXME: for now map schedule(auto) to schedule(static).
540 There should be analysis to determine whether all iterations
541 are approximately the same amount of work (then schedule(static)
542 is best) or if it varies (then schedule(dynamic,N) is better). */
543 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
544 {
545 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
546 gcc_assert (fd->chunk_size == NULL);
547 }
548 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
549 if (taskloop)
550 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
551 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
552 gcc_assert (fd->chunk_size == NULL);
553 else if (fd->chunk_size == NULL)
554 {
555 /* We only need to compute a default chunk size for ordered
556 static loops and dynamic loops. */
557 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
558 || fd->have_ordered)
559 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
560 ? integer_zero_node : integer_one_node;
561 }
562
563 int cnt = fd->ordered ? fd->ordered : fd->collapse;
564 for (i = 0; i < cnt; i++)
565 {
566 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
567 loop = &fd->loop;
568 else if (loops != NULL)
569 loop = loops + i;
570 else
571 loop = &dummy_loop;
572
573 loop->v = gimple_omp_for_index (for_stmt, i);
574 gcc_assert (SSA_VAR_P (loop->v));
575 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
576 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
577 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
578 loop->n1 = gimple_omp_for_initial (for_stmt, i);
579
580 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
581 loop->n2 = gimple_omp_for_final (for_stmt, i);
582 switch (loop->cond_code)
583 {
584 case LT_EXPR:
585 case GT_EXPR:
586 break;
587 case NE_EXPR:
588 gcc_assert (gimple_omp_for_kind (for_stmt)
589 == GF_OMP_FOR_KIND_CILKSIMD
590 || (gimple_omp_for_kind (for_stmt)
591 == GF_OMP_FOR_KIND_CILKFOR));
592 break;
593 case LE_EXPR:
594 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
595 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, 1);
596 else
597 loop->n2 = fold_build2_loc (loc,
598 PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
599 build_int_cst (TREE_TYPE (loop->n2), 1));
600 loop->cond_code = LT_EXPR;
601 break;
602 case GE_EXPR:
603 if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
604 loop->n2 = fold_build_pointer_plus_hwi_loc (loc, loop->n2, -1);
605 else
606 loop->n2 = fold_build2_loc (loc,
607 MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
608 build_int_cst (TREE_TYPE (loop->n2), 1));
609 loop->cond_code = GT_EXPR;
610 break;
611 default:
612 gcc_unreachable ();
613 }
614
615 t = gimple_omp_for_incr (for_stmt, i);
616 gcc_assert (TREE_OPERAND (t, 0) == var);
617 switch (TREE_CODE (t))
618 {
619 case PLUS_EXPR:
620 loop->step = TREE_OPERAND (t, 1);
621 break;
622 case POINTER_PLUS_EXPR:
623 loop->step = fold_convert (ssizetype, TREE_OPERAND (t, 1));
624 break;
625 case MINUS_EXPR:
626 loop->step = TREE_OPERAND (t, 1);
627 loop->step = fold_build1_loc (loc,
628 NEGATE_EXPR, TREE_TYPE (loop->step),
629 loop->step);
630 break;
631 default:
632 gcc_unreachable ();
633 }
634
635 if (simd
636 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
637 && !fd->have_ordered))
638 {
639 if (fd->collapse == 1)
640 iter_type = TREE_TYPE (loop->v);
641 else if (i == 0
642 || TYPE_PRECISION (iter_type)
643 < TYPE_PRECISION (TREE_TYPE (loop->v)))
644 iter_type
645 = build_nonstandard_integer_type
646 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
647 }
648 else if (iter_type != long_long_unsigned_type_node)
649 {
650 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
651 iter_type = long_long_unsigned_type_node;
652 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
653 && TYPE_PRECISION (TREE_TYPE (loop->v))
654 >= TYPE_PRECISION (iter_type))
655 {
656 tree n;
657
658 if (loop->cond_code == LT_EXPR)
659 n = fold_build2_loc (loc,
660 PLUS_EXPR, TREE_TYPE (loop->v),
661 loop->n2, loop->step);
662 else
663 n = loop->n1;
664 if (TREE_CODE (n) != INTEGER_CST
665 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
666 iter_type = long_long_unsigned_type_node;
667 }
668 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
669 > TYPE_PRECISION (iter_type))
670 {
671 tree n1, n2;
672
673 if (loop->cond_code == LT_EXPR)
674 {
675 n1 = loop->n1;
676 n2 = fold_build2_loc (loc,
677 PLUS_EXPR, TREE_TYPE (loop->v),
678 loop->n2, loop->step);
679 }
680 else
681 {
682 n1 = fold_build2_loc (loc,
683 MINUS_EXPR, TREE_TYPE (loop->v),
684 loop->n2, loop->step);
685 n2 = loop->n1;
686 }
687 if (TREE_CODE (n1) != INTEGER_CST
688 || TREE_CODE (n2) != INTEGER_CST
689 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
690 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
691 iter_type = long_long_unsigned_type_node;
692 }
693 }
694
695 if (i >= fd->collapse)
696 continue;
697
698 if (collapse_count && *collapse_count == NULL)
699 {
700 t = fold_binary (loop->cond_code, boolean_type_node,
701 fold_convert (TREE_TYPE (loop->v), loop->n1),
702 fold_convert (TREE_TYPE (loop->v), loop->n2));
703 if (t && integer_zerop (t))
704 count = build_zero_cst (long_long_unsigned_type_node);
705 else if ((i == 0 || count != NULL_TREE)
706 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
707 && TREE_CONSTANT (loop->n1)
708 && TREE_CONSTANT (loop->n2)
709 && TREE_CODE (loop->step) == INTEGER_CST)
710 {
711 tree itype = TREE_TYPE (loop->v);
712
713 if (POINTER_TYPE_P (itype))
714 itype = signed_type_for (itype);
715 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
716 t = fold_build2_loc (loc,
717 PLUS_EXPR, itype,
718 fold_convert_loc (loc, itype, loop->step), t);
719 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
720 fold_convert_loc (loc, itype, loop->n2));
721 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
722 fold_convert_loc (loc, itype, loop->n1));
723 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
724 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
725 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
726 fold_build1_loc (loc, NEGATE_EXPR, itype,
727 fold_convert_loc (loc, itype,
728 loop->step)));
729 else
730 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
731 fold_convert_loc (loc, itype, loop->step));
732 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
733 if (count != NULL_TREE)
734 count = fold_build2_loc (loc,
735 MULT_EXPR, long_long_unsigned_type_node,
736 count, t);
737 else
738 count = t;
739 if (TREE_CODE (count) != INTEGER_CST)
740 count = NULL_TREE;
741 }
742 else if (count && !integer_zerop (count))
743 count = NULL_TREE;
744 }
745 }
746
747 if (count
748 && !simd
749 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
750 || fd->have_ordered))
751 {
752 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
753 iter_type = long_long_unsigned_type_node;
754 else
755 iter_type = long_integer_type_node;
756 }
757 else if (collapse_iter && *collapse_iter != NULL)
758 iter_type = TREE_TYPE (*collapse_iter);
759 fd->iter_type = iter_type;
760 if (collapse_iter && *collapse_iter == NULL)
761 *collapse_iter = create_tmp_var (iter_type, ".iter");
762 if (collapse_count && *collapse_count == NULL)
763 {
764 if (count)
765 *collapse_count = fold_convert_loc (loc, iter_type, count);
766 else
767 *collapse_count = create_tmp_var (iter_type, ".count");
768 }
769
770 if (fd->collapse > 1 || (fd->ordered && loops))
771 {
772 fd->loop.v = *collapse_iter;
773 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
774 fd->loop.n2 = *collapse_count;
775 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
776 fd->loop.cond_code = LT_EXPR;
777 }
778 else if (loops)
779 loops[0] = fd->loop;
780 }
781
782
783 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
784 is the immediate dominator of PAR_ENTRY_BB, return true if there
785 are no data dependencies that would prevent expanding the parallel
786 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
787
788 When expanding a combined parallel+workshare region, the call to
789 the child function may need additional arguments in the case of
790 GIMPLE_OMP_FOR regions. In some cases, these arguments are
791 computed out of variables passed in from the parent to the child
792 via 'struct .omp_data_s'. For instance:
793
794 #pragma omp parallel for schedule (guided, i * 4)
795 for (j ...)
796
797 Is lowered into:
798
799 # BLOCK 2 (PAR_ENTRY_BB)
800 .omp_data_o.i = i;
801 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
802
803 # BLOCK 3 (WS_ENTRY_BB)
804 .omp_data_i = &.omp_data_o;
805 D.1667 = .omp_data_i->i;
806 D.1598 = D.1667 * 4;
807 #pragma omp for schedule (guided, D.1598)
808
809 When we outline the parallel region, the call to the child function
810 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
811 that value is computed *after* the call site. So, in principle we
812 cannot do the transformation.
813
814 To see whether the code in WS_ENTRY_BB blocks the combined
815 parallel+workshare call, we collect all the variables used in the
816 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
817 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
818 call.
819
820 FIXME. If we had the SSA form built at this point, we could merely
821 hoist the code in block 3 into block 2 and be done with it. But at
822 this point we don't have dataflow information and though we could
823 hack something up here, it is really not worth the aggravation. */
824
825 static bool
826 workshare_safe_to_combine_p (basic_block ws_entry_bb)
827 {
828 struct omp_for_data fd;
829 gimple *ws_stmt = last_stmt (ws_entry_bb);
830
831 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
832 return true;
833
834 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
835
836 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
837
838 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
839 return false;
840 if (fd.iter_type != long_integer_type_node)
841 return false;
842
843 /* FIXME. We give up too easily here. If any of these arguments
844 are not constants, they will likely involve variables that have
845 been mapped into fields of .omp_data_s for sharing with the child
846 function. With appropriate data flow, it would be possible to
847 see through this. */
848 if (!is_gimple_min_invariant (fd.loop.n1)
849 || !is_gimple_min_invariant (fd.loop.n2)
850 || !is_gimple_min_invariant (fd.loop.step)
851 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
852 return false;
853
854 return true;
855 }
856
857
858 static int omp_max_vf (void);
859
860 /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
861 presence (SIMD_SCHEDULE). */
862
863 static tree
864 omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
865 {
866 if (!simd_schedule)
867 return chunk_size;
868
869 int vf = omp_max_vf ();
870 if (vf == 1)
871 return chunk_size;
872
873 tree type = TREE_TYPE (chunk_size);
874 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
875 build_int_cst (type, vf - 1));
876 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
877 build_int_cst (type, -vf));
878 }
879
880
881 /* Collect additional arguments needed to emit a combined
882 parallel+workshare call. WS_STMT is the workshare directive being
883 expanded. */
884
885 static vec<tree, va_gc> *
886 get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
887 {
888 tree t;
889 location_t loc = gimple_location (ws_stmt);
890 vec<tree, va_gc> *ws_args;
891
892 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
893 {
894 struct omp_for_data fd;
895 tree n1, n2;
896
897 extract_omp_for_data (for_stmt, &fd, NULL);
898 n1 = fd.loop.n1;
899 n2 = fd.loop.n2;
900
901 if (gimple_omp_for_combined_into_p (for_stmt))
902 {
903 tree innerc
904 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
905 OMP_CLAUSE__LOOPTEMP_);
906 gcc_assert (innerc);
907 n1 = OMP_CLAUSE_DECL (innerc);
908 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
909 OMP_CLAUSE__LOOPTEMP_);
910 gcc_assert (innerc);
911 n2 = OMP_CLAUSE_DECL (innerc);
912 }
913
914 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
915
916 t = fold_convert_loc (loc, long_integer_type_node, n1);
917 ws_args->quick_push (t);
918
919 t = fold_convert_loc (loc, long_integer_type_node, n2);
920 ws_args->quick_push (t);
921
922 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
923 ws_args->quick_push (t);
924
925 if (fd.chunk_size)
926 {
927 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
928 t = omp_adjust_chunk_size (t, fd.simd_schedule);
929 ws_args->quick_push (t);
930 }
931
932 return ws_args;
933 }
934 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
935 {
936 /* Number of sections is equal to the number of edges from the
937 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
938 the exit of the sections region. */
939 basic_block bb = single_succ (gimple_bb (ws_stmt));
940 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
941 vec_alloc (ws_args, 1);
942 ws_args->quick_push (t);
943 return ws_args;
944 }
945
946 gcc_unreachable ();
947 }
948
949
950 /* Discover whether REGION is a combined parallel+workshare region. */
951
952 static void
953 determine_parallel_type (struct omp_region *region)
954 {
955 basic_block par_entry_bb, par_exit_bb;
956 basic_block ws_entry_bb, ws_exit_bb;
957
958 if (region == NULL || region->inner == NULL
959 || region->exit == NULL || region->inner->exit == NULL
960 || region->inner->cont == NULL)
961 return;
962
963 /* We only support parallel+for and parallel+sections. */
964 if (region->type != GIMPLE_OMP_PARALLEL
965 || (region->inner->type != GIMPLE_OMP_FOR
966 && region->inner->type != GIMPLE_OMP_SECTIONS))
967 return;
968
969 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
970 WS_EXIT_BB -> PAR_EXIT_BB. */
971 par_entry_bb = region->entry;
972 par_exit_bb = region->exit;
973 ws_entry_bb = region->inner->entry;
974 ws_exit_bb = region->inner->exit;
975
976 if (single_succ (par_entry_bb) == ws_entry_bb
977 && single_succ (ws_exit_bb) == par_exit_bb
978 && workshare_safe_to_combine_p (ws_entry_bb)
979 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
980 || (last_and_only_stmt (ws_entry_bb)
981 && last_and_only_stmt (par_exit_bb))))
982 {
983 gimple *par_stmt = last_stmt (par_entry_bb);
984 gimple *ws_stmt = last_stmt (ws_entry_bb);
985
986 if (region->inner->type == GIMPLE_OMP_FOR)
987 {
988 /* If this is a combined parallel loop, we need to determine
989 whether or not to use the combined library calls. There
990 are two cases where we do not apply the transformation:
991 static loops and any kind of ordered loop. In the first
992 case, we already open code the loop so there is no need
993 to do anything else. In the latter case, the combined
994 parallel loop call would still need extra synchronization
995 to implement ordered semantics, so there would not be any
996 gain in using the combined call. */
997 tree clauses = gimple_omp_for_clauses (ws_stmt);
998 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
999 if (c == NULL
1000 || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
1001 == OMP_CLAUSE_SCHEDULE_STATIC)
1002 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1003 {
1004 region->is_combined_parallel = false;
1005 region->inner->is_combined_parallel = false;
1006 return;
1007 }
1008 }
1009
1010 region->is_combined_parallel = true;
1011 region->inner->is_combined_parallel = true;
1012 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
1013 }
1014 }
1015
1016
1017 /* Return true if EXPR is variable sized. */
1018
1019 static inline bool
1020 is_variable_sized (const_tree expr)
1021 {
1022 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1023 }
1024
1025 /* Return true if DECL is a reference type. */
1026
1027 static inline bool
1028 is_reference (tree decl)
1029 {
1030 return lang_hooks.decls.omp_privatize_by_reference (decl);
1031 }
1032
1033 /* Return the type of a decl. If the decl is reference type,
1034 return its base type. */
1035 static inline tree
1036 get_base_type (tree decl)
1037 {
1038 tree type = TREE_TYPE (decl);
1039 if (is_reference (decl))
1040 type = TREE_TYPE (type);
1041 return type;
1042 }
1043
1044 /* Lookup variables. The "maybe" form
1045 allows for the variable form to not have been entered, otherwise we
1046 assert that the variable must have been entered. */
1047
1048 static inline tree
1049 lookup_decl (tree var, omp_context *ctx)
1050 {
1051 tree *n = ctx->cb.decl_map->get (var);
1052 return *n;
1053 }
1054
1055 static inline tree
1056 maybe_lookup_decl (const_tree var, omp_context *ctx)
1057 {
1058 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
1059 return n ? *n : NULL_TREE;
1060 }
1061
1062 static inline tree
1063 lookup_field (tree var, omp_context *ctx)
1064 {
1065 splay_tree_node n;
1066 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1067 return (tree) n->value;
1068 }
1069
1070 static inline tree
1071 lookup_sfield (splay_tree_key key, omp_context *ctx)
1072 {
1073 splay_tree_node n;
1074 n = splay_tree_lookup (ctx->sfield_map
1075 ? ctx->sfield_map : ctx->field_map, key);
1076 return (tree) n->value;
1077 }
1078
1079 static inline tree
1080 lookup_sfield (tree var, omp_context *ctx)
1081 {
1082 return lookup_sfield ((splay_tree_key) var, ctx);
1083 }
1084
1085 static inline tree
1086 maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1087 {
1088 splay_tree_node n;
1089 n = splay_tree_lookup (ctx->field_map, key);
1090 return n ? (tree) n->value : NULL_TREE;
1091 }
1092
1093 static inline tree
1094 maybe_lookup_field (tree var, omp_context *ctx)
1095 {
1096 return maybe_lookup_field ((splay_tree_key) var, ctx);
1097 }
1098
1099 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1100 the parallel context if DECL is to be shared. */
1101
1102 static bool
1103 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1104 {
1105 if (AGGREGATE_TYPE_P (TREE_TYPE (decl)))
1106 return true;
1107
1108 /* We can only use copy-in/copy-out semantics for shared variables
1109 when we know the value is not accessible from an outer scope. */
1110 if (shared_ctx)
1111 {
1112 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1113
1114 /* ??? Trivially accessible from anywhere. But why would we even
1115 be passing an address in this case? Should we simply assert
1116 this to be false, or should we have a cleanup pass that removes
1117 these from the list of mappings? */
1118 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1119 return true;
1120
1121 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1122 without analyzing the expression whether or not its location
1123 is accessible to anyone else. In the case of nested parallel
1124 regions it certainly may be. */
1125 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1126 return true;
1127
1128 /* Do not use copy-in/copy-out for variables that have their
1129 address taken. */
1130 if (TREE_ADDRESSABLE (decl))
1131 return true;
1132
1133 /* lower_send_shared_vars only uses copy-in, but not copy-out
1134 for these. */
1135 if (TREE_READONLY (decl)
1136 || ((TREE_CODE (decl) == RESULT_DECL
1137 || TREE_CODE (decl) == PARM_DECL)
1138 && DECL_BY_REFERENCE (decl)))
1139 return false;
1140
1141 /* Disallow copy-in/out in nested parallel if
1142 decl is shared in outer parallel, otherwise
1143 each thread could store the shared variable
1144 in its own copy-in location, making the
1145 variable no longer really shared. */
1146 if (shared_ctx->is_nested)
1147 {
1148 omp_context *up;
1149
1150 for (up = shared_ctx->outer; up; up = up->outer)
1151 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1152 break;
1153
1154 if (up)
1155 {
1156 tree c;
1157
1158 for (c = gimple_omp_taskreg_clauses (up->stmt);
1159 c; c = OMP_CLAUSE_CHAIN (c))
1160 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1161 && OMP_CLAUSE_DECL (c) == decl)
1162 break;
1163
1164 if (c)
1165 goto maybe_mark_addressable_and_ret;
1166 }
1167 }
1168
1169 /* For tasks avoid using copy-in/out. As tasks can be
1170 deferred or executed in different thread, when GOMP_task
1171 returns, the task hasn't necessarily terminated. */
1172 if (is_task_ctx (shared_ctx))
1173 {
1174 tree outer;
1175 maybe_mark_addressable_and_ret:
1176 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1177 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
1178 {
1179 /* Taking address of OUTER in lower_send_shared_vars
1180 might need regimplification of everything that uses the
1181 variable. */
1182 if (!task_shared_vars)
1183 task_shared_vars = BITMAP_ALLOC (NULL);
1184 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1185 TREE_ADDRESSABLE (outer) = 1;
1186 }
1187 return true;
1188 }
1189 }
1190
1191 return false;
1192 }
1193
1194 /* Construct a new automatic decl similar to VAR. */
1195
1196 static tree
1197 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1198 {
1199 tree copy = copy_var_decl (var, name, type);
1200
1201 DECL_CONTEXT (copy) = current_function_decl;
1202 DECL_CHAIN (copy) = ctx->block_vars;
1203 /* If VAR is listed in task_shared_vars, it means it wasn't
1204 originally addressable and is just because task needs to take
1205 it's address. But we don't need to take address of privatizations
1206 from that var. */
1207 if (TREE_ADDRESSABLE (var)
1208 && task_shared_vars
1209 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1210 TREE_ADDRESSABLE (copy) = 0;
1211 ctx->block_vars = copy;
1212
1213 return copy;
1214 }
1215
1216 static tree
1217 omp_copy_decl_1 (tree var, omp_context *ctx)
1218 {
1219 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1220 }
1221
1222 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1223 as appropriate. */
1224 static tree
1225 omp_build_component_ref (tree obj, tree field)
1226 {
1227 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1228 if (TREE_THIS_VOLATILE (field))
1229 TREE_THIS_VOLATILE (ret) |= 1;
1230 if (TREE_READONLY (field))
1231 TREE_READONLY (ret) |= 1;
1232 return ret;
1233 }
1234
1235 /* Build tree nodes to access the field for VAR on the receiver side. */
1236
1237 static tree
1238 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1239 {
1240 tree x, field = lookup_field (var, ctx);
1241
1242 /* If the receiver record type was remapped in the child function,
1243 remap the field into the new record type. */
1244 x = maybe_lookup_field (field, ctx);
1245 if (x != NULL)
1246 field = x;
1247
1248 x = build_simple_mem_ref (ctx->receiver_decl);
1249 TREE_THIS_NOTRAP (x) = 1;
1250 x = omp_build_component_ref (x, field);
1251 if (by_ref)
1252 x = build_simple_mem_ref (x);
1253
1254 return x;
1255 }
1256
1257 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1258 of a parallel, this is a component reference; for workshare constructs
1259 this is some variable. */
1260
1261 static tree
1262 build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1263 {
1264 tree x;
1265
1266 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1267 x = var;
1268 else if (is_variable_sized (var))
1269 {
1270 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1271 x = build_outer_var_ref (x, ctx, lastprivate);
1272 x = build_simple_mem_ref (x);
1273 }
1274 else if (is_taskreg_ctx (ctx))
1275 {
1276 bool by_ref = use_pointer_for_field (var, NULL);
1277 x = build_receiver_ref (var, by_ref, ctx);
1278 }
1279 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1280 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1281 {
1282 /* #pragma omp simd isn't a worksharing construct, and can reference even
1283 private vars in its linear etc. clauses. */
1284 x = NULL_TREE;
1285 if (ctx->outer && is_taskreg_ctx (ctx))
1286 x = lookup_decl (var, ctx->outer);
1287 else if (ctx->outer)
1288 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1289 if (x == NULL_TREE)
1290 x = var;
1291 }
1292 else if (lastprivate && is_taskloop_ctx (ctx))
1293 {
1294 gcc_assert (ctx->outer);
1295 splay_tree_node n
1296 = splay_tree_lookup (ctx->outer->field_map,
1297 (splay_tree_key) &DECL_UID (var));
1298 if (n == NULL)
1299 {
1300 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1301 x = var;
1302 else
1303 x = lookup_decl (var, ctx->outer);
1304 }
1305 else
1306 {
1307 tree field = (tree) n->value;
1308 /* If the receiver record type was remapped in the child function,
1309 remap the field into the new record type. */
1310 x = maybe_lookup_field (field, ctx->outer);
1311 if (x != NULL)
1312 field = x;
1313
1314 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1315 x = omp_build_component_ref (x, field);
1316 if (use_pointer_for_field (var, ctx->outer))
1317 x = build_simple_mem_ref (x);
1318 }
1319 }
1320 else if (ctx->outer)
1321 x = lookup_decl (var, ctx->outer);
1322 else if (is_reference (var))
1323 /* This can happen with orphaned constructs. If var is reference, it is
1324 possible it is shared and as such valid. */
1325 x = var;
1326 else if (omp_member_access_dummy_var (var))
1327 x = var;
1328 else
1329 gcc_unreachable ();
1330
1331 if (x == var)
1332 {
1333 tree t = omp_member_access_dummy_var (var);
1334 if (t)
1335 {
1336 x = DECL_VALUE_EXPR (var);
1337 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1338 if (o != t)
1339 x = unshare_and_remap (x, t, o);
1340 else
1341 x = unshare_expr (x);
1342 }
1343 }
1344
1345 if (is_reference (var))
1346 x = build_simple_mem_ref (x);
1347
1348 return x;
1349 }
1350
1351 /* Build tree nodes to access the field for VAR on the sender side. */
1352
1353 static tree
1354 build_sender_ref (splay_tree_key key, omp_context *ctx)
1355 {
1356 tree field = lookup_sfield (key, ctx);
1357 return omp_build_component_ref (ctx->sender_decl, field);
1358 }
1359
1360 static tree
1361 build_sender_ref (tree var, omp_context *ctx)
1362 {
1363 return build_sender_ref ((splay_tree_key) var, ctx);
1364 }
1365
1366 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. */
1367
1368 static void
1369 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx)
1370 {
1371 tree field, type, sfield = NULL_TREE;
1372 splay_tree_key key = (splay_tree_key) var;
1373
1374 if ((mask & 8) != 0)
1375 {
1376 key = (splay_tree_key) &DECL_UID (var);
1377 gcc_checking_assert (key != (splay_tree_key) var);
1378 }
1379 gcc_assert ((mask & 1) == 0
1380 || !splay_tree_lookup (ctx->field_map, key));
1381 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1382 || !splay_tree_lookup (ctx->sfield_map, key));
1383 gcc_assert ((mask & 3) == 3
1384 || !is_gimple_omp_oacc (ctx->stmt));
1385
1386 type = TREE_TYPE (var);
1387 if (mask & 4)
1388 {
1389 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1390 type = build_pointer_type (build_pointer_type (type));
1391 }
1392 else if (by_ref)
1393 type = build_pointer_type (type);
1394 else if ((mask & 3) == 1 && is_reference (var))
1395 type = TREE_TYPE (type);
1396
1397 field = build_decl (DECL_SOURCE_LOCATION (var),
1398 FIELD_DECL, DECL_NAME (var), type);
1399
1400 /* Remember what variable this field was created for. This does have a
1401 side effect of making dwarf2out ignore this member, so for helpful
1402 debugging we clear it later in delete_omp_context. */
1403 DECL_ABSTRACT_ORIGIN (field) = var;
1404 if (type == TREE_TYPE (var))
1405 {
1406 DECL_ALIGN (field) = DECL_ALIGN (var);
1407 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1408 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1409 }
1410 else
1411 DECL_ALIGN (field) = TYPE_ALIGN (type);
1412
1413 if ((mask & 3) == 3)
1414 {
1415 insert_field_into_struct (ctx->record_type, field);
1416 if (ctx->srecord_type)
1417 {
1418 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1419 FIELD_DECL, DECL_NAME (var), type);
1420 DECL_ABSTRACT_ORIGIN (sfield) = var;
1421 DECL_ALIGN (sfield) = DECL_ALIGN (field);
1422 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1423 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1424 insert_field_into_struct (ctx->srecord_type, sfield);
1425 }
1426 }
1427 else
1428 {
1429 if (ctx->srecord_type == NULL_TREE)
1430 {
1431 tree t;
1432
1433 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1434 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1435 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1436 {
1437 sfield = build_decl (DECL_SOURCE_LOCATION (t),
1438 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1439 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1440 insert_field_into_struct (ctx->srecord_type, sfield);
1441 splay_tree_insert (ctx->sfield_map,
1442 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1443 (splay_tree_value) sfield);
1444 }
1445 }
1446 sfield = field;
1447 insert_field_into_struct ((mask & 1) ? ctx->record_type
1448 : ctx->srecord_type, field);
1449 }
1450
1451 if (mask & 1)
1452 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
1453 if ((mask & 2) && ctx->sfield_map)
1454 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1455 }
1456
1457 static tree
1458 install_var_local (tree var, omp_context *ctx)
1459 {
1460 tree new_var = omp_copy_decl_1 (var, ctx);
1461 insert_decl_map (&ctx->cb, var, new_var);
1462 return new_var;
1463 }
1464
1465 /* Adjust the replacement for DECL in CTX for the new context. This means
1466 copying the DECL_VALUE_EXPR, and fixing up the type. */
1467
1468 static void
1469 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1470 {
1471 tree new_decl, size;
1472
1473 new_decl = lookup_decl (decl, ctx);
1474
1475 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1476
1477 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1478 && DECL_HAS_VALUE_EXPR_P (decl))
1479 {
1480 tree ve = DECL_VALUE_EXPR (decl);
1481 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1482 SET_DECL_VALUE_EXPR (new_decl, ve);
1483 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1484 }
1485
1486 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1487 {
1488 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1489 if (size == error_mark_node)
1490 size = TYPE_SIZE (TREE_TYPE (new_decl));
1491 DECL_SIZE (new_decl) = size;
1492
1493 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1494 if (size == error_mark_node)
1495 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1496 DECL_SIZE_UNIT (new_decl) = size;
1497 }
1498 }
1499
1500 /* The callback for remap_decl. Search all containing contexts for a
1501 mapping of the variable; this avoids having to duplicate the splay
1502 tree ahead of time. We know a mapping doesn't already exist in the
1503 given context. Create new mappings to implement default semantics. */
1504
1505 static tree
1506 omp_copy_decl (tree var, copy_body_data *cb)
1507 {
1508 omp_context *ctx = (omp_context *) cb;
1509 tree new_var;
1510
1511 if (TREE_CODE (var) == LABEL_DECL)
1512 {
1513 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1514 DECL_CONTEXT (new_var) = current_function_decl;
1515 insert_decl_map (&ctx->cb, var, new_var);
1516 return new_var;
1517 }
1518
1519 while (!is_taskreg_ctx (ctx))
1520 {
1521 ctx = ctx->outer;
1522 if (ctx == NULL)
1523 return var;
1524 new_var = maybe_lookup_decl (var, ctx);
1525 if (new_var)
1526 return new_var;
1527 }
1528
1529 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1530 return var;
1531
1532 return error_mark_node;
1533 }
1534
1535
1536 /* Debugging dumps for parallel regions. */
1537 void dump_omp_region (FILE *, struct omp_region *, int);
1538 void debug_omp_region (struct omp_region *);
1539 void debug_all_omp_regions (void);
1540
1541 /* Dump the parallel region tree rooted at REGION. */
1542
1543 void
1544 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1545 {
1546 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1547 gimple_code_name[region->type]);
1548
1549 if (region->inner)
1550 dump_omp_region (file, region->inner, indent + 4);
1551
1552 if (region->cont)
1553 {
1554 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1555 region->cont->index);
1556 }
1557
1558 if (region->exit)
1559 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1560 region->exit->index);
1561 else
1562 fprintf (file, "%*s[no exit marker]\n", indent, "");
1563
1564 if (region->next)
1565 dump_omp_region (file, region->next, indent);
1566 }
1567
1568 DEBUG_FUNCTION void
1569 debug_omp_region (struct omp_region *region)
1570 {
1571 dump_omp_region (stderr, region, 0);
1572 }
1573
1574 DEBUG_FUNCTION void
1575 debug_all_omp_regions (void)
1576 {
1577 dump_omp_region (stderr, root_omp_region, 0);
1578 }
1579
1580
1581 /* Create a new parallel region starting at STMT inside region PARENT. */
1582
1583 static struct omp_region *
1584 new_omp_region (basic_block bb, enum gimple_code type,
1585 struct omp_region *parent)
1586 {
1587 struct omp_region *region = XCNEW (struct omp_region);
1588
1589 region->outer = parent;
1590 region->entry = bb;
1591 region->type = type;
1592
1593 if (parent)
1594 {
1595 /* This is a nested region. Add it to the list of inner
1596 regions in PARENT. */
1597 region->next = parent->inner;
1598 parent->inner = region;
1599 }
1600 else
1601 {
1602 /* This is a toplevel region. Add it to the list of toplevel
1603 regions in ROOT_OMP_REGION. */
1604 region->next = root_omp_region;
1605 root_omp_region = region;
1606 }
1607
1608 return region;
1609 }
1610
1611 /* Release the memory associated with the region tree rooted at REGION. */
1612
1613 static void
1614 free_omp_region_1 (struct omp_region *region)
1615 {
1616 struct omp_region *i, *n;
1617
1618 for (i = region->inner; i ; i = n)
1619 {
1620 n = i->next;
1621 free_omp_region_1 (i);
1622 }
1623
1624 free (region);
1625 }
1626
1627 /* Release the memory for the entire omp region tree. */
1628
1629 void
1630 free_omp_regions (void)
1631 {
1632 struct omp_region *r, *n;
1633 for (r = root_omp_region; r ; r = n)
1634 {
1635 n = r->next;
1636 free_omp_region_1 (r);
1637 }
1638 root_omp_region = NULL;
1639 }
1640
1641
1642 /* Create a new context, with OUTER_CTX being the surrounding context. */
1643
1644 static omp_context *
1645 new_omp_context (gimple *stmt, omp_context *outer_ctx)
1646 {
1647 omp_context *ctx = XCNEW (omp_context);
1648
1649 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1650 (splay_tree_value) ctx);
1651 ctx->stmt = stmt;
1652
1653 if (outer_ctx)
1654 {
1655 ctx->outer = outer_ctx;
1656 ctx->cb = outer_ctx->cb;
1657 ctx->cb.block = NULL;
1658 ctx->depth = outer_ctx->depth + 1;
1659 }
1660 else
1661 {
1662 ctx->cb.src_fn = current_function_decl;
1663 ctx->cb.dst_fn = current_function_decl;
1664 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1665 gcc_checking_assert (ctx->cb.src_node);
1666 ctx->cb.dst_node = ctx->cb.src_node;
1667 ctx->cb.src_cfun = cfun;
1668 ctx->cb.copy_decl = omp_copy_decl;
1669 ctx->cb.eh_lp_nr = 0;
1670 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1671 ctx->depth = 1;
1672 }
1673
1674 ctx->cb.decl_map = new hash_map<tree, tree>;
1675
1676 return ctx;
1677 }
1678
1679 static gimple_seq maybe_catch_exception (gimple_seq);
1680
1681 /* Finalize task copyfn. */
1682
1683 static void
1684 finalize_task_copyfn (gomp_task *task_stmt)
1685 {
1686 struct function *child_cfun;
1687 tree child_fn;
1688 gimple_seq seq = NULL, new_seq;
1689 gbind *bind;
1690
1691 child_fn = gimple_omp_task_copy_fn (task_stmt);
1692 if (child_fn == NULL_TREE)
1693 return;
1694
1695 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1696 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1697
1698 push_cfun (child_cfun);
1699 bind = gimplify_body (child_fn, false);
1700 gimple_seq_add_stmt (&seq, bind);
1701 new_seq = maybe_catch_exception (seq);
1702 if (new_seq != seq)
1703 {
1704 bind = gimple_build_bind (NULL, new_seq, NULL);
1705 seq = NULL;
1706 gimple_seq_add_stmt (&seq, bind);
1707 }
1708 gimple_set_body (child_fn, seq);
1709 pop_cfun ();
1710
1711 /* Inform the callgraph about the new function. */
1712 cgraph_node *node = cgraph_node::get_create (child_fn);
1713 node->parallelized_function = 1;
1714 cgraph_node::add_new_function (child_fn, false);
1715 }
1716
1717 /* Destroy a omp_context data structures. Called through the splay tree
1718 value delete callback. */
1719
1720 static void
1721 delete_omp_context (splay_tree_value value)
1722 {
1723 omp_context *ctx = (omp_context *) value;
1724
1725 delete ctx->cb.decl_map;
1726
1727 if (ctx->field_map)
1728 splay_tree_delete (ctx->field_map);
1729 if (ctx->sfield_map)
1730 splay_tree_delete (ctx->sfield_map);
1731
1732 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1733 it produces corrupt debug information. */
1734 if (ctx->record_type)
1735 {
1736 tree t;
1737 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1738 DECL_ABSTRACT_ORIGIN (t) = NULL;
1739 }
1740 if (ctx->srecord_type)
1741 {
1742 tree t;
1743 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1744 DECL_ABSTRACT_ORIGIN (t) = NULL;
1745 }
1746
1747 if (is_task_ctx (ctx))
1748 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1749
1750 XDELETE (ctx);
1751 }
1752
1753 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1754 context. */
1755
1756 static void
1757 fixup_child_record_type (omp_context *ctx)
1758 {
1759 tree f, type = ctx->record_type;
1760
1761 /* ??? It isn't sufficient to just call remap_type here, because
1762 variably_modified_type_p doesn't work the way we expect for
1763 record types. Testing each field for whether it needs remapping
1764 and creating a new record by hand works, however. */
1765 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1766 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1767 break;
1768 if (f)
1769 {
1770 tree name, new_fields = NULL;
1771
1772 type = lang_hooks.types.make_type (RECORD_TYPE);
1773 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1774 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1775 TYPE_DECL, name, type);
1776 TYPE_NAME (type) = name;
1777
1778 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1779 {
1780 tree new_f = copy_node (f);
1781 DECL_CONTEXT (new_f) = type;
1782 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1783 DECL_CHAIN (new_f) = new_fields;
1784 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1785 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1786 &ctx->cb, NULL);
1787 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1788 &ctx->cb, NULL);
1789 new_fields = new_f;
1790
1791 /* Arrange to be able to look up the receiver field
1792 given the sender field. */
1793 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1794 (splay_tree_value) new_f);
1795 }
1796 TYPE_FIELDS (type) = nreverse (new_fields);
1797 layout_type (type);
1798 }
1799
1800 /* In a target region we never modify any of the pointers in *.omp_data_i,
1801 so attempt to help the optimizers. */
1802 if (is_gimple_omp_offloaded (ctx->stmt))
1803 type = build_qualified_type (type, TYPE_QUAL_CONST);
1804
1805 TREE_TYPE (ctx->receiver_decl)
1806 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1807 }
1808
1809 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1810 specified by CLAUSES. */
1811
1812 static void
1813 scan_sharing_clauses (tree clauses, omp_context *ctx)
1814 {
1815 tree c, decl;
1816 bool scan_array_reductions = false;
1817
1818 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1819 {
1820 bool by_ref;
1821
1822 switch (OMP_CLAUSE_CODE (c))
1823 {
1824 case OMP_CLAUSE_PRIVATE:
1825 decl = OMP_CLAUSE_DECL (c);
1826 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1827 goto do_private;
1828 else if (!is_variable_sized (decl))
1829 install_var_local (decl, ctx);
1830 break;
1831
1832 case OMP_CLAUSE_SHARED:
1833 decl = OMP_CLAUSE_DECL (c);
1834 /* Ignore shared directives in teams construct. */
1835 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1836 {
1837 /* Global variables don't need to be copied,
1838 the receiver side will use them directly. */
1839 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1840 if (is_global_var (odecl))
1841 break;
1842 insert_decl_map (&ctx->cb, decl, odecl);
1843 break;
1844 }
1845 gcc_assert (is_taskreg_ctx (ctx));
1846 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1847 || !is_variable_sized (decl));
1848 /* Global variables don't need to be copied,
1849 the receiver side will use them directly. */
1850 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1851 break;
1852 by_ref = use_pointer_for_field (decl, ctx);
1853 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1854 break;
1855 if (! TREE_READONLY (decl)
1856 || TREE_ADDRESSABLE (decl)
1857 || by_ref
1858 || is_reference (decl))
1859 {
1860 install_var_field (decl, by_ref, 3, ctx);
1861 install_var_local (decl, ctx);
1862 break;
1863 }
1864 /* We don't need to copy const scalar vars back. */
1865 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1866 goto do_private;
1867
1868 case OMP_CLAUSE_REDUCTION:
1869 decl = OMP_CLAUSE_DECL (c);
1870 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1871 && TREE_CODE (decl) == MEM_REF)
1872 {
1873 tree t = TREE_OPERAND (decl, 0);
1874 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1875 t = TREE_OPERAND (t, 0);
1876 if (TREE_CODE (t) == INDIRECT_REF
1877 || TREE_CODE (t) == ADDR_EXPR)
1878 t = TREE_OPERAND (t, 0);
1879 install_var_local (t, ctx);
1880 if (is_taskreg_ctx (ctx)
1881 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1882 && !is_variable_sized (t))
1883 {
1884 by_ref = use_pointer_for_field (t, ctx);
1885 install_var_field (t, by_ref, 3, ctx);
1886 }
1887 break;
1888 }
1889 goto do_private;
1890
1891 case OMP_CLAUSE_LASTPRIVATE:
1892 /* Let the corresponding firstprivate clause create
1893 the variable. */
1894 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1895 break;
1896 /* FALLTHRU */
1897
1898 case OMP_CLAUSE_FIRSTPRIVATE:
1899 case OMP_CLAUSE_LINEAR:
1900 decl = OMP_CLAUSE_DECL (c);
1901 do_private:
1902 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1903 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1904 && is_gimple_omp_offloaded (ctx->stmt))
1905 {
1906 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1907 install_var_field (decl, !is_reference (decl), 3, ctx);
1908 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1909 install_var_field (decl, true, 3, ctx);
1910 else
1911 install_var_field (decl, false, 3, ctx);
1912 }
1913 if (is_variable_sized (decl))
1914 {
1915 if (is_task_ctx (ctx))
1916 install_var_field (decl, false, 1, ctx);
1917 break;
1918 }
1919 else if (is_taskreg_ctx (ctx))
1920 {
1921 bool global
1922 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1923 by_ref = use_pointer_for_field (decl, NULL);
1924
1925 if (is_task_ctx (ctx)
1926 && (global || by_ref || is_reference (decl)))
1927 {
1928 install_var_field (decl, false, 1, ctx);
1929 if (!global)
1930 install_var_field (decl, by_ref, 2, ctx);
1931 }
1932 else if (!global)
1933 install_var_field (decl, by_ref, 3, ctx);
1934 }
1935 install_var_local (decl, ctx);
1936 break;
1937
1938 case OMP_CLAUSE_USE_DEVICE_PTR:
1939 decl = OMP_CLAUSE_DECL (c);
1940 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1941 install_var_field (decl, true, 3, ctx);
1942 else
1943 install_var_field (decl, false, 3, ctx);
1944 if (DECL_SIZE (decl)
1945 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1946 {
1947 tree decl2 = DECL_VALUE_EXPR (decl);
1948 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
1949 decl2 = TREE_OPERAND (decl2, 0);
1950 gcc_assert (DECL_P (decl2));
1951 install_var_local (decl2, ctx);
1952 }
1953 install_var_local (decl, ctx);
1954 break;
1955
1956 case OMP_CLAUSE_IS_DEVICE_PTR:
1957 decl = OMP_CLAUSE_DECL (c);
1958 goto do_private;
1959
1960 case OMP_CLAUSE__LOOPTEMP_:
1961 gcc_assert (is_taskreg_ctx (ctx));
1962 decl = OMP_CLAUSE_DECL (c);
1963 install_var_field (decl, false, 3, ctx);
1964 install_var_local (decl, ctx);
1965 break;
1966
1967 case OMP_CLAUSE_COPYPRIVATE:
1968 case OMP_CLAUSE_COPYIN:
1969 decl = OMP_CLAUSE_DECL (c);
1970 by_ref = use_pointer_for_field (decl, NULL);
1971 install_var_field (decl, by_ref, 3, ctx);
1972 break;
1973
1974 case OMP_CLAUSE_DEFAULT:
1975 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
1976 break;
1977
1978 case OMP_CLAUSE_FINAL:
1979 case OMP_CLAUSE_IF:
1980 case OMP_CLAUSE_NUM_THREADS:
1981 case OMP_CLAUSE_NUM_TEAMS:
1982 case OMP_CLAUSE_THREAD_LIMIT:
1983 case OMP_CLAUSE_DEVICE:
1984 case OMP_CLAUSE_SCHEDULE:
1985 case OMP_CLAUSE_DIST_SCHEDULE:
1986 case OMP_CLAUSE_DEPEND:
1987 case OMP_CLAUSE_PRIORITY:
1988 case OMP_CLAUSE_GRAINSIZE:
1989 case OMP_CLAUSE_NUM_TASKS:
1990 case OMP_CLAUSE__CILK_FOR_COUNT_:
1991 case OMP_CLAUSE_NUM_GANGS:
1992 case OMP_CLAUSE_NUM_WORKERS:
1993 case OMP_CLAUSE_VECTOR_LENGTH:
1994 if (ctx->outer)
1995 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
1996 break;
1997
1998 case OMP_CLAUSE_TO:
1999 case OMP_CLAUSE_FROM:
2000 case OMP_CLAUSE_MAP:
2001 if (ctx->outer)
2002 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2003 decl = OMP_CLAUSE_DECL (c);
2004 /* Global variables with "omp declare target" attribute
2005 don't need to be copied, the receiver side will use them
2006 directly. */
2007 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2008 && DECL_P (decl)
2009 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2010 && (OMP_CLAUSE_MAP_KIND (c)
2011 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2012 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2013 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2014 && varpool_node::get_create (decl)->offloadable)
2015 break;
2016 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2017 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
2018 {
2019 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2020 not offloaded; there is nothing to map for those. */
2021 if (!is_gimple_omp_offloaded (ctx->stmt)
2022 && !POINTER_TYPE_P (TREE_TYPE (decl))
2023 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
2024 break;
2025 }
2026 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2027 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2028 || (OMP_CLAUSE_MAP_KIND (c)
2029 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
2030 {
2031 if (TREE_CODE (decl) == COMPONENT_REF
2032 || (TREE_CODE (decl) == INDIRECT_REF
2033 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2034 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2035 == REFERENCE_TYPE)))
2036 break;
2037 if (DECL_SIZE (decl)
2038 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2039 {
2040 tree decl2 = DECL_VALUE_EXPR (decl);
2041 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2042 decl2 = TREE_OPERAND (decl2, 0);
2043 gcc_assert (DECL_P (decl2));
2044 install_var_local (decl2, ctx);
2045 }
2046 install_var_local (decl, ctx);
2047 break;
2048 }
2049 if (DECL_P (decl))
2050 {
2051 if (DECL_SIZE (decl)
2052 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2053 {
2054 tree decl2 = DECL_VALUE_EXPR (decl);
2055 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2056 decl2 = TREE_OPERAND (decl2, 0);
2057 gcc_assert (DECL_P (decl2));
2058 install_var_field (decl2, true, 3, ctx);
2059 install_var_local (decl2, ctx);
2060 install_var_local (decl, ctx);
2061 }
2062 else
2063 {
2064 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2065 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2066 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2067 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2068 install_var_field (decl, true, 7, ctx);
2069 else
2070 install_var_field (decl, true, 3, ctx);
2071 if (is_gimple_omp_offloaded (ctx->stmt))
2072 install_var_local (decl, ctx);
2073 }
2074 }
2075 else
2076 {
2077 tree base = get_base_address (decl);
2078 tree nc = OMP_CLAUSE_CHAIN (c);
2079 if (DECL_P (base)
2080 && nc != NULL_TREE
2081 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2082 && OMP_CLAUSE_DECL (nc) == base
2083 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
2084 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2085 {
2086 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2087 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2088 }
2089 else
2090 {
2091 if (ctx->outer)
2092 {
2093 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2094 decl = OMP_CLAUSE_DECL (c);
2095 }
2096 gcc_assert (!splay_tree_lookup (ctx->field_map,
2097 (splay_tree_key) decl));
2098 tree field
2099 = build_decl (OMP_CLAUSE_LOCATION (c),
2100 FIELD_DECL, NULL_TREE, ptr_type_node);
2101 DECL_ALIGN (field) = TYPE_ALIGN (ptr_type_node);
2102 insert_field_into_struct (ctx->record_type, field);
2103 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2104 (splay_tree_value) field);
2105 }
2106 }
2107 break;
2108
2109 case OMP_CLAUSE_NOWAIT:
2110 case OMP_CLAUSE_ORDERED:
2111 case OMP_CLAUSE_COLLAPSE:
2112 case OMP_CLAUSE_UNTIED:
2113 case OMP_CLAUSE_MERGEABLE:
2114 case OMP_CLAUSE_PROC_BIND:
2115 case OMP_CLAUSE_SAFELEN:
2116 case OMP_CLAUSE_SIMDLEN:
2117 case OMP_CLAUSE_THREADS:
2118 case OMP_CLAUSE_SIMD:
2119 case OMP_CLAUSE_NOGROUP:
2120 case OMP_CLAUSE_DEFAULTMAP:
2121 case OMP_CLAUSE_ASYNC:
2122 case OMP_CLAUSE_WAIT:
2123 case OMP_CLAUSE_GANG:
2124 case OMP_CLAUSE_WORKER:
2125 case OMP_CLAUSE_VECTOR:
2126 case OMP_CLAUSE_TILE:
2127 break;
2128
2129 case OMP_CLAUSE_ALIGNED:
2130 decl = OMP_CLAUSE_DECL (c);
2131 if (is_global_var (decl)
2132 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2133 install_var_local (decl, ctx);
2134 break;
2135
2136 case OMP_CLAUSE_DEVICE_RESIDENT:
2137 case OMP_CLAUSE_USE_DEVICE:
2138 case OMP_CLAUSE__CACHE_:
2139 case OMP_CLAUSE_INDEPENDENT:
2140 case OMP_CLAUSE_AUTO:
2141 case OMP_CLAUSE_SEQ:
2142 sorry ("Clause not supported yet");
2143 break;
2144
2145 default:
2146 gcc_unreachable ();
2147 }
2148 }
2149
2150 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2151 {
2152 switch (OMP_CLAUSE_CODE (c))
2153 {
2154 case OMP_CLAUSE_LASTPRIVATE:
2155 /* Let the corresponding firstprivate clause create
2156 the variable. */
2157 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2158 scan_array_reductions = true;
2159 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2160 break;
2161 /* FALLTHRU */
2162
2163 case OMP_CLAUSE_FIRSTPRIVATE:
2164 case OMP_CLAUSE_PRIVATE:
2165 case OMP_CLAUSE_LINEAR:
2166 case OMP_CLAUSE_IS_DEVICE_PTR:
2167 decl = OMP_CLAUSE_DECL (c);
2168 if (is_variable_sized (decl))
2169 {
2170 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2171 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2172 && is_gimple_omp_offloaded (ctx->stmt))
2173 {
2174 tree decl2 = DECL_VALUE_EXPR (decl);
2175 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2176 decl2 = TREE_OPERAND (decl2, 0);
2177 gcc_assert (DECL_P (decl2));
2178 install_var_local (decl2, ctx);
2179 fixup_remapped_decl (decl2, ctx, false);
2180 }
2181 install_var_local (decl, ctx);
2182 }
2183 fixup_remapped_decl (decl, ctx,
2184 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2185 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2186 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2187 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2188 scan_array_reductions = true;
2189 break;
2190
2191 case OMP_CLAUSE_REDUCTION:
2192 decl = OMP_CLAUSE_DECL (c);
2193 if (TREE_CODE (decl) != MEM_REF)
2194 {
2195 if (is_variable_sized (decl))
2196 install_var_local (decl, ctx);
2197 fixup_remapped_decl (decl, ctx, false);
2198 }
2199 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2200 scan_array_reductions = true;
2201 break;
2202
2203 case OMP_CLAUSE_SHARED:
2204 /* Ignore shared directives in teams construct. */
2205 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2206 break;
2207 decl = OMP_CLAUSE_DECL (c);
2208 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2209 break;
2210 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2211 {
2212 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2213 ctx->outer)))
2214 break;
2215 bool by_ref = use_pointer_for_field (decl, ctx);
2216 install_var_field (decl, by_ref, 11, ctx);
2217 break;
2218 }
2219 fixup_remapped_decl (decl, ctx, false);
2220 break;
2221
2222 case OMP_CLAUSE_MAP:
2223 if (!is_gimple_omp_offloaded (ctx->stmt))
2224 break;
2225 decl = OMP_CLAUSE_DECL (c);
2226 if (DECL_P (decl)
2227 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2228 && (OMP_CLAUSE_MAP_KIND (c)
2229 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2230 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2231 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2232 && varpool_node::get_create (decl)->offloadable)
2233 break;
2234 if (DECL_P (decl))
2235 {
2236 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2237 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2238 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2239 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2240 {
2241 tree new_decl = lookup_decl (decl, ctx);
2242 TREE_TYPE (new_decl)
2243 = remap_type (TREE_TYPE (decl), &ctx->cb);
2244 }
2245 else if (DECL_SIZE (decl)
2246 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2247 {
2248 tree decl2 = DECL_VALUE_EXPR (decl);
2249 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2250 decl2 = TREE_OPERAND (decl2, 0);
2251 gcc_assert (DECL_P (decl2));
2252 fixup_remapped_decl (decl2, ctx, false);
2253 fixup_remapped_decl (decl, ctx, true);
2254 }
2255 else
2256 fixup_remapped_decl (decl, ctx, false);
2257 }
2258 break;
2259
2260 case OMP_CLAUSE_COPYPRIVATE:
2261 case OMP_CLAUSE_COPYIN:
2262 case OMP_CLAUSE_DEFAULT:
2263 case OMP_CLAUSE_IF:
2264 case OMP_CLAUSE_NUM_THREADS:
2265 case OMP_CLAUSE_NUM_TEAMS:
2266 case OMP_CLAUSE_THREAD_LIMIT:
2267 case OMP_CLAUSE_DEVICE:
2268 case OMP_CLAUSE_SCHEDULE:
2269 case OMP_CLAUSE_DIST_SCHEDULE:
2270 case OMP_CLAUSE_NOWAIT:
2271 case OMP_CLAUSE_ORDERED:
2272 case OMP_CLAUSE_COLLAPSE:
2273 case OMP_CLAUSE_UNTIED:
2274 case OMP_CLAUSE_FINAL:
2275 case OMP_CLAUSE_MERGEABLE:
2276 case OMP_CLAUSE_PROC_BIND:
2277 case OMP_CLAUSE_SAFELEN:
2278 case OMP_CLAUSE_SIMDLEN:
2279 case OMP_CLAUSE_ALIGNED:
2280 case OMP_CLAUSE_DEPEND:
2281 case OMP_CLAUSE__LOOPTEMP_:
2282 case OMP_CLAUSE_TO:
2283 case OMP_CLAUSE_FROM:
2284 case OMP_CLAUSE_PRIORITY:
2285 case OMP_CLAUSE_GRAINSIZE:
2286 case OMP_CLAUSE_NUM_TASKS:
2287 case OMP_CLAUSE_THREADS:
2288 case OMP_CLAUSE_SIMD:
2289 case OMP_CLAUSE_NOGROUP:
2290 case OMP_CLAUSE_DEFAULTMAP:
2291 case OMP_CLAUSE_USE_DEVICE_PTR:
2292 case OMP_CLAUSE__CILK_FOR_COUNT_:
2293 case OMP_CLAUSE_ASYNC:
2294 case OMP_CLAUSE_WAIT:
2295 case OMP_CLAUSE_NUM_GANGS:
2296 case OMP_CLAUSE_NUM_WORKERS:
2297 case OMP_CLAUSE_VECTOR_LENGTH:
2298 case OMP_CLAUSE_GANG:
2299 case OMP_CLAUSE_WORKER:
2300 case OMP_CLAUSE_VECTOR:
2301 case OMP_CLAUSE_TILE:
2302 break;
2303
2304 case OMP_CLAUSE_DEVICE_RESIDENT:
2305 case OMP_CLAUSE_USE_DEVICE:
2306 case OMP_CLAUSE__CACHE_:
2307 case OMP_CLAUSE_INDEPENDENT:
2308 case OMP_CLAUSE_AUTO:
2309 case OMP_CLAUSE_SEQ:
2310 sorry ("Clause not supported yet");
2311 break;
2312
2313 default:
2314 gcc_unreachable ();
2315 }
2316 }
2317
2318 gcc_checking_assert (!scan_array_reductions
2319 || !is_gimple_omp_oacc (ctx->stmt));
2320 if (scan_array_reductions)
2321 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2322 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2323 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2324 {
2325 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2326 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2327 }
2328 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2329 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2330 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2331 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2332 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2333 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2334 }
2335
2336 /* Create a new name for omp child function. Returns an identifier. If
2337 IS_CILK_FOR is true then the suffix for the child function is
2338 "_cilk_for_fn." */
2339
2340 static tree
2341 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2342 {
2343 if (is_cilk_for)
2344 return clone_function_name (current_function_decl, "_cilk_for_fn");
2345 return clone_function_name (current_function_decl,
2346 task_copy ? "_omp_cpyfn" : "_omp_fn");
2347 }
2348
2349 /* Returns the type of the induction variable for the child function for
2350 _Cilk_for and the types for _high and _low variables based on TYPE. */
2351
2352 static tree
2353 cilk_for_check_loop_diff_type (tree type)
2354 {
2355 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2356 {
2357 if (TYPE_UNSIGNED (type))
2358 return uint32_type_node;
2359 else
2360 return integer_type_node;
2361 }
2362 else
2363 {
2364 if (TYPE_UNSIGNED (type))
2365 return uint64_type_node;
2366 else
2367 return long_long_integer_type_node;
2368 }
2369 }
2370
2371 /* Build a decl for the omp child function. It'll not contain a body
2372 yet, just the bare decl. */
2373
2374 static void
2375 create_omp_child_function (omp_context *ctx, bool task_copy)
2376 {
2377 tree decl, type, name, t;
2378
2379 tree cilk_for_count
2380 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2381 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2382 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2383 tree cilk_var_type = NULL_TREE;
2384
2385 name = create_omp_child_function_name (task_copy,
2386 cilk_for_count != NULL_TREE);
2387 if (task_copy)
2388 type = build_function_type_list (void_type_node, ptr_type_node,
2389 ptr_type_node, NULL_TREE);
2390 else if (cilk_for_count)
2391 {
2392 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2393 cilk_var_type = cilk_for_check_loop_diff_type (type);
2394 type = build_function_type_list (void_type_node, ptr_type_node,
2395 cilk_var_type, cilk_var_type, NULL_TREE);
2396 }
2397 else
2398 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2399
2400 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2401
2402 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2403 || !task_copy);
2404 if (!task_copy)
2405 ctx->cb.dst_fn = decl;
2406 else
2407 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2408
2409 TREE_STATIC (decl) = 1;
2410 TREE_USED (decl) = 1;
2411 DECL_ARTIFICIAL (decl) = 1;
2412 DECL_IGNORED_P (decl) = 0;
2413 TREE_PUBLIC (decl) = 0;
2414 DECL_UNINLINABLE (decl) = 1;
2415 DECL_EXTERNAL (decl) = 0;
2416 DECL_CONTEXT (decl) = NULL_TREE;
2417 DECL_INITIAL (decl) = make_node (BLOCK);
2418 if (cgraph_node::get (current_function_decl)->offloadable)
2419 cgraph_node::get_create (decl)->offloadable = 1;
2420 else
2421 {
2422 omp_context *octx;
2423 for (octx = ctx; octx; octx = octx->outer)
2424 if (is_gimple_omp_offloaded (octx->stmt))
2425 {
2426 cgraph_node::get_create (decl)->offloadable = 1;
2427 #ifdef ENABLE_OFFLOADING
2428 g->have_offload = true;
2429 #endif
2430 break;
2431 }
2432 }
2433
2434 if (cgraph_node::get_create (decl)->offloadable
2435 && !lookup_attribute ("omp declare target",
2436 DECL_ATTRIBUTES (current_function_decl)))
2437 DECL_ATTRIBUTES (decl)
2438 = tree_cons (get_identifier ("omp target entrypoint"),
2439 NULL_TREE, DECL_ATTRIBUTES (decl));
2440
2441 t = build_decl (DECL_SOURCE_LOCATION (decl),
2442 RESULT_DECL, NULL_TREE, void_type_node);
2443 DECL_ARTIFICIAL (t) = 1;
2444 DECL_IGNORED_P (t) = 1;
2445 DECL_CONTEXT (t) = decl;
2446 DECL_RESULT (decl) = t;
2447
2448 /* _Cilk_for's child function requires two extra parameters called
2449 __low and __high that are set the by Cilk runtime when it calls this
2450 function. */
2451 if (cilk_for_count)
2452 {
2453 t = build_decl (DECL_SOURCE_LOCATION (decl),
2454 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2455 DECL_ARTIFICIAL (t) = 1;
2456 DECL_NAMELESS (t) = 1;
2457 DECL_ARG_TYPE (t) = ptr_type_node;
2458 DECL_CONTEXT (t) = current_function_decl;
2459 TREE_USED (t) = 1;
2460 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2461 DECL_ARGUMENTS (decl) = t;
2462
2463 t = build_decl (DECL_SOURCE_LOCATION (decl),
2464 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2465 DECL_ARTIFICIAL (t) = 1;
2466 DECL_NAMELESS (t) = 1;
2467 DECL_ARG_TYPE (t) = ptr_type_node;
2468 DECL_CONTEXT (t) = current_function_decl;
2469 TREE_USED (t) = 1;
2470 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2471 DECL_ARGUMENTS (decl) = t;
2472 }
2473
2474 tree data_name = get_identifier (".omp_data_i");
2475 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2476 ptr_type_node);
2477 DECL_ARTIFICIAL (t) = 1;
2478 DECL_NAMELESS (t) = 1;
2479 DECL_ARG_TYPE (t) = ptr_type_node;
2480 DECL_CONTEXT (t) = current_function_decl;
2481 TREE_USED (t) = 1;
2482 TREE_READONLY (t) = 1;
2483 if (cilk_for_count)
2484 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2485 DECL_ARGUMENTS (decl) = t;
2486 if (!task_copy)
2487 ctx->receiver_decl = t;
2488 else
2489 {
2490 t = build_decl (DECL_SOURCE_LOCATION (decl),
2491 PARM_DECL, get_identifier (".omp_data_o"),
2492 ptr_type_node);
2493 DECL_ARTIFICIAL (t) = 1;
2494 DECL_NAMELESS (t) = 1;
2495 DECL_ARG_TYPE (t) = ptr_type_node;
2496 DECL_CONTEXT (t) = current_function_decl;
2497 TREE_USED (t) = 1;
2498 TREE_ADDRESSABLE (t) = 1;
2499 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2500 DECL_ARGUMENTS (decl) = t;
2501 }
2502
2503 /* Allocate memory for the function structure. The call to
2504 allocate_struct_function clobbers CFUN, so we need to restore
2505 it afterward. */
2506 push_struct_function (decl);
2507 cfun->function_end_locus = gimple_location (ctx->stmt);
2508 pop_cfun ();
2509 }
2510
2511 /* Callback for walk_gimple_seq. Check if combined parallel
2512 contains gimple_omp_for_combined_into_p OMP_FOR. */
2513
2514 static tree
2515 find_combined_for (gimple_stmt_iterator *gsi_p,
2516 bool *handled_ops_p,
2517 struct walk_stmt_info *wi)
2518 {
2519 gimple *stmt = gsi_stmt (*gsi_p);
2520
2521 *handled_ops_p = true;
2522 switch (gimple_code (stmt))
2523 {
2524 WALK_SUBSTMTS;
2525
2526 case GIMPLE_OMP_FOR:
2527 if (gimple_omp_for_combined_into_p (stmt)
2528 && gimple_omp_for_kind (stmt)
2529 == *(const enum gf_mask *) (wi->info))
2530 {
2531 wi->info = stmt;
2532 return integer_zero_node;
2533 }
2534 break;
2535 default:
2536 break;
2537 }
2538 return NULL;
2539 }
2540
2541 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2542
2543 static void
2544 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2545 omp_context *outer_ctx)
2546 {
2547 struct walk_stmt_info wi;
2548
2549 memset (&wi, 0, sizeof (wi));
2550 wi.val_only = true;
2551 wi.info = (void *) &msk;
2552 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2553 if (wi.info != (void *) &msk)
2554 {
2555 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2556 struct omp_for_data fd;
2557 extract_omp_for_data (for_stmt, &fd, NULL);
2558 /* We need two temporaries with fd.loop.v type (istart/iend)
2559 and then (fd.collapse - 1) temporaries with the same
2560 type for count2 ... countN-1 vars if not constant. */
2561 size_t count = 2, i;
2562 tree type = fd.iter_type;
2563 if (fd.collapse > 1
2564 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2565 {
2566 count += fd.collapse - 1;
2567 /* If there are lastprivate clauses on the inner
2568 GIMPLE_OMP_FOR, add one more temporaries for the total number
2569 of iterations (product of count1 ... countN-1). */
2570 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2571 OMP_CLAUSE_LASTPRIVATE))
2572 count++;
2573 else if (msk == GF_OMP_FOR_KIND_FOR
2574 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2575 OMP_CLAUSE_LASTPRIVATE))
2576 count++;
2577 }
2578 for (i = 0; i < count; i++)
2579 {
2580 tree temp = create_tmp_var (type);
2581 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2582 insert_decl_map (&outer_ctx->cb, temp, temp);
2583 OMP_CLAUSE_DECL (c) = temp;
2584 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2585 gimple_omp_taskreg_set_clauses (stmt, c);
2586 }
2587 }
2588 }
2589
2590 /* Scan an OpenMP parallel directive. */
2591
2592 static void
2593 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2594 {
2595 omp_context *ctx;
2596 tree name;
2597 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2598
2599 /* Ignore parallel directives with empty bodies, unless there
2600 are copyin clauses. */
2601 if (optimize > 0
2602 && empty_body_p (gimple_omp_body (stmt))
2603 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2604 OMP_CLAUSE_COPYIN) == NULL)
2605 {
2606 gsi_replace (gsi, gimple_build_nop (), false);
2607 return;
2608 }
2609
2610 if (gimple_omp_parallel_combined_p (stmt))
2611 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2612
2613 ctx = new_omp_context (stmt, outer_ctx);
2614 taskreg_contexts.safe_push (ctx);
2615 if (taskreg_nesting_level > 1)
2616 ctx->is_nested = true;
2617 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2618 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2619 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2620 name = create_tmp_var_name (".omp_data_s");
2621 name = build_decl (gimple_location (stmt),
2622 TYPE_DECL, name, ctx->record_type);
2623 DECL_ARTIFICIAL (name) = 1;
2624 DECL_NAMELESS (name) = 1;
2625 TYPE_NAME (ctx->record_type) = name;
2626 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2627 create_omp_child_function (ctx, false);
2628 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2629
2630 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2631 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2632
2633 if (TYPE_FIELDS (ctx->record_type) == NULL)
2634 ctx->record_type = ctx->receiver_decl = NULL;
2635 }
2636
2637 /* Scan an OpenMP task directive. */
2638
2639 static void
2640 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2641 {
2642 omp_context *ctx;
2643 tree name, t;
2644 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2645
2646 /* Ignore task directives with empty bodies. */
2647 if (optimize > 0
2648 && empty_body_p (gimple_omp_body (stmt)))
2649 {
2650 gsi_replace (gsi, gimple_build_nop (), false);
2651 return;
2652 }
2653
2654 if (gimple_omp_task_taskloop_p (stmt))
2655 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2656
2657 ctx = new_omp_context (stmt, outer_ctx);
2658 taskreg_contexts.safe_push (ctx);
2659 if (taskreg_nesting_level > 1)
2660 ctx->is_nested = true;
2661 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2662 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2663 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2664 name = create_tmp_var_name (".omp_data_s");
2665 name = build_decl (gimple_location (stmt),
2666 TYPE_DECL, name, ctx->record_type);
2667 DECL_ARTIFICIAL (name) = 1;
2668 DECL_NAMELESS (name) = 1;
2669 TYPE_NAME (ctx->record_type) = name;
2670 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2671 create_omp_child_function (ctx, false);
2672 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2673
2674 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2675
2676 if (ctx->srecord_type)
2677 {
2678 name = create_tmp_var_name (".omp_data_a");
2679 name = build_decl (gimple_location (stmt),
2680 TYPE_DECL, name, ctx->srecord_type);
2681 DECL_ARTIFICIAL (name) = 1;
2682 DECL_NAMELESS (name) = 1;
2683 TYPE_NAME (ctx->srecord_type) = name;
2684 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2685 create_omp_child_function (ctx, true);
2686 }
2687
2688 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2689
2690 if (TYPE_FIELDS (ctx->record_type) == NULL)
2691 {
2692 ctx->record_type = ctx->receiver_decl = NULL;
2693 t = build_int_cst (long_integer_type_node, 0);
2694 gimple_omp_task_set_arg_size (stmt, t);
2695 t = build_int_cst (long_integer_type_node, 1);
2696 gimple_omp_task_set_arg_align (stmt, t);
2697 }
2698 }
2699
2700
2701 /* If any decls have been made addressable during scan_omp,
2702 adjust their fields if needed, and layout record types
2703 of parallel/task constructs. */
2704
2705 static void
2706 finish_taskreg_scan (omp_context *ctx)
2707 {
2708 if (ctx->record_type == NULL_TREE)
2709 return;
2710
2711 /* If any task_shared_vars were needed, verify all
2712 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2713 statements if use_pointer_for_field hasn't changed
2714 because of that. If it did, update field types now. */
2715 if (task_shared_vars)
2716 {
2717 tree c;
2718
2719 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2720 c; c = OMP_CLAUSE_CHAIN (c))
2721 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2722 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2723 {
2724 tree decl = OMP_CLAUSE_DECL (c);
2725
2726 /* Global variables don't need to be copied,
2727 the receiver side will use them directly. */
2728 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2729 continue;
2730 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2731 || !use_pointer_for_field (decl, ctx))
2732 continue;
2733 tree field = lookup_field (decl, ctx);
2734 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2735 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2736 continue;
2737 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2738 TREE_THIS_VOLATILE (field) = 0;
2739 DECL_USER_ALIGN (field) = 0;
2740 DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field));
2741 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2742 TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field);
2743 if (ctx->srecord_type)
2744 {
2745 tree sfield = lookup_sfield (decl, ctx);
2746 TREE_TYPE (sfield) = TREE_TYPE (field);
2747 TREE_THIS_VOLATILE (sfield) = 0;
2748 DECL_USER_ALIGN (sfield) = 0;
2749 DECL_ALIGN (sfield) = DECL_ALIGN (field);
2750 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2751 TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield);
2752 }
2753 }
2754 }
2755
2756 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2757 {
2758 layout_type (ctx->record_type);
2759 fixup_child_record_type (ctx);
2760 }
2761 else
2762 {
2763 location_t loc = gimple_location (ctx->stmt);
2764 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2765 /* Move VLA fields to the end. */
2766 p = &TYPE_FIELDS (ctx->record_type);
2767 while (*p)
2768 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2769 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2770 {
2771 *q = *p;
2772 *p = TREE_CHAIN (*p);
2773 TREE_CHAIN (*q) = NULL_TREE;
2774 q = &TREE_CHAIN (*q);
2775 }
2776 else
2777 p = &DECL_CHAIN (*p);
2778 *p = vla_fields;
2779 if (gimple_omp_task_taskloop_p (ctx->stmt))
2780 {
2781 /* Move fields corresponding to first and second _looptemp_
2782 clause first. There are filled by GOMP_taskloop
2783 and thus need to be in specific positions. */
2784 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2785 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2786 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2787 OMP_CLAUSE__LOOPTEMP_);
2788 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2789 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2790 p = &TYPE_FIELDS (ctx->record_type);
2791 while (*p)
2792 if (*p == f1 || *p == f2)
2793 *p = DECL_CHAIN (*p);
2794 else
2795 p = &DECL_CHAIN (*p);
2796 DECL_CHAIN (f1) = f2;
2797 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2798 TYPE_FIELDS (ctx->record_type) = f1;
2799 if (ctx->srecord_type)
2800 {
2801 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2802 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2803 p = &TYPE_FIELDS (ctx->srecord_type);
2804 while (*p)
2805 if (*p == f1 || *p == f2)
2806 *p = DECL_CHAIN (*p);
2807 else
2808 p = &DECL_CHAIN (*p);
2809 DECL_CHAIN (f1) = f2;
2810 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2811 TYPE_FIELDS (ctx->srecord_type) = f1;
2812 }
2813 }
2814 layout_type (ctx->record_type);
2815 fixup_child_record_type (ctx);
2816 if (ctx->srecord_type)
2817 layout_type (ctx->srecord_type);
2818 tree t = fold_convert_loc (loc, long_integer_type_node,
2819 TYPE_SIZE_UNIT (ctx->record_type));
2820 gimple_omp_task_set_arg_size (ctx->stmt, t);
2821 t = build_int_cst (long_integer_type_node,
2822 TYPE_ALIGN_UNIT (ctx->record_type));
2823 gimple_omp_task_set_arg_align (ctx->stmt, t);
2824 }
2825 }
2826
2827 /* Find the enclosing offload context. */
2828
2829 static omp_context *
2830 enclosing_target_ctx (omp_context *ctx)
2831 {
2832 for (; ctx; ctx = ctx->outer)
2833 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2834 break;
2835
2836 return ctx;
2837 }
2838
2839 /* Return true if ctx is part of an oacc kernels region. */
2840
2841 static bool
2842 ctx_in_oacc_kernels_region (omp_context *ctx)
2843 {
2844 for (;ctx != NULL; ctx = ctx->outer)
2845 {
2846 gimple *stmt = ctx->stmt;
2847 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2848 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2849 return true;
2850 }
2851
2852 return false;
2853 }
2854
2855 /* Check the parallelism clauses inside a kernels regions.
2856 Until kernels handling moves to use the same loop indirection
2857 scheme as parallel, we need to do this checking early. */
2858
2859 static unsigned
2860 check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2861 {
2862 bool checking = true;
2863 unsigned outer_mask = 0;
2864 unsigned this_mask = 0;
2865 bool has_seq = false, has_auto = false;
2866
2867 if (ctx->outer)
2868 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2869 if (!stmt)
2870 {
2871 checking = false;
2872 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2873 return outer_mask;
2874 stmt = as_a <gomp_for *> (ctx->stmt);
2875 }
2876
2877 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2878 {
2879 switch (OMP_CLAUSE_CODE (c))
2880 {
2881 case OMP_CLAUSE_GANG:
2882 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2883 break;
2884 case OMP_CLAUSE_WORKER:
2885 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2886 break;
2887 case OMP_CLAUSE_VECTOR:
2888 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2889 break;
2890 case OMP_CLAUSE_SEQ:
2891 has_seq = true;
2892 break;
2893 case OMP_CLAUSE_AUTO:
2894 has_auto = true;
2895 break;
2896 default:
2897 break;
2898 }
2899 }
2900
2901 if (checking)
2902 {
2903 if (has_seq && (this_mask || has_auto))
2904 error_at (gimple_location (stmt), "%<seq%> overrides other"
2905 " OpenACC loop specifiers");
2906 else if (has_auto && this_mask)
2907 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2908 " OpenACC loop specifiers");
2909
2910 if (this_mask & outer_mask)
2911 error_at (gimple_location (stmt), "inner loop uses same"
2912 " OpenACC parallelism as containing loop");
2913 }
2914
2915 return outer_mask | this_mask;
2916 }
2917
2918 /* Scan a GIMPLE_OMP_FOR. */
2919
2920 static void
2921 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2922 {
2923 omp_context *ctx;
2924 size_t i;
2925 tree clauses = gimple_omp_for_clauses (stmt);
2926
2927 ctx = new_omp_context (stmt, outer_ctx);
2928
2929 if (is_gimple_omp_oacc (stmt))
2930 {
2931 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2932
2933 if (!tgt || is_oacc_parallel (tgt))
2934 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2935 {
2936 char const *check = NULL;
2937
2938 switch (OMP_CLAUSE_CODE (c))
2939 {
2940 case OMP_CLAUSE_GANG:
2941 check = "gang";
2942 break;
2943
2944 case OMP_CLAUSE_WORKER:
2945 check = "worker";
2946 break;
2947
2948 case OMP_CLAUSE_VECTOR:
2949 check = "vector";
2950 break;
2951
2952 default:
2953 break;
2954 }
2955
2956 if (check && OMP_CLAUSE_OPERAND (c, 0))
2957 error_at (gimple_location (stmt),
2958 "argument not permitted on %qs clause in"
2959 " OpenACC %<parallel%>", check);
2960 }
2961
2962 if (tgt && is_oacc_kernels (tgt))
2963 {
2964 /* Strip out reductions, as they are not handled yet. */
2965 tree *prev_ptr = &clauses;
2966
2967 while (tree probe = *prev_ptr)
2968 {
2969 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
2970
2971 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
2972 *prev_ptr = *next_ptr;
2973 else
2974 prev_ptr = next_ptr;
2975 }
2976
2977 gimple_omp_for_set_clauses (stmt, clauses);
2978 check_oacc_kernel_gwv (stmt, ctx);
2979 }
2980 }
2981
2982 scan_sharing_clauses (clauses, ctx);
2983
2984 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
2985 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
2986 {
2987 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
2988 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
2989 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
2990 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
2991 }
2992 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2993 }
2994
2995 /* Scan an OpenMP sections directive. */
2996
2997 static void
2998 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
2999 {
3000 omp_context *ctx;
3001
3002 ctx = new_omp_context (stmt, outer_ctx);
3003 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3004 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3005 }
3006
3007 /* Scan an OpenMP single directive. */
3008
3009 static void
3010 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3011 {
3012 omp_context *ctx;
3013 tree name;
3014
3015 ctx = new_omp_context (stmt, outer_ctx);
3016 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3017 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3018 name = create_tmp_var_name (".omp_copy_s");
3019 name = build_decl (gimple_location (stmt),
3020 TYPE_DECL, name, ctx->record_type);
3021 TYPE_NAME (ctx->record_type) = name;
3022
3023 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3024 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3025
3026 if (TYPE_FIELDS (ctx->record_type) == NULL)
3027 ctx->record_type = NULL;
3028 else
3029 layout_type (ctx->record_type);
3030 }
3031
3032 /* Scan a GIMPLE_OMP_TARGET. */
3033
3034 static void
3035 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3036 {
3037 omp_context *ctx;
3038 tree name;
3039 bool offloaded = is_gimple_omp_offloaded (stmt);
3040 tree clauses = gimple_omp_target_clauses (stmt);
3041
3042 ctx = new_omp_context (stmt, outer_ctx);
3043 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3044 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3045 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3046 name = create_tmp_var_name (".omp_data_t");
3047 name = build_decl (gimple_location (stmt),
3048 TYPE_DECL, name, ctx->record_type);
3049 DECL_ARTIFICIAL (name) = 1;
3050 DECL_NAMELESS (name) = 1;
3051 TYPE_NAME (ctx->record_type) = name;
3052 TYPE_ARTIFICIAL (ctx->record_type) = 1;
3053 if (offloaded)
3054 {
3055 create_omp_child_function (ctx, false);
3056 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3057 }
3058
3059 scan_sharing_clauses (clauses, ctx);
3060 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3061
3062 if (TYPE_FIELDS (ctx->record_type) == NULL)
3063 ctx->record_type = ctx->receiver_decl = NULL;
3064 else
3065 {
3066 TYPE_FIELDS (ctx->record_type)
3067 = nreverse (TYPE_FIELDS (ctx->record_type));
3068 if (flag_checking)
3069 {
3070 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3071 for (tree field = TYPE_FIELDS (ctx->record_type);
3072 field;
3073 field = DECL_CHAIN (field))
3074 gcc_assert (DECL_ALIGN (field) == align);
3075 }
3076 layout_type (ctx->record_type);
3077 if (offloaded)
3078 fixup_child_record_type (ctx);
3079 }
3080 }
3081
3082 /* Scan an OpenMP teams directive. */
3083
3084 static void
3085 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3086 {
3087 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3088 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3089 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3090 }
3091
3092 /* Check nesting restrictions. */
3093 static bool
3094 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3095 {
3096 tree c;
3097
3098 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3099 inside an OpenACC CTX. */
3100 if (!(is_gimple_omp (stmt)
3101 && is_gimple_omp_oacc (stmt)))
3102 {
3103 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3104 if (is_gimple_omp (octx->stmt)
3105 && is_gimple_omp_oacc (octx->stmt)
3106 /* Except for atomic codes that we share with OpenMP. */
3107 && ! (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3108 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3109 {
3110 error_at (gimple_location (stmt),
3111 "non-OpenACC construct inside of OpenACC region");
3112 return false;
3113 }
3114 }
3115
3116 if (ctx != NULL)
3117 {
3118 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3119 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3120 {
3121 c = NULL_TREE;
3122 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3123 {
3124 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3125 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3126 {
3127 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3128 && (ctx->outer == NULL
3129 || !gimple_omp_for_combined_into_p (ctx->stmt)
3130 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3131 || (gimple_omp_for_kind (ctx->outer->stmt)
3132 != GF_OMP_FOR_KIND_FOR)
3133 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3134 {
3135 error_at (gimple_location (stmt),
3136 "%<ordered simd threads%> must be closely "
3137 "nested inside of %<for simd%> region");
3138 return false;
3139 }
3140 return true;
3141 }
3142 }
3143 error_at (gimple_location (stmt),
3144 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3145 " may not be nested inside %<simd%> region");
3146 return false;
3147 }
3148 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3149 {
3150 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3151 || (gimple_omp_for_kind (stmt)
3152 != GF_OMP_FOR_KIND_DISTRIBUTE))
3153 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3154 {
3155 error_at (gimple_location (stmt),
3156 "only %<distribute%> or %<parallel%> regions are "
3157 "allowed to be strictly nested inside %<teams%> "
3158 "region");
3159 return false;
3160 }
3161 }
3162 }
3163 switch (gimple_code (stmt))
3164 {
3165 case GIMPLE_OMP_FOR:
3166 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3167 return true;
3168 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3169 {
3170 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3171 {
3172 error_at (gimple_location (stmt),
3173 "%<distribute%> region must be strictly nested "
3174 "inside %<teams%> construct");
3175 return false;
3176 }
3177 return true;
3178 }
3179 /* We split taskloop into task and nested taskloop in it. */
3180 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3181 return true;
3182 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3183 {
3184 bool ok = false;
3185
3186 if (ctx)
3187 switch (gimple_code (ctx->stmt))
3188 {
3189 case GIMPLE_OMP_FOR:
3190 ok = (gimple_omp_for_kind (ctx->stmt)
3191 == GF_OMP_FOR_KIND_OACC_LOOP);
3192 break;
3193
3194 case GIMPLE_OMP_TARGET:
3195 switch (gimple_omp_target_kind (ctx->stmt))
3196 {
3197 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3198 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3199 ok = true;
3200 break;
3201
3202 default:
3203 break;
3204 }
3205
3206 default:
3207 break;
3208 }
3209 else if (get_oacc_fn_attrib (current_function_decl))
3210 ok = true;
3211 if (!ok)
3212 {
3213 error_at (gimple_location (stmt),
3214 "OpenACC loop directive must be associated with"
3215 " an OpenACC compute region");
3216 return false;
3217 }
3218 }
3219 /* FALLTHRU */
3220 case GIMPLE_CALL:
3221 if (is_gimple_call (stmt)
3222 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3223 == BUILT_IN_GOMP_CANCEL
3224 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3225 == BUILT_IN_GOMP_CANCELLATION_POINT))
3226 {
3227 const char *bad = NULL;
3228 const char *kind = NULL;
3229 const char *construct
3230 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3231 == BUILT_IN_GOMP_CANCEL)
3232 ? "#pragma omp cancel"
3233 : "#pragma omp cancellation point";
3234 if (ctx == NULL)
3235 {
3236 error_at (gimple_location (stmt), "orphaned %qs construct",
3237 construct);
3238 return false;
3239 }
3240 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3241 ? tree_to_shwi (gimple_call_arg (stmt, 0))
3242 : 0)
3243 {
3244 case 1:
3245 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3246 bad = "#pragma omp parallel";
3247 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3248 == BUILT_IN_GOMP_CANCEL
3249 && !integer_zerop (gimple_call_arg (stmt, 1)))
3250 ctx->cancellable = true;
3251 kind = "parallel";
3252 break;
3253 case 2:
3254 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3255 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3256 bad = "#pragma omp for";
3257 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3258 == BUILT_IN_GOMP_CANCEL
3259 && !integer_zerop (gimple_call_arg (stmt, 1)))
3260 {
3261 ctx->cancellable = true;
3262 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3263 OMP_CLAUSE_NOWAIT))
3264 warning_at (gimple_location (stmt), 0,
3265 "%<#pragma omp cancel for%> inside "
3266 "%<nowait%> for construct");
3267 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3268 OMP_CLAUSE_ORDERED))
3269 warning_at (gimple_location (stmt), 0,
3270 "%<#pragma omp cancel for%> inside "
3271 "%<ordered%> for construct");
3272 }
3273 kind = "for";
3274 break;
3275 case 4:
3276 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3277 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3278 bad = "#pragma omp sections";
3279 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3280 == BUILT_IN_GOMP_CANCEL
3281 && !integer_zerop (gimple_call_arg (stmt, 1)))
3282 {
3283 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3284 {
3285 ctx->cancellable = true;
3286 if (find_omp_clause (gimple_omp_sections_clauses
3287 (ctx->stmt),
3288 OMP_CLAUSE_NOWAIT))
3289 warning_at (gimple_location (stmt), 0,
3290 "%<#pragma omp cancel sections%> inside "
3291 "%<nowait%> sections construct");
3292 }
3293 else
3294 {
3295 gcc_assert (ctx->outer
3296 && gimple_code (ctx->outer->stmt)
3297 == GIMPLE_OMP_SECTIONS);
3298 ctx->outer->cancellable = true;
3299 if (find_omp_clause (gimple_omp_sections_clauses
3300 (ctx->outer->stmt),
3301 OMP_CLAUSE_NOWAIT))
3302 warning_at (gimple_location (stmt), 0,
3303 "%<#pragma omp cancel sections%> inside "
3304 "%<nowait%> sections construct");
3305 }
3306 }
3307 kind = "sections";
3308 break;
3309 case 8:
3310 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3311 bad = "#pragma omp task";
3312 else
3313 {
3314 for (omp_context *octx = ctx->outer;
3315 octx; octx = octx->outer)
3316 {
3317 switch (gimple_code (octx->stmt))
3318 {
3319 case GIMPLE_OMP_TASKGROUP:
3320 break;
3321 case GIMPLE_OMP_TARGET:
3322 if (gimple_omp_target_kind (octx->stmt)
3323 != GF_OMP_TARGET_KIND_REGION)
3324 continue;
3325 /* FALLTHRU */
3326 case GIMPLE_OMP_PARALLEL:
3327 case GIMPLE_OMP_TEAMS:
3328 error_at (gimple_location (stmt),
3329 "%<%s taskgroup%> construct not closely "
3330 "nested inside of %<taskgroup%> region",
3331 construct);
3332 return false;
3333 default:
3334 continue;
3335 }
3336 break;
3337 }
3338 ctx->cancellable = true;
3339 }
3340 kind = "taskgroup";
3341 break;
3342 default:
3343 error_at (gimple_location (stmt), "invalid arguments");
3344 return false;
3345 }
3346 if (bad)
3347 {
3348 error_at (gimple_location (stmt),
3349 "%<%s %s%> construct not closely nested inside of %qs",
3350 construct, kind, bad);
3351 return false;
3352 }
3353 }
3354 /* FALLTHRU */
3355 case GIMPLE_OMP_SECTIONS:
3356 case GIMPLE_OMP_SINGLE:
3357 for (; ctx != NULL; ctx = ctx->outer)
3358 switch (gimple_code (ctx->stmt))
3359 {
3360 case GIMPLE_OMP_FOR:
3361 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3362 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3363 break;
3364 /* FALLTHRU */
3365 case GIMPLE_OMP_SECTIONS:
3366 case GIMPLE_OMP_SINGLE:
3367 case GIMPLE_OMP_ORDERED:
3368 case GIMPLE_OMP_MASTER:
3369 case GIMPLE_OMP_TASK:
3370 case GIMPLE_OMP_CRITICAL:
3371 if (is_gimple_call (stmt))
3372 {
3373 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3374 != BUILT_IN_GOMP_BARRIER)
3375 return true;
3376 error_at (gimple_location (stmt),
3377 "barrier region may not be closely nested inside "
3378 "of work-sharing, %<critical%>, %<ordered%>, "
3379 "%<master%>, explicit %<task%> or %<taskloop%> "
3380 "region");
3381 return false;
3382 }
3383 error_at (gimple_location (stmt),
3384 "work-sharing region may not be closely nested inside "
3385 "of work-sharing, %<critical%>, %<ordered%>, "
3386 "%<master%>, explicit %<task%> or %<taskloop%> region");
3387 return false;
3388 case GIMPLE_OMP_PARALLEL:
3389 case GIMPLE_OMP_TEAMS:
3390 return true;
3391 case GIMPLE_OMP_TARGET:
3392 if (gimple_omp_target_kind (ctx->stmt)
3393 == GF_OMP_TARGET_KIND_REGION)
3394 return true;
3395 break;
3396 default:
3397 break;
3398 }
3399 break;
3400 case GIMPLE_OMP_MASTER:
3401 for (; ctx != NULL; ctx = ctx->outer)
3402 switch (gimple_code (ctx->stmt))
3403 {
3404 case GIMPLE_OMP_FOR:
3405 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3406 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3407 break;
3408 /* FALLTHRU */
3409 case GIMPLE_OMP_SECTIONS:
3410 case GIMPLE_OMP_SINGLE:
3411 case GIMPLE_OMP_TASK:
3412 error_at (gimple_location (stmt),
3413 "%<master%> region may not be closely nested inside "
3414 "of work-sharing, explicit %<task%> or %<taskloop%> "
3415 "region");
3416 return false;
3417 case GIMPLE_OMP_PARALLEL:
3418 case GIMPLE_OMP_TEAMS:
3419 return true;
3420 case GIMPLE_OMP_TARGET:
3421 if (gimple_omp_target_kind (ctx->stmt)
3422 == GF_OMP_TARGET_KIND_REGION)
3423 return true;
3424 break;
3425 default:
3426 break;
3427 }
3428 break;
3429 case GIMPLE_OMP_TASK:
3430 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3431 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3432 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3433 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3434 {
3435 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3436 error_at (OMP_CLAUSE_LOCATION (c),
3437 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3438 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3439 return false;
3440 }
3441 break;
3442 case GIMPLE_OMP_ORDERED:
3443 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3444 c; c = OMP_CLAUSE_CHAIN (c))
3445 {
3446 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3447 {
3448 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3449 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
3450 continue;
3451 }
3452 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3453 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3454 || kind == OMP_CLAUSE_DEPEND_SINK)
3455 {
3456 tree oclause;
3457 /* Look for containing ordered(N) loop. */
3458 if (ctx == NULL
3459 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3460 || (oclause
3461 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3462 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3463 {
3464 error_at (OMP_CLAUSE_LOCATION (c),
3465 "%<ordered%> construct with %<depend%> clause "
3466 "must be closely nested inside an %<ordered%> "
3467 "loop");
3468 return false;
3469 }
3470 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3471 {
3472 error_at (OMP_CLAUSE_LOCATION (c),
3473 "%<ordered%> construct with %<depend%> clause "
3474 "must be closely nested inside a loop with "
3475 "%<ordered%> clause with a parameter");
3476 return false;
3477 }
3478 }
3479 else
3480 {
3481 error_at (OMP_CLAUSE_LOCATION (c),
3482 "invalid depend kind in omp %<ordered%> %<depend%>");
3483 return false;
3484 }
3485 }
3486 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3487 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3488 {
3489 /* ordered simd must be closely nested inside of simd region,
3490 and simd region must not encounter constructs other than
3491 ordered simd, therefore ordered simd may be either orphaned,
3492 or ctx->stmt must be simd. The latter case is handled already
3493 earlier. */
3494 if (ctx != NULL)
3495 {
3496 error_at (gimple_location (stmt),
3497 "%<ordered%> %<simd%> must be closely nested inside "
3498 "%<simd%> region");
3499 return false;
3500 }
3501 }
3502 for (; ctx != NULL; ctx = ctx->outer)
3503 switch (gimple_code (ctx->stmt))
3504 {
3505 case GIMPLE_OMP_CRITICAL:
3506 case GIMPLE_OMP_TASK:
3507 case GIMPLE_OMP_ORDERED:
3508 ordered_in_taskloop:
3509 error_at (gimple_location (stmt),
3510 "%<ordered%> region may not be closely nested inside "
3511 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3512 "%<taskloop%> region");
3513 return false;
3514 case GIMPLE_OMP_FOR:
3515 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3516 goto ordered_in_taskloop;
3517 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3518 OMP_CLAUSE_ORDERED) == NULL)
3519 {
3520 error_at (gimple_location (stmt),
3521 "%<ordered%> region must be closely nested inside "
3522 "a loop region with an %<ordered%> clause");
3523 return false;
3524 }
3525 return true;
3526 case GIMPLE_OMP_TARGET:
3527 if (gimple_omp_target_kind (ctx->stmt)
3528 != GF_OMP_TARGET_KIND_REGION)
3529 break;
3530 /* FALLTHRU */
3531 case GIMPLE_OMP_PARALLEL:
3532 case GIMPLE_OMP_TEAMS:
3533 error_at (gimple_location (stmt),
3534 "%<ordered%> region must be closely nested inside "
3535 "a loop region with an %<ordered%> clause");
3536 return false;
3537 default:
3538 break;
3539 }
3540 break;
3541 case GIMPLE_OMP_CRITICAL:
3542 {
3543 tree this_stmt_name
3544 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3545 for (; ctx != NULL; ctx = ctx->outer)
3546 if (gomp_critical *other_crit
3547 = dyn_cast <gomp_critical *> (ctx->stmt))
3548 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3549 {
3550 error_at (gimple_location (stmt),
3551 "%<critical%> region may not be nested inside "
3552 "a %<critical%> region with the same name");
3553 return false;
3554 }
3555 }
3556 break;
3557 case GIMPLE_OMP_TEAMS:
3558 if (ctx == NULL
3559 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3560 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3561 {
3562 error_at (gimple_location (stmt),
3563 "%<teams%> construct not closely nested inside of "
3564 "%<target%> construct");
3565 return false;
3566 }
3567 break;
3568 case GIMPLE_OMP_TARGET:
3569 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3570 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3571 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3572 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3573 {
3574 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3575 error_at (OMP_CLAUSE_LOCATION (c),
3576 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3577 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3578 return false;
3579 }
3580 for (; ctx != NULL; ctx = ctx->outer)
3581 {
3582 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3583 {
3584 if (is_gimple_omp (stmt)
3585 && is_gimple_omp_oacc (stmt)
3586 && is_gimple_omp (ctx->stmt))
3587 {
3588 error_at (gimple_location (stmt),
3589 "OpenACC construct inside of non-OpenACC region");
3590 return false;
3591 }
3592 continue;
3593 }
3594
3595 const char *stmt_name, *ctx_stmt_name;
3596 switch (gimple_omp_target_kind (stmt))
3597 {
3598 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3599 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3600 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3601 case GF_OMP_TARGET_KIND_ENTER_DATA:
3602 stmt_name = "target enter data"; break;
3603 case GF_OMP_TARGET_KIND_EXIT_DATA:
3604 stmt_name = "target exit data"; break;
3605 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3606 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3607 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3608 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3609 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3610 stmt_name = "enter/exit data"; break;
3611 default: gcc_unreachable ();
3612 }
3613 switch (gimple_omp_target_kind (ctx->stmt))
3614 {
3615 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3616 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3617 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3618 ctx_stmt_name = "parallel"; break;
3619 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3620 ctx_stmt_name = "kernels"; break;
3621 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3622 default: gcc_unreachable ();
3623 }
3624
3625 /* OpenACC/OpenMP mismatch? */
3626 if (is_gimple_omp_oacc (stmt)
3627 != is_gimple_omp_oacc (ctx->stmt))
3628 {
3629 error_at (gimple_location (stmt),
3630 "%s %qs construct inside of %s %qs region",
3631 (is_gimple_omp_oacc (stmt)
3632 ? "OpenACC" : "OpenMP"), stmt_name,
3633 (is_gimple_omp_oacc (ctx->stmt)
3634 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3635 return false;
3636 }
3637 if (is_gimple_omp_offloaded (ctx->stmt))
3638 {
3639 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3640 if (is_gimple_omp_oacc (ctx->stmt))
3641 {
3642 error_at (gimple_location (stmt),
3643 "%qs construct inside of %qs region",
3644 stmt_name, ctx_stmt_name);
3645 return false;
3646 }
3647 else
3648 {
3649 warning_at (gimple_location (stmt), 0,
3650 "%qs construct inside of %qs region",
3651 stmt_name, ctx_stmt_name);
3652 }
3653 }
3654 }
3655 break;
3656 default:
3657 break;
3658 }
3659 return true;
3660 }
3661
3662
3663 /* Helper function scan_omp.
3664
3665 Callback for walk_tree or operators in walk_gimple_stmt used to
3666 scan for OMP directives in TP. */
3667
3668 static tree
3669 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3670 {
3671 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3672 omp_context *ctx = (omp_context *) wi->info;
3673 tree t = *tp;
3674
3675 switch (TREE_CODE (t))
3676 {
3677 case VAR_DECL:
3678 case PARM_DECL:
3679 case LABEL_DECL:
3680 case RESULT_DECL:
3681 if (ctx)
3682 *tp = remap_decl (t, &ctx->cb);
3683 break;
3684
3685 default:
3686 if (ctx && TYPE_P (t))
3687 *tp = remap_type (t, &ctx->cb);
3688 else if (!DECL_P (t))
3689 {
3690 *walk_subtrees = 1;
3691 if (ctx)
3692 {
3693 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3694 if (tem != TREE_TYPE (t))
3695 {
3696 if (TREE_CODE (t) == INTEGER_CST)
3697 *tp = wide_int_to_tree (tem, t);
3698 else
3699 TREE_TYPE (t) = tem;
3700 }
3701 }
3702 }
3703 break;
3704 }
3705
3706 return NULL_TREE;
3707 }
3708
3709 /* Return true if FNDECL is a setjmp or a longjmp. */
3710
3711 static bool
3712 setjmp_or_longjmp_p (const_tree fndecl)
3713 {
3714 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3715 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3716 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3717 return true;
3718
3719 tree declname = DECL_NAME (fndecl);
3720 if (!declname)
3721 return false;
3722 const char *name = IDENTIFIER_POINTER (declname);
3723 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3724 }
3725
3726
3727 /* Helper function for scan_omp.
3728
3729 Callback for walk_gimple_stmt used to scan for OMP directives in
3730 the current statement in GSI. */
3731
3732 static tree
3733 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3734 struct walk_stmt_info *wi)
3735 {
3736 gimple *stmt = gsi_stmt (*gsi);
3737 omp_context *ctx = (omp_context *) wi->info;
3738
3739 if (gimple_has_location (stmt))
3740 input_location = gimple_location (stmt);
3741
3742 /* Check the nesting restrictions. */
3743 bool remove = false;
3744 if (is_gimple_omp (stmt))
3745 remove = !check_omp_nesting_restrictions (stmt, ctx);
3746 else if (is_gimple_call (stmt))
3747 {
3748 tree fndecl = gimple_call_fndecl (stmt);
3749 if (fndecl)
3750 {
3751 if (setjmp_or_longjmp_p (fndecl)
3752 && ctx
3753 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3754 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3755 {
3756 remove = true;
3757 error_at (gimple_location (stmt),
3758 "setjmp/longjmp inside simd construct");
3759 }
3760 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3761 switch (DECL_FUNCTION_CODE (fndecl))
3762 {
3763 case BUILT_IN_GOMP_BARRIER:
3764 case BUILT_IN_GOMP_CANCEL:
3765 case BUILT_IN_GOMP_CANCELLATION_POINT:
3766 case BUILT_IN_GOMP_TASKYIELD:
3767 case BUILT_IN_GOMP_TASKWAIT:
3768 case BUILT_IN_GOMP_TASKGROUP_START:
3769 case BUILT_IN_GOMP_TASKGROUP_END:
3770 remove = !check_omp_nesting_restrictions (stmt, ctx);
3771 break;
3772 default:
3773 break;
3774 }
3775 }
3776 }
3777 if (remove)
3778 {
3779 stmt = gimple_build_nop ();
3780 gsi_replace (gsi, stmt, false);
3781 }
3782
3783 *handled_ops_p = true;
3784
3785 switch (gimple_code (stmt))
3786 {
3787 case GIMPLE_OMP_PARALLEL:
3788 taskreg_nesting_level++;
3789 scan_omp_parallel (gsi, ctx);
3790 taskreg_nesting_level--;
3791 break;
3792
3793 case GIMPLE_OMP_TASK:
3794 taskreg_nesting_level++;
3795 scan_omp_task (gsi, ctx);
3796 taskreg_nesting_level--;
3797 break;
3798
3799 case GIMPLE_OMP_FOR:
3800 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3801 break;
3802
3803 case GIMPLE_OMP_SECTIONS:
3804 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3805 break;
3806
3807 case GIMPLE_OMP_SINGLE:
3808 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3809 break;
3810
3811 case GIMPLE_OMP_SECTION:
3812 case GIMPLE_OMP_MASTER:
3813 case GIMPLE_OMP_TASKGROUP:
3814 case GIMPLE_OMP_ORDERED:
3815 case GIMPLE_OMP_CRITICAL:
3816 ctx = new_omp_context (stmt, ctx);
3817 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3818 break;
3819
3820 case GIMPLE_OMP_TARGET:
3821 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3822 break;
3823
3824 case GIMPLE_OMP_TEAMS:
3825 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3826 break;
3827
3828 case GIMPLE_BIND:
3829 {
3830 tree var;
3831
3832 *handled_ops_p = false;
3833 if (ctx)
3834 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3835 var ;
3836 var = DECL_CHAIN (var))
3837 insert_decl_map (&ctx->cb, var, var);
3838 }
3839 break;
3840 default:
3841 *handled_ops_p = false;
3842 break;
3843 }
3844
3845 return NULL_TREE;
3846 }
3847
3848
3849 /* Scan all the statements starting at the current statement. CTX
3850 contains context information about the OMP directives and
3851 clauses found during the scan. */
3852
3853 static void
3854 scan_omp (gimple_seq *body_p, omp_context *ctx)
3855 {
3856 location_t saved_location;
3857 struct walk_stmt_info wi;
3858
3859 memset (&wi, 0, sizeof (wi));
3860 wi.info = ctx;
3861 wi.want_locations = true;
3862
3863 saved_location = input_location;
3864 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
3865 input_location = saved_location;
3866 }
3867 \f
3868 /* Re-gimplification and code generation routines. */
3869
3870 /* Build a call to GOMP_barrier. */
3871
3872 static gimple *
3873 build_omp_barrier (tree lhs)
3874 {
3875 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
3876 : BUILT_IN_GOMP_BARRIER);
3877 gcall *g = gimple_build_call (fndecl, 0);
3878 if (lhs)
3879 gimple_call_set_lhs (g, lhs);
3880 return g;
3881 }
3882
3883 /* If a context was created for STMT when it was scanned, return it. */
3884
3885 static omp_context *
3886 maybe_lookup_ctx (gimple *stmt)
3887 {
3888 splay_tree_node n;
3889 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
3890 return n ? (omp_context *) n->value : NULL;
3891 }
3892
3893
3894 /* Find the mapping for DECL in CTX or the immediately enclosing
3895 context that has a mapping for DECL.
3896
3897 If CTX is a nested parallel directive, we may have to use the decl
3898 mappings created in CTX's parent context. Suppose that we have the
3899 following parallel nesting (variable UIDs showed for clarity):
3900
3901 iD.1562 = 0;
3902 #omp parallel shared(iD.1562) -> outer parallel
3903 iD.1562 = iD.1562 + 1;
3904
3905 #omp parallel shared (iD.1562) -> inner parallel
3906 iD.1562 = iD.1562 - 1;
3907
3908 Each parallel structure will create a distinct .omp_data_s structure
3909 for copying iD.1562 in/out of the directive:
3910
3911 outer parallel .omp_data_s.1.i -> iD.1562
3912 inner parallel .omp_data_s.2.i -> iD.1562
3913
3914 A shared variable mapping will produce a copy-out operation before
3915 the parallel directive and a copy-in operation after it. So, in
3916 this case we would have:
3917
3918 iD.1562 = 0;
3919 .omp_data_o.1.i = iD.1562;
3920 #omp parallel shared(iD.1562) -> outer parallel
3921 .omp_data_i.1 = &.omp_data_o.1
3922 .omp_data_i.1->i = .omp_data_i.1->i + 1;
3923
3924 .omp_data_o.2.i = iD.1562; -> **
3925 #omp parallel shared(iD.1562) -> inner parallel
3926 .omp_data_i.2 = &.omp_data_o.2
3927 .omp_data_i.2->i = .omp_data_i.2->i - 1;
3928
3929
3930 ** This is a problem. The symbol iD.1562 cannot be referenced
3931 inside the body of the outer parallel region. But since we are
3932 emitting this copy operation while expanding the inner parallel
3933 directive, we need to access the CTX structure of the outer
3934 parallel directive to get the correct mapping:
3935
3936 .omp_data_o.2.i = .omp_data_i.1->i
3937
3938 Since there may be other workshare or parallel directives enclosing
3939 the parallel directive, it may be necessary to walk up the context
3940 parent chain. This is not a problem in general because nested
3941 parallelism happens only rarely. */
3942
3943 static tree
3944 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3945 {
3946 tree t;
3947 omp_context *up;
3948
3949 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3950 t = maybe_lookup_decl (decl, up);
3951
3952 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
3953
3954 return t ? t : decl;
3955 }
3956
3957
3958 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
3959 in outer contexts. */
3960
3961 static tree
3962 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
3963 {
3964 tree t = NULL;
3965 omp_context *up;
3966
3967 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
3968 t = maybe_lookup_decl (decl, up);
3969
3970 return t ? t : decl;
3971 }
3972
3973
3974 /* Construct the initialization value for reduction operation OP. */
3975
3976 tree
3977 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
3978 {
3979 switch (op)
3980 {
3981 case PLUS_EXPR:
3982 case MINUS_EXPR:
3983 case BIT_IOR_EXPR:
3984 case BIT_XOR_EXPR:
3985 case TRUTH_OR_EXPR:
3986 case TRUTH_ORIF_EXPR:
3987 case TRUTH_XOR_EXPR:
3988 case NE_EXPR:
3989 return build_zero_cst (type);
3990
3991 case MULT_EXPR:
3992 case TRUTH_AND_EXPR:
3993 case TRUTH_ANDIF_EXPR:
3994 case EQ_EXPR:
3995 return fold_convert_loc (loc, type, integer_one_node);
3996
3997 case BIT_AND_EXPR:
3998 return fold_convert_loc (loc, type, integer_minus_one_node);
3999
4000 case MAX_EXPR:
4001 if (SCALAR_FLOAT_TYPE_P (type))
4002 {
4003 REAL_VALUE_TYPE max, min;
4004 if (HONOR_INFINITIES (type))
4005 {
4006 real_inf (&max);
4007 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4008 }
4009 else
4010 real_maxval (&min, 1, TYPE_MODE (type));
4011 return build_real (type, min);
4012 }
4013 else if (POINTER_TYPE_P (type))
4014 {
4015 wide_int min
4016 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4017 return wide_int_to_tree (type, min);
4018 }
4019 else
4020 {
4021 gcc_assert (INTEGRAL_TYPE_P (type));
4022 return TYPE_MIN_VALUE (type);
4023 }
4024
4025 case MIN_EXPR:
4026 if (SCALAR_FLOAT_TYPE_P (type))
4027 {
4028 REAL_VALUE_TYPE max;
4029 if (HONOR_INFINITIES (type))
4030 real_inf (&max);
4031 else
4032 real_maxval (&max, 0, TYPE_MODE (type));
4033 return build_real (type, max);
4034 }
4035 else if (POINTER_TYPE_P (type))
4036 {
4037 wide_int max
4038 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4039 return wide_int_to_tree (type, max);
4040 }
4041 else
4042 {
4043 gcc_assert (INTEGRAL_TYPE_P (type));
4044 return TYPE_MAX_VALUE (type);
4045 }
4046
4047 default:
4048 gcc_unreachable ();
4049 }
4050 }
4051
4052 /* Construct the initialization value for reduction CLAUSE. */
4053
4054 tree
4055 omp_reduction_init (tree clause, tree type)
4056 {
4057 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4058 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4059 }
4060
4061 /* Return alignment to be assumed for var in CLAUSE, which should be
4062 OMP_CLAUSE_ALIGNED. */
4063
4064 static tree
4065 omp_clause_aligned_alignment (tree clause)
4066 {
4067 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4068 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4069
4070 /* Otherwise return implementation defined alignment. */
4071 unsigned int al = 1;
4072 machine_mode mode, vmode;
4073 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4074 if (vs)
4075 vs = 1 << floor_log2 (vs);
4076 static enum mode_class classes[]
4077 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4078 for (int i = 0; i < 4; i += 2)
4079 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4080 mode != VOIDmode;
4081 mode = GET_MODE_WIDER_MODE (mode))
4082 {
4083 vmode = targetm.vectorize.preferred_simd_mode (mode);
4084 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4085 continue;
4086 while (vs
4087 && GET_MODE_SIZE (vmode) < vs
4088 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4089 vmode = GET_MODE_2XWIDER_MODE (vmode);
4090
4091 tree type = lang_hooks.types.type_for_mode (mode, 1);
4092 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4093 continue;
4094 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4095 / GET_MODE_SIZE (mode));
4096 if (TYPE_MODE (type) != vmode)
4097 continue;
4098 if (TYPE_ALIGN_UNIT (type) > al)
4099 al = TYPE_ALIGN_UNIT (type);
4100 }
4101 return build_int_cst (integer_type_node, al);
4102 }
4103
4104 /* Return maximum possible vectorization factor for the target. */
4105
4106 static int
4107 omp_max_vf (void)
4108 {
4109 if (!optimize
4110 || optimize_debug
4111 || !flag_tree_loop_optimize
4112 || (!flag_tree_loop_vectorize
4113 && (global_options_set.x_flag_tree_loop_vectorize
4114 || global_options_set.x_flag_tree_vectorize)))
4115 return 1;
4116
4117 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4118 if (vs)
4119 {
4120 vs = 1 << floor_log2 (vs);
4121 return vs;
4122 }
4123 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
4124 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4125 return GET_MODE_NUNITS (vqimode);
4126 return 1;
4127 }
4128
4129 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4130 privatization. */
4131
4132 static bool
4133 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4134 tree &idx, tree &lane, tree &ivar, tree &lvar)
4135 {
4136 if (max_vf == 0)
4137 {
4138 max_vf = omp_max_vf ();
4139 if (max_vf > 1)
4140 {
4141 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4142 OMP_CLAUSE_SAFELEN);
4143 if (c && TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST)
4144 max_vf = 1;
4145 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4146 max_vf) == -1)
4147 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4148 }
4149 if (max_vf > 1)
4150 {
4151 idx = create_tmp_var (unsigned_type_node);
4152 lane = create_tmp_var (unsigned_type_node);
4153 }
4154 }
4155 if (max_vf == 1)
4156 return false;
4157
4158 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4159 tree avar = create_tmp_var_raw (atype);
4160 if (TREE_ADDRESSABLE (new_var))
4161 TREE_ADDRESSABLE (avar) = 1;
4162 DECL_ATTRIBUTES (avar)
4163 = tree_cons (get_identifier ("omp simd array"), NULL,
4164 DECL_ATTRIBUTES (avar));
4165 gimple_add_tmp_var (avar);
4166 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4167 NULL_TREE, NULL_TREE);
4168 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4169 NULL_TREE, NULL_TREE);
4170 if (DECL_P (new_var))
4171 {
4172 SET_DECL_VALUE_EXPR (new_var, lvar);
4173 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4174 }
4175 return true;
4176 }
4177
4178 /* Helper function of lower_rec_input_clauses. For a reference
4179 in simd reduction, add an underlying variable it will reference. */
4180
4181 static void
4182 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4183 {
4184 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4185 if (TREE_CONSTANT (z))
4186 {
4187 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4188 get_name (new_vard));
4189 gimple_add_tmp_var (z);
4190 TREE_ADDRESSABLE (z) = 1;
4191 z = build_fold_addr_expr_loc (loc, z);
4192 gimplify_assign (new_vard, z, ilist);
4193 }
4194 }
4195
4196 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4197 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4198 private variables. Initialization statements go in ILIST, while calls
4199 to destructors go in DLIST. */
4200
4201 static void
4202 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4203 omp_context *ctx, struct omp_for_data *fd)
4204 {
4205 tree c, dtor, copyin_seq, x, ptr;
4206 bool copyin_by_ref = false;
4207 bool lastprivate_firstprivate = false;
4208 bool reduction_omp_orig_ref = false;
4209 int pass;
4210 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4211 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4212 int max_vf = 0;
4213 tree lane = NULL_TREE, idx = NULL_TREE;
4214 tree ivar = NULL_TREE, lvar = NULL_TREE;
4215 gimple_seq llist[2] = { NULL, NULL };
4216
4217 copyin_seq = NULL;
4218
4219 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4220 with data sharing clauses referencing variable sized vars. That
4221 is unnecessarily hard to support and very unlikely to result in
4222 vectorized code anyway. */
4223 if (is_simd)
4224 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4225 switch (OMP_CLAUSE_CODE (c))
4226 {
4227 case OMP_CLAUSE_LINEAR:
4228 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4229 max_vf = 1;
4230 /* FALLTHRU */
4231 case OMP_CLAUSE_PRIVATE:
4232 case OMP_CLAUSE_FIRSTPRIVATE:
4233 case OMP_CLAUSE_LASTPRIVATE:
4234 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4235 max_vf = 1;
4236 break;
4237 case OMP_CLAUSE_REDUCTION:
4238 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4239 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4240 max_vf = 1;
4241 break;
4242 default:
4243 continue;
4244 }
4245
4246 /* Do all the fixed sized types in the first pass, and the variable sized
4247 types in the second pass. This makes sure that the scalar arguments to
4248 the variable sized types are processed before we use them in the
4249 variable sized operations. */
4250 for (pass = 0; pass < 2; ++pass)
4251 {
4252 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4253 {
4254 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4255 tree var, new_var;
4256 bool by_ref;
4257 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4258
4259 switch (c_kind)
4260 {
4261 case OMP_CLAUSE_PRIVATE:
4262 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4263 continue;
4264 break;
4265 case OMP_CLAUSE_SHARED:
4266 /* Ignore shared directives in teams construct. */
4267 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4268 continue;
4269 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4270 {
4271 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4272 || is_global_var (OMP_CLAUSE_DECL (c)));
4273 continue;
4274 }
4275 case OMP_CLAUSE_FIRSTPRIVATE:
4276 case OMP_CLAUSE_COPYIN:
4277 break;
4278 case OMP_CLAUSE_LINEAR:
4279 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4280 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4281 lastprivate_firstprivate = true;
4282 break;
4283 case OMP_CLAUSE_REDUCTION:
4284 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4285 reduction_omp_orig_ref = true;
4286 break;
4287 case OMP_CLAUSE__LOOPTEMP_:
4288 /* Handle _looptemp_ clauses only on parallel/task. */
4289 if (fd)
4290 continue;
4291 break;
4292 case OMP_CLAUSE_LASTPRIVATE:
4293 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4294 {
4295 lastprivate_firstprivate = true;
4296 if (pass != 0 || is_taskloop_ctx (ctx))
4297 continue;
4298 }
4299 /* Even without corresponding firstprivate, if
4300 decl is Fortran allocatable, it needs outer var
4301 reference. */
4302 else if (pass == 0
4303 && lang_hooks.decls.omp_private_outer_ref
4304 (OMP_CLAUSE_DECL (c)))
4305 lastprivate_firstprivate = true;
4306 break;
4307 case OMP_CLAUSE_ALIGNED:
4308 if (pass == 0)
4309 continue;
4310 var = OMP_CLAUSE_DECL (c);
4311 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4312 && !is_global_var (var))
4313 {
4314 new_var = maybe_lookup_decl (var, ctx);
4315 if (new_var == NULL_TREE)
4316 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4317 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4318 x = build_call_expr_loc (clause_loc, x, 2, new_var,
4319 omp_clause_aligned_alignment (c));
4320 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4321 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4322 gimplify_and_add (x, ilist);
4323 }
4324 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4325 && is_global_var (var))
4326 {
4327 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4328 new_var = lookup_decl (var, ctx);
4329 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4330 t = build_fold_addr_expr_loc (clause_loc, t);
4331 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4332 t = build_call_expr_loc (clause_loc, t2, 2, t,
4333 omp_clause_aligned_alignment (c));
4334 t = fold_convert_loc (clause_loc, ptype, t);
4335 x = create_tmp_var (ptype);
4336 t = build2 (MODIFY_EXPR, ptype, x, t);
4337 gimplify_and_add (t, ilist);
4338 t = build_simple_mem_ref_loc (clause_loc, x);
4339 SET_DECL_VALUE_EXPR (new_var, t);
4340 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4341 }
4342 continue;
4343 default:
4344 continue;
4345 }
4346
4347 new_var = var = OMP_CLAUSE_DECL (c);
4348 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4349 {
4350 var = TREE_OPERAND (var, 0);
4351 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4352 var = TREE_OPERAND (var, 0);
4353 if (TREE_CODE (var) == INDIRECT_REF
4354 || TREE_CODE (var) == ADDR_EXPR)
4355 var = TREE_OPERAND (var, 0);
4356 if (is_variable_sized (var))
4357 {
4358 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4359 var = DECL_VALUE_EXPR (var);
4360 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4361 var = TREE_OPERAND (var, 0);
4362 gcc_assert (DECL_P (var));
4363 }
4364 new_var = var;
4365 }
4366 if (c_kind != OMP_CLAUSE_COPYIN)
4367 new_var = lookup_decl (var, ctx);
4368
4369 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4370 {
4371 if (pass != 0)
4372 continue;
4373 }
4374 /* C/C++ array section reductions. */
4375 else if (c_kind == OMP_CLAUSE_REDUCTION
4376 && var != OMP_CLAUSE_DECL (c))
4377 {
4378 if (pass == 0)
4379 continue;
4380
4381 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
4382 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4383 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4384 {
4385 tree b = TREE_OPERAND (orig_var, 1);
4386 b = maybe_lookup_decl (b, ctx);
4387 if (b == NULL)
4388 {
4389 b = TREE_OPERAND (orig_var, 1);
4390 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4391 }
4392 if (integer_zerop (bias))
4393 bias = b;
4394 else
4395 {
4396 bias = fold_convert_loc (clause_loc,
4397 TREE_TYPE (b), bias);
4398 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4399 TREE_TYPE (b), b, bias);
4400 }
4401 orig_var = TREE_OPERAND (orig_var, 0);
4402 }
4403 if (TREE_CODE (orig_var) == INDIRECT_REF
4404 || TREE_CODE (orig_var) == ADDR_EXPR)
4405 orig_var = TREE_OPERAND (orig_var, 0);
4406 tree d = OMP_CLAUSE_DECL (c);
4407 tree type = TREE_TYPE (d);
4408 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4409 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4410 const char *name = get_name (orig_var);
4411 if (TREE_CONSTANT (v))
4412 {
4413 x = create_tmp_var_raw (type, name);
4414 gimple_add_tmp_var (x);
4415 TREE_ADDRESSABLE (x) = 1;
4416 x = build_fold_addr_expr_loc (clause_loc, x);
4417 }
4418 else
4419 {
4420 tree atmp
4421 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4422 tree t = maybe_lookup_decl (v, ctx);
4423 if (t)
4424 v = t;
4425 else
4426 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4427 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4428 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4429 TREE_TYPE (v), v,
4430 build_int_cst (TREE_TYPE (v), 1));
4431 t = fold_build2_loc (clause_loc, MULT_EXPR,
4432 TREE_TYPE (v), t,
4433 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4434 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4435 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4436 }
4437
4438 tree ptype = build_pointer_type (TREE_TYPE (type));
4439 x = fold_convert_loc (clause_loc, ptype, x);
4440 tree y = create_tmp_var (ptype, name);
4441 gimplify_assign (y, x, ilist);
4442 x = y;
4443 tree yb = y;
4444
4445 if (!integer_zerop (bias))
4446 {
4447 bias = fold_convert_loc (clause_loc, sizetype, bias);
4448 bias = fold_build1_loc (clause_loc, NEGATE_EXPR,
4449 sizetype, bias);
4450 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
4451 TREE_TYPE (x), x, bias);
4452 yb = create_tmp_var (ptype, name);
4453 gimplify_assign (yb, x, ilist);
4454 x = yb;
4455 }
4456
4457 d = TREE_OPERAND (d, 0);
4458 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4459 d = TREE_OPERAND (d, 0);
4460 if (TREE_CODE (d) == ADDR_EXPR)
4461 {
4462 if (orig_var != var)
4463 {
4464 gcc_assert (is_variable_sized (orig_var));
4465 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4466 x);
4467 gimplify_assign (new_var, x, ilist);
4468 tree new_orig_var = lookup_decl (orig_var, ctx);
4469 tree t = build_fold_indirect_ref (new_var);
4470 DECL_IGNORED_P (new_var) = 0;
4471 TREE_THIS_NOTRAP (t);
4472 SET_DECL_VALUE_EXPR (new_orig_var, t);
4473 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4474 }
4475 else
4476 {
4477 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4478 build_int_cst (ptype, 0));
4479 SET_DECL_VALUE_EXPR (new_var, x);
4480 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4481 }
4482 }
4483 else
4484 {
4485 gcc_assert (orig_var == var);
4486 if (TREE_CODE (d) == INDIRECT_REF)
4487 {
4488 x = create_tmp_var (ptype, name);
4489 TREE_ADDRESSABLE (x) = 1;
4490 gimplify_assign (x, yb, ilist);
4491 x = build_fold_addr_expr_loc (clause_loc, x);
4492 }
4493 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4494 gimplify_assign (new_var, x, ilist);
4495 }
4496 tree y1 = create_tmp_var (ptype, NULL);
4497 gimplify_assign (y1, y, ilist);
4498 tree i2 = NULL_TREE, y2 = NULL_TREE;
4499 tree body2 = NULL_TREE, end2 = NULL_TREE;
4500 tree y3 = NULL_TREE, y4 = NULL_TREE;
4501 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4502 {
4503 y2 = create_tmp_var (ptype, NULL);
4504 gimplify_assign (y2, y, ilist);
4505 tree ref = build_outer_var_ref (var, ctx);
4506 /* For ref build_outer_var_ref already performs this. */
4507 if (TREE_CODE (d) == INDIRECT_REF)
4508 gcc_assert (is_reference (var));
4509 else if (TREE_CODE (d) == ADDR_EXPR)
4510 ref = build_fold_addr_expr (ref);
4511 else if (is_reference (var))
4512 ref = build_fold_addr_expr (ref);
4513 ref = fold_convert_loc (clause_loc, ptype, ref);
4514 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4515 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4516 {
4517 y3 = create_tmp_var (ptype, NULL);
4518 gimplify_assign (y3, unshare_expr (ref), ilist);
4519 }
4520 if (is_simd)
4521 {
4522 y4 = create_tmp_var (ptype, NULL);
4523 gimplify_assign (y4, ref, dlist);
4524 }
4525 }
4526 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4527 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4528 tree body = create_artificial_label (UNKNOWN_LOCATION);
4529 tree end = create_artificial_label (UNKNOWN_LOCATION);
4530 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4531 if (y2)
4532 {
4533 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4534 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4535 body2 = create_artificial_label (UNKNOWN_LOCATION);
4536 end2 = create_artificial_label (UNKNOWN_LOCATION);
4537 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4538 }
4539 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4540 {
4541 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4542 tree decl_placeholder
4543 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4544 SET_DECL_VALUE_EXPR (decl_placeholder,
4545 build_simple_mem_ref (y1));
4546 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4547 SET_DECL_VALUE_EXPR (placeholder,
4548 y3 ? build_simple_mem_ref (y3)
4549 : error_mark_node);
4550 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4551 x = lang_hooks.decls.omp_clause_default_ctor
4552 (c, build_simple_mem_ref (y1),
4553 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4554 if (x)
4555 gimplify_and_add (x, ilist);
4556 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4557 {
4558 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4559 lower_omp (&tseq, ctx);
4560 gimple_seq_add_seq (ilist, tseq);
4561 }
4562 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4563 if (is_simd)
4564 {
4565 SET_DECL_VALUE_EXPR (decl_placeholder,
4566 build_simple_mem_ref (y2));
4567 SET_DECL_VALUE_EXPR (placeholder,
4568 build_simple_mem_ref (y4));
4569 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4570 lower_omp (&tseq, ctx);
4571 gimple_seq_add_seq (dlist, tseq);
4572 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4573 }
4574 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4575 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4576 x = lang_hooks.decls.omp_clause_dtor
4577 (c, build_simple_mem_ref (y2));
4578 if (x)
4579 {
4580 gimple_seq tseq = NULL;
4581 dtor = x;
4582 gimplify_stmt (&dtor, &tseq);
4583 gimple_seq_add_seq (dlist, tseq);
4584 }
4585 }
4586 else
4587 {
4588 x = omp_reduction_init (c, TREE_TYPE (type));
4589 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4590
4591 /* reduction(-:var) sums up the partial results, so it
4592 acts identically to reduction(+:var). */
4593 if (code == MINUS_EXPR)
4594 code = PLUS_EXPR;
4595
4596 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4597 if (is_simd)
4598 {
4599 x = build2 (code, TREE_TYPE (type),
4600 build_simple_mem_ref (y4),
4601 build_simple_mem_ref (y2));
4602 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4603 }
4604 }
4605 gimple *g
4606 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4607 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4608 gimple_seq_add_stmt (ilist, g);
4609 if (y3)
4610 {
4611 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4612 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4613 gimple_seq_add_stmt (ilist, g);
4614 }
4615 g = gimple_build_assign (i, PLUS_EXPR, i,
4616 build_int_cst (TREE_TYPE (i), 1));
4617 gimple_seq_add_stmt (ilist, g);
4618 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4619 gimple_seq_add_stmt (ilist, g);
4620 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4621 if (y2)
4622 {
4623 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4624 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4625 gimple_seq_add_stmt (dlist, g);
4626 if (y4)
4627 {
4628 g = gimple_build_assign
4629 (y4, POINTER_PLUS_EXPR, y4,
4630 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4631 gimple_seq_add_stmt (dlist, g);
4632 }
4633 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4634 build_int_cst (TREE_TYPE (i2), 1));
4635 gimple_seq_add_stmt (dlist, g);
4636 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4637 gimple_seq_add_stmt (dlist, g);
4638 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4639 }
4640 continue;
4641 }
4642 else if (is_variable_sized (var))
4643 {
4644 /* For variable sized types, we need to allocate the
4645 actual storage here. Call alloca and store the
4646 result in the pointer decl that we created elsewhere. */
4647 if (pass == 0)
4648 continue;
4649
4650 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4651 {
4652 gcall *stmt;
4653 tree tmp, atmp;
4654
4655 ptr = DECL_VALUE_EXPR (new_var);
4656 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4657 ptr = TREE_OPERAND (ptr, 0);
4658 gcc_assert (DECL_P (ptr));
4659 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4660
4661 /* void *tmp = __builtin_alloca */
4662 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4663 stmt = gimple_build_call (atmp, 2, x,
4664 size_int (DECL_ALIGN (var)));
4665 tmp = create_tmp_var_raw (ptr_type_node);
4666 gimple_add_tmp_var (tmp);
4667 gimple_call_set_lhs (stmt, tmp);
4668
4669 gimple_seq_add_stmt (ilist, stmt);
4670
4671 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4672 gimplify_assign (ptr, x, ilist);
4673 }
4674 }
4675 else if (is_reference (var) && !is_oacc_parallel (ctx))
4676 {
4677 /* For references that are being privatized for Fortran,
4678 allocate new backing storage for the new pointer
4679 variable. This allows us to avoid changing all the
4680 code that expects a pointer to something that expects
4681 a direct variable. */
4682 if (pass == 0)
4683 continue;
4684
4685 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4686 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4687 {
4688 x = build_receiver_ref (var, false, ctx);
4689 x = build_fold_addr_expr_loc (clause_loc, x);
4690 }
4691 else if (TREE_CONSTANT (x))
4692 {
4693 /* For reduction in SIMD loop, defer adding the
4694 initialization of the reference, because if we decide
4695 to use SIMD array for it, the initilization could cause
4696 expansion ICE. */
4697 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4698 x = NULL_TREE;
4699 else
4700 {
4701 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4702 get_name (var));
4703 gimple_add_tmp_var (x);
4704 TREE_ADDRESSABLE (x) = 1;
4705 x = build_fold_addr_expr_loc (clause_loc, x);
4706 }
4707 }
4708 else
4709 {
4710 tree atmp
4711 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4712 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4713 tree al = size_int (TYPE_ALIGN (rtype));
4714 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4715 }
4716
4717 if (x)
4718 {
4719 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4720 gimplify_assign (new_var, x, ilist);
4721 }
4722
4723 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4724 }
4725 else if (c_kind == OMP_CLAUSE_REDUCTION
4726 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4727 {
4728 if (pass == 0)
4729 continue;
4730 }
4731 else if (pass != 0)
4732 continue;
4733
4734 switch (OMP_CLAUSE_CODE (c))
4735 {
4736 case OMP_CLAUSE_SHARED:
4737 /* Ignore shared directives in teams construct. */
4738 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4739 continue;
4740 /* Shared global vars are just accessed directly. */
4741 if (is_global_var (new_var))
4742 break;
4743 /* For taskloop firstprivate/lastprivate, represented
4744 as firstprivate and shared clause on the task, new_var
4745 is the firstprivate var. */
4746 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4747 break;
4748 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4749 needs to be delayed until after fixup_child_record_type so
4750 that we get the correct type during the dereference. */
4751 by_ref = use_pointer_for_field (var, ctx);
4752 x = build_receiver_ref (var, by_ref, ctx);
4753 SET_DECL_VALUE_EXPR (new_var, x);
4754 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4755
4756 /* ??? If VAR is not passed by reference, and the variable
4757 hasn't been initialized yet, then we'll get a warning for
4758 the store into the omp_data_s structure. Ideally, we'd be
4759 able to notice this and not store anything at all, but
4760 we're generating code too early. Suppress the warning. */
4761 if (!by_ref)
4762 TREE_NO_WARNING (var) = 1;
4763 break;
4764
4765 case OMP_CLAUSE_LASTPRIVATE:
4766 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4767 break;
4768 /* FALLTHRU */
4769
4770 case OMP_CLAUSE_PRIVATE:
4771 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4772 x = build_outer_var_ref (var, ctx);
4773 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4774 {
4775 if (is_task_ctx (ctx))
4776 x = build_receiver_ref (var, false, ctx);
4777 else
4778 x = build_outer_var_ref (var, ctx);
4779 }
4780 else
4781 x = NULL;
4782 do_private:
4783 tree nx;
4784 nx = lang_hooks.decls.omp_clause_default_ctor
4785 (c, unshare_expr (new_var), x);
4786 if (is_simd)
4787 {
4788 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4789 if ((TREE_ADDRESSABLE (new_var) || nx || y
4790 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4791 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4792 idx, lane, ivar, lvar))
4793 {
4794 if (nx)
4795 x = lang_hooks.decls.omp_clause_default_ctor
4796 (c, unshare_expr (ivar), x);
4797 if (nx && x)
4798 gimplify_and_add (x, &llist[0]);
4799 if (y)
4800 {
4801 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4802 if (y)
4803 {
4804 gimple_seq tseq = NULL;
4805
4806 dtor = y;
4807 gimplify_stmt (&dtor, &tseq);
4808 gimple_seq_add_seq (&llist[1], tseq);
4809 }
4810 }
4811 break;
4812 }
4813 }
4814 if (nx)
4815 gimplify_and_add (nx, ilist);
4816 /* FALLTHRU */
4817
4818 do_dtor:
4819 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4820 if (x)
4821 {
4822 gimple_seq tseq = NULL;
4823
4824 dtor = x;
4825 gimplify_stmt (&dtor, &tseq);
4826 gimple_seq_add_seq (dlist, tseq);
4827 }
4828 break;
4829
4830 case OMP_CLAUSE_LINEAR:
4831 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
4832 goto do_firstprivate;
4833 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4834 x = NULL;
4835 else
4836 x = build_outer_var_ref (var, ctx);
4837 goto do_private;
4838
4839 case OMP_CLAUSE_FIRSTPRIVATE:
4840 if (is_task_ctx (ctx))
4841 {
4842 if (is_reference (var) || is_variable_sized (var))
4843 goto do_dtor;
4844 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
4845 ctx))
4846 || use_pointer_for_field (var, NULL))
4847 {
4848 x = build_receiver_ref (var, false, ctx);
4849 SET_DECL_VALUE_EXPR (new_var, x);
4850 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4851 goto do_dtor;
4852 }
4853 }
4854 do_firstprivate:
4855 x = build_outer_var_ref (var, ctx);
4856 if (is_simd)
4857 {
4858 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
4859 && gimple_omp_for_combined_into_p (ctx->stmt))
4860 {
4861 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4862 tree stept = TREE_TYPE (t);
4863 tree ct = find_omp_clause (clauses,
4864 OMP_CLAUSE__LOOPTEMP_);
4865 gcc_assert (ct);
4866 tree l = OMP_CLAUSE_DECL (ct);
4867 tree n1 = fd->loop.n1;
4868 tree step = fd->loop.step;
4869 tree itype = TREE_TYPE (l);
4870 if (POINTER_TYPE_P (itype))
4871 itype = signed_type_for (itype);
4872 l = fold_build2 (MINUS_EXPR, itype, l, n1);
4873 if (TYPE_UNSIGNED (itype)
4874 && fd->loop.cond_code == GT_EXPR)
4875 l = fold_build2 (TRUNC_DIV_EXPR, itype,
4876 fold_build1 (NEGATE_EXPR, itype, l),
4877 fold_build1 (NEGATE_EXPR,
4878 itype, step));
4879 else
4880 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
4881 t = fold_build2 (MULT_EXPR, stept,
4882 fold_convert (stept, l), t);
4883
4884 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4885 {
4886 x = lang_hooks.decls.omp_clause_linear_ctor
4887 (c, new_var, x, t);
4888 gimplify_and_add (x, ilist);
4889 goto do_dtor;
4890 }
4891
4892 if (POINTER_TYPE_P (TREE_TYPE (x)))
4893 x = fold_build2 (POINTER_PLUS_EXPR,
4894 TREE_TYPE (x), x, t);
4895 else
4896 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
4897 }
4898
4899 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
4900 || TREE_ADDRESSABLE (new_var))
4901 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4902 idx, lane, ivar, lvar))
4903 {
4904 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
4905 {
4906 tree iv = create_tmp_var (TREE_TYPE (new_var));
4907 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
4908 gimplify_and_add (x, ilist);
4909 gimple_stmt_iterator gsi
4910 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
4911 gassign *g
4912 = gimple_build_assign (unshare_expr (lvar), iv);
4913 gsi_insert_before_without_update (&gsi, g,
4914 GSI_SAME_STMT);
4915 tree t = OMP_CLAUSE_LINEAR_STEP (c);
4916 enum tree_code code = PLUS_EXPR;
4917 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
4918 code = POINTER_PLUS_EXPR;
4919 g = gimple_build_assign (iv, code, iv, t);
4920 gsi_insert_before_without_update (&gsi, g,
4921 GSI_SAME_STMT);
4922 break;
4923 }
4924 x = lang_hooks.decls.omp_clause_copy_ctor
4925 (c, unshare_expr (ivar), x);
4926 gimplify_and_add (x, &llist[0]);
4927 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
4928 if (x)
4929 {
4930 gimple_seq tseq = NULL;
4931
4932 dtor = x;
4933 gimplify_stmt (&dtor, &tseq);
4934 gimple_seq_add_seq (&llist[1], tseq);
4935 }
4936 break;
4937 }
4938 }
4939 x = lang_hooks.decls.omp_clause_copy_ctor
4940 (c, unshare_expr (new_var), x);
4941 gimplify_and_add (x, ilist);
4942 goto do_dtor;
4943
4944 case OMP_CLAUSE__LOOPTEMP_:
4945 gcc_assert (is_taskreg_ctx (ctx));
4946 x = build_outer_var_ref (var, ctx);
4947 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4948 gimplify_and_add (x, ilist);
4949 break;
4950
4951 case OMP_CLAUSE_COPYIN:
4952 by_ref = use_pointer_for_field (var, NULL);
4953 x = build_receiver_ref (var, by_ref, ctx);
4954 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
4955 append_to_statement_list (x, &copyin_seq);
4956 copyin_by_ref |= by_ref;
4957 break;
4958
4959 case OMP_CLAUSE_REDUCTION:
4960 /* OpenACC reductions are initialized using the
4961 GOACC_REDUCTION internal function. */
4962 if (is_gimple_omp_oacc (ctx->stmt))
4963 break;
4964 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4965 {
4966 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4967 gimple *tseq;
4968 x = build_outer_var_ref (var, ctx);
4969
4970 if (is_reference (var)
4971 && !useless_type_conversion_p (TREE_TYPE (placeholder),
4972 TREE_TYPE (x)))
4973 x = build_fold_addr_expr_loc (clause_loc, x);
4974 SET_DECL_VALUE_EXPR (placeholder, x);
4975 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4976 tree new_vard = new_var;
4977 if (is_reference (var))
4978 {
4979 gcc_assert (TREE_CODE (new_var) == MEM_REF);
4980 new_vard = TREE_OPERAND (new_var, 0);
4981 gcc_assert (DECL_P (new_vard));
4982 }
4983 if (is_simd
4984 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4985 idx, lane, ivar, lvar))
4986 {
4987 if (new_vard == new_var)
4988 {
4989 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
4990 SET_DECL_VALUE_EXPR (new_var, ivar);
4991 }
4992 else
4993 {
4994 SET_DECL_VALUE_EXPR (new_vard,
4995 build_fold_addr_expr (ivar));
4996 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
4997 }
4998 x = lang_hooks.decls.omp_clause_default_ctor
4999 (c, unshare_expr (ivar),
5000 build_outer_var_ref (var, ctx));
5001 if (x)
5002 gimplify_and_add (x, &llist[0]);
5003 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5004 {
5005 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5006 lower_omp (&tseq, ctx);
5007 gimple_seq_add_seq (&llist[0], tseq);
5008 }
5009 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5010 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5011 lower_omp (&tseq, ctx);
5012 gimple_seq_add_seq (&llist[1], tseq);
5013 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5014 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5015 if (new_vard == new_var)
5016 SET_DECL_VALUE_EXPR (new_var, lvar);
5017 else
5018 SET_DECL_VALUE_EXPR (new_vard,
5019 build_fold_addr_expr (lvar));
5020 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5021 if (x)
5022 {
5023 tseq = NULL;
5024 dtor = x;
5025 gimplify_stmt (&dtor, &tseq);
5026 gimple_seq_add_seq (&llist[1], tseq);
5027 }
5028 break;
5029 }
5030 /* If this is a reference to constant size reduction var
5031 with placeholder, we haven't emitted the initializer
5032 for it because it is undesirable if SIMD arrays are used.
5033 But if they aren't used, we need to emit the deferred
5034 initialization now. */
5035 else if (is_reference (var) && is_simd)
5036 handle_simd_reference (clause_loc, new_vard, ilist);
5037 x = lang_hooks.decls.omp_clause_default_ctor
5038 (c, unshare_expr (new_var),
5039 build_outer_var_ref (var, ctx));
5040 if (x)
5041 gimplify_and_add (x, ilist);
5042 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5043 {
5044 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5045 lower_omp (&tseq, ctx);
5046 gimple_seq_add_seq (ilist, tseq);
5047 }
5048 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5049 if (is_simd)
5050 {
5051 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5052 lower_omp (&tseq, ctx);
5053 gimple_seq_add_seq (dlist, tseq);
5054 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5055 }
5056 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5057 goto do_dtor;
5058 }
5059 else
5060 {
5061 x = omp_reduction_init (c, TREE_TYPE (new_var));
5062 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
5063 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5064
5065 /* reduction(-:var) sums up the partial results, so it
5066 acts identically to reduction(+:var). */
5067 if (code == MINUS_EXPR)
5068 code = PLUS_EXPR;
5069
5070 tree new_vard = new_var;
5071 if (is_simd && is_reference (var))
5072 {
5073 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5074 new_vard = TREE_OPERAND (new_var, 0);
5075 gcc_assert (DECL_P (new_vard));
5076 }
5077 if (is_simd
5078 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5079 idx, lane, ivar, lvar))
5080 {
5081 tree ref = build_outer_var_ref (var, ctx);
5082
5083 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5084
5085 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5086 ref = build_outer_var_ref (var, ctx);
5087 gimplify_assign (ref, x, &llist[1]);
5088
5089 if (new_vard != new_var)
5090 {
5091 SET_DECL_VALUE_EXPR (new_vard,
5092 build_fold_addr_expr (lvar));
5093 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5094 }
5095 }
5096 else
5097 {
5098 if (is_reference (var) && is_simd)
5099 handle_simd_reference (clause_loc, new_vard, ilist);
5100 gimplify_assign (new_var, x, ilist);
5101 if (is_simd)
5102 {
5103 tree ref = build_outer_var_ref (var, ctx);
5104
5105 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5106 ref = build_outer_var_ref (var, ctx);
5107 gimplify_assign (ref, x, dlist);
5108 }
5109 }
5110 }
5111 break;
5112
5113 default:
5114 gcc_unreachable ();
5115 }
5116 }
5117 }
5118
5119 if (lane)
5120 {
5121 tree uid = create_tmp_var (ptr_type_node, "simduid");
5122 /* Don't want uninit warnings on simduid, it is always uninitialized,
5123 but we use it not for the value, but for the DECL_UID only. */
5124 TREE_NO_WARNING (uid) = 1;
5125 gimple *g
5126 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5127 gimple_call_set_lhs (g, lane);
5128 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5129 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5130 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5131 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5132 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5133 gimple_omp_for_set_clauses (ctx->stmt, c);
5134 g = gimple_build_assign (lane, INTEGER_CST,
5135 build_int_cst (unsigned_type_node, 0));
5136 gimple_seq_add_stmt (ilist, g);
5137 for (int i = 0; i < 2; i++)
5138 if (llist[i])
5139 {
5140 tree vf = create_tmp_var (unsigned_type_node);
5141 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5142 gimple_call_set_lhs (g, vf);
5143 gimple_seq *seq = i == 0 ? ilist : dlist;
5144 gimple_seq_add_stmt (seq, g);
5145 tree t = build_int_cst (unsigned_type_node, 0);
5146 g = gimple_build_assign (idx, INTEGER_CST, t);
5147 gimple_seq_add_stmt (seq, g);
5148 tree body = create_artificial_label (UNKNOWN_LOCATION);
5149 tree header = create_artificial_label (UNKNOWN_LOCATION);
5150 tree end = create_artificial_label (UNKNOWN_LOCATION);
5151 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5152 gimple_seq_add_stmt (seq, gimple_build_label (body));
5153 gimple_seq_add_seq (seq, llist[i]);
5154 t = build_int_cst (unsigned_type_node, 1);
5155 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5156 gimple_seq_add_stmt (seq, g);
5157 gimple_seq_add_stmt (seq, gimple_build_label (header));
5158 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5159 gimple_seq_add_stmt (seq, g);
5160 gimple_seq_add_stmt (seq, gimple_build_label (end));
5161 }
5162 }
5163
5164 /* The copyin sequence is not to be executed by the main thread, since
5165 that would result in self-copies. Perhaps not visible to scalars,
5166 but it certainly is to C++ operator=. */
5167 if (copyin_seq)
5168 {
5169 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5170 0);
5171 x = build2 (NE_EXPR, boolean_type_node, x,
5172 build_int_cst (TREE_TYPE (x), 0));
5173 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5174 gimplify_and_add (x, ilist);
5175 }
5176
5177 /* If any copyin variable is passed by reference, we must ensure the
5178 master thread doesn't modify it before it is copied over in all
5179 threads. Similarly for variables in both firstprivate and
5180 lastprivate clauses we need to ensure the lastprivate copying
5181 happens after firstprivate copying in all threads. And similarly
5182 for UDRs if initializer expression refers to omp_orig. */
5183 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5184 {
5185 /* Don't add any barrier for #pragma omp simd or
5186 #pragma omp distribute. */
5187 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5188 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5189 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5190 }
5191
5192 /* If max_vf is non-zero, then we can use only a vectorization factor
5193 up to the max_vf we chose. So stick it into the safelen clause. */
5194 if (max_vf)
5195 {
5196 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5197 OMP_CLAUSE_SAFELEN);
5198 if (c == NULL_TREE
5199 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5200 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5201 max_vf) == 1))
5202 {
5203 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5204 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5205 max_vf);
5206 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5207 gimple_omp_for_set_clauses (ctx->stmt, c);
5208 }
5209 }
5210 }
5211
5212
5213 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5214 both parallel and workshare constructs. PREDICATE may be NULL if it's
5215 always true. */
5216
5217 static void
5218 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5219 omp_context *ctx)
5220 {
5221 tree x, c, label = NULL, orig_clauses = clauses;
5222 bool par_clauses = false;
5223 tree simduid = NULL, lastlane = NULL;
5224
5225 /* Early exit if there are no lastprivate or linear clauses. */
5226 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5227 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5228 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5229 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5230 break;
5231 if (clauses == NULL)
5232 {
5233 /* If this was a workshare clause, see if it had been combined
5234 with its parallel. In that case, look for the clauses on the
5235 parallel statement itself. */
5236 if (is_parallel_ctx (ctx))
5237 return;
5238
5239 ctx = ctx->outer;
5240 if (ctx == NULL || !is_parallel_ctx (ctx))
5241 return;
5242
5243 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5244 OMP_CLAUSE_LASTPRIVATE);
5245 if (clauses == NULL)
5246 return;
5247 par_clauses = true;
5248 }
5249
5250 if (predicate)
5251 {
5252 gcond *stmt;
5253 tree label_true, arm1, arm2;
5254
5255 label = create_artificial_label (UNKNOWN_LOCATION);
5256 label_true = create_artificial_label (UNKNOWN_LOCATION);
5257 arm1 = TREE_OPERAND (predicate, 0);
5258 arm2 = TREE_OPERAND (predicate, 1);
5259 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5260 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5261 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5262 label_true, label);
5263 gimple_seq_add_stmt (stmt_list, stmt);
5264 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5265 }
5266
5267 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5268 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5269 {
5270 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5271 if (simduid)
5272 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5273 }
5274
5275 for (c = clauses; c ;)
5276 {
5277 tree var, new_var;
5278 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5279
5280 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5281 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5282 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5283 {
5284 var = OMP_CLAUSE_DECL (c);
5285 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5286 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5287 && is_taskloop_ctx (ctx))
5288 {
5289 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5290 new_var = lookup_decl (var, ctx->outer);
5291 }
5292 else
5293 new_var = lookup_decl (var, ctx);
5294
5295 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5296 {
5297 tree val = DECL_VALUE_EXPR (new_var);
5298 if (TREE_CODE (val) == ARRAY_REF
5299 && VAR_P (TREE_OPERAND (val, 0))
5300 && lookup_attribute ("omp simd array",
5301 DECL_ATTRIBUTES (TREE_OPERAND (val,
5302 0))))
5303 {
5304 if (lastlane == NULL)
5305 {
5306 lastlane = create_tmp_var (unsigned_type_node);
5307 gcall *g
5308 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5309 2, simduid,
5310 TREE_OPERAND (val, 1));
5311 gimple_call_set_lhs (g, lastlane);
5312 gimple_seq_add_stmt (stmt_list, g);
5313 }
5314 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5315 TREE_OPERAND (val, 0), lastlane,
5316 NULL_TREE, NULL_TREE);
5317 }
5318 }
5319
5320 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5321 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5322 {
5323 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5324 gimple_seq_add_seq (stmt_list,
5325 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5326 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5327 }
5328 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5329 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5330 {
5331 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5332 gimple_seq_add_seq (stmt_list,
5333 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5334 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5335 }
5336
5337 x = NULL_TREE;
5338 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5339 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5340 {
5341 gcc_checking_assert (is_taskloop_ctx (ctx));
5342 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5343 ctx->outer->outer);
5344 if (is_global_var (ovar))
5345 x = ovar;
5346 }
5347 if (!x)
5348 x = build_outer_var_ref (var, ctx, true);
5349 if (is_reference (var))
5350 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5351 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5352 gimplify_and_add (x, stmt_list);
5353 }
5354 c = OMP_CLAUSE_CHAIN (c);
5355 if (c == NULL && !par_clauses)
5356 {
5357 /* If this was a workshare clause, see if it had been combined
5358 with its parallel. In that case, continue looking for the
5359 clauses also on the parallel statement itself. */
5360 if (is_parallel_ctx (ctx))
5361 break;
5362
5363 ctx = ctx->outer;
5364 if (ctx == NULL || !is_parallel_ctx (ctx))
5365 break;
5366
5367 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5368 OMP_CLAUSE_LASTPRIVATE);
5369 par_clauses = true;
5370 }
5371 }
5372
5373 if (label)
5374 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5375 }
5376
5377 /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5378 (which might be a placeholder). INNER is true if this is an inner
5379 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5380 join markers. Generate the before-loop forking sequence in
5381 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5382 general form of these sequences is
5383
5384 GOACC_REDUCTION_SETUP
5385 GOACC_FORK
5386 GOACC_REDUCTION_INIT
5387 ...
5388 GOACC_REDUCTION_FINI
5389 GOACC_JOIN
5390 GOACC_REDUCTION_TEARDOWN. */
5391
5392 static void
5393 lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5394 gcall *fork, gcall *join, gimple_seq *fork_seq,
5395 gimple_seq *join_seq, omp_context *ctx)
5396 {
5397 gimple_seq before_fork = NULL;
5398 gimple_seq after_fork = NULL;
5399 gimple_seq before_join = NULL;
5400 gimple_seq after_join = NULL;
5401 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5402 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5403 unsigned offset = 0;
5404
5405 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5406 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5407 {
5408 tree orig = OMP_CLAUSE_DECL (c);
5409 tree var = maybe_lookup_decl (orig, ctx);
5410 tree ref_to_res = NULL_TREE;
5411 tree incoming, outgoing;
5412
5413 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5414 if (rcode == MINUS_EXPR)
5415 rcode = PLUS_EXPR;
5416 else if (rcode == TRUTH_ANDIF_EXPR)
5417 rcode = BIT_AND_EXPR;
5418 else if (rcode == TRUTH_ORIF_EXPR)
5419 rcode = BIT_IOR_EXPR;
5420 tree op = build_int_cst (unsigned_type_node, rcode);
5421
5422 if (!var)
5423 var = orig;
5424 gcc_assert (!is_reference (var));
5425
5426 incoming = outgoing = var;
5427
5428 if (!inner)
5429 {
5430 /* See if an outer construct also reduces this variable. */
5431 omp_context *outer = ctx;
5432
5433 while (omp_context *probe = outer->outer)
5434 {
5435 enum gimple_code type = gimple_code (probe->stmt);
5436 tree cls;
5437
5438 switch (type)
5439 {
5440 case GIMPLE_OMP_FOR:
5441 cls = gimple_omp_for_clauses (probe->stmt);
5442 break;
5443
5444 case GIMPLE_OMP_TARGET:
5445 if (gimple_omp_target_kind (probe->stmt)
5446 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5447 goto do_lookup;
5448
5449 cls = gimple_omp_target_clauses (probe->stmt);
5450 break;
5451
5452 default:
5453 goto do_lookup;
5454 }
5455
5456 outer = probe;
5457 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5458 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5459 && orig == OMP_CLAUSE_DECL (cls))
5460 goto has_outer_reduction;
5461 }
5462
5463 do_lookup:
5464 /* This is the outermost construct with this reduction,
5465 see if there's a mapping for it. */
5466 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5467 && maybe_lookup_field (orig, outer))
5468 {
5469 ref_to_res = build_receiver_ref (orig, false, outer);
5470 if (is_reference (orig))
5471 ref_to_res = build_simple_mem_ref (ref_to_res);
5472
5473 outgoing = var;
5474 incoming = omp_reduction_init_op (loc, rcode, TREE_TYPE (var));
5475 }
5476 else
5477 incoming = outgoing = orig;
5478
5479 has_outer_reduction:;
5480 }
5481
5482 if (!ref_to_res)
5483 ref_to_res = integer_zero_node;
5484
5485 /* Determine position in reduction buffer, which may be used
5486 by target. */
5487 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5488 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5489 offset = (offset + align - 1) & ~(align - 1);
5490 tree off = build_int_cst (sizetype, offset);
5491 offset += GET_MODE_SIZE (mode);
5492
5493 if (!init_code)
5494 {
5495 init_code = build_int_cst (integer_type_node,
5496 IFN_GOACC_REDUCTION_INIT);
5497 fini_code = build_int_cst (integer_type_node,
5498 IFN_GOACC_REDUCTION_FINI);
5499 setup_code = build_int_cst (integer_type_node,
5500 IFN_GOACC_REDUCTION_SETUP);
5501 teardown_code = build_int_cst (integer_type_node,
5502 IFN_GOACC_REDUCTION_TEARDOWN);
5503 }
5504
5505 tree setup_call
5506 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5507 TREE_TYPE (var), 6, setup_code,
5508 unshare_expr (ref_to_res),
5509 incoming, level, op, off);
5510 tree init_call
5511 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5512 TREE_TYPE (var), 6, init_code,
5513 unshare_expr (ref_to_res),
5514 var, level, op, off);
5515 tree fini_call
5516 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5517 TREE_TYPE (var), 6, fini_code,
5518 unshare_expr (ref_to_res),
5519 var, level, op, off);
5520 tree teardown_call
5521 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5522 TREE_TYPE (var), 6, teardown_code,
5523 ref_to_res, var, level, op, off);
5524
5525 gimplify_assign (var, setup_call, &before_fork);
5526 gimplify_assign (var, init_call, &after_fork);
5527 gimplify_assign (var, fini_call, &before_join);
5528 gimplify_assign (outgoing, teardown_call, &after_join);
5529 }
5530
5531 /* Now stitch things together. */
5532 gimple_seq_add_seq (fork_seq, before_fork);
5533 if (fork)
5534 gimple_seq_add_stmt (fork_seq, fork);
5535 gimple_seq_add_seq (fork_seq, after_fork);
5536
5537 gimple_seq_add_seq (join_seq, before_join);
5538 if (join)
5539 gimple_seq_add_stmt (join_seq, join);
5540 gimple_seq_add_seq (join_seq, after_join);
5541 }
5542
5543 /* Generate code to implement the REDUCTION clauses. */
5544
5545 static void
5546 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5547 {
5548 gimple_seq sub_seq = NULL;
5549 gimple *stmt;
5550 tree x, c;
5551 int count = 0;
5552
5553 /* OpenACC loop reductions are handled elsewhere. */
5554 if (is_gimple_omp_oacc (ctx->stmt))
5555 return;
5556
5557 /* SIMD reductions are handled in lower_rec_input_clauses. */
5558 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5559 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5560 return;
5561
5562 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5563 update in that case, otherwise use a lock. */
5564 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5565 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5566 {
5567 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5568 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5569 {
5570 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5571 count = -1;
5572 break;
5573 }
5574 count++;
5575 }
5576
5577 if (count == 0)
5578 return;
5579
5580 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5581 {
5582 tree var, ref, new_var, orig_var;
5583 enum tree_code code;
5584 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5585
5586 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5587 continue;
5588
5589 orig_var = var = OMP_CLAUSE_DECL (c);
5590 if (TREE_CODE (var) == MEM_REF)
5591 {
5592 var = TREE_OPERAND (var, 0);
5593 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5594 var = TREE_OPERAND (var, 0);
5595 if (TREE_CODE (var) == INDIRECT_REF
5596 || TREE_CODE (var) == ADDR_EXPR)
5597 var = TREE_OPERAND (var, 0);
5598 orig_var = var;
5599 if (is_variable_sized (var))
5600 {
5601 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5602 var = DECL_VALUE_EXPR (var);
5603 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5604 var = TREE_OPERAND (var, 0);
5605 gcc_assert (DECL_P (var));
5606 }
5607 }
5608 new_var = lookup_decl (var, ctx);
5609 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5610 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5611 ref = build_outer_var_ref (var, ctx);
5612 code = OMP_CLAUSE_REDUCTION_CODE (c);
5613
5614 /* reduction(-:var) sums up the partial results, so it acts
5615 identically to reduction(+:var). */
5616 if (code == MINUS_EXPR)
5617 code = PLUS_EXPR;
5618
5619 if (count == 1)
5620 {
5621 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5622
5623 addr = save_expr (addr);
5624 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5625 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5626 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5627 gimplify_and_add (x, stmt_seqp);
5628 return;
5629 }
5630 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5631 {
5632 tree d = OMP_CLAUSE_DECL (c);
5633 tree type = TREE_TYPE (d);
5634 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5635 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5636 tree ptype = build_pointer_type (TREE_TYPE (type));
5637 tree bias = TREE_OPERAND (d, 1);
5638 d = TREE_OPERAND (d, 0);
5639 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5640 {
5641 tree b = TREE_OPERAND (d, 1);
5642 b = maybe_lookup_decl (b, ctx);
5643 if (b == NULL)
5644 {
5645 b = TREE_OPERAND (d, 1);
5646 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5647 }
5648 if (integer_zerop (bias))
5649 bias = b;
5650 else
5651 {
5652 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5653 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5654 TREE_TYPE (b), b, bias);
5655 }
5656 d = TREE_OPERAND (d, 0);
5657 }
5658 /* For ref build_outer_var_ref already performs this, so
5659 only new_var needs a dereference. */
5660 if (TREE_CODE (d) == INDIRECT_REF)
5661 {
5662 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5663 gcc_assert (is_reference (var) && var == orig_var);
5664 }
5665 else if (TREE_CODE (d) == ADDR_EXPR)
5666 {
5667 if (orig_var == var)
5668 {
5669 new_var = build_fold_addr_expr (new_var);
5670 ref = build_fold_addr_expr (ref);
5671 }
5672 }
5673 else
5674 {
5675 gcc_assert (orig_var == var);
5676 if (is_reference (var))
5677 ref = build_fold_addr_expr (ref);
5678 }
5679 if (DECL_P (v))
5680 {
5681 tree t = maybe_lookup_decl (v, ctx);
5682 if (t)
5683 v = t;
5684 else
5685 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5686 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5687 }
5688 if (!integer_zerop (bias))
5689 {
5690 bias = fold_convert_loc (clause_loc, sizetype, bias);
5691 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5692 TREE_TYPE (new_var), new_var,
5693 unshare_expr (bias));
5694 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5695 TREE_TYPE (ref), ref, bias);
5696 }
5697 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5698 ref = fold_convert_loc (clause_loc, ptype, ref);
5699 tree m = create_tmp_var (ptype, NULL);
5700 gimplify_assign (m, new_var, stmt_seqp);
5701 new_var = m;
5702 m = create_tmp_var (ptype, NULL);
5703 gimplify_assign (m, ref, stmt_seqp);
5704 ref = m;
5705 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5706 tree body = create_artificial_label (UNKNOWN_LOCATION);
5707 tree end = create_artificial_label (UNKNOWN_LOCATION);
5708 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5709 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5710 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5711 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5712 {
5713 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5714 tree decl_placeholder
5715 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5716 SET_DECL_VALUE_EXPR (placeholder, out);
5717 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5718 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5719 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5720 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5721 gimple_seq_add_seq (&sub_seq,
5722 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5723 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5724 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5725 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5726 }
5727 else
5728 {
5729 x = build2 (code, TREE_TYPE (out), out, priv);
5730 out = unshare_expr (out);
5731 gimplify_assign (out, x, &sub_seq);
5732 }
5733 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5734 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5735 gimple_seq_add_stmt (&sub_seq, g);
5736 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5737 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5738 gimple_seq_add_stmt (&sub_seq, g);
5739 g = gimple_build_assign (i, PLUS_EXPR, i,
5740 build_int_cst (TREE_TYPE (i), 1));
5741 gimple_seq_add_stmt (&sub_seq, g);
5742 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5743 gimple_seq_add_stmt (&sub_seq, g);
5744 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5745 }
5746 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5747 {
5748 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5749
5750 if (is_reference (var)
5751 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5752 TREE_TYPE (ref)))
5753 ref = build_fold_addr_expr_loc (clause_loc, ref);
5754 SET_DECL_VALUE_EXPR (placeholder, ref);
5755 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5756 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5757 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5758 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5759 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5760 }
5761 else
5762 {
5763 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5764 ref = build_outer_var_ref (var, ctx);
5765 gimplify_assign (ref, x, &sub_seq);
5766 }
5767 }
5768
5769 if (is_gimple_omp_oacc (ctx->stmt))
5770 return;
5771
5772 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
5773 0);
5774 gimple_seq_add_stmt (stmt_seqp, stmt);
5775
5776 gimple_seq_add_seq (stmt_seqp, sub_seq);
5777
5778 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
5779 0);
5780 gimple_seq_add_stmt (stmt_seqp, stmt);
5781 }
5782
5783
5784 /* Generate code to implement the COPYPRIVATE clauses. */
5785
5786 static void
5787 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
5788 omp_context *ctx)
5789 {
5790 tree c;
5791
5792 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5793 {
5794 tree var, new_var, ref, x;
5795 bool by_ref;
5796 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5797
5798 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
5799 continue;
5800
5801 var = OMP_CLAUSE_DECL (c);
5802 by_ref = use_pointer_for_field (var, NULL);
5803
5804 ref = build_sender_ref (var, ctx);
5805 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
5806 if (by_ref)
5807 {
5808 x = build_fold_addr_expr_loc (clause_loc, new_var);
5809 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
5810 }
5811 gimplify_assign (ref, x, slist);
5812
5813 ref = build_receiver_ref (var, false, ctx);
5814 if (by_ref)
5815 {
5816 ref = fold_convert_loc (clause_loc,
5817 build_pointer_type (TREE_TYPE (new_var)),
5818 ref);
5819 ref = build_fold_indirect_ref_loc (clause_loc, ref);
5820 }
5821 if (is_reference (var))
5822 {
5823 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
5824 ref = build_simple_mem_ref_loc (clause_loc, ref);
5825 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5826 }
5827 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
5828 gimplify_and_add (x, rlist);
5829 }
5830 }
5831
5832
5833 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
5834 and REDUCTION from the sender (aka parent) side. */
5835
5836 static void
5837 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
5838 omp_context *ctx)
5839 {
5840 tree c, t;
5841 int ignored_looptemp = 0;
5842 bool is_taskloop = false;
5843
5844 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
5845 by GOMP_taskloop. */
5846 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
5847 {
5848 ignored_looptemp = 2;
5849 is_taskloop = true;
5850 }
5851
5852 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5853 {
5854 tree val, ref, x, var;
5855 bool by_ref, do_in = false, do_out = false;
5856 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5857
5858 switch (OMP_CLAUSE_CODE (c))
5859 {
5860 case OMP_CLAUSE_PRIVATE:
5861 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
5862 break;
5863 continue;
5864 case OMP_CLAUSE_FIRSTPRIVATE:
5865 case OMP_CLAUSE_COPYIN:
5866 case OMP_CLAUSE_LASTPRIVATE:
5867 case OMP_CLAUSE_REDUCTION:
5868 break;
5869 case OMP_CLAUSE_SHARED:
5870 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5871 break;
5872 continue;
5873 case OMP_CLAUSE__LOOPTEMP_:
5874 if (ignored_looptemp)
5875 {
5876 ignored_looptemp--;
5877 continue;
5878 }
5879 break;
5880 default:
5881 continue;
5882 }
5883
5884 val = OMP_CLAUSE_DECL (c);
5885 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
5886 && TREE_CODE (val) == MEM_REF)
5887 {
5888 val = TREE_OPERAND (val, 0);
5889 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
5890 val = TREE_OPERAND (val, 0);
5891 if (TREE_CODE (val) == INDIRECT_REF
5892 || TREE_CODE (val) == ADDR_EXPR)
5893 val = TREE_OPERAND (val, 0);
5894 if (is_variable_sized (val))
5895 continue;
5896 }
5897
5898 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
5899 outer taskloop region. */
5900 omp_context *ctx_for_o = ctx;
5901 if (is_taskloop
5902 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
5903 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
5904 ctx_for_o = ctx->outer;
5905
5906 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
5907
5908 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
5909 && is_global_var (var))
5910 continue;
5911
5912 t = omp_member_access_dummy_var (var);
5913 if (t)
5914 {
5915 var = DECL_VALUE_EXPR (var);
5916 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
5917 if (o != t)
5918 var = unshare_and_remap (var, t, o);
5919 else
5920 var = unshare_expr (var);
5921 }
5922
5923 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
5924 {
5925 /* Handle taskloop firstprivate/lastprivate, where the
5926 lastprivate on GIMPLE_OMP_TASK is represented as
5927 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
5928 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
5929 x = omp_build_component_ref (ctx->sender_decl, f);
5930 if (use_pointer_for_field (val, ctx))
5931 var = build_fold_addr_expr (var);
5932 gimplify_assign (x, var, ilist);
5933 DECL_ABSTRACT_ORIGIN (f) = NULL;
5934 continue;
5935 }
5936
5937 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
5938 || val == OMP_CLAUSE_DECL (c))
5939 && is_variable_sized (val))
5940 continue;
5941 by_ref = use_pointer_for_field (val, NULL);
5942
5943 switch (OMP_CLAUSE_CODE (c))
5944 {
5945 case OMP_CLAUSE_PRIVATE:
5946 case OMP_CLAUSE_FIRSTPRIVATE:
5947 case OMP_CLAUSE_COPYIN:
5948 case OMP_CLAUSE__LOOPTEMP_:
5949 do_in = true;
5950 break;
5951
5952 case OMP_CLAUSE_LASTPRIVATE:
5953 if (by_ref || is_reference (val))
5954 {
5955 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
5956 continue;
5957 do_in = true;
5958 }
5959 else
5960 {
5961 do_out = true;
5962 if (lang_hooks.decls.omp_private_outer_ref (val))
5963 do_in = true;
5964 }
5965 break;
5966
5967 case OMP_CLAUSE_REDUCTION:
5968 do_in = true;
5969 if (val == OMP_CLAUSE_DECL (c))
5970 do_out = !(by_ref || is_reference (val));
5971 else
5972 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
5973 break;
5974
5975 default:
5976 gcc_unreachable ();
5977 }
5978
5979 if (do_in)
5980 {
5981 ref = build_sender_ref (val, ctx);
5982 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
5983 gimplify_assign (ref, x, ilist);
5984 if (is_task_ctx (ctx))
5985 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
5986 }
5987
5988 if (do_out)
5989 {
5990 ref = build_sender_ref (val, ctx);
5991 gimplify_assign (var, ref, olist);
5992 }
5993 }
5994 }
5995
5996 /* Generate code to implement SHARED from the sender (aka parent)
5997 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
5998 list things that got automatically shared. */
5999
6000 static void
6001 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
6002 {
6003 tree var, ovar, nvar, t, f, x, record_type;
6004
6005 if (ctx->record_type == NULL)
6006 return;
6007
6008 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
6009 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6010 {
6011 ovar = DECL_ABSTRACT_ORIGIN (f);
6012 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6013 continue;
6014
6015 nvar = maybe_lookup_decl (ovar, ctx);
6016 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6017 continue;
6018
6019 /* If CTX is a nested parallel directive. Find the immediately
6020 enclosing parallel or workshare construct that contains a
6021 mapping for OVAR. */
6022 var = lookup_decl_in_outer_ctx (ovar, ctx);
6023
6024 t = omp_member_access_dummy_var (var);
6025 if (t)
6026 {
6027 var = DECL_VALUE_EXPR (var);
6028 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6029 if (o != t)
6030 var = unshare_and_remap (var, t, o);
6031 else
6032 var = unshare_expr (var);
6033 }
6034
6035 if (use_pointer_for_field (ovar, ctx))
6036 {
6037 x = build_sender_ref (ovar, ctx);
6038 var = build_fold_addr_expr (var);
6039 gimplify_assign (x, var, ilist);
6040 }
6041 else
6042 {
6043 x = build_sender_ref (ovar, ctx);
6044 gimplify_assign (x, var, ilist);
6045
6046 if (!TREE_READONLY (var)
6047 /* We don't need to receive a new reference to a result
6048 or parm decl. In fact we may not store to it as we will
6049 invalidate any pending RSO and generate wrong gimple
6050 during inlining. */
6051 && !((TREE_CODE (var) == RESULT_DECL
6052 || TREE_CODE (var) == PARM_DECL)
6053 && DECL_BY_REFERENCE (var)))
6054 {
6055 x = build_sender_ref (ovar, ctx);
6056 gimplify_assign (var, x, olist);
6057 }
6058 }
6059 }
6060 }
6061
6062 /* Emit an OpenACC head marker call, encapulating the partitioning and
6063 other information that must be processed by the target compiler.
6064 Return the maximum number of dimensions the associated loop might
6065 be partitioned over. */
6066
6067 static unsigned
6068 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6069 gimple_seq *seq, omp_context *ctx)
6070 {
6071 unsigned levels = 0;
6072 unsigned tag = 0;
6073 tree gang_static = NULL_TREE;
6074 auto_vec<tree, 5> args;
6075
6076 args.quick_push (build_int_cst
6077 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6078 args.quick_push (ddvar);
6079 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6080 {
6081 switch (OMP_CLAUSE_CODE (c))
6082 {
6083 case OMP_CLAUSE_GANG:
6084 tag |= OLF_DIM_GANG;
6085 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6086 /* static:* is represented by -1, and we can ignore it, as
6087 scheduling is always static. */
6088 if (gang_static && integer_minus_onep (gang_static))
6089 gang_static = NULL_TREE;
6090 levels++;
6091 break;
6092
6093 case OMP_CLAUSE_WORKER:
6094 tag |= OLF_DIM_WORKER;
6095 levels++;
6096 break;
6097
6098 case OMP_CLAUSE_VECTOR:
6099 tag |= OLF_DIM_VECTOR;
6100 levels++;
6101 break;
6102
6103 case OMP_CLAUSE_SEQ:
6104 tag |= OLF_SEQ;
6105 break;
6106
6107 case OMP_CLAUSE_AUTO:
6108 tag |= OLF_AUTO;
6109 break;
6110
6111 case OMP_CLAUSE_INDEPENDENT:
6112 tag |= OLF_INDEPENDENT;
6113 break;
6114
6115 default:
6116 continue;
6117 }
6118 }
6119
6120 if (gang_static)
6121 {
6122 if (DECL_P (gang_static))
6123 gang_static = build_outer_var_ref (gang_static, ctx);
6124 tag |= OLF_GANG_STATIC;
6125 }
6126
6127 /* In a parallel region, loops are implicitly INDEPENDENT. */
6128 omp_context *tgt = enclosing_target_ctx (ctx);
6129 if (!tgt || is_oacc_parallel (tgt))
6130 tag |= OLF_INDEPENDENT;
6131
6132 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6133 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6134 | OLF_SEQ)))
6135 tag |= OLF_AUTO;
6136
6137 /* Ensure at least one level. */
6138 if (!levels)
6139 levels++;
6140
6141 args.quick_push (build_int_cst (integer_type_node, levels));
6142 args.quick_push (build_int_cst (integer_type_node, tag));
6143 if (gang_static)
6144 args.quick_push (gang_static);
6145
6146 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6147 gimple_set_location (call, loc);
6148 gimple_set_lhs (call, ddvar);
6149 gimple_seq_add_stmt (seq, call);
6150
6151 return levels;
6152 }
6153
6154 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6155 partitioning level of the enclosed region. */
6156
6157 static void
6158 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6159 tree tofollow, gimple_seq *seq)
6160 {
6161 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6162 : IFN_UNIQUE_OACC_TAIL_MARK);
6163 tree marker = build_int_cst (integer_type_node, marker_kind);
6164 int nargs = 2 + (tofollow != NULL_TREE);
6165 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6166 marker, ddvar, tofollow);
6167 gimple_set_location (call, loc);
6168 gimple_set_lhs (call, ddvar);
6169 gimple_seq_add_stmt (seq, call);
6170 }
6171
6172 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6173 the loop clauses, from which we extract reductions. Initialize
6174 HEAD and TAIL. */
6175
6176 static void
6177 lower_oacc_head_tail (location_t loc, tree clauses,
6178 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6179 {
6180 bool inner = false;
6181 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6182 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6183
6184 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6185 if (!count)
6186 lower_oacc_loop_marker (loc, ddvar, false, integer_zero_node, tail);
6187
6188 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6189 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6190
6191 for (unsigned done = 1; count; count--, done++)
6192 {
6193 gimple_seq fork_seq = NULL;
6194 gimple_seq join_seq = NULL;
6195
6196 tree place = build_int_cst (integer_type_node, -1);
6197 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6198 fork_kind, ddvar, place);
6199 gimple_set_location (fork, loc);
6200 gimple_set_lhs (fork, ddvar);
6201
6202 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6203 join_kind, ddvar, place);
6204 gimple_set_location (join, loc);
6205 gimple_set_lhs (join, ddvar);
6206
6207 /* Mark the beginning of this level sequence. */
6208 if (inner)
6209 lower_oacc_loop_marker (loc, ddvar, true,
6210 build_int_cst (integer_type_node, count),
6211 &fork_seq);
6212 lower_oacc_loop_marker (loc, ddvar, false,
6213 build_int_cst (integer_type_node, done),
6214 &join_seq);
6215
6216 lower_oacc_reductions (loc, clauses, place, inner,
6217 fork, join, &fork_seq, &join_seq, ctx);
6218
6219 /* Append this level to head. */
6220 gimple_seq_add_seq (head, fork_seq);
6221 /* Prepend it to tail. */
6222 gimple_seq_add_seq (&join_seq, *tail);
6223 *tail = join_seq;
6224
6225 inner = true;
6226 }
6227
6228 /* Mark the end of the sequence. */
6229 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6230 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6231 }
6232
6233 /* A convenience function to build an empty GIMPLE_COND with just the
6234 condition. */
6235
6236 static gcond *
6237 gimple_build_cond_empty (tree cond)
6238 {
6239 enum tree_code pred_code;
6240 tree lhs, rhs;
6241
6242 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6243 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6244 }
6245
6246 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6247 bool = false);
6248
6249 /* Build the function calls to GOMP_parallel_start etc to actually
6250 generate the parallel operation. REGION is the parallel region
6251 being expanded. BB is the block where to insert the code. WS_ARGS
6252 will be set if this is a call to a combined parallel+workshare
6253 construct, it contains the list of additional arguments needed by
6254 the workshare construct. */
6255
6256 static void
6257 expand_parallel_call (struct omp_region *region, basic_block bb,
6258 gomp_parallel *entry_stmt,
6259 vec<tree, va_gc> *ws_args)
6260 {
6261 tree t, t1, t2, val, cond, c, clauses, flags;
6262 gimple_stmt_iterator gsi;
6263 gimple *stmt;
6264 enum built_in_function start_ix;
6265 int start_ix2;
6266 location_t clause_loc;
6267 vec<tree, va_gc> *args;
6268
6269 clauses = gimple_omp_parallel_clauses (entry_stmt);
6270
6271 /* Determine what flavor of GOMP_parallel we will be
6272 emitting. */
6273 start_ix = BUILT_IN_GOMP_PARALLEL;
6274 if (is_combined_parallel (region))
6275 {
6276 switch (region->inner->type)
6277 {
6278 case GIMPLE_OMP_FOR:
6279 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6280 switch (region->inner->sched_kind)
6281 {
6282 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6283 start_ix2 = 3;
6284 break;
6285 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6286 case OMP_CLAUSE_SCHEDULE_GUIDED:
6287 if (region->inner->sched_modifiers
6288 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6289 {
6290 start_ix2 = 3 + region->inner->sched_kind;
6291 break;
6292 }
6293 /* FALLTHRU */
6294 default:
6295 start_ix2 = region->inner->sched_kind;
6296 break;
6297 }
6298 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6299 start_ix = (enum built_in_function) start_ix2;
6300 break;
6301 case GIMPLE_OMP_SECTIONS:
6302 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
6303 break;
6304 default:
6305 gcc_unreachable ();
6306 }
6307 }
6308
6309 /* By default, the value of NUM_THREADS is zero (selected at run time)
6310 and there is no conditional. */
6311 cond = NULL_TREE;
6312 val = build_int_cst (unsigned_type_node, 0);
6313 flags = build_int_cst (unsigned_type_node, 0);
6314
6315 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6316 if (c)
6317 cond = OMP_CLAUSE_IF_EXPR (c);
6318
6319 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6320 if (c)
6321 {
6322 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6323 clause_loc = OMP_CLAUSE_LOCATION (c);
6324 }
6325 else
6326 clause_loc = gimple_location (entry_stmt);
6327
6328 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6329 if (c)
6330 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6331
6332 /* Ensure 'val' is of the correct type. */
6333 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
6334
6335 /* If we found the clause 'if (cond)', build either
6336 (cond != 0) or (cond ? val : 1u). */
6337 if (cond)
6338 {
6339 cond = gimple_boolify (cond);
6340
6341 if (integer_zerop (val))
6342 val = fold_build2_loc (clause_loc,
6343 EQ_EXPR, unsigned_type_node, cond,
6344 build_int_cst (TREE_TYPE (cond), 0));
6345 else
6346 {
6347 basic_block cond_bb, then_bb, else_bb;
6348 edge e, e_then, e_else;
6349 tree tmp_then, tmp_else, tmp_join, tmp_var;
6350
6351 tmp_var = create_tmp_var (TREE_TYPE (val));
6352 if (gimple_in_ssa_p (cfun))
6353 {
6354 tmp_then = make_ssa_name (tmp_var);
6355 tmp_else = make_ssa_name (tmp_var);
6356 tmp_join = make_ssa_name (tmp_var);
6357 }
6358 else
6359 {
6360 tmp_then = tmp_var;
6361 tmp_else = tmp_var;
6362 tmp_join = tmp_var;
6363 }
6364
6365 e = split_block_after_labels (bb);
6366 cond_bb = e->src;
6367 bb = e->dest;
6368 remove_edge (e);
6369
6370 then_bb = create_empty_bb (cond_bb);
6371 else_bb = create_empty_bb (then_bb);
6372 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6373 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
6374
6375 stmt = gimple_build_cond_empty (cond);
6376 gsi = gsi_start_bb (cond_bb);
6377 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6378
6379 gsi = gsi_start_bb (then_bb);
6380 expand_omp_build_assign (&gsi, tmp_then, val, true);
6381
6382 gsi = gsi_start_bb (else_bb);
6383 expand_omp_build_assign (&gsi, tmp_else,
6384 build_int_cst (unsigned_type_node, 1),
6385 true);
6386
6387 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6388 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
6389 add_bb_to_loop (then_bb, cond_bb->loop_father);
6390 add_bb_to_loop (else_bb, cond_bb->loop_father);
6391 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6392 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
6393
6394 if (gimple_in_ssa_p (cfun))
6395 {
6396 gphi *phi = create_phi_node (tmp_join, bb);
6397 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6398 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
6399 }
6400
6401 val = tmp_join;
6402 }
6403
6404 gsi = gsi_start_bb (bb);
6405 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6406 false, GSI_CONTINUE_LINKING);
6407 }
6408
6409 gsi = gsi_last_bb (bb);
6410 t = gimple_omp_parallel_data_arg (entry_stmt);
6411 if (t == NULL)
6412 t1 = null_pointer_node;
6413 else
6414 t1 = build_fold_addr_expr (t);
6415 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6416
6417 vec_alloc (args, 4 + vec_safe_length (ws_args));
6418 args->quick_push (t2);
6419 args->quick_push (t1);
6420 args->quick_push (val);
6421 if (ws_args)
6422 args->splice (*ws_args);
6423 args->quick_push (flags);
6424
6425 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
6426 builtin_decl_explicit (start_ix), args);
6427
6428 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6429 false, GSI_CONTINUE_LINKING);
6430 }
6431
6432 /* Insert a function call whose name is FUNC_NAME with the information from
6433 ENTRY_STMT into the basic_block BB. */
6434
6435 static void
6436 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
6437 vec <tree, va_gc> *ws_args)
6438 {
6439 tree t, t1, t2;
6440 gimple_stmt_iterator gsi;
6441 vec <tree, va_gc> *args;
6442
6443 gcc_assert (vec_safe_length (ws_args) == 2);
6444 tree func_name = (*ws_args)[0];
6445 tree grain = (*ws_args)[1];
6446
6447 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6448 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6449 gcc_assert (count != NULL_TREE);
6450 count = OMP_CLAUSE_OPERAND (count, 0);
6451
6452 gsi = gsi_last_bb (bb);
6453 t = gimple_omp_parallel_data_arg (entry_stmt);
6454 if (t == NULL)
6455 t1 = null_pointer_node;
6456 else
6457 t1 = build_fold_addr_expr (t);
6458 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6459
6460 vec_alloc (args, 4);
6461 args->quick_push (t2);
6462 args->quick_push (t1);
6463 args->quick_push (count);
6464 args->quick_push (grain);
6465 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6466
6467 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6468 GSI_CONTINUE_LINKING);
6469 }
6470
6471 /* Build the function call to GOMP_task to actually
6472 generate the task operation. BB is the block where to insert the code. */
6473
6474 static void
6475 expand_task_call (struct omp_region *region, basic_block bb,
6476 gomp_task *entry_stmt)
6477 {
6478 tree t1, t2, t3;
6479 gimple_stmt_iterator gsi;
6480 location_t loc = gimple_location (entry_stmt);
6481
6482 tree clauses = gimple_omp_task_clauses (entry_stmt);
6483
6484 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6485 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6486 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6487 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6488 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6489 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6490
6491 unsigned int iflags
6492 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6493 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6494 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6495
6496 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6497 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6498 tree num_tasks = NULL_TREE;
6499 bool ull = false;
6500 if (taskloop_p)
6501 {
6502 gimple *g = last_stmt (region->outer->entry);
6503 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6504 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6505 struct omp_for_data fd;
6506 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6507 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6508 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6509 OMP_CLAUSE__LOOPTEMP_);
6510 startvar = OMP_CLAUSE_DECL (startvar);
6511 endvar = OMP_CLAUSE_DECL (endvar);
6512 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6513 if (fd.loop.cond_code == LT_EXPR)
6514 iflags |= GOMP_TASK_FLAG_UP;
6515 tree tclauses = gimple_omp_for_clauses (g);
6516 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6517 if (num_tasks)
6518 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6519 else
6520 {
6521 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6522 if (num_tasks)
6523 {
6524 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6525 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6526 }
6527 else
6528 num_tasks = integer_zero_node;
6529 }
6530 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6531 if (ifc == NULL_TREE)
6532 iflags |= GOMP_TASK_FLAG_IF;
6533 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6534 iflags |= GOMP_TASK_FLAG_NOGROUP;
6535 ull = fd.iter_type == long_long_unsigned_type_node;
6536 }
6537 else if (priority)
6538 iflags |= GOMP_TASK_FLAG_PRIORITY;
6539
6540 tree flags = build_int_cst (unsigned_type_node, iflags);
6541
6542 tree cond = boolean_true_node;
6543 if (ifc)
6544 {
6545 if (taskloop_p)
6546 {
6547 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6548 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6549 build_int_cst (unsigned_type_node,
6550 GOMP_TASK_FLAG_IF),
6551 build_int_cst (unsigned_type_node, 0));
6552 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6553 flags, t);
6554 }
6555 else
6556 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6557 }
6558
6559 if (finalc)
6560 {
6561 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6562 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6563 build_int_cst (unsigned_type_node,
6564 GOMP_TASK_FLAG_FINAL),
6565 build_int_cst (unsigned_type_node, 0));
6566 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6567 }
6568 if (depend)
6569 depend = OMP_CLAUSE_DECL (depend);
6570 else
6571 depend = build_int_cst (ptr_type_node, 0);
6572 if (priority)
6573 priority = fold_convert (integer_type_node,
6574 OMP_CLAUSE_PRIORITY_EXPR (priority));
6575 else
6576 priority = integer_zero_node;
6577
6578 gsi = gsi_last_bb (bb);
6579 tree t = gimple_omp_task_data_arg (entry_stmt);
6580 if (t == NULL)
6581 t2 = null_pointer_node;
6582 else
6583 t2 = build_fold_addr_expr_loc (loc, t);
6584 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6585 t = gimple_omp_task_copy_fn (entry_stmt);
6586 if (t == NULL)
6587 t3 = null_pointer_node;
6588 else
6589 t3 = build_fold_addr_expr_loc (loc, t);
6590
6591 if (taskloop_p)
6592 t = build_call_expr (ull
6593 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6594 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6595 11, t1, t2, t3,
6596 gimple_omp_task_arg_size (entry_stmt),
6597 gimple_omp_task_arg_align (entry_stmt), flags,
6598 num_tasks, priority, startvar, endvar, step);
6599 else
6600 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6601 9, t1, t2, t3,
6602 gimple_omp_task_arg_size (entry_stmt),
6603 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6604 depend, priority);
6605
6606 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6607 false, GSI_CONTINUE_LINKING);
6608 }
6609
6610
6611 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6612 catch handler and return it. This prevents programs from violating the
6613 structured block semantics with throws. */
6614
6615 static gimple_seq
6616 maybe_catch_exception (gimple_seq body)
6617 {
6618 gimple *g;
6619 tree decl;
6620
6621 if (!flag_exceptions)
6622 return body;
6623
6624 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6625 decl = lang_hooks.eh_protect_cleanup_actions ();
6626 else
6627 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6628
6629 g = gimple_build_eh_must_not_throw (decl);
6630 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6631 GIMPLE_TRY_CATCH);
6632
6633 return gimple_seq_alloc_with_stmt (g);
6634 }
6635
6636 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6637
6638 static tree
6639 vec2chain (vec<tree, va_gc> *v)
6640 {
6641 tree chain = NULL_TREE, t;
6642 unsigned ix;
6643
6644 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6645 {
6646 DECL_CHAIN (t) = chain;
6647 chain = t;
6648 }
6649
6650 return chain;
6651 }
6652
6653
6654 /* Remove barriers in REGION->EXIT's block. Note that this is only
6655 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6656 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6657 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6658 removed. */
6659
6660 static void
6661 remove_exit_barrier (struct omp_region *region)
6662 {
6663 gimple_stmt_iterator gsi;
6664 basic_block exit_bb;
6665 edge_iterator ei;
6666 edge e;
6667 gimple *stmt;
6668 int any_addressable_vars = -1;
6669
6670 exit_bb = region->exit;
6671
6672 /* If the parallel region doesn't return, we don't have REGION->EXIT
6673 block at all. */
6674 if (! exit_bb)
6675 return;
6676
6677 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6678 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6679 statements that can appear in between are extremely limited -- no
6680 memory operations at all. Here, we allow nothing at all, so the
6681 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6682 gsi = gsi_last_bb (exit_bb);
6683 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6684 gsi_prev (&gsi);
6685 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6686 return;
6687
6688 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6689 {
6690 gsi = gsi_last_bb (e->src);
6691 if (gsi_end_p (gsi))
6692 continue;
6693 stmt = gsi_stmt (gsi);
6694 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6695 && !gimple_omp_return_nowait_p (stmt))
6696 {
6697 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6698 in many cases. If there could be tasks queued, the barrier
6699 might be needed to let the tasks run before some local
6700 variable of the parallel that the task uses as shared
6701 runs out of scope. The task can be spawned either
6702 from within current function (this would be easy to check)
6703 or from some function it calls and gets passed an address
6704 of such a variable. */
6705 if (any_addressable_vars < 0)
6706 {
6707 gomp_parallel *parallel_stmt
6708 = as_a <gomp_parallel *> (last_stmt (region->entry));
6709 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6710 tree local_decls, block, decl;
6711 unsigned ix;
6712
6713 any_addressable_vars = 0;
6714 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6715 if (TREE_ADDRESSABLE (decl))
6716 {
6717 any_addressable_vars = 1;
6718 break;
6719 }
6720 for (block = gimple_block (stmt);
6721 !any_addressable_vars
6722 && block
6723 && TREE_CODE (block) == BLOCK;
6724 block = BLOCK_SUPERCONTEXT (block))
6725 {
6726 for (local_decls = BLOCK_VARS (block);
6727 local_decls;
6728 local_decls = DECL_CHAIN (local_decls))
6729 if (TREE_ADDRESSABLE (local_decls))
6730 {
6731 any_addressable_vars = 1;
6732 break;
6733 }
6734 if (block == gimple_block (parallel_stmt))
6735 break;
6736 }
6737 }
6738 if (!any_addressable_vars)
6739 gimple_omp_return_set_nowait (stmt);
6740 }
6741 }
6742 }
6743
6744 static void
6745 remove_exit_barriers (struct omp_region *region)
6746 {
6747 if (region->type == GIMPLE_OMP_PARALLEL)
6748 remove_exit_barrier (region);
6749
6750 if (region->inner)
6751 {
6752 region = region->inner;
6753 remove_exit_barriers (region);
6754 while (region->next)
6755 {
6756 region = region->next;
6757 remove_exit_barriers (region);
6758 }
6759 }
6760 }
6761
6762 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
6763 calls. These can't be declared as const functions, but
6764 within one parallel body they are constant, so they can be
6765 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
6766 which are declared const. Similarly for task body, except
6767 that in untied task omp_get_thread_num () can change at any task
6768 scheduling point. */
6769
6770 static void
6771 optimize_omp_library_calls (gimple *entry_stmt)
6772 {
6773 basic_block bb;
6774 gimple_stmt_iterator gsi;
6775 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6776 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
6777 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6778 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
6779 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
6780 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
6781 OMP_CLAUSE_UNTIED) != NULL);
6782
6783 FOR_EACH_BB_FN (bb, cfun)
6784 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
6785 {
6786 gimple *call = gsi_stmt (gsi);
6787 tree decl;
6788
6789 if (is_gimple_call (call)
6790 && (decl = gimple_call_fndecl (call))
6791 && DECL_EXTERNAL (decl)
6792 && TREE_PUBLIC (decl)
6793 && DECL_INITIAL (decl) == NULL)
6794 {
6795 tree built_in;
6796
6797 if (DECL_NAME (decl) == thr_num_id)
6798 {
6799 /* In #pragma omp task untied omp_get_thread_num () can change
6800 during the execution of the task region. */
6801 if (untied_task)
6802 continue;
6803 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
6804 }
6805 else if (DECL_NAME (decl) == num_thr_id)
6806 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
6807 else
6808 continue;
6809
6810 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
6811 || gimple_call_num_args (call) != 0)
6812 continue;
6813
6814 if (flag_exceptions && !TREE_NOTHROW (decl))
6815 continue;
6816
6817 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
6818 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
6819 TREE_TYPE (TREE_TYPE (built_in))))
6820 continue;
6821
6822 gimple_call_set_fndecl (call, built_in);
6823 }
6824 }
6825 }
6826
6827 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
6828 regimplified. */
6829
6830 static tree
6831 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
6832 {
6833 tree t = *tp;
6834
6835 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
6836 if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t))
6837 return t;
6838
6839 if (TREE_CODE (t) == ADDR_EXPR)
6840 recompute_tree_invariant_for_addr_expr (t);
6841
6842 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
6843 return NULL_TREE;
6844 }
6845
6846 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
6847
6848 static void
6849 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
6850 bool after)
6851 {
6852 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
6853 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
6854 !after, after ? GSI_CONTINUE_LINKING
6855 : GSI_SAME_STMT);
6856 gimple *stmt = gimple_build_assign (to, from);
6857 if (after)
6858 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
6859 else
6860 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
6861 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
6862 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
6863 {
6864 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
6865 gimple_regimplify_operands (stmt, &gsi);
6866 }
6867 }
6868
6869 /* Expand the OpenMP parallel or task directive starting at REGION. */
6870
6871 static void
6872 expand_omp_taskreg (struct omp_region *region)
6873 {
6874 basic_block entry_bb, exit_bb, new_bb;
6875 struct function *child_cfun;
6876 tree child_fn, block, t;
6877 gimple_stmt_iterator gsi;
6878 gimple *entry_stmt, *stmt;
6879 edge e;
6880 vec<tree, va_gc> *ws_args;
6881
6882 entry_stmt = last_stmt (region->entry);
6883 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
6884 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
6885
6886 entry_bb = region->entry;
6887 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
6888 exit_bb = region->cont;
6889 else
6890 exit_bb = region->exit;
6891
6892 bool is_cilk_for
6893 = (flag_cilkplus
6894 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
6895 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
6896 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
6897
6898 if (is_cilk_for)
6899 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
6900 and the inner statement contains the name of the built-in function
6901 and grain. */
6902 ws_args = region->inner->ws_args;
6903 else if (is_combined_parallel (region))
6904 ws_args = region->ws_args;
6905 else
6906 ws_args = NULL;
6907
6908 if (child_cfun->cfg)
6909 {
6910 /* Due to inlining, it may happen that we have already outlined
6911 the region, in which case all we need to do is make the
6912 sub-graph unreachable and emit the parallel call. */
6913 edge entry_succ_e, exit_succ_e;
6914
6915 entry_succ_e = single_succ_edge (entry_bb);
6916
6917 gsi = gsi_last_bb (entry_bb);
6918 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
6919 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
6920 gsi_remove (&gsi, true);
6921
6922 new_bb = entry_bb;
6923 if (exit_bb)
6924 {
6925 exit_succ_e = single_succ_edge (exit_bb);
6926 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
6927 }
6928 remove_edge_and_dominated_blocks (entry_succ_e);
6929 }
6930 else
6931 {
6932 unsigned srcidx, dstidx, num;
6933
6934 /* If the parallel region needs data sent from the parent
6935 function, then the very first statement (except possible
6936 tree profile counter updates) of the parallel body
6937 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
6938 &.OMP_DATA_O is passed as an argument to the child function,
6939 we need to replace it with the argument as seen by the child
6940 function.
6941
6942 In most cases, this will end up being the identity assignment
6943 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
6944 a function call that has been inlined, the original PARM_DECL
6945 .OMP_DATA_I may have been converted into a different local
6946 variable. In which case, we need to keep the assignment. */
6947 if (gimple_omp_taskreg_data_arg (entry_stmt))
6948 {
6949 basic_block entry_succ_bb
6950 = single_succ_p (entry_bb) ? single_succ (entry_bb)
6951 : FALLTHRU_EDGE (entry_bb)->dest;
6952 tree arg;
6953 gimple *parcopy_stmt = NULL;
6954
6955 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
6956 {
6957 gimple *stmt;
6958
6959 gcc_assert (!gsi_end_p (gsi));
6960 stmt = gsi_stmt (gsi);
6961 if (gimple_code (stmt) != GIMPLE_ASSIGN)
6962 continue;
6963
6964 if (gimple_num_ops (stmt) == 2)
6965 {
6966 tree arg = gimple_assign_rhs1 (stmt);
6967
6968 /* We're ignore the subcode because we're
6969 effectively doing a STRIP_NOPS. */
6970
6971 if (TREE_CODE (arg) == ADDR_EXPR
6972 && TREE_OPERAND (arg, 0)
6973 == gimple_omp_taskreg_data_arg (entry_stmt))
6974 {
6975 parcopy_stmt = stmt;
6976 break;
6977 }
6978 }
6979 }
6980
6981 gcc_assert (parcopy_stmt != NULL);
6982 arg = DECL_ARGUMENTS (child_fn);
6983
6984 if (!gimple_in_ssa_p (cfun))
6985 {
6986 if (gimple_assign_lhs (parcopy_stmt) == arg)
6987 gsi_remove (&gsi, true);
6988 else
6989 {
6990 /* ?? Is setting the subcode really necessary ?? */
6991 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
6992 gimple_assign_set_rhs1 (parcopy_stmt, arg);
6993 }
6994 }
6995 else
6996 {
6997 tree lhs = gimple_assign_lhs (parcopy_stmt);
6998 gcc_assert (SSA_NAME_VAR (lhs) == arg);
6999 /* We'd like to set the rhs to the default def in the child_fn,
7000 but it's too early to create ssa names in the child_fn.
7001 Instead, we set the rhs to the parm. In
7002 move_sese_region_to_fn, we introduce a default def for the
7003 parm, map the parm to it's default def, and once we encounter
7004 this stmt, replace the parm with the default def. */
7005 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7006 update_stmt (parcopy_stmt);
7007 }
7008 }
7009
7010 /* Declare local variables needed in CHILD_CFUN. */
7011 block = DECL_INITIAL (child_fn);
7012 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7013 /* The gimplifier could record temporaries in parallel/task block
7014 rather than in containing function's local_decls chain,
7015 which would mean cgraph missed finalizing them. Do it now. */
7016 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7017 if (TREE_CODE (t) == VAR_DECL
7018 && TREE_STATIC (t)
7019 && !DECL_EXTERNAL (t))
7020 varpool_node::finalize_decl (t);
7021 DECL_SAVED_TREE (child_fn) = NULL;
7022 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7023 gimple_set_body (child_fn, NULL);
7024 TREE_USED (block) = 1;
7025
7026 /* Reset DECL_CONTEXT on function arguments. */
7027 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7028 DECL_CONTEXT (t) = child_fn;
7029
7030 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7031 so that it can be moved to the child function. */
7032 gsi = gsi_last_bb (entry_bb);
7033 stmt = gsi_stmt (gsi);
7034 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7035 || gimple_code (stmt) == GIMPLE_OMP_TASK));
7036 e = split_block (entry_bb, stmt);
7037 gsi_remove (&gsi, true);
7038 entry_bb = e->dest;
7039 edge e2 = NULL;
7040 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7041 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7042 else
7043 {
7044 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7045 gcc_assert (e2->dest == region->exit);
7046 remove_edge (BRANCH_EDGE (entry_bb));
7047 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7048 gsi = gsi_last_bb (region->exit);
7049 gcc_assert (!gsi_end_p (gsi)
7050 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7051 gsi_remove (&gsi, true);
7052 }
7053
7054 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
7055 if (exit_bb)
7056 {
7057 gsi = gsi_last_bb (exit_bb);
7058 gcc_assert (!gsi_end_p (gsi)
7059 && (gimple_code (gsi_stmt (gsi))
7060 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
7061 stmt = gimple_build_return (NULL);
7062 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7063 gsi_remove (&gsi, true);
7064 }
7065
7066 /* Move the parallel region into CHILD_CFUN. */
7067
7068 if (gimple_in_ssa_p (cfun))
7069 {
7070 init_tree_ssa (child_cfun);
7071 init_ssa_operands (child_cfun);
7072 child_cfun->gimple_df->in_ssa_p = true;
7073 block = NULL_TREE;
7074 }
7075 else
7076 block = gimple_block (entry_stmt);
7077
7078 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7079 if (exit_bb)
7080 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7081 if (e2)
7082 {
7083 basic_block dest_bb = e2->dest;
7084 if (!exit_bb)
7085 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7086 remove_edge (e2);
7087 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7088 }
7089 /* When the OMP expansion process cannot guarantee an up-to-date
7090 loop tree arrange for the child function to fixup loops. */
7091 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7092 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7093
7094 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7095 num = vec_safe_length (child_cfun->local_decls);
7096 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7097 {
7098 t = (*child_cfun->local_decls)[srcidx];
7099 if (DECL_CONTEXT (t) == cfun->decl)
7100 continue;
7101 if (srcidx != dstidx)
7102 (*child_cfun->local_decls)[dstidx] = t;
7103 dstidx++;
7104 }
7105 if (dstidx != num)
7106 vec_safe_truncate (child_cfun->local_decls, dstidx);
7107
7108 /* Inform the callgraph about the new function. */
7109 child_cfun->curr_properties = cfun->curr_properties;
7110 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7111 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
7112 cgraph_node *node = cgraph_node::get_create (child_fn);
7113 node->parallelized_function = 1;
7114 cgraph_node::add_new_function (child_fn, true);
7115
7116 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7117 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7118
7119 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7120 fixed in a following pass. */
7121 push_cfun (child_cfun);
7122 if (need_asm)
7123 assign_assembler_name_if_neeeded (child_fn);
7124
7125 if (optimize)
7126 optimize_omp_library_calls (entry_stmt);
7127 cgraph_edge::rebuild_edges ();
7128
7129 /* Some EH regions might become dead, see PR34608. If
7130 pass_cleanup_cfg isn't the first pass to happen with the
7131 new child, these dead EH edges might cause problems.
7132 Clean them up now. */
7133 if (flag_exceptions)
7134 {
7135 basic_block bb;
7136 bool changed = false;
7137
7138 FOR_EACH_BB_FN (bb, cfun)
7139 changed |= gimple_purge_dead_eh_edges (bb);
7140 if (changed)
7141 cleanup_tree_cfg ();
7142 }
7143 if (gimple_in_ssa_p (cfun))
7144 update_ssa (TODO_update_ssa);
7145 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7146 verify_loop_structure ();
7147 pop_cfun ();
7148
7149 if (dump_file && !gimple_in_ssa_p (cfun))
7150 {
7151 omp_any_child_fn_dumped = true;
7152 dump_function_header (dump_file, child_fn, dump_flags);
7153 dump_function_to_file (child_fn, dump_file, dump_flags);
7154 }
7155 }
7156
7157 /* Emit a library call to launch the children threads. */
7158 if (is_cilk_for)
7159 expand_cilk_for_call (new_bb,
7160 as_a <gomp_parallel *> (entry_stmt), ws_args);
7161 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7162 expand_parallel_call (region, new_bb,
7163 as_a <gomp_parallel *> (entry_stmt), ws_args);
7164 else
7165 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
7166 if (gimple_in_ssa_p (cfun))
7167 update_ssa (TODO_update_ssa_only_virtuals);
7168 }
7169
7170 /* Information about members of an OpenACC collapsed loop nest. */
7171
7172 struct oacc_collapse
7173 {
7174 tree base; /* Base value. */
7175 tree iters; /* Number of steps. */
7176 tree step; /* step size. */
7177 };
7178
7179 /* Helper for expand_oacc_for. Determine collapsed loop information.
7180 Fill in COUNTS array. Emit any initialization code before GSI.
7181 Return the calculated outer loop bound of BOUND_TYPE. */
7182
7183 static tree
7184 expand_oacc_collapse_init (const struct omp_for_data *fd,
7185 gimple_stmt_iterator *gsi,
7186 oacc_collapse *counts, tree bound_type)
7187 {
7188 tree total = build_int_cst (bound_type, 1);
7189 int ix;
7190
7191 gcc_assert (integer_onep (fd->loop.step));
7192 gcc_assert (integer_zerop (fd->loop.n1));
7193
7194 for (ix = 0; ix != fd->collapse; ix++)
7195 {
7196 const omp_for_data_loop *loop = &fd->loops[ix];
7197
7198 tree iter_type = TREE_TYPE (loop->v);
7199 tree diff_type = iter_type;
7200 tree plus_type = iter_type;
7201
7202 gcc_assert (loop->cond_code == fd->loop.cond_code);
7203
7204 if (POINTER_TYPE_P (iter_type))
7205 plus_type = sizetype;
7206 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7207 diff_type = signed_type_for (diff_type);
7208
7209 tree b = loop->n1;
7210 tree e = loop->n2;
7211 tree s = loop->step;
7212 bool up = loop->cond_code == LT_EXPR;
7213 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7214 bool negating;
7215 tree expr;
7216
7217 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7218 true, GSI_SAME_STMT);
7219 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7220 true, GSI_SAME_STMT);
7221
7222 /* Convert the step, avoiding possible unsigned->signed overflow. */
7223 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7224 if (negating)
7225 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7226 s = fold_convert (diff_type, s);
7227 if (negating)
7228 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7229 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7230 true, GSI_SAME_STMT);
7231
7232 /* Determine the range, avoiding possible unsigned->signed overflow. */
7233 negating = !up && TYPE_UNSIGNED (iter_type);
7234 expr = fold_build2 (MINUS_EXPR, plus_type,
7235 fold_convert (plus_type, negating ? b : e),
7236 fold_convert (plus_type, negating ? e : b));
7237 expr = fold_convert (diff_type, expr);
7238 if (negating)
7239 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7240 tree range = force_gimple_operand_gsi
7241 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7242
7243 /* Determine number of iterations. */
7244 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7245 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7246 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7247
7248 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7249 true, GSI_SAME_STMT);
7250
7251 counts[ix].base = b;
7252 counts[ix].iters = iters;
7253 counts[ix].step = s;
7254
7255 total = fold_build2 (MULT_EXPR, bound_type, total,
7256 fold_convert (bound_type, iters));
7257 }
7258
7259 return total;
7260 }
7261
7262 /* Emit initializers for collapsed loop members. IVAR is the outer
7263 loop iteration variable, from which collapsed loop iteration values
7264 are calculated. COUNTS array has been initialized by
7265 expand_oacc_collapse_inits. */
7266
7267 static void
7268 expand_oacc_collapse_vars (const struct omp_for_data *fd,
7269 gimple_stmt_iterator *gsi,
7270 const oacc_collapse *counts, tree ivar)
7271 {
7272 tree ivar_type = TREE_TYPE (ivar);
7273
7274 /* The most rapidly changing iteration variable is the innermost
7275 one. */
7276 for (int ix = fd->collapse; ix--;)
7277 {
7278 const omp_for_data_loop *loop = &fd->loops[ix];
7279 const oacc_collapse *collapse = &counts[ix];
7280 tree iter_type = TREE_TYPE (loop->v);
7281 tree diff_type = TREE_TYPE (collapse->step);
7282 tree plus_type = iter_type;
7283 enum tree_code plus_code = PLUS_EXPR;
7284 tree expr;
7285
7286 if (POINTER_TYPE_P (iter_type))
7287 {
7288 plus_code = POINTER_PLUS_EXPR;
7289 plus_type = sizetype;
7290 }
7291
7292 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7293 fold_convert (ivar_type, collapse->iters));
7294 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7295 collapse->step);
7296 expr = fold_build2 (plus_code, iter_type, collapse->base,
7297 fold_convert (plus_type, expr));
7298 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7299 true, GSI_SAME_STMT);
7300 gassign *ass = gimple_build_assign (loop->v, expr);
7301 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7302
7303 if (ix)
7304 {
7305 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7306 fold_convert (ivar_type, collapse->iters));
7307 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7308 true, GSI_SAME_STMT);
7309 }
7310 }
7311 }
7312
7313
7314 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7315 of the combined collapse > 1 loop constructs, generate code like:
7316 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7317 if (cond3 is <)
7318 adj = STEP3 - 1;
7319 else
7320 adj = STEP3 + 1;
7321 count3 = (adj + N32 - N31) / STEP3;
7322 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7323 if (cond2 is <)
7324 adj = STEP2 - 1;
7325 else
7326 adj = STEP2 + 1;
7327 count2 = (adj + N22 - N21) / STEP2;
7328 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7329 if (cond1 is <)
7330 adj = STEP1 - 1;
7331 else
7332 adj = STEP1 + 1;
7333 count1 = (adj + N12 - N11) / STEP1;
7334 count = count1 * count2 * count3;
7335 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7336 count = 0;
7337 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7338 of the combined loop constructs, just initialize COUNTS array
7339 from the _looptemp_ clauses. */
7340
7341 /* NOTE: It *could* be better to moosh all of the BBs together,
7342 creating one larger BB with all the computation and the unexpected
7343 jump at the end. I.e.
7344
7345 bool zero3, zero2, zero1, zero;
7346
7347 zero3 = N32 c3 N31;
7348 count3 = (N32 - N31) /[cl] STEP3;
7349 zero2 = N22 c2 N21;
7350 count2 = (N22 - N21) /[cl] STEP2;
7351 zero1 = N12 c1 N11;
7352 count1 = (N12 - N11) /[cl] STEP1;
7353 zero = zero3 || zero2 || zero1;
7354 count = count1 * count2 * count3;
7355 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7356
7357 After all, we expect the zero=false, and thus we expect to have to
7358 evaluate all of the comparison expressions, so short-circuiting
7359 oughtn't be a win. Since the condition isn't protecting a
7360 denominator, we're not concerned about divide-by-zero, so we can
7361 fully evaluate count even if a numerator turned out to be wrong.
7362
7363 It seems like putting this all together would create much better
7364 scheduling opportunities, and less pressure on the chip's branch
7365 predictor. */
7366
7367 static void
7368 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7369 basic_block &entry_bb, tree *counts,
7370 basic_block &zero_iter1_bb, int &first_zero_iter1,
7371 basic_block &zero_iter2_bb, int &first_zero_iter2,
7372 basic_block &l2_dom_bb)
7373 {
7374 tree t, type = TREE_TYPE (fd->loop.v);
7375 edge e, ne;
7376 int i;
7377
7378 /* Collapsed loops need work for expansion into SSA form. */
7379 gcc_assert (!gimple_in_ssa_p (cfun));
7380
7381 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7382 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7383 {
7384 gcc_assert (fd->ordered == 0);
7385 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7386 isn't supposed to be handled, as the inner loop doesn't
7387 use it. */
7388 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7389 OMP_CLAUSE__LOOPTEMP_);
7390 gcc_assert (innerc);
7391 for (i = 0; i < fd->collapse; i++)
7392 {
7393 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7394 OMP_CLAUSE__LOOPTEMP_);
7395 gcc_assert (innerc);
7396 if (i)
7397 counts[i] = OMP_CLAUSE_DECL (innerc);
7398 else
7399 counts[0] = NULL_TREE;
7400 }
7401 return;
7402 }
7403
7404 for (i = fd->collapse; i < fd->ordered; i++)
7405 {
7406 tree itype = TREE_TYPE (fd->loops[i].v);
7407 counts[i] = NULL_TREE;
7408 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7409 fold_convert (itype, fd->loops[i].n1),
7410 fold_convert (itype, fd->loops[i].n2));
7411 if (t && integer_zerop (t))
7412 {
7413 for (i = fd->collapse; i < fd->ordered; i++)
7414 counts[i] = build_int_cst (type, 0);
7415 break;
7416 }
7417 }
7418 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7419 {
7420 tree itype = TREE_TYPE (fd->loops[i].v);
7421
7422 if (i >= fd->collapse && counts[i])
7423 continue;
7424 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
7425 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7426 fold_convert (itype, fd->loops[i].n1),
7427 fold_convert (itype, fd->loops[i].n2)))
7428 == NULL_TREE || !integer_onep (t)))
7429 {
7430 gcond *cond_stmt;
7431 tree n1, n2;
7432 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7433 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7434 true, GSI_SAME_STMT);
7435 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7436 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7437 true, GSI_SAME_STMT);
7438 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7439 NULL_TREE, NULL_TREE);
7440 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7441 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7442 expand_omp_regimplify_p, NULL, NULL)
7443 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7444 expand_omp_regimplify_p, NULL, NULL))
7445 {
7446 *gsi = gsi_for_stmt (cond_stmt);
7447 gimple_regimplify_operands (cond_stmt, gsi);
7448 }
7449 e = split_block (entry_bb, cond_stmt);
7450 basic_block &zero_iter_bb
7451 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7452 int &first_zero_iter
7453 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
7454 if (zero_iter_bb == NULL)
7455 {
7456 gassign *assign_stmt;
7457 first_zero_iter = i;
7458 zero_iter_bb = create_empty_bb (entry_bb);
7459 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
7460 *gsi = gsi_after_labels (zero_iter_bb);
7461 if (i < fd->collapse)
7462 assign_stmt = gimple_build_assign (fd->loop.n2,
7463 build_zero_cst (type));
7464 else
7465 {
7466 counts[i] = create_tmp_reg (type, ".count");
7467 assign_stmt
7468 = gimple_build_assign (counts[i], build_zero_cst (type));
7469 }
7470 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
7471 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7472 entry_bb);
7473 }
7474 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7475 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7476 e->flags = EDGE_TRUE_VALUE;
7477 e->probability = REG_BR_PROB_BASE - ne->probability;
7478 if (l2_dom_bb == NULL)
7479 l2_dom_bb = entry_bb;
7480 entry_bb = e->dest;
7481 *gsi = gsi_last_bb (entry_bb);
7482 }
7483
7484 if (POINTER_TYPE_P (itype))
7485 itype = signed_type_for (itype);
7486 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7487 ? -1 : 1));
7488 t = fold_build2 (PLUS_EXPR, itype,
7489 fold_convert (itype, fd->loops[i].step), t);
7490 t = fold_build2 (PLUS_EXPR, itype, t,
7491 fold_convert (itype, fd->loops[i].n2));
7492 t = fold_build2 (MINUS_EXPR, itype, t,
7493 fold_convert (itype, fd->loops[i].n1));
7494 /* ?? We could probably use CEIL_DIV_EXPR instead of
7495 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7496 generate the same code in the end because generically we
7497 don't know that the values involved must be negative for
7498 GT?? */
7499 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7500 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7501 fold_build1 (NEGATE_EXPR, itype, t),
7502 fold_build1 (NEGATE_EXPR, itype,
7503 fold_convert (itype,
7504 fd->loops[i].step)));
7505 else
7506 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7507 fold_convert (itype, fd->loops[i].step));
7508 t = fold_convert (type, t);
7509 if (TREE_CODE (t) == INTEGER_CST)
7510 counts[i] = t;
7511 else
7512 {
7513 if (i < fd->collapse || i != first_zero_iter2)
7514 counts[i] = create_tmp_reg (type, ".count");
7515 expand_omp_build_assign (gsi, counts[i], t);
7516 }
7517 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
7518 {
7519 if (i == 0)
7520 t = counts[0];
7521 else
7522 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7523 expand_omp_build_assign (gsi, fd->loop.n2, t);
7524 }
7525 }
7526 }
7527
7528
7529 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7530 T = V;
7531 V3 = N31 + (T % count3) * STEP3;
7532 T = T / count3;
7533 V2 = N21 + (T % count2) * STEP2;
7534 T = T / count2;
7535 V1 = N11 + T * STEP1;
7536 if this loop doesn't have an inner loop construct combined with it.
7537 If it does have an inner loop construct combined with it and the
7538 iteration count isn't known constant, store values from counts array
7539 into its _looptemp_ temporaries instead. */
7540
7541 static void
7542 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7543 tree *counts, gimple *inner_stmt, tree startvar)
7544 {
7545 int i;
7546 if (gimple_omp_for_combined_p (fd->for_stmt))
7547 {
7548 /* If fd->loop.n2 is constant, then no propagation of the counts
7549 is needed, they are constant. */
7550 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7551 return;
7552
7553 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7554 ? gimple_omp_taskreg_clauses (inner_stmt)
7555 : gimple_omp_for_clauses (inner_stmt);
7556 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7557 isn't supposed to be handled, as the inner loop doesn't
7558 use it. */
7559 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7560 gcc_assert (innerc);
7561 for (i = 0; i < fd->collapse; i++)
7562 {
7563 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7564 OMP_CLAUSE__LOOPTEMP_);
7565 gcc_assert (innerc);
7566 if (i)
7567 {
7568 tree tem = OMP_CLAUSE_DECL (innerc);
7569 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7570 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7571 false, GSI_CONTINUE_LINKING);
7572 gassign *stmt = gimple_build_assign (tem, t);
7573 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7574 }
7575 }
7576 return;
7577 }
7578
7579 tree type = TREE_TYPE (fd->loop.v);
7580 tree tem = create_tmp_reg (type, ".tem");
7581 gassign *stmt = gimple_build_assign (tem, startvar);
7582 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7583
7584 for (i = fd->collapse - 1; i >= 0; i--)
7585 {
7586 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7587 itype = vtype;
7588 if (POINTER_TYPE_P (vtype))
7589 itype = signed_type_for (vtype);
7590 if (i != 0)
7591 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7592 else
7593 t = tem;
7594 t = fold_convert (itype, t);
7595 t = fold_build2 (MULT_EXPR, itype, t,
7596 fold_convert (itype, fd->loops[i].step));
7597 if (POINTER_TYPE_P (vtype))
7598 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7599 else
7600 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7601 t = force_gimple_operand_gsi (gsi, t,
7602 DECL_P (fd->loops[i].v)
7603 && TREE_ADDRESSABLE (fd->loops[i].v),
7604 NULL_TREE, false,
7605 GSI_CONTINUE_LINKING);
7606 stmt = gimple_build_assign (fd->loops[i].v, t);
7607 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7608 if (i != 0)
7609 {
7610 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7611 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7612 false, GSI_CONTINUE_LINKING);
7613 stmt = gimple_build_assign (tem, t);
7614 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7615 }
7616 }
7617 }
7618
7619
7620 /* Helper function for expand_omp_for_*. Generate code like:
7621 L10:
7622 V3 += STEP3;
7623 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7624 L11:
7625 V3 = N31;
7626 V2 += STEP2;
7627 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7628 L12:
7629 V2 = N21;
7630 V1 += STEP1;
7631 goto BODY_BB; */
7632
7633 static basic_block
7634 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7635 basic_block body_bb)
7636 {
7637 basic_block last_bb, bb, collapse_bb = NULL;
7638 int i;
7639 gimple_stmt_iterator gsi;
7640 edge e;
7641 tree t;
7642 gimple *stmt;
7643
7644 last_bb = cont_bb;
7645 for (i = fd->collapse - 1; i >= 0; i--)
7646 {
7647 tree vtype = TREE_TYPE (fd->loops[i].v);
7648
7649 bb = create_empty_bb (last_bb);
7650 add_bb_to_loop (bb, last_bb->loop_father);
7651 gsi = gsi_start_bb (bb);
7652
7653 if (i < fd->collapse - 1)
7654 {
7655 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7656 e->probability = REG_BR_PROB_BASE / 8;
7657
7658 t = fd->loops[i + 1].n1;
7659 t = force_gimple_operand_gsi (&gsi, t,
7660 DECL_P (fd->loops[i + 1].v)
7661 && TREE_ADDRESSABLE (fd->loops[i
7662 + 1].v),
7663 NULL_TREE, false,
7664 GSI_CONTINUE_LINKING);
7665 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7666 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7667 }
7668 else
7669 collapse_bb = bb;
7670
7671 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7672
7673 if (POINTER_TYPE_P (vtype))
7674 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7675 else
7676 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7677 t = force_gimple_operand_gsi (&gsi, t,
7678 DECL_P (fd->loops[i].v)
7679 && TREE_ADDRESSABLE (fd->loops[i].v),
7680 NULL_TREE, false, GSI_CONTINUE_LINKING);
7681 stmt = gimple_build_assign (fd->loops[i].v, t);
7682 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7683
7684 if (i > 0)
7685 {
7686 t = fd->loops[i].n2;
7687 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7688 false, GSI_CONTINUE_LINKING);
7689 tree v = fd->loops[i].v;
7690 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7691 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7692 false, GSI_CONTINUE_LINKING);
7693 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7694 stmt = gimple_build_cond_empty (t);
7695 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7696 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7697 e->probability = REG_BR_PROB_BASE * 7 / 8;
7698 }
7699 else
7700 make_edge (bb, body_bb, EDGE_FALLTHRU);
7701 last_bb = bb;
7702 }
7703
7704 return collapse_bb;
7705 }
7706
7707
7708 /* Expand #pragma omp ordered depend(source). */
7709
7710 static void
7711 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7712 tree *counts, location_t loc)
7713 {
7714 enum built_in_function source_ix
7715 = fd->iter_type == long_integer_type_node
7716 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7717 gimple *g
7718 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7719 build_fold_addr_expr (counts[fd->ordered]));
7720 gimple_set_location (g, loc);
7721 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7722 }
7723
7724 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7725
7726 static void
7727 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7728 tree *counts, tree c, location_t loc)
7729 {
7730 auto_vec<tree, 10> args;
7731 enum built_in_function sink_ix
7732 = fd->iter_type == long_integer_type_node
7733 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
7734 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
7735 int i;
7736 gimple_stmt_iterator gsi2 = *gsi;
7737 bool warned_step = false;
7738
7739 for (i = 0; i < fd->ordered; i++)
7740 {
7741 off = TREE_PURPOSE (deps);
7742 if (!integer_zerop (off))
7743 {
7744 gcc_assert (fd->loops[i].cond_code == LT_EXPR
7745 || fd->loops[i].cond_code == GT_EXPR);
7746 bool forward = fd->loops[i].cond_code == LT_EXPR;
7747 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7748 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
7749 "lexically later iteration");
7750 break;
7751 }
7752 deps = TREE_CHAIN (deps);
7753 }
7754 /* If all offsets corresponding to the collapsed loops are zero,
7755 this depend clause can be ignored. FIXME: but there is still a
7756 flush needed. We need to emit one __sync_synchronize () for it
7757 though (perhaps conditionally)? Solve this together with the
7758 conservative dependence folding optimization.
7759 if (i >= fd->collapse)
7760 return; */
7761
7762 deps = OMP_CLAUSE_DECL (c);
7763 gsi_prev (&gsi2);
7764 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
7765 edge e2 = split_block_after_labels (e1->dest);
7766
7767 *gsi = gsi_after_labels (e1->dest);
7768 for (i = 0; i < fd->ordered; i++)
7769 {
7770 tree itype = TREE_TYPE (fd->loops[i].v);
7771 if (POINTER_TYPE_P (itype))
7772 itype = sizetype;
7773 if (i)
7774 deps = TREE_CHAIN (deps);
7775 off = TREE_PURPOSE (deps);
7776 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
7777
7778 if (integer_zerop (off))
7779 t = boolean_true_node;
7780 else
7781 {
7782 tree a;
7783 tree co = fold_convert_loc (loc, itype, off);
7784 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
7785 {
7786 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7787 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
7788 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
7789 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
7790 co);
7791 }
7792 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7793 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7794 fd->loops[i].v, co);
7795 else
7796 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
7797 fd->loops[i].v, co);
7798 if (fd->loops[i].cond_code == LT_EXPR)
7799 {
7800 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7801 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
7802 fd->loops[i].n1);
7803 else
7804 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
7805 fd->loops[i].n2);
7806 }
7807 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7808 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
7809 fd->loops[i].n2);
7810 else
7811 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
7812 fd->loops[i].n1);
7813 }
7814 if (cond)
7815 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
7816 else
7817 cond = t;
7818
7819 off = fold_convert_loc (loc, itype, off);
7820
7821 if (fd->loops[i].cond_code == LT_EXPR
7822 ? !integer_onep (fd->loops[i].step)
7823 : !integer_minus_onep (fd->loops[i].step))
7824 {
7825 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7826 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
7827 fold_build1_loc (loc, NEGATE_EXPR, itype,
7828 s));
7829 else
7830 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
7831 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
7832 build_int_cst (itype, 0));
7833 if (integer_zerop (t) && !warned_step)
7834 {
7835 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
7836 "in the iteration space");
7837 warned_step = true;
7838 }
7839 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
7840 cond, t);
7841 }
7842
7843 if (i <= fd->collapse - 1 && fd->collapse > 1)
7844 t = fd->loop.v;
7845 else if (counts[i])
7846 t = counts[i];
7847 else
7848 {
7849 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
7850 fd->loops[i].v, fd->loops[i].n1);
7851 t = fold_convert_loc (loc, fd->iter_type, t);
7852 }
7853 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7854 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
7855 fold_build1_loc (loc, NEGATE_EXPR, itype,
7856 s));
7857 else
7858 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
7859 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
7860 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
7861 off = fold_convert_loc (loc, fd->iter_type, off);
7862 if (i <= fd->collapse - 1 && fd->collapse > 1)
7863 {
7864 if (i)
7865 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
7866 off);
7867 if (i < fd->collapse - 1)
7868 {
7869 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
7870 counts[i]);
7871 continue;
7872 }
7873 }
7874 off = unshare_expr (off);
7875 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
7876 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
7877 true, GSI_SAME_STMT);
7878 args.safe_push (t);
7879 }
7880 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
7881 gimple_set_location (g, loc);
7882 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7883
7884 *gsi = gsi_last_bb (e1->src);
7885 cond = unshare_expr (cond);
7886 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
7887 GSI_CONTINUE_LINKING);
7888 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
7889 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
7890 e3->probability = REG_BR_PROB_BASE / 8;
7891 e1->probability = REG_BR_PROB_BASE - e3->probability;
7892 e1->flags = EDGE_TRUE_VALUE;
7893 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
7894
7895 *gsi = gsi_after_labels (e2->dest);
7896 }
7897
7898 /* Expand all #pragma omp ordered depend(source) and
7899 #pragma omp ordered depend(sink:...) constructs in the current
7900 #pragma omp for ordered(n) region. */
7901
7902 static void
7903 expand_omp_ordered_source_sink (struct omp_region *region,
7904 struct omp_for_data *fd, tree *counts,
7905 basic_block cont_bb)
7906 {
7907 struct omp_region *inner;
7908 int i;
7909 for (i = fd->collapse - 1; i < fd->ordered; i++)
7910 if (i == fd->collapse - 1 && fd->collapse > 1)
7911 counts[i] = NULL_TREE;
7912 else if (i >= fd->collapse && !cont_bb)
7913 counts[i] = build_zero_cst (fd->iter_type);
7914 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
7915 && integer_onep (fd->loops[i].step))
7916 counts[i] = NULL_TREE;
7917 else
7918 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
7919 tree atype
7920 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
7921 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
7922 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
7923
7924 for (inner = region->inner; inner; inner = inner->next)
7925 if (inner->type == GIMPLE_OMP_ORDERED)
7926 {
7927 gomp_ordered *ord_stmt = inner->ord_stmt;
7928 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
7929 location_t loc = gimple_location (ord_stmt);
7930 tree c;
7931 for (c = gimple_omp_ordered_clauses (ord_stmt);
7932 c; c = OMP_CLAUSE_CHAIN (c))
7933 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
7934 break;
7935 if (c)
7936 expand_omp_ordered_source (&gsi, fd, counts, loc);
7937 for (c = gimple_omp_ordered_clauses (ord_stmt);
7938 c; c = OMP_CLAUSE_CHAIN (c))
7939 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
7940 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
7941 gsi_remove (&gsi, true);
7942 }
7943 }
7944
7945 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
7946 collapsed. */
7947
7948 static basic_block
7949 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
7950 basic_block cont_bb, basic_block body_bb,
7951 bool ordered_lastprivate)
7952 {
7953 if (fd->ordered == fd->collapse)
7954 return cont_bb;
7955
7956 if (!cont_bb)
7957 {
7958 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7959 for (int i = fd->collapse; i < fd->ordered; i++)
7960 {
7961 tree type = TREE_TYPE (fd->loops[i].v);
7962 tree n1 = fold_convert (type, fd->loops[i].n1);
7963 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
7964 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7965 size_int (i - fd->collapse + 1),
7966 NULL_TREE, NULL_TREE);
7967 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
7968 }
7969 return NULL;
7970 }
7971
7972 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
7973 {
7974 tree t, type = TREE_TYPE (fd->loops[i].v);
7975 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
7976 expand_omp_build_assign (&gsi, fd->loops[i].v,
7977 fold_convert (type, fd->loops[i].n1));
7978 if (counts[i])
7979 expand_omp_build_assign (&gsi, counts[i],
7980 build_zero_cst (fd->iter_type));
7981 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
7982 size_int (i - fd->collapse + 1),
7983 NULL_TREE, NULL_TREE);
7984 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
7985 if (!gsi_end_p (gsi))
7986 gsi_prev (&gsi);
7987 else
7988 gsi = gsi_last_bb (body_bb);
7989 edge e1 = split_block (body_bb, gsi_stmt (gsi));
7990 basic_block new_body = e1->dest;
7991 if (body_bb == cont_bb)
7992 cont_bb = new_body;
7993 edge e2 = NULL;
7994 basic_block new_header;
7995 if (EDGE_COUNT (cont_bb->preds) > 0)
7996 {
7997 gsi = gsi_last_bb (cont_bb);
7998 if (POINTER_TYPE_P (type))
7999 t = fold_build_pointer_plus (fd->loops[i].v,
8000 fold_convert (sizetype,
8001 fd->loops[i].step));
8002 else
8003 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8004 fold_convert (type, fd->loops[i].step));
8005 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8006 if (counts[i])
8007 {
8008 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8009 build_int_cst (fd->iter_type, 1));
8010 expand_omp_build_assign (&gsi, counts[i], t);
8011 t = counts[i];
8012 }
8013 else
8014 {
8015 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8016 fd->loops[i].v, fd->loops[i].n1);
8017 t = fold_convert (fd->iter_type, t);
8018 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8019 true, GSI_SAME_STMT);
8020 }
8021 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8022 size_int (i - fd->collapse + 1),
8023 NULL_TREE, NULL_TREE);
8024 expand_omp_build_assign (&gsi, aref, t);
8025 gsi_prev (&gsi);
8026 e2 = split_block (cont_bb, gsi_stmt (gsi));
8027 new_header = e2->dest;
8028 }
8029 else
8030 new_header = cont_bb;
8031 gsi = gsi_after_labels (new_header);
8032 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8033 true, GSI_SAME_STMT);
8034 tree n2
8035 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8036 true, NULL_TREE, true, GSI_SAME_STMT);
8037 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8038 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8039 edge e3 = split_block (new_header, gsi_stmt (gsi));
8040 cont_bb = e3->dest;
8041 remove_edge (e1);
8042 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8043 e3->flags = EDGE_FALSE_VALUE;
8044 e3->probability = REG_BR_PROB_BASE / 8;
8045 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8046 e1->probability = REG_BR_PROB_BASE - e3->probability;
8047
8048 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8049 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8050
8051 if (e2)
8052 {
8053 struct loop *loop = alloc_loop ();
8054 loop->header = new_header;
8055 loop->latch = e2->src;
8056 add_loop (loop, body_bb->loop_father);
8057 }
8058 }
8059
8060 /* If there are any lastprivate clauses and it is possible some loops
8061 might have zero iterations, ensure all the decls are initialized,
8062 otherwise we could crash evaluating C++ class iterators with lastprivate
8063 clauses. */
8064 bool need_inits = false;
8065 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8066 if (need_inits)
8067 {
8068 tree type = TREE_TYPE (fd->loops[i].v);
8069 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8070 expand_omp_build_assign (&gsi, fd->loops[i].v,
8071 fold_convert (type, fd->loops[i].n1));
8072 }
8073 else
8074 {
8075 tree type = TREE_TYPE (fd->loops[i].v);
8076 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8077 boolean_type_node,
8078 fold_convert (type, fd->loops[i].n1),
8079 fold_convert (type, fd->loops[i].n2));
8080 if (!integer_onep (this_cond))
8081 need_inits = true;
8082 }
8083
8084 return cont_bb;
8085 }
8086
8087
8088 /* A subroutine of expand_omp_for. Generate code for a parallel
8089 loop with any schedule. Given parameters:
8090
8091 for (V = N1; V cond N2; V += STEP) BODY;
8092
8093 where COND is "<" or ">", we generate pseudocode
8094
8095 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8096 if (more) goto L0; else goto L3;
8097 L0:
8098 V = istart0;
8099 iend = iend0;
8100 L1:
8101 BODY;
8102 V += STEP;
8103 if (V cond iend) goto L1; else goto L2;
8104 L2:
8105 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8106 L3:
8107
8108 If this is a combined omp parallel loop, instead of the call to
8109 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8110 If this is gimple_omp_for_combined_p loop, then instead of assigning
8111 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8112 inner GIMPLE_OMP_FOR and V += STEP; and
8113 if (V cond iend) goto L1; else goto L2; are removed.
8114
8115 For collapsed loops, given parameters:
8116 collapse(3)
8117 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8118 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8119 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8120 BODY;
8121
8122 we generate pseudocode
8123
8124 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8125 if (cond3 is <)
8126 adj = STEP3 - 1;
8127 else
8128 adj = STEP3 + 1;
8129 count3 = (adj + N32 - N31) / STEP3;
8130 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8131 if (cond2 is <)
8132 adj = STEP2 - 1;
8133 else
8134 adj = STEP2 + 1;
8135 count2 = (adj + N22 - N21) / STEP2;
8136 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
8137 if (cond1 is <)
8138 adj = STEP1 - 1;
8139 else
8140 adj = STEP1 + 1;
8141 count1 = (adj + N12 - N11) / STEP1;
8142 count = count1 * count2 * count3;
8143 goto Z1;
8144 Z0:
8145 count = 0;
8146 Z1:
8147 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8148 if (more) goto L0; else goto L3;
8149 L0:
8150 V = istart0;
8151 T = V;
8152 V3 = N31 + (T % count3) * STEP3;
8153 T = T / count3;
8154 V2 = N21 + (T % count2) * STEP2;
8155 T = T / count2;
8156 V1 = N11 + T * STEP1;
8157 iend = iend0;
8158 L1:
8159 BODY;
8160 V += 1;
8161 if (V < iend) goto L10; else goto L2;
8162 L10:
8163 V3 += STEP3;
8164 if (V3 cond3 N32) goto L1; else goto L11;
8165 L11:
8166 V3 = N31;
8167 V2 += STEP2;
8168 if (V2 cond2 N22) goto L1; else goto L12;
8169 L12:
8170 V2 = N21;
8171 V1 += STEP1;
8172 goto L1;
8173 L2:
8174 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8175 L3:
8176
8177 */
8178
8179 static void
8180 expand_omp_for_generic (struct omp_region *region,
8181 struct omp_for_data *fd,
8182 enum built_in_function start_fn,
8183 enum built_in_function next_fn,
8184 gimple *inner_stmt)
8185 {
8186 tree type, istart0, iend0, iend;
8187 tree t, vmain, vback, bias = NULL_TREE;
8188 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
8189 basic_block l2_bb = NULL, l3_bb = NULL;
8190 gimple_stmt_iterator gsi;
8191 gassign *assign_stmt;
8192 bool in_combined_parallel = is_combined_parallel (region);
8193 bool broken_loop = region->cont == NULL;
8194 edge e, ne;
8195 tree *counts = NULL;
8196 int i;
8197 bool ordered_lastprivate = false;
8198
8199 gcc_assert (!broken_loop || !in_combined_parallel);
8200 gcc_assert (fd->iter_type == long_integer_type_node
8201 || !in_combined_parallel);
8202
8203 entry_bb = region->entry;
8204 cont_bb = region->cont;
8205 collapse_bb = NULL;
8206 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8207 gcc_assert (broken_loop
8208 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8209 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8210 l1_bb = single_succ (l0_bb);
8211 if (!broken_loop)
8212 {
8213 l2_bb = create_empty_bb (cont_bb);
8214 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8215 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8216 == l1_bb));
8217 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8218 }
8219 else
8220 l2_bb = NULL;
8221 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8222 exit_bb = region->exit;
8223
8224 gsi = gsi_last_bb (entry_bb);
8225
8226 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8227 if (fd->ordered
8228 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8229 OMP_CLAUSE_LASTPRIVATE))
8230 ordered_lastprivate = false;
8231 if (fd->collapse > 1 || fd->ordered)
8232 {
8233 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8234 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8235
8236 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
8237 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8238 zero_iter1_bb, first_zero_iter1,
8239 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
8240
8241 if (zero_iter1_bb)
8242 {
8243 /* Some counts[i] vars might be uninitialized if
8244 some loop has zero iterations. But the body shouldn't
8245 be executed in that case, so just avoid uninit warnings. */
8246 for (i = first_zero_iter1;
8247 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8248 if (SSA_VAR_P (counts[i]))
8249 TREE_NO_WARNING (counts[i]) = 1;
8250 gsi_prev (&gsi);
8251 e = split_block (entry_bb, gsi_stmt (gsi));
8252 entry_bb = e->dest;
8253 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8254 gsi = gsi_last_bb (entry_bb);
8255 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8256 get_immediate_dominator (CDI_DOMINATORS,
8257 zero_iter1_bb));
8258 }
8259 if (zero_iter2_bb)
8260 {
8261 /* Some counts[i] vars might be uninitialized if
8262 some loop has zero iterations. But the body shouldn't
8263 be executed in that case, so just avoid uninit warnings. */
8264 for (i = first_zero_iter2; i < fd->ordered; i++)
8265 if (SSA_VAR_P (counts[i]))
8266 TREE_NO_WARNING (counts[i]) = 1;
8267 if (zero_iter1_bb)
8268 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8269 else
8270 {
8271 gsi_prev (&gsi);
8272 e = split_block (entry_bb, gsi_stmt (gsi));
8273 entry_bb = e->dest;
8274 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8275 gsi = gsi_last_bb (entry_bb);
8276 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8277 get_immediate_dominator
8278 (CDI_DOMINATORS, zero_iter2_bb));
8279 }
8280 }
8281 if (fd->collapse == 1)
8282 {
8283 counts[0] = fd->loop.n2;
8284 fd->loop = fd->loops[0];
8285 }
8286 }
8287
8288 type = TREE_TYPE (fd->loop.v);
8289 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8290 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8291 TREE_ADDRESSABLE (istart0) = 1;
8292 TREE_ADDRESSABLE (iend0) = 1;
8293
8294 /* See if we need to bias by LLONG_MIN. */
8295 if (fd->iter_type == long_long_unsigned_type_node
8296 && TREE_CODE (type) == INTEGER_TYPE
8297 && !TYPE_UNSIGNED (type)
8298 && fd->ordered == 0)
8299 {
8300 tree n1, n2;
8301
8302 if (fd->loop.cond_code == LT_EXPR)
8303 {
8304 n1 = fd->loop.n1;
8305 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8306 }
8307 else
8308 {
8309 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8310 n2 = fd->loop.n1;
8311 }
8312 if (TREE_CODE (n1) != INTEGER_CST
8313 || TREE_CODE (n2) != INTEGER_CST
8314 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8315 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
8316 }
8317
8318 gimple_stmt_iterator gsif = gsi;
8319 gsi_prev (&gsif);
8320
8321 tree arr = NULL_TREE;
8322 if (in_combined_parallel)
8323 {
8324 gcc_assert (fd->ordered == 0);
8325 /* In a combined parallel loop, emit a call to
8326 GOMP_loop_foo_next. */
8327 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8328 build_fold_addr_expr (istart0),
8329 build_fold_addr_expr (iend0));
8330 }
8331 else
8332 {
8333 tree t0, t1, t2, t3, t4;
8334 /* If this is not a combined parallel loop, emit a call to
8335 GOMP_loop_foo_start in ENTRY_BB. */
8336 t4 = build_fold_addr_expr (iend0);
8337 t3 = build_fold_addr_expr (istart0);
8338 if (fd->ordered)
8339 {
8340 t0 = build_int_cst (unsigned_type_node,
8341 fd->ordered - fd->collapse + 1);
8342 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8343 fd->ordered
8344 - fd->collapse + 1),
8345 ".omp_counts");
8346 DECL_NAMELESS (arr) = 1;
8347 TREE_ADDRESSABLE (arr) = 1;
8348 TREE_STATIC (arr) = 1;
8349 vec<constructor_elt, va_gc> *v;
8350 vec_alloc (v, fd->ordered - fd->collapse + 1);
8351 int idx;
8352
8353 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8354 {
8355 tree c;
8356 if (idx == 0 && fd->collapse > 1)
8357 c = fd->loop.n2;
8358 else
8359 c = counts[idx + fd->collapse - 1];
8360 tree purpose = size_int (idx);
8361 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8362 if (TREE_CODE (c) != INTEGER_CST)
8363 TREE_STATIC (arr) = 0;
8364 }
8365
8366 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8367 if (!TREE_STATIC (arr))
8368 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8369 void_type_node, arr),
8370 true, NULL_TREE, true, GSI_SAME_STMT);
8371 t1 = build_fold_addr_expr (arr);
8372 t2 = NULL_TREE;
8373 }
8374 else
8375 {
8376 t2 = fold_convert (fd->iter_type, fd->loop.step);
8377 t1 = fd->loop.n2;
8378 t0 = fd->loop.n1;
8379 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8380 {
8381 tree innerc
8382 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8383 OMP_CLAUSE__LOOPTEMP_);
8384 gcc_assert (innerc);
8385 t0 = OMP_CLAUSE_DECL (innerc);
8386 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8387 OMP_CLAUSE__LOOPTEMP_);
8388 gcc_assert (innerc);
8389 t1 = OMP_CLAUSE_DECL (innerc);
8390 }
8391 if (POINTER_TYPE_P (TREE_TYPE (t0))
8392 && TYPE_PRECISION (TREE_TYPE (t0))
8393 != TYPE_PRECISION (fd->iter_type))
8394 {
8395 /* Avoid casting pointers to integer of a different size. */
8396 tree itype = signed_type_for (type);
8397 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8398 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8399 }
8400 else
8401 {
8402 t1 = fold_convert (fd->iter_type, t1);
8403 t0 = fold_convert (fd->iter_type, t0);
8404 }
8405 if (bias)
8406 {
8407 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8408 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8409 }
8410 }
8411 if (fd->iter_type == long_integer_type_node || fd->ordered)
8412 {
8413 if (fd->chunk_size)
8414 {
8415 t = fold_convert (fd->iter_type, fd->chunk_size);
8416 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8417 if (fd->ordered)
8418 t = build_call_expr (builtin_decl_explicit (start_fn),
8419 5, t0, t1, t, t3, t4);
8420 else
8421 t = build_call_expr (builtin_decl_explicit (start_fn),
8422 6, t0, t1, t2, t, t3, t4);
8423 }
8424 else if (fd->ordered)
8425 t = build_call_expr (builtin_decl_explicit (start_fn),
8426 4, t0, t1, t3, t4);
8427 else
8428 t = build_call_expr (builtin_decl_explicit (start_fn),
8429 5, t0, t1, t2, t3, t4);
8430 }
8431 else
8432 {
8433 tree t5;
8434 tree c_bool_type;
8435 tree bfn_decl;
8436
8437 /* The GOMP_loop_ull_*start functions have additional boolean
8438 argument, true for < loops and false for > loops.
8439 In Fortran, the C bool type can be different from
8440 boolean_type_node. */
8441 bfn_decl = builtin_decl_explicit (start_fn);
8442 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
8443 t5 = build_int_cst (c_bool_type,
8444 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8445 if (fd->chunk_size)
8446 {
8447 tree bfn_decl = builtin_decl_explicit (start_fn);
8448 t = fold_convert (fd->iter_type, fd->chunk_size);
8449 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8450 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
8451 }
8452 else
8453 t = build_call_expr (builtin_decl_explicit (start_fn),
8454 6, t5, t0, t1, t2, t3, t4);
8455 }
8456 }
8457 if (TREE_TYPE (t) != boolean_type_node)
8458 t = fold_build2 (NE_EXPR, boolean_type_node,
8459 t, build_int_cst (TREE_TYPE (t), 0));
8460 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8461 true, GSI_SAME_STMT);
8462 if (arr && !TREE_STATIC (arr))
8463 {
8464 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8465 TREE_THIS_VOLATILE (clobber) = 1;
8466 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8467 GSI_SAME_STMT);
8468 }
8469 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8470
8471 /* Remove the GIMPLE_OMP_FOR statement. */
8472 gsi_remove (&gsi, true);
8473
8474 if (gsi_end_p (gsif))
8475 gsif = gsi_after_labels (gsi_bb (gsif));
8476 gsi_next (&gsif);
8477
8478 /* Iteration setup for sequential loop goes in L0_BB. */
8479 tree startvar = fd->loop.v;
8480 tree endvar = NULL_TREE;
8481
8482 if (gimple_omp_for_combined_p (fd->for_stmt))
8483 {
8484 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8485 && gimple_omp_for_kind (inner_stmt)
8486 == GF_OMP_FOR_KIND_SIMD);
8487 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8488 OMP_CLAUSE__LOOPTEMP_);
8489 gcc_assert (innerc);
8490 startvar = OMP_CLAUSE_DECL (innerc);
8491 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8492 OMP_CLAUSE__LOOPTEMP_);
8493 gcc_assert (innerc);
8494 endvar = OMP_CLAUSE_DECL (innerc);
8495 }
8496
8497 gsi = gsi_start_bb (l0_bb);
8498 t = istart0;
8499 if (fd->ordered && fd->collapse == 1)
8500 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8501 fold_convert (fd->iter_type, fd->loop.step));
8502 else if (bias)
8503 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8504 if (fd->ordered && fd->collapse == 1)
8505 {
8506 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8507 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8508 fd->loop.n1, fold_convert (sizetype, t));
8509 else
8510 {
8511 t = fold_convert (TREE_TYPE (startvar), t);
8512 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8513 fd->loop.n1, t);
8514 }
8515 }
8516 else
8517 {
8518 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8519 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8520 t = fold_convert (TREE_TYPE (startvar), t);
8521 }
8522 t = force_gimple_operand_gsi (&gsi, t,
8523 DECL_P (startvar)
8524 && TREE_ADDRESSABLE (startvar),
8525 NULL_TREE, false, GSI_CONTINUE_LINKING);
8526 assign_stmt = gimple_build_assign (startvar, t);
8527 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8528
8529 t = iend0;
8530 if (fd->ordered && fd->collapse == 1)
8531 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8532 fold_convert (fd->iter_type, fd->loop.step));
8533 else if (bias)
8534 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8535 if (fd->ordered && fd->collapse == 1)
8536 {
8537 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8538 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8539 fd->loop.n1, fold_convert (sizetype, t));
8540 else
8541 {
8542 t = fold_convert (TREE_TYPE (startvar), t);
8543 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8544 fd->loop.n1, t);
8545 }
8546 }
8547 else
8548 {
8549 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8550 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8551 t = fold_convert (TREE_TYPE (startvar), t);
8552 }
8553 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8554 false, GSI_CONTINUE_LINKING);
8555 if (endvar)
8556 {
8557 assign_stmt = gimple_build_assign (endvar, iend);
8558 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8559 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
8560 assign_stmt = gimple_build_assign (fd->loop.v, iend);
8561 else
8562 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
8563 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8564 }
8565 /* Handle linear clause adjustments. */
8566 tree itercnt = NULL_TREE;
8567 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8568 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8569 c; c = OMP_CLAUSE_CHAIN (c))
8570 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8571 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8572 {
8573 tree d = OMP_CLAUSE_DECL (c);
8574 bool is_ref = is_reference (d);
8575 tree t = d, a, dest;
8576 if (is_ref)
8577 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8578 tree type = TREE_TYPE (t);
8579 if (POINTER_TYPE_P (type))
8580 type = sizetype;
8581 dest = unshare_expr (t);
8582 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8583 expand_omp_build_assign (&gsif, v, t);
8584 if (itercnt == NULL_TREE)
8585 {
8586 itercnt = startvar;
8587 tree n1 = fd->loop.n1;
8588 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8589 {
8590 itercnt
8591 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8592 itercnt);
8593 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8594 }
8595 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8596 itercnt, n1);
8597 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8598 itercnt, fd->loop.step);
8599 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8600 NULL_TREE, false,
8601 GSI_CONTINUE_LINKING);
8602 }
8603 a = fold_build2 (MULT_EXPR, type,
8604 fold_convert (type, itercnt),
8605 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8606 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8607 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8608 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8609 false, GSI_CONTINUE_LINKING);
8610 assign_stmt = gimple_build_assign (dest, t);
8611 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8612 }
8613 if (fd->collapse > 1)
8614 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8615
8616 if (fd->ordered)
8617 {
8618 /* Until now, counts array contained number of iterations or
8619 variable containing it for ith loop. From now on, we need
8620 those counts only for collapsed loops, and only for the 2nd
8621 till the last collapsed one. Move those one element earlier,
8622 we'll use counts[fd->collapse - 1] for the first source/sink
8623 iteration counter and so on and counts[fd->ordered]
8624 as the array holding the current counter values for
8625 depend(source). */
8626 if (fd->collapse > 1)
8627 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8628 if (broken_loop)
8629 {
8630 int i;
8631 for (i = fd->collapse; i < fd->ordered; i++)
8632 {
8633 tree type = TREE_TYPE (fd->loops[i].v);
8634 tree this_cond
8635 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8636 fold_convert (type, fd->loops[i].n1),
8637 fold_convert (type, fd->loops[i].n2));
8638 if (!integer_onep (this_cond))
8639 break;
8640 }
8641 if (i < fd->ordered)
8642 {
8643 cont_bb
8644 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8645 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8646 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8647 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8648 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8649 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8650 make_edge (cont_bb, l1_bb, 0);
8651 l2_bb = create_empty_bb (cont_bb);
8652 broken_loop = false;
8653 }
8654 }
8655 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8656 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8657 ordered_lastprivate);
8658 if (counts[fd->collapse - 1])
8659 {
8660 gcc_assert (fd->collapse == 1);
8661 gsi = gsi_last_bb (l0_bb);
8662 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8663 istart0, true);
8664 gsi = gsi_last_bb (cont_bb);
8665 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8666 build_int_cst (fd->iter_type, 1));
8667 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8668 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8669 size_zero_node, NULL_TREE, NULL_TREE);
8670 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8671 t = counts[fd->collapse - 1];
8672 }
8673 else if (fd->collapse > 1)
8674 t = fd->loop.v;
8675 else
8676 {
8677 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8678 fd->loops[0].v, fd->loops[0].n1);
8679 t = fold_convert (fd->iter_type, t);
8680 }
8681 gsi = gsi_last_bb (l0_bb);
8682 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8683 size_zero_node, NULL_TREE, NULL_TREE);
8684 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8685 false, GSI_CONTINUE_LINKING);
8686 expand_omp_build_assign (&gsi, aref, t, true);
8687 }
8688
8689 if (!broken_loop)
8690 {
8691 /* Code to control the increment and predicate for the sequential
8692 loop goes in the CONT_BB. */
8693 gsi = gsi_last_bb (cont_bb);
8694 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8695 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8696 vmain = gimple_omp_continue_control_use (cont_stmt);
8697 vback = gimple_omp_continue_control_def (cont_stmt);
8698
8699 if (!gimple_omp_for_combined_p (fd->for_stmt))
8700 {
8701 if (POINTER_TYPE_P (type))
8702 t = fold_build_pointer_plus (vmain, fd->loop.step);
8703 else
8704 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8705 t = force_gimple_operand_gsi (&gsi, t,
8706 DECL_P (vback)
8707 && TREE_ADDRESSABLE (vback),
8708 NULL_TREE, true, GSI_SAME_STMT);
8709 assign_stmt = gimple_build_assign (vback, t);
8710 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8711
8712 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8713 {
8714 if (fd->collapse > 1)
8715 t = fd->loop.v;
8716 else
8717 {
8718 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8719 fd->loops[0].v, fd->loops[0].n1);
8720 t = fold_convert (fd->iter_type, t);
8721 }
8722 tree aref = build4 (ARRAY_REF, fd->iter_type,
8723 counts[fd->ordered], size_zero_node,
8724 NULL_TREE, NULL_TREE);
8725 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8726 true, GSI_SAME_STMT);
8727 expand_omp_build_assign (&gsi, aref, t);
8728 }
8729
8730 t = build2 (fd->loop.cond_code, boolean_type_node,
8731 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
8732 iend);
8733 gcond *cond_stmt = gimple_build_cond_empty (t);
8734 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
8735 }
8736
8737 /* Remove GIMPLE_OMP_CONTINUE. */
8738 gsi_remove (&gsi, true);
8739
8740 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
8741 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
8742
8743 /* Emit code to get the next parallel iteration in L2_BB. */
8744 gsi = gsi_start_bb (l2_bb);
8745
8746 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8747 build_fold_addr_expr (istart0),
8748 build_fold_addr_expr (iend0));
8749 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8750 false, GSI_CONTINUE_LINKING);
8751 if (TREE_TYPE (t) != boolean_type_node)
8752 t = fold_build2 (NE_EXPR, boolean_type_node,
8753 t, build_int_cst (TREE_TYPE (t), 0));
8754 gcond *cond_stmt = gimple_build_cond_empty (t);
8755 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
8756 }
8757
8758 /* Add the loop cleanup function. */
8759 gsi = gsi_last_bb (exit_bb);
8760 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
8761 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
8762 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8763 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
8764 else
8765 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
8766 gcall *call_stmt = gimple_build_call (t, 0);
8767 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
8768 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
8769 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
8770 if (fd->ordered)
8771 {
8772 tree arr = counts[fd->ordered];
8773 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8774 TREE_THIS_VOLATILE (clobber) = 1;
8775 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
8776 GSI_SAME_STMT);
8777 }
8778 gsi_remove (&gsi, true);
8779
8780 /* Connect the new blocks. */
8781 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
8782 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
8783
8784 if (!broken_loop)
8785 {
8786 gimple_seq phis;
8787
8788 e = find_edge (cont_bb, l3_bb);
8789 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
8790
8791 phis = phi_nodes (l3_bb);
8792 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
8793 {
8794 gimple *phi = gsi_stmt (gsi);
8795 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
8796 PHI_ARG_DEF_FROM_EDGE (phi, e));
8797 }
8798 remove_edge (e);
8799
8800 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
8801 e = find_edge (cont_bb, l1_bb);
8802 if (e == NULL)
8803 {
8804 e = BRANCH_EDGE (cont_bb);
8805 gcc_assert (single_succ (e->dest) == l1_bb);
8806 }
8807 if (gimple_omp_for_combined_p (fd->for_stmt))
8808 {
8809 remove_edge (e);
8810 e = NULL;
8811 }
8812 else if (fd->collapse > 1)
8813 {
8814 remove_edge (e);
8815 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
8816 }
8817 else
8818 e->flags = EDGE_TRUE_VALUE;
8819 if (e)
8820 {
8821 e->probability = REG_BR_PROB_BASE * 7 / 8;
8822 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
8823 }
8824 else
8825 {
8826 e = find_edge (cont_bb, l2_bb);
8827 e->flags = EDGE_FALLTHRU;
8828 }
8829 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
8830
8831 if (gimple_in_ssa_p (cfun))
8832 {
8833 /* Add phis to the outer loop that connect to the phis in the inner,
8834 original loop, and move the loop entry value of the inner phi to
8835 the loop entry value of the outer phi. */
8836 gphi_iterator psi;
8837 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
8838 {
8839 source_location locus;
8840 gphi *nphi;
8841 gphi *exit_phi = psi.phi ();
8842
8843 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
8844 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
8845
8846 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
8847 edge latch_to_l1 = find_edge (latch, l1_bb);
8848 gphi *inner_phi
8849 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
8850
8851 tree t = gimple_phi_result (exit_phi);
8852 tree new_res = copy_ssa_name (t, NULL);
8853 nphi = create_phi_node (new_res, l0_bb);
8854
8855 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
8856 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
8857 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
8858 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
8859 add_phi_arg (nphi, t, entry_to_l0, locus);
8860
8861 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
8862 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
8863
8864 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
8865 };
8866 }
8867
8868 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
8869 recompute_dominator (CDI_DOMINATORS, l2_bb));
8870 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
8871 recompute_dominator (CDI_DOMINATORS, l3_bb));
8872 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
8873 recompute_dominator (CDI_DOMINATORS, l0_bb));
8874 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
8875 recompute_dominator (CDI_DOMINATORS, l1_bb));
8876
8877 /* We enter expand_omp_for_generic with a loop. This original loop may
8878 have its own loop struct, or it may be part of an outer loop struct
8879 (which may be the fake loop). */
8880 struct loop *outer_loop = entry_bb->loop_father;
8881 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
8882
8883 add_bb_to_loop (l2_bb, outer_loop);
8884
8885 /* We've added a new loop around the original loop. Allocate the
8886 corresponding loop struct. */
8887 struct loop *new_loop = alloc_loop ();
8888 new_loop->header = l0_bb;
8889 new_loop->latch = l2_bb;
8890 add_loop (new_loop, outer_loop);
8891
8892 /* Allocate a loop structure for the original loop unless we already
8893 had one. */
8894 if (!orig_loop_has_loop_struct
8895 && !gimple_omp_for_combined_p (fd->for_stmt))
8896 {
8897 struct loop *orig_loop = alloc_loop ();
8898 orig_loop->header = l1_bb;
8899 /* The loop may have multiple latches. */
8900 add_loop (orig_loop, new_loop);
8901 }
8902 }
8903 }
8904
8905
8906 /* A subroutine of expand_omp_for. Generate code for a parallel
8907 loop with static schedule and no specified chunk size. Given
8908 parameters:
8909
8910 for (V = N1; V cond N2; V += STEP) BODY;
8911
8912 where COND is "<" or ">", we generate pseudocode
8913
8914 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
8915 if (cond is <)
8916 adj = STEP - 1;
8917 else
8918 adj = STEP + 1;
8919 if ((__typeof (V)) -1 > 0 && cond is >)
8920 n = -(adj + N2 - N1) / -STEP;
8921 else
8922 n = (adj + N2 - N1) / STEP;
8923 q = n / nthreads;
8924 tt = n % nthreads;
8925 if (threadid < tt) goto L3; else goto L4;
8926 L3:
8927 tt = 0;
8928 q = q + 1;
8929 L4:
8930 s0 = q * threadid + tt;
8931 e0 = s0 + q;
8932 V = s0 * STEP + N1;
8933 if (s0 >= e0) goto L2; else goto L0;
8934 L0:
8935 e = e0 * STEP + N1;
8936 L1:
8937 BODY;
8938 V += STEP;
8939 if (V cond e) goto L1;
8940 L2:
8941 */
8942
8943 static void
8944 expand_omp_for_static_nochunk (struct omp_region *region,
8945 struct omp_for_data *fd,
8946 gimple *inner_stmt)
8947 {
8948 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
8949 tree type, itype, vmain, vback;
8950 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
8951 basic_block body_bb, cont_bb, collapse_bb = NULL;
8952 basic_block fin_bb;
8953 gimple_stmt_iterator gsi;
8954 edge ep;
8955 bool broken_loop = region->cont == NULL;
8956 tree *counts = NULL;
8957 tree n1, n2, step;
8958
8959 itype = type = TREE_TYPE (fd->loop.v);
8960 if (POINTER_TYPE_P (type))
8961 itype = signed_type_for (type);
8962
8963 entry_bb = region->entry;
8964 cont_bb = region->cont;
8965 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8966 fin_bb = BRANCH_EDGE (entry_bb)->dest;
8967 gcc_assert (broken_loop
8968 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
8969 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8970 body_bb = single_succ (seq_start_bb);
8971 if (!broken_loop)
8972 {
8973 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
8974 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
8975 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8976 }
8977 exit_bb = region->exit;
8978
8979 /* Iteration space partitioning goes in ENTRY_BB. */
8980 gsi = gsi_last_bb (entry_bb);
8981 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8982
8983 if (fd->collapse > 1)
8984 {
8985 int first_zero_iter = -1, dummy = -1;
8986 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
8987
8988 counts = XALLOCAVEC (tree, fd->collapse);
8989 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8990 fin_bb, first_zero_iter,
8991 dummy_bb, dummy, l2_dom_bb);
8992 t = NULL_TREE;
8993 }
8994 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
8995 t = integer_one_node;
8996 else
8997 t = fold_binary (fd->loop.cond_code, boolean_type_node,
8998 fold_convert (type, fd->loop.n1),
8999 fold_convert (type, fd->loop.n2));
9000 if (fd->collapse == 1
9001 && TYPE_UNSIGNED (type)
9002 && (t == NULL_TREE || !integer_onep (t)))
9003 {
9004 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9005 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9006 true, GSI_SAME_STMT);
9007 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9008 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9009 true, GSI_SAME_STMT);
9010 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9011 NULL_TREE, NULL_TREE);
9012 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9013 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9014 expand_omp_regimplify_p, NULL, NULL)
9015 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9016 expand_omp_regimplify_p, NULL, NULL))
9017 {
9018 gsi = gsi_for_stmt (cond_stmt);
9019 gimple_regimplify_operands (cond_stmt, &gsi);
9020 }
9021 ep = split_block (entry_bb, cond_stmt);
9022 ep->flags = EDGE_TRUE_VALUE;
9023 entry_bb = ep->dest;
9024 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9025 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9026 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9027 if (gimple_in_ssa_p (cfun))
9028 {
9029 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
9030 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9031 !gsi_end_p (gpi); gsi_next (&gpi))
9032 {
9033 gphi *phi = gpi.phi ();
9034 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9035 ep, UNKNOWN_LOCATION);
9036 }
9037 }
9038 gsi = gsi_last_bb (entry_bb);
9039 }
9040
9041 switch (gimple_omp_for_kind (fd->for_stmt))
9042 {
9043 case GF_OMP_FOR_KIND_FOR:
9044 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9045 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9046 break;
9047 case GF_OMP_FOR_KIND_DISTRIBUTE:
9048 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9049 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9050 break;
9051 default:
9052 gcc_unreachable ();
9053 }
9054 nthreads = build_call_expr (nthreads, 0);
9055 nthreads = fold_convert (itype, nthreads);
9056 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9057 true, GSI_SAME_STMT);
9058 threadid = build_call_expr (threadid, 0);
9059 threadid = fold_convert (itype, threadid);
9060 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9061 true, GSI_SAME_STMT);
9062
9063 n1 = fd->loop.n1;
9064 n2 = fd->loop.n2;
9065 step = fd->loop.step;
9066 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9067 {
9068 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9069 OMP_CLAUSE__LOOPTEMP_);
9070 gcc_assert (innerc);
9071 n1 = OMP_CLAUSE_DECL (innerc);
9072 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9073 OMP_CLAUSE__LOOPTEMP_);
9074 gcc_assert (innerc);
9075 n2 = OMP_CLAUSE_DECL (innerc);
9076 }
9077 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9078 true, NULL_TREE, true, GSI_SAME_STMT);
9079 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9080 true, NULL_TREE, true, GSI_SAME_STMT);
9081 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9082 true, NULL_TREE, true, GSI_SAME_STMT);
9083
9084 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9085 t = fold_build2 (PLUS_EXPR, itype, step, t);
9086 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9087 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9088 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9089 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9090 fold_build1 (NEGATE_EXPR, itype, t),
9091 fold_build1 (NEGATE_EXPR, itype, step));
9092 else
9093 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9094 t = fold_convert (itype, t);
9095 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9096
9097 q = create_tmp_reg (itype, "q");
9098 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
9099 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9100 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9101
9102 tt = create_tmp_reg (itype, "tt");
9103 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9104 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9105 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
9106
9107 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
9108 gcond *cond_stmt = gimple_build_cond_empty (t);
9109 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9110
9111 second_bb = split_block (entry_bb, cond_stmt)->dest;
9112 gsi = gsi_last_bb (second_bb);
9113 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9114
9115 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9116 GSI_SAME_STMT);
9117 gassign *assign_stmt
9118 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
9119 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9120
9121 third_bb = split_block (second_bb, assign_stmt)->dest;
9122 gsi = gsi_last_bb (third_bb);
9123 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9124
9125 t = build2 (MULT_EXPR, itype, q, threadid);
9126 t = build2 (PLUS_EXPR, itype, t, tt);
9127 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9128
9129 t = fold_build2 (PLUS_EXPR, itype, s0, q);
9130 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9131
9132 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
9133 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9134
9135 /* Remove the GIMPLE_OMP_FOR statement. */
9136 gsi_remove (&gsi, true);
9137
9138 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9139 gsi = gsi_start_bb (seq_start_bb);
9140
9141 tree startvar = fd->loop.v;
9142 tree endvar = NULL_TREE;
9143
9144 if (gimple_omp_for_combined_p (fd->for_stmt))
9145 {
9146 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9147 ? gimple_omp_parallel_clauses (inner_stmt)
9148 : gimple_omp_for_clauses (inner_stmt);
9149 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9150 gcc_assert (innerc);
9151 startvar = OMP_CLAUSE_DECL (innerc);
9152 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9153 OMP_CLAUSE__LOOPTEMP_);
9154 gcc_assert (innerc);
9155 endvar = OMP_CLAUSE_DECL (innerc);
9156 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9157 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9158 {
9159 int i;
9160 for (i = 1; i < fd->collapse; i++)
9161 {
9162 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9163 OMP_CLAUSE__LOOPTEMP_);
9164 gcc_assert (innerc);
9165 }
9166 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9167 OMP_CLAUSE__LOOPTEMP_);
9168 if (innerc)
9169 {
9170 /* If needed (distribute parallel for with lastprivate),
9171 propagate down the total number of iterations. */
9172 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9173 fd->loop.n2);
9174 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9175 GSI_CONTINUE_LINKING);
9176 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9177 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9178 }
9179 }
9180 }
9181 t = fold_convert (itype, s0);
9182 t = fold_build2 (MULT_EXPR, itype, t, step);
9183 if (POINTER_TYPE_P (type))
9184 t = fold_build_pointer_plus (n1, t);
9185 else
9186 t = fold_build2 (PLUS_EXPR, type, t, n1);
9187 t = fold_convert (TREE_TYPE (startvar), t);
9188 t = force_gimple_operand_gsi (&gsi, t,
9189 DECL_P (startvar)
9190 && TREE_ADDRESSABLE (startvar),
9191 NULL_TREE, false, GSI_CONTINUE_LINKING);
9192 assign_stmt = gimple_build_assign (startvar, t);
9193 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9194
9195 t = fold_convert (itype, e0);
9196 t = fold_build2 (MULT_EXPR, itype, t, step);
9197 if (POINTER_TYPE_P (type))
9198 t = fold_build_pointer_plus (n1, t);
9199 else
9200 t = fold_build2 (PLUS_EXPR, type, t, n1);
9201 t = fold_convert (TREE_TYPE (startvar), t);
9202 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9203 false, GSI_CONTINUE_LINKING);
9204 if (endvar)
9205 {
9206 assign_stmt = gimple_build_assign (endvar, e);
9207 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9208 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9209 assign_stmt = gimple_build_assign (fd->loop.v, e);
9210 else
9211 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9212 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9213 }
9214 /* Handle linear clause adjustments. */
9215 tree itercnt = NULL_TREE;
9216 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9217 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9218 c; c = OMP_CLAUSE_CHAIN (c))
9219 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9220 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9221 {
9222 tree d = OMP_CLAUSE_DECL (c);
9223 bool is_ref = is_reference (d);
9224 tree t = d, a, dest;
9225 if (is_ref)
9226 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9227 if (itercnt == NULL_TREE)
9228 {
9229 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9230 {
9231 itercnt = fold_build2 (MINUS_EXPR, itype,
9232 fold_convert (itype, n1),
9233 fold_convert (itype, fd->loop.n1));
9234 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9235 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9236 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9237 NULL_TREE, false,
9238 GSI_CONTINUE_LINKING);
9239 }
9240 else
9241 itercnt = s0;
9242 }
9243 tree type = TREE_TYPE (t);
9244 if (POINTER_TYPE_P (type))
9245 type = sizetype;
9246 a = fold_build2 (MULT_EXPR, type,
9247 fold_convert (type, itercnt),
9248 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9249 dest = unshare_expr (t);
9250 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9251 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9252 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9253 false, GSI_CONTINUE_LINKING);
9254 assign_stmt = gimple_build_assign (dest, t);
9255 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9256 }
9257 if (fd->collapse > 1)
9258 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9259
9260 if (!broken_loop)
9261 {
9262 /* The code controlling the sequential loop replaces the
9263 GIMPLE_OMP_CONTINUE. */
9264 gsi = gsi_last_bb (cont_bb);
9265 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9266 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9267 vmain = gimple_omp_continue_control_use (cont_stmt);
9268 vback = gimple_omp_continue_control_def (cont_stmt);
9269
9270 if (!gimple_omp_for_combined_p (fd->for_stmt))
9271 {
9272 if (POINTER_TYPE_P (type))
9273 t = fold_build_pointer_plus (vmain, step);
9274 else
9275 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9276 t = force_gimple_operand_gsi (&gsi, t,
9277 DECL_P (vback)
9278 && TREE_ADDRESSABLE (vback),
9279 NULL_TREE, true, GSI_SAME_STMT);
9280 assign_stmt = gimple_build_assign (vback, t);
9281 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9282
9283 t = build2 (fd->loop.cond_code, boolean_type_node,
9284 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9285 ? t : vback, e);
9286 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9287 }
9288
9289 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9290 gsi_remove (&gsi, true);
9291
9292 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9293 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9294 }
9295
9296 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9297 gsi = gsi_last_bb (exit_bb);
9298 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9299 {
9300 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9301 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9302 }
9303 gsi_remove (&gsi, true);
9304
9305 /* Connect all the blocks. */
9306 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9307 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9308 ep = find_edge (entry_bb, second_bb);
9309 ep->flags = EDGE_TRUE_VALUE;
9310 ep->probability = REG_BR_PROB_BASE / 4;
9311 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9312 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
9313
9314 if (!broken_loop)
9315 {
9316 ep = find_edge (cont_bb, body_bb);
9317 if (ep == NULL)
9318 {
9319 ep = BRANCH_EDGE (cont_bb);
9320 gcc_assert (single_succ (ep->dest) == body_bb);
9321 }
9322 if (gimple_omp_for_combined_p (fd->for_stmt))
9323 {
9324 remove_edge (ep);
9325 ep = NULL;
9326 }
9327 else if (fd->collapse > 1)
9328 {
9329 remove_edge (ep);
9330 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9331 }
9332 else
9333 ep->flags = EDGE_TRUE_VALUE;
9334 find_edge (cont_bb, fin_bb)->flags
9335 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9336 }
9337
9338 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9339 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9340 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
9341
9342 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9343 recompute_dominator (CDI_DOMINATORS, body_bb));
9344 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9345 recompute_dominator (CDI_DOMINATORS, fin_bb));
9346
9347 struct loop *loop = body_bb->loop_father;
9348 if (loop != entry_bb->loop_father)
9349 {
9350 gcc_assert (loop->header == body_bb);
9351 gcc_assert (broken_loop
9352 || loop->latch == region->cont
9353 || single_pred (loop->latch) == region->cont);
9354 return;
9355 }
9356
9357 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9358 {
9359 loop = alloc_loop ();
9360 loop->header = body_bb;
9361 if (collapse_bb == NULL)
9362 loop->latch = cont_bb;
9363 add_loop (loop, body_bb->loop_father);
9364 }
9365 }
9366
9367 /* Return phi in E->DEST with ARG on edge E. */
9368
9369 static gphi *
9370 find_phi_with_arg_on_edge (tree arg, edge e)
9371 {
9372 basic_block bb = e->dest;
9373
9374 for (gphi_iterator gpi = gsi_start_phis (bb);
9375 !gsi_end_p (gpi);
9376 gsi_next (&gpi))
9377 {
9378 gphi *phi = gpi.phi ();
9379 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9380 return phi;
9381 }
9382
9383 return NULL;
9384 }
9385
9386 /* A subroutine of expand_omp_for. Generate code for a parallel
9387 loop with static schedule and a specified chunk size. Given
9388 parameters:
9389
9390 for (V = N1; V cond N2; V += STEP) BODY;
9391
9392 where COND is "<" or ">", we generate pseudocode
9393
9394 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9395 if (cond is <)
9396 adj = STEP - 1;
9397 else
9398 adj = STEP + 1;
9399 if ((__typeof (V)) -1 > 0 && cond is >)
9400 n = -(adj + N2 - N1) / -STEP;
9401 else
9402 n = (adj + N2 - N1) / STEP;
9403 trip = 0;
9404 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9405 here so that V is defined
9406 if the loop is not entered
9407 L0:
9408 s0 = (trip * nthreads + threadid) * CHUNK;
9409 e0 = min(s0 + CHUNK, n);
9410 if (s0 < n) goto L1; else goto L4;
9411 L1:
9412 V = s0 * STEP + N1;
9413 e = e0 * STEP + N1;
9414 L2:
9415 BODY;
9416 V += STEP;
9417 if (V cond e) goto L2; else goto L3;
9418 L3:
9419 trip += 1;
9420 goto L0;
9421 L4:
9422 */
9423
9424 static void
9425 expand_omp_for_static_chunk (struct omp_region *region,
9426 struct omp_for_data *fd, gimple *inner_stmt)
9427 {
9428 tree n, s0, e0, e, t;
9429 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
9430 tree type, itype, vmain, vback, vextra;
9431 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
9432 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
9433 gimple_stmt_iterator gsi;
9434 edge se;
9435 bool broken_loop = region->cont == NULL;
9436 tree *counts = NULL;
9437 tree n1, n2, step;
9438
9439 itype = type = TREE_TYPE (fd->loop.v);
9440 if (POINTER_TYPE_P (type))
9441 itype = signed_type_for (type);
9442
9443 entry_bb = region->entry;
9444 se = split_block (entry_bb, last_stmt (entry_bb));
9445 entry_bb = se->src;
9446 iter_part_bb = se->dest;
9447 cont_bb = region->cont;
9448 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
9449 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9450 gcc_assert (broken_loop
9451 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
9452 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9453 body_bb = single_succ (seq_start_bb);
9454 if (!broken_loop)
9455 {
9456 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9457 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9458 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9459 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9460 }
9461 exit_bb = region->exit;
9462
9463 /* Trip and adjustment setup goes in ENTRY_BB. */
9464 gsi = gsi_last_bb (entry_bb);
9465 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9466
9467 if (fd->collapse > 1)
9468 {
9469 int first_zero_iter = -1, dummy = -1;
9470 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9471
9472 counts = XALLOCAVEC (tree, fd->collapse);
9473 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9474 fin_bb, first_zero_iter,
9475 dummy_bb, dummy, l2_dom_bb);
9476 t = NULL_TREE;
9477 }
9478 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9479 t = integer_one_node;
9480 else
9481 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9482 fold_convert (type, fd->loop.n1),
9483 fold_convert (type, fd->loop.n2));
9484 if (fd->collapse == 1
9485 && TYPE_UNSIGNED (type)
9486 && (t == NULL_TREE || !integer_onep (t)))
9487 {
9488 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9489 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9490 true, GSI_SAME_STMT);
9491 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9492 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9493 true, GSI_SAME_STMT);
9494 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9495 NULL_TREE, NULL_TREE);
9496 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9497 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9498 expand_omp_regimplify_p, NULL, NULL)
9499 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9500 expand_omp_regimplify_p, NULL, NULL))
9501 {
9502 gsi = gsi_for_stmt (cond_stmt);
9503 gimple_regimplify_operands (cond_stmt, &gsi);
9504 }
9505 se = split_block (entry_bb, cond_stmt);
9506 se->flags = EDGE_TRUE_VALUE;
9507 entry_bb = se->dest;
9508 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9509 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9510 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9511 if (gimple_in_ssa_p (cfun))
9512 {
9513 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
9514 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9515 !gsi_end_p (gpi); gsi_next (&gpi))
9516 {
9517 gphi *phi = gpi.phi ();
9518 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9519 se, UNKNOWN_LOCATION);
9520 }
9521 }
9522 gsi = gsi_last_bb (entry_bb);
9523 }
9524
9525 switch (gimple_omp_for_kind (fd->for_stmt))
9526 {
9527 case GF_OMP_FOR_KIND_FOR:
9528 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9529 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9530 break;
9531 case GF_OMP_FOR_KIND_DISTRIBUTE:
9532 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9533 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9534 break;
9535 default:
9536 gcc_unreachable ();
9537 }
9538 nthreads = build_call_expr (nthreads, 0);
9539 nthreads = fold_convert (itype, nthreads);
9540 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9541 true, GSI_SAME_STMT);
9542 threadid = build_call_expr (threadid, 0);
9543 threadid = fold_convert (itype, threadid);
9544 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9545 true, GSI_SAME_STMT);
9546
9547 n1 = fd->loop.n1;
9548 n2 = fd->loop.n2;
9549 step = fd->loop.step;
9550 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9551 {
9552 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9553 OMP_CLAUSE__LOOPTEMP_);
9554 gcc_assert (innerc);
9555 n1 = OMP_CLAUSE_DECL (innerc);
9556 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9557 OMP_CLAUSE__LOOPTEMP_);
9558 gcc_assert (innerc);
9559 n2 = OMP_CLAUSE_DECL (innerc);
9560 }
9561 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9562 true, NULL_TREE, true, GSI_SAME_STMT);
9563 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9564 true, NULL_TREE, true, GSI_SAME_STMT);
9565 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9566 true, NULL_TREE, true, GSI_SAME_STMT);
9567 tree chunk_size = fold_convert (itype, fd->chunk_size);
9568 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9569 chunk_size
9570 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9571 GSI_SAME_STMT);
9572
9573 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9574 t = fold_build2 (PLUS_EXPR, itype, step, t);
9575 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9576 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9577 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9578 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9579 fold_build1 (NEGATE_EXPR, itype, t),
9580 fold_build1 (NEGATE_EXPR, itype, step));
9581 else
9582 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9583 t = fold_convert (itype, t);
9584 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9585 true, GSI_SAME_STMT);
9586
9587 trip_var = create_tmp_reg (itype, ".trip");
9588 if (gimple_in_ssa_p (cfun))
9589 {
9590 trip_init = make_ssa_name (trip_var);
9591 trip_main = make_ssa_name (trip_var);
9592 trip_back = make_ssa_name (trip_var);
9593 }
9594 else
9595 {
9596 trip_init = trip_var;
9597 trip_main = trip_var;
9598 trip_back = trip_var;
9599 }
9600
9601 gassign *assign_stmt
9602 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9603 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9604
9605 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
9606 t = fold_build2 (MULT_EXPR, itype, t, step);
9607 if (POINTER_TYPE_P (type))
9608 t = fold_build_pointer_plus (n1, t);
9609 else
9610 t = fold_build2 (PLUS_EXPR, type, t, n1);
9611 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9612 true, GSI_SAME_STMT);
9613
9614 /* Remove the GIMPLE_OMP_FOR. */
9615 gsi_remove (&gsi, true);
9616
9617 gimple_stmt_iterator gsif = gsi;
9618
9619 /* Iteration space partitioning goes in ITER_PART_BB. */
9620 gsi = gsi_last_bb (iter_part_bb);
9621
9622 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9623 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
9624 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
9625 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9626 false, GSI_CONTINUE_LINKING);
9627
9628 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
9629 t = fold_build2 (MIN_EXPR, itype, t, n);
9630 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9631 false, GSI_CONTINUE_LINKING);
9632
9633 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9634 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9635
9636 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9637 gsi = gsi_start_bb (seq_start_bb);
9638
9639 tree startvar = fd->loop.v;
9640 tree endvar = NULL_TREE;
9641
9642 if (gimple_omp_for_combined_p (fd->for_stmt))
9643 {
9644 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9645 ? gimple_omp_parallel_clauses (inner_stmt)
9646 : gimple_omp_for_clauses (inner_stmt);
9647 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9648 gcc_assert (innerc);
9649 startvar = OMP_CLAUSE_DECL (innerc);
9650 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9651 OMP_CLAUSE__LOOPTEMP_);
9652 gcc_assert (innerc);
9653 endvar = OMP_CLAUSE_DECL (innerc);
9654 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9655 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9656 {
9657 int i;
9658 for (i = 1; i < fd->collapse; i++)
9659 {
9660 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9661 OMP_CLAUSE__LOOPTEMP_);
9662 gcc_assert (innerc);
9663 }
9664 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9665 OMP_CLAUSE__LOOPTEMP_);
9666 if (innerc)
9667 {
9668 /* If needed (distribute parallel for with lastprivate),
9669 propagate down the total number of iterations. */
9670 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9671 fd->loop.n2);
9672 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9673 GSI_CONTINUE_LINKING);
9674 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9675 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9676 }
9677 }
9678 }
9679
9680 t = fold_convert (itype, s0);
9681 t = fold_build2 (MULT_EXPR, itype, t, step);
9682 if (POINTER_TYPE_P (type))
9683 t = fold_build_pointer_plus (n1, t);
9684 else
9685 t = fold_build2 (PLUS_EXPR, type, t, n1);
9686 t = fold_convert (TREE_TYPE (startvar), t);
9687 t = force_gimple_operand_gsi (&gsi, t,
9688 DECL_P (startvar)
9689 && TREE_ADDRESSABLE (startvar),
9690 NULL_TREE, false, GSI_CONTINUE_LINKING);
9691 assign_stmt = gimple_build_assign (startvar, t);
9692 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9693
9694 t = fold_convert (itype, e0);
9695 t = fold_build2 (MULT_EXPR, itype, t, step);
9696 if (POINTER_TYPE_P (type))
9697 t = fold_build_pointer_plus (n1, t);
9698 else
9699 t = fold_build2 (PLUS_EXPR, type, t, n1);
9700 t = fold_convert (TREE_TYPE (startvar), t);
9701 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9702 false, GSI_CONTINUE_LINKING);
9703 if (endvar)
9704 {
9705 assign_stmt = gimple_build_assign (endvar, e);
9706 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9707 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9708 assign_stmt = gimple_build_assign (fd->loop.v, e);
9709 else
9710 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9711 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9712 }
9713 /* Handle linear clause adjustments. */
9714 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9715 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9716 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9717 c; c = OMP_CLAUSE_CHAIN (c))
9718 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9719 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9720 {
9721 tree d = OMP_CLAUSE_DECL (c);
9722 bool is_ref = is_reference (d);
9723 tree t = d, a, dest;
9724 if (is_ref)
9725 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9726 tree type = TREE_TYPE (t);
9727 if (POINTER_TYPE_P (type))
9728 type = sizetype;
9729 dest = unshare_expr (t);
9730 tree v = create_tmp_var (TREE_TYPE (t), NULL);
9731 expand_omp_build_assign (&gsif, v, t);
9732 if (itercnt == NULL_TREE)
9733 {
9734 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9735 {
9736 itercntbias
9737 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
9738 fold_convert (itype, fd->loop.n1));
9739 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
9740 itercntbias, step);
9741 itercntbias
9742 = force_gimple_operand_gsi (&gsif, itercntbias, true,
9743 NULL_TREE, true,
9744 GSI_SAME_STMT);
9745 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
9746 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9747 NULL_TREE, false,
9748 GSI_CONTINUE_LINKING);
9749 }
9750 else
9751 itercnt = s0;
9752 }
9753 a = fold_build2 (MULT_EXPR, type,
9754 fold_convert (type, itercnt),
9755 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9756 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9757 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
9758 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9759 false, GSI_CONTINUE_LINKING);
9760 assign_stmt = gimple_build_assign (dest, t);
9761 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9762 }
9763 if (fd->collapse > 1)
9764 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9765
9766 if (!broken_loop)
9767 {
9768 /* The code controlling the sequential loop goes in CONT_BB,
9769 replacing the GIMPLE_OMP_CONTINUE. */
9770 gsi = gsi_last_bb (cont_bb);
9771 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9772 vmain = gimple_omp_continue_control_use (cont_stmt);
9773 vback = gimple_omp_continue_control_def (cont_stmt);
9774
9775 if (!gimple_omp_for_combined_p (fd->for_stmt))
9776 {
9777 if (POINTER_TYPE_P (type))
9778 t = fold_build_pointer_plus (vmain, step);
9779 else
9780 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9781 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
9782 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9783 true, GSI_SAME_STMT);
9784 assign_stmt = gimple_build_assign (vback, t);
9785 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9786
9787 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
9788 t = build2 (EQ_EXPR, boolean_type_node,
9789 build_int_cst (itype, 0),
9790 build_int_cst (itype, 1));
9791 else
9792 t = build2 (fd->loop.cond_code, boolean_type_node,
9793 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9794 ? t : vback, e);
9795 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9796 }
9797
9798 /* Remove GIMPLE_OMP_CONTINUE. */
9799 gsi_remove (&gsi, true);
9800
9801 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9802 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9803
9804 /* Trip update code goes into TRIP_UPDATE_BB. */
9805 gsi = gsi_start_bb (trip_update_bb);
9806
9807 t = build_int_cst (itype, 1);
9808 t = build2 (PLUS_EXPR, itype, trip_main, t);
9809 assign_stmt = gimple_build_assign (trip_back, t);
9810 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9811 }
9812
9813 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9814 gsi = gsi_last_bb (exit_bb);
9815 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9816 {
9817 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9818 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9819 }
9820 gsi_remove (&gsi, true);
9821
9822 /* Connect the new blocks. */
9823 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
9824 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
9825
9826 if (!broken_loop)
9827 {
9828 se = find_edge (cont_bb, body_bb);
9829 if (se == NULL)
9830 {
9831 se = BRANCH_EDGE (cont_bb);
9832 gcc_assert (single_succ (se->dest) == body_bb);
9833 }
9834 if (gimple_omp_for_combined_p (fd->for_stmt))
9835 {
9836 remove_edge (se);
9837 se = NULL;
9838 }
9839 else if (fd->collapse > 1)
9840 {
9841 remove_edge (se);
9842 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9843 }
9844 else
9845 se->flags = EDGE_TRUE_VALUE;
9846 find_edge (cont_bb, trip_update_bb)->flags
9847 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9848
9849 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
9850 }
9851
9852 if (gimple_in_ssa_p (cfun))
9853 {
9854 gphi_iterator psi;
9855 gphi *phi;
9856 edge re, ene;
9857 edge_var_map *vm;
9858 size_t i;
9859
9860 gcc_assert (fd->collapse == 1 && !broken_loop);
9861
9862 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
9863 remove arguments of the phi nodes in fin_bb. We need to create
9864 appropriate phi nodes in iter_part_bb instead. */
9865 se = find_edge (iter_part_bb, fin_bb);
9866 re = single_succ_edge (trip_update_bb);
9867 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
9868 ene = single_succ_edge (entry_bb);
9869
9870 psi = gsi_start_phis (fin_bb);
9871 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
9872 gsi_next (&psi), ++i)
9873 {
9874 gphi *nphi;
9875 source_location locus;
9876
9877 phi = psi.phi ();
9878 t = gimple_phi_result (phi);
9879 gcc_assert (t == redirect_edge_var_map_result (vm));
9880
9881 if (!single_pred_p (fin_bb))
9882 t = copy_ssa_name (t, phi);
9883
9884 nphi = create_phi_node (t, iter_part_bb);
9885
9886 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
9887 locus = gimple_phi_arg_location_from_edge (phi, se);
9888
9889 /* A special case -- fd->loop.v is not yet computed in
9890 iter_part_bb, we need to use vextra instead. */
9891 if (t == fd->loop.v)
9892 t = vextra;
9893 add_phi_arg (nphi, t, ene, locus);
9894 locus = redirect_edge_var_map_location (vm);
9895 tree back_arg = redirect_edge_var_map_def (vm);
9896 add_phi_arg (nphi, back_arg, re, locus);
9897 edge ce = find_edge (cont_bb, body_bb);
9898 if (ce == NULL)
9899 {
9900 ce = BRANCH_EDGE (cont_bb);
9901 gcc_assert (single_succ (ce->dest) == body_bb);
9902 ce = single_succ_edge (ce->dest);
9903 }
9904 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
9905 gcc_assert (inner_loop_phi != NULL);
9906 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
9907 find_edge (seq_start_bb, body_bb), locus);
9908
9909 if (!single_pred_p (fin_bb))
9910 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
9911 }
9912 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
9913 redirect_edge_var_map_clear (re);
9914 if (single_pred_p (fin_bb))
9915 while (1)
9916 {
9917 psi = gsi_start_phis (fin_bb);
9918 if (gsi_end_p (psi))
9919 break;
9920 remove_phi_node (&psi, false);
9921 }
9922
9923 /* Make phi node for trip. */
9924 phi = create_phi_node (trip_main, iter_part_bb);
9925 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
9926 UNKNOWN_LOCATION);
9927 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
9928 UNKNOWN_LOCATION);
9929 }
9930
9931 if (!broken_loop)
9932 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
9933 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
9934 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
9935 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9936 recompute_dominator (CDI_DOMINATORS, fin_bb));
9937 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
9938 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
9939 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9940 recompute_dominator (CDI_DOMINATORS, body_bb));
9941
9942 if (!broken_loop)
9943 {
9944 struct loop *loop = body_bb->loop_father;
9945 struct loop *trip_loop = alloc_loop ();
9946 trip_loop->header = iter_part_bb;
9947 trip_loop->latch = trip_update_bb;
9948 add_loop (trip_loop, iter_part_bb->loop_father);
9949
9950 if (loop != entry_bb->loop_father)
9951 {
9952 gcc_assert (loop->header == body_bb);
9953 gcc_assert (loop->latch == region->cont
9954 || single_pred (loop->latch) == region->cont);
9955 trip_loop->inner = loop;
9956 return;
9957 }
9958
9959 if (!gimple_omp_for_combined_p (fd->for_stmt))
9960 {
9961 loop = alloc_loop ();
9962 loop->header = body_bb;
9963 if (collapse_bb == NULL)
9964 loop->latch = cont_bb;
9965 add_loop (loop, trip_loop);
9966 }
9967 }
9968 }
9969
9970 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
9971 Given parameters:
9972 for (V = N1; V cond N2; V += STEP) BODY;
9973
9974 where COND is "<" or ">" or "!=", we generate pseudocode
9975
9976 for (ind_var = low; ind_var < high; ind_var++)
9977 {
9978 V = n1 + (ind_var * STEP)
9979
9980 <BODY>
9981 }
9982
9983 In the above pseudocode, low and high are function parameters of the
9984 child function. In the function below, we are inserting a temp.
9985 variable that will be making a call to two OMP functions that will not be
9986 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
9987 with _Cilk_for). These functions are replaced with low and high
9988 by the function that handles taskreg. */
9989
9990
9991 static void
9992 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
9993 {
9994 bool broken_loop = region->cont == NULL;
9995 basic_block entry_bb = region->entry;
9996 basic_block cont_bb = region->cont;
9997
9998 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9999 gcc_assert (broken_loop
10000 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10001 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10002 basic_block l1_bb, l2_bb;
10003
10004 if (!broken_loop)
10005 {
10006 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10007 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10008 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10009 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10010 }
10011 else
10012 {
10013 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10014 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10015 l2_bb = single_succ (l1_bb);
10016 }
10017 basic_block exit_bb = region->exit;
10018 basic_block l2_dom_bb = NULL;
10019
10020 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10021
10022 /* Below statements until the "tree high_val = ..." are pseudo statements
10023 used to pass information to be used by expand_omp_taskreg.
10024 low_val and high_val will be replaced by the __low and __high
10025 parameter from the child function.
10026
10027 The call_exprs part is a place-holder, it is mainly used
10028 to distinctly identify to the top-level part that this is
10029 where we should put low and high (reasoning given in header
10030 comment). */
10031
10032 tree child_fndecl
10033 = gimple_omp_parallel_child_fn (
10034 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
10035 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10036 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10037 {
10038 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10039 high_val = t;
10040 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10041 low_val = t;
10042 }
10043 gcc_assert (low_val && high_val);
10044
10045 tree type = TREE_TYPE (low_val);
10046 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10047 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10048
10049 /* Not needed in SSA form right now. */
10050 gcc_assert (!gimple_in_ssa_p (cfun));
10051 if (l2_dom_bb == NULL)
10052 l2_dom_bb = l1_bb;
10053
10054 tree n1 = low_val;
10055 tree n2 = high_val;
10056
10057 gimple *stmt = gimple_build_assign (ind_var, n1);
10058
10059 /* Replace the GIMPLE_OMP_FOR statement. */
10060 gsi_replace (&gsi, stmt, true);
10061
10062 if (!broken_loop)
10063 {
10064 /* Code to control the increment goes in the CONT_BB. */
10065 gsi = gsi_last_bb (cont_bb);
10066 stmt = gsi_stmt (gsi);
10067 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10068 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10069 build_one_cst (type));
10070
10071 /* Replace GIMPLE_OMP_CONTINUE. */
10072 gsi_replace (&gsi, stmt, true);
10073 }
10074
10075 /* Emit the condition in L1_BB. */
10076 gsi = gsi_after_labels (l1_bb);
10077 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10078 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10079 fd->loop.step);
10080 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10081 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10082 fd->loop.n1, fold_convert (sizetype, t));
10083 else
10084 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10085 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10086 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10087 expand_omp_build_assign (&gsi, fd->loop.v, t);
10088
10089 /* The condition is always '<' since the runtime will fill in the low
10090 and high values. */
10091 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10092 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10093
10094 /* Remove GIMPLE_OMP_RETURN. */
10095 gsi = gsi_last_bb (exit_bb);
10096 gsi_remove (&gsi, true);
10097
10098 /* Connect the new blocks. */
10099 remove_edge (FALLTHRU_EDGE (entry_bb));
10100
10101 edge e, ne;
10102 if (!broken_loop)
10103 {
10104 remove_edge (BRANCH_EDGE (entry_bb));
10105 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10106
10107 e = BRANCH_EDGE (l1_bb);
10108 ne = FALLTHRU_EDGE (l1_bb);
10109 e->flags = EDGE_TRUE_VALUE;
10110 }
10111 else
10112 {
10113 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10114
10115 ne = single_succ_edge (l1_bb);
10116 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10117
10118 }
10119 ne->flags = EDGE_FALSE_VALUE;
10120 e->probability = REG_BR_PROB_BASE * 7 / 8;
10121 ne->probability = REG_BR_PROB_BASE / 8;
10122
10123 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10124 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10125 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10126
10127 if (!broken_loop)
10128 {
10129 struct loop *loop = alloc_loop ();
10130 loop->header = l1_bb;
10131 loop->latch = cont_bb;
10132 add_loop (loop, l1_bb->loop_father);
10133 loop->safelen = INT_MAX;
10134 }
10135
10136 /* Pick the correct library function based on the precision of the
10137 induction variable type. */
10138 tree lib_fun = NULL_TREE;
10139 if (TYPE_PRECISION (type) == 32)
10140 lib_fun = cilk_for_32_fndecl;
10141 else if (TYPE_PRECISION (type) == 64)
10142 lib_fun = cilk_for_64_fndecl;
10143 else
10144 gcc_unreachable ();
10145
10146 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10147
10148 /* WS_ARGS contains the library function flavor to call:
10149 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10150 user-defined grain value. If the user does not define one, then zero
10151 is passed in by the parser. */
10152 vec_alloc (region->ws_args, 2);
10153 region->ws_args->quick_push (lib_fun);
10154 region->ws_args->quick_push (fd->chunk_size);
10155 }
10156
10157 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10158 loop. Given parameters:
10159
10160 for (V = N1; V cond N2; V += STEP) BODY;
10161
10162 where COND is "<" or ">", we generate pseudocode
10163
10164 V = N1;
10165 goto L1;
10166 L0:
10167 BODY;
10168 V += STEP;
10169 L1:
10170 if (V cond N2) goto L0; else goto L2;
10171 L2:
10172
10173 For collapsed loops, given parameters:
10174 collapse(3)
10175 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10176 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10177 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10178 BODY;
10179
10180 we generate pseudocode
10181
10182 if (cond3 is <)
10183 adj = STEP3 - 1;
10184 else
10185 adj = STEP3 + 1;
10186 count3 = (adj + N32 - N31) / STEP3;
10187 if (cond2 is <)
10188 adj = STEP2 - 1;
10189 else
10190 adj = STEP2 + 1;
10191 count2 = (adj + N22 - N21) / STEP2;
10192 if (cond1 is <)
10193 adj = STEP1 - 1;
10194 else
10195 adj = STEP1 + 1;
10196 count1 = (adj + N12 - N11) / STEP1;
10197 count = count1 * count2 * count3;
10198 V = 0;
10199 V1 = N11;
10200 V2 = N21;
10201 V3 = N31;
10202 goto L1;
10203 L0:
10204 BODY;
10205 V += 1;
10206 V3 += STEP3;
10207 V2 += (V3 cond3 N32) ? 0 : STEP2;
10208 V3 = (V3 cond3 N32) ? V3 : N31;
10209 V1 += (V2 cond2 N22) ? 0 : STEP1;
10210 V2 = (V2 cond2 N22) ? V2 : N21;
10211 L1:
10212 if (V < count) goto L0; else goto L2;
10213 L2:
10214
10215 */
10216
10217 static void
10218 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10219 {
10220 tree type, t;
10221 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10222 gimple_stmt_iterator gsi;
10223 gimple *stmt;
10224 gcond *cond_stmt;
10225 bool broken_loop = region->cont == NULL;
10226 edge e, ne;
10227 tree *counts = NULL;
10228 int i;
10229 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10230 OMP_CLAUSE_SAFELEN);
10231 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10232 OMP_CLAUSE__SIMDUID_);
10233 tree n1, n2;
10234
10235 type = TREE_TYPE (fd->loop.v);
10236 entry_bb = region->entry;
10237 cont_bb = region->cont;
10238 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10239 gcc_assert (broken_loop
10240 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10241 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10242 if (!broken_loop)
10243 {
10244 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10245 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10246 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10247 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10248 }
10249 else
10250 {
10251 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10252 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10253 l2_bb = single_succ (l1_bb);
10254 }
10255 exit_bb = region->exit;
10256 l2_dom_bb = NULL;
10257
10258 gsi = gsi_last_bb (entry_bb);
10259
10260 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10261 /* Not needed in SSA form right now. */
10262 gcc_assert (!gimple_in_ssa_p (cfun));
10263 if (fd->collapse > 1)
10264 {
10265 int first_zero_iter = -1, dummy = -1;
10266 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
10267
10268 counts = XALLOCAVEC (tree, fd->collapse);
10269 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10270 zero_iter_bb, first_zero_iter,
10271 dummy_bb, dummy, l2_dom_bb);
10272 }
10273 if (l2_dom_bb == NULL)
10274 l2_dom_bb = l1_bb;
10275
10276 n1 = fd->loop.n1;
10277 n2 = fd->loop.n2;
10278 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10279 {
10280 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10281 OMP_CLAUSE__LOOPTEMP_);
10282 gcc_assert (innerc);
10283 n1 = OMP_CLAUSE_DECL (innerc);
10284 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10285 OMP_CLAUSE__LOOPTEMP_);
10286 gcc_assert (innerc);
10287 n2 = OMP_CLAUSE_DECL (innerc);
10288 expand_omp_build_assign (&gsi, fd->loop.v,
10289 fold_convert (type, n1));
10290 if (fd->collapse > 1)
10291 {
10292 gsi_prev (&gsi);
10293 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10294 gsi_next (&gsi);
10295 }
10296 }
10297 else
10298 {
10299 expand_omp_build_assign (&gsi, fd->loop.v,
10300 fold_convert (type, fd->loop.n1));
10301 if (fd->collapse > 1)
10302 for (i = 0; i < fd->collapse; i++)
10303 {
10304 tree itype = TREE_TYPE (fd->loops[i].v);
10305 if (POINTER_TYPE_P (itype))
10306 itype = signed_type_for (itype);
10307 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10308 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10309 }
10310 }
10311
10312 /* Remove the GIMPLE_OMP_FOR statement. */
10313 gsi_remove (&gsi, true);
10314
10315 if (!broken_loop)
10316 {
10317 /* Code to control the increment goes in the CONT_BB. */
10318 gsi = gsi_last_bb (cont_bb);
10319 stmt = gsi_stmt (gsi);
10320 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10321
10322 if (POINTER_TYPE_P (type))
10323 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10324 else
10325 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10326 expand_omp_build_assign (&gsi, fd->loop.v, t);
10327
10328 if (fd->collapse > 1)
10329 {
10330 i = fd->collapse - 1;
10331 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10332 {
10333 t = fold_convert (sizetype, fd->loops[i].step);
10334 t = fold_build_pointer_plus (fd->loops[i].v, t);
10335 }
10336 else
10337 {
10338 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10339 fd->loops[i].step);
10340 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10341 fd->loops[i].v, t);
10342 }
10343 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10344
10345 for (i = fd->collapse - 1; i > 0; i--)
10346 {
10347 tree itype = TREE_TYPE (fd->loops[i].v);
10348 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10349 if (POINTER_TYPE_P (itype2))
10350 itype2 = signed_type_for (itype2);
10351 t = build3 (COND_EXPR, itype2,
10352 build2 (fd->loops[i].cond_code, boolean_type_node,
10353 fd->loops[i].v,
10354 fold_convert (itype, fd->loops[i].n2)),
10355 build_int_cst (itype2, 0),
10356 fold_convert (itype2, fd->loops[i - 1].step));
10357 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10358 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10359 else
10360 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10361 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10362
10363 t = build3 (COND_EXPR, itype,
10364 build2 (fd->loops[i].cond_code, boolean_type_node,
10365 fd->loops[i].v,
10366 fold_convert (itype, fd->loops[i].n2)),
10367 fd->loops[i].v,
10368 fold_convert (itype, fd->loops[i].n1));
10369 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10370 }
10371 }
10372
10373 /* Remove GIMPLE_OMP_CONTINUE. */
10374 gsi_remove (&gsi, true);
10375 }
10376
10377 /* Emit the condition in L1_BB. */
10378 gsi = gsi_start_bb (l1_bb);
10379
10380 t = fold_convert (type, n2);
10381 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10382 false, GSI_CONTINUE_LINKING);
10383 tree v = fd->loop.v;
10384 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10385 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10386 false, GSI_CONTINUE_LINKING);
10387 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
10388 cond_stmt = gimple_build_cond_empty (t);
10389 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10390 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
10391 NULL, NULL)
10392 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
10393 NULL, NULL))
10394 {
10395 gsi = gsi_for_stmt (cond_stmt);
10396 gimple_regimplify_operands (cond_stmt, &gsi);
10397 }
10398
10399 /* Remove GIMPLE_OMP_RETURN. */
10400 gsi = gsi_last_bb (exit_bb);
10401 gsi_remove (&gsi, true);
10402
10403 /* Connect the new blocks. */
10404 remove_edge (FALLTHRU_EDGE (entry_bb));
10405
10406 if (!broken_loop)
10407 {
10408 remove_edge (BRANCH_EDGE (entry_bb));
10409 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10410
10411 e = BRANCH_EDGE (l1_bb);
10412 ne = FALLTHRU_EDGE (l1_bb);
10413 e->flags = EDGE_TRUE_VALUE;
10414 }
10415 else
10416 {
10417 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10418
10419 ne = single_succ_edge (l1_bb);
10420 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10421
10422 }
10423 ne->flags = EDGE_FALSE_VALUE;
10424 e->probability = REG_BR_PROB_BASE * 7 / 8;
10425 ne->probability = REG_BR_PROB_BASE / 8;
10426
10427 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10428 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10429 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10430
10431 if (!broken_loop)
10432 {
10433 struct loop *loop = alloc_loop ();
10434 loop->header = l1_bb;
10435 loop->latch = cont_bb;
10436 add_loop (loop, l1_bb->loop_father);
10437 if (safelen == NULL_TREE)
10438 loop->safelen = INT_MAX;
10439 else
10440 {
10441 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
10442 if (TREE_CODE (safelen) != INTEGER_CST)
10443 loop->safelen = 0;
10444 else if (!tree_fits_uhwi_p (safelen)
10445 || tree_to_uhwi (safelen) > INT_MAX)
10446 loop->safelen = INT_MAX;
10447 else
10448 loop->safelen = tree_to_uhwi (safelen);
10449 if (loop->safelen == 1)
10450 loop->safelen = 0;
10451 }
10452 if (simduid)
10453 {
10454 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10455 cfun->has_simduid_loops = true;
10456 }
10457 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10458 the loop. */
10459 if ((flag_tree_loop_vectorize
10460 || (!global_options_set.x_flag_tree_loop_vectorize
10461 && !global_options_set.x_flag_tree_vectorize))
10462 && flag_tree_loop_optimize
10463 && loop->safelen > 1)
10464 {
10465 loop->force_vectorize = true;
10466 cfun->has_force_vectorize_loops = true;
10467 }
10468 }
10469 else if (simduid)
10470 cfun->has_simduid_loops = true;
10471 }
10472
10473 /* Taskloop construct is represented after gimplification with
10474 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10475 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10476 which should just compute all the needed loop temporaries
10477 for GIMPLE_OMP_TASK. */
10478
10479 static void
10480 expand_omp_taskloop_for_outer (struct omp_region *region,
10481 struct omp_for_data *fd,
10482 gimple *inner_stmt)
10483 {
10484 tree type, bias = NULL_TREE;
10485 basic_block entry_bb, cont_bb, exit_bb;
10486 gimple_stmt_iterator gsi;
10487 gassign *assign_stmt;
10488 tree *counts = NULL;
10489 int i;
10490
10491 gcc_assert (inner_stmt);
10492 gcc_assert (region->cont);
10493 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10494 && gimple_omp_task_taskloop_p (inner_stmt));
10495 type = TREE_TYPE (fd->loop.v);
10496
10497 /* See if we need to bias by LLONG_MIN. */
10498 if (fd->iter_type == long_long_unsigned_type_node
10499 && TREE_CODE (type) == INTEGER_TYPE
10500 && !TYPE_UNSIGNED (type))
10501 {
10502 tree n1, n2;
10503
10504 if (fd->loop.cond_code == LT_EXPR)
10505 {
10506 n1 = fd->loop.n1;
10507 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10508 }
10509 else
10510 {
10511 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10512 n2 = fd->loop.n1;
10513 }
10514 if (TREE_CODE (n1) != INTEGER_CST
10515 || TREE_CODE (n2) != INTEGER_CST
10516 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10517 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10518 }
10519
10520 entry_bb = region->entry;
10521 cont_bb = region->cont;
10522 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10523 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10524 exit_bb = region->exit;
10525
10526 gsi = gsi_last_bb (entry_bb);
10527 gimple *for_stmt = gsi_stmt (gsi);
10528 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10529 if (fd->collapse > 1)
10530 {
10531 int first_zero_iter = -1, dummy = -1;
10532 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10533
10534 counts = XALLOCAVEC (tree, fd->collapse);
10535 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10536 zero_iter_bb, first_zero_iter,
10537 dummy_bb, dummy, l2_dom_bb);
10538
10539 if (zero_iter_bb)
10540 {
10541 /* Some counts[i] vars might be uninitialized if
10542 some loop has zero iterations. But the body shouldn't
10543 be executed in that case, so just avoid uninit warnings. */
10544 for (i = first_zero_iter; i < fd->collapse; i++)
10545 if (SSA_VAR_P (counts[i]))
10546 TREE_NO_WARNING (counts[i]) = 1;
10547 gsi_prev (&gsi);
10548 edge e = split_block (entry_bb, gsi_stmt (gsi));
10549 entry_bb = e->dest;
10550 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10551 gsi = gsi_last_bb (entry_bb);
10552 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10553 get_immediate_dominator (CDI_DOMINATORS,
10554 zero_iter_bb));
10555 }
10556 }
10557
10558 tree t0, t1;
10559 t1 = fd->loop.n2;
10560 t0 = fd->loop.n1;
10561 if (POINTER_TYPE_P (TREE_TYPE (t0))
10562 && TYPE_PRECISION (TREE_TYPE (t0))
10563 != TYPE_PRECISION (fd->iter_type))
10564 {
10565 /* Avoid casting pointers to integer of a different size. */
10566 tree itype = signed_type_for (type);
10567 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10568 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10569 }
10570 else
10571 {
10572 t1 = fold_convert (fd->iter_type, t1);
10573 t0 = fold_convert (fd->iter_type, t0);
10574 }
10575 if (bias)
10576 {
10577 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10578 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10579 }
10580
10581 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10582 OMP_CLAUSE__LOOPTEMP_);
10583 gcc_assert (innerc);
10584 tree startvar = OMP_CLAUSE_DECL (innerc);
10585 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10586 gcc_assert (innerc);
10587 tree endvar = OMP_CLAUSE_DECL (innerc);
10588 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10589 {
10590 gcc_assert (innerc);
10591 for (i = 1; i < fd->collapse; i++)
10592 {
10593 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10594 OMP_CLAUSE__LOOPTEMP_);
10595 gcc_assert (innerc);
10596 }
10597 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10598 OMP_CLAUSE__LOOPTEMP_);
10599 if (innerc)
10600 {
10601 /* If needed (inner taskloop has lastprivate clause), propagate
10602 down the total number of iterations. */
10603 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10604 NULL_TREE, false,
10605 GSI_CONTINUE_LINKING);
10606 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10607 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10608 }
10609 }
10610
10611 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10612 GSI_CONTINUE_LINKING);
10613 assign_stmt = gimple_build_assign (startvar, t0);
10614 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10615
10616 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10617 GSI_CONTINUE_LINKING);
10618 assign_stmt = gimple_build_assign (endvar, t1);
10619 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10620 if (fd->collapse > 1)
10621 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10622
10623 /* Remove the GIMPLE_OMP_FOR statement. */
10624 gsi = gsi_for_stmt (for_stmt);
10625 gsi_remove (&gsi, true);
10626
10627 gsi = gsi_last_bb (cont_bb);
10628 gsi_remove (&gsi, true);
10629
10630 gsi = gsi_last_bb (exit_bb);
10631 gsi_remove (&gsi, true);
10632
10633 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10634 remove_edge (BRANCH_EDGE (entry_bb));
10635 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10636 remove_edge (BRANCH_EDGE (cont_bb));
10637 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10638 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10639 recompute_dominator (CDI_DOMINATORS, region->entry));
10640 }
10641
10642 /* Taskloop construct is represented after gimplification with
10643 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10644 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10645 GOMP_taskloop{,_ull} function arranges for each task to be given just
10646 a single range of iterations. */
10647
10648 static void
10649 expand_omp_taskloop_for_inner (struct omp_region *region,
10650 struct omp_for_data *fd,
10651 gimple *inner_stmt)
10652 {
10653 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10654 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10655 basic_block fin_bb;
10656 gimple_stmt_iterator gsi;
10657 edge ep;
10658 bool broken_loop = region->cont == NULL;
10659 tree *counts = NULL;
10660 tree n1, n2, step;
10661
10662 itype = type = TREE_TYPE (fd->loop.v);
10663 if (POINTER_TYPE_P (type))
10664 itype = signed_type_for (type);
10665
10666 /* See if we need to bias by LLONG_MIN. */
10667 if (fd->iter_type == long_long_unsigned_type_node
10668 && TREE_CODE (type) == INTEGER_TYPE
10669 && !TYPE_UNSIGNED (type))
10670 {
10671 tree n1, n2;
10672
10673 if (fd->loop.cond_code == LT_EXPR)
10674 {
10675 n1 = fd->loop.n1;
10676 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10677 }
10678 else
10679 {
10680 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10681 n2 = fd->loop.n1;
10682 }
10683 if (TREE_CODE (n1) != INTEGER_CST
10684 || TREE_CODE (n2) != INTEGER_CST
10685 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10686 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10687 }
10688
10689 entry_bb = region->entry;
10690 cont_bb = region->cont;
10691 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10692 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10693 gcc_assert (broken_loop
10694 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10695 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10696 if (!broken_loop)
10697 {
10698 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10699 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10700 }
10701 exit_bb = region->exit;
10702
10703 /* Iteration space partitioning goes in ENTRY_BB. */
10704 gsi = gsi_last_bb (entry_bb);
10705 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10706
10707 if (fd->collapse > 1)
10708 {
10709 int first_zero_iter = -1, dummy = -1;
10710 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10711
10712 counts = XALLOCAVEC (tree, fd->collapse);
10713 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10714 fin_bb, first_zero_iter,
10715 dummy_bb, dummy, l2_dom_bb);
10716 t = NULL_TREE;
10717 }
10718 else
10719 t = integer_one_node;
10720
10721 step = fd->loop.step;
10722 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10723 OMP_CLAUSE__LOOPTEMP_);
10724 gcc_assert (innerc);
10725 n1 = OMP_CLAUSE_DECL (innerc);
10726 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10727 gcc_assert (innerc);
10728 n2 = OMP_CLAUSE_DECL (innerc);
10729 if (bias)
10730 {
10731 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
10732 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
10733 }
10734 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
10735 true, NULL_TREE, true, GSI_SAME_STMT);
10736 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
10737 true, NULL_TREE, true, GSI_SAME_STMT);
10738 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
10739 true, NULL_TREE, true, GSI_SAME_STMT);
10740
10741 tree startvar = fd->loop.v;
10742 tree endvar = NULL_TREE;
10743
10744 if (gimple_omp_for_combined_p (fd->for_stmt))
10745 {
10746 tree clauses = gimple_omp_for_clauses (inner_stmt);
10747 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
10748 gcc_assert (innerc);
10749 startvar = OMP_CLAUSE_DECL (innerc);
10750 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10751 OMP_CLAUSE__LOOPTEMP_);
10752 gcc_assert (innerc);
10753 endvar = OMP_CLAUSE_DECL (innerc);
10754 }
10755 t = fold_convert (TREE_TYPE (startvar), n1);
10756 t = force_gimple_operand_gsi (&gsi, t,
10757 DECL_P (startvar)
10758 && TREE_ADDRESSABLE (startvar),
10759 NULL_TREE, false, GSI_CONTINUE_LINKING);
10760 gimple *assign_stmt = gimple_build_assign (startvar, t);
10761 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10762
10763 t = fold_convert (TREE_TYPE (startvar), n2);
10764 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10765 false, GSI_CONTINUE_LINKING);
10766 if (endvar)
10767 {
10768 assign_stmt = gimple_build_assign (endvar, e);
10769 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10770 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
10771 assign_stmt = gimple_build_assign (fd->loop.v, e);
10772 else
10773 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
10774 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10775 }
10776 if (fd->collapse > 1)
10777 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10778
10779 if (!broken_loop)
10780 {
10781 /* The code controlling the sequential loop replaces the
10782 GIMPLE_OMP_CONTINUE. */
10783 gsi = gsi_last_bb (cont_bb);
10784 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10785 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
10786 vmain = gimple_omp_continue_control_use (cont_stmt);
10787 vback = gimple_omp_continue_control_def (cont_stmt);
10788
10789 if (!gimple_omp_for_combined_p (fd->for_stmt))
10790 {
10791 if (POINTER_TYPE_P (type))
10792 t = fold_build_pointer_plus (vmain, step);
10793 else
10794 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10795 t = force_gimple_operand_gsi (&gsi, t,
10796 DECL_P (vback)
10797 && TREE_ADDRESSABLE (vback),
10798 NULL_TREE, true, GSI_SAME_STMT);
10799 assign_stmt = gimple_build_assign (vback, t);
10800 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10801
10802 t = build2 (fd->loop.cond_code, boolean_type_node,
10803 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10804 ? t : vback, e);
10805 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10806 }
10807
10808 /* Remove the GIMPLE_OMP_CONTINUE statement. */
10809 gsi_remove (&gsi, true);
10810
10811 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10812 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10813 }
10814
10815 /* Remove the GIMPLE_OMP_FOR statement. */
10816 gsi = gsi_for_stmt (fd->for_stmt);
10817 gsi_remove (&gsi, true);
10818
10819 /* Remove the GIMPLE_OMP_RETURN statement. */
10820 gsi = gsi_last_bb (exit_bb);
10821 gsi_remove (&gsi, true);
10822
10823 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10824 if (!broken_loop)
10825 remove_edge (BRANCH_EDGE (entry_bb));
10826 else
10827 {
10828 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
10829 region->outer->cont = NULL;
10830 }
10831
10832 /* Connect all the blocks. */
10833 if (!broken_loop)
10834 {
10835 ep = find_edge (cont_bb, body_bb);
10836 if (gimple_omp_for_combined_p (fd->for_stmt))
10837 {
10838 remove_edge (ep);
10839 ep = NULL;
10840 }
10841 else if (fd->collapse > 1)
10842 {
10843 remove_edge (ep);
10844 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10845 }
10846 else
10847 ep->flags = EDGE_TRUE_VALUE;
10848 find_edge (cont_bb, fin_bb)->flags
10849 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10850 }
10851
10852 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10853 recompute_dominator (CDI_DOMINATORS, body_bb));
10854 if (!broken_loop)
10855 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10856 recompute_dominator (CDI_DOMINATORS, fin_bb));
10857
10858 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
10859 {
10860 struct loop *loop = alloc_loop ();
10861 loop->header = body_bb;
10862 if (collapse_bb == NULL)
10863 loop->latch = cont_bb;
10864 add_loop (loop, body_bb->loop_father);
10865 }
10866 }
10867
10868 /* A subroutine of expand_omp_for. Generate code for an OpenACC
10869 partitioned loop. The lowering here is abstracted, in that the
10870 loop parameters are passed through internal functions, which are
10871 further lowered by oacc_device_lower, once we get to the target
10872 compiler. The loop is of the form:
10873
10874 for (V = B; V LTGT E; V += S) {BODY}
10875
10876 where LTGT is < or >. We may have a specified chunking size, CHUNKING
10877 (constant 0 for no chunking) and we will have a GWV partitioning
10878 mask, specifying dimensions over which the loop is to be
10879 partitioned (see note below). We generate code that looks like:
10880
10881 <entry_bb> [incoming FALL->body, BRANCH->exit]
10882 typedef signedintify (typeof (V)) T; // underlying signed integral type
10883 T range = E - B;
10884 T chunk_no = 0;
10885 T DIR = LTGT == '<' ? +1 : -1;
10886 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
10887 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
10888
10889 <head_bb> [created by splitting end of entry_bb]
10890 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
10891 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
10892 if (!(offset LTGT bound)) goto bottom_bb;
10893
10894 <body_bb> [incoming]
10895 V = B + offset;
10896 {BODY}
10897
10898 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
10899 offset += step;
10900 if (offset LTGT bound) goto body_bb; [*]
10901
10902 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
10903 chunk_no++;
10904 if (chunk < chunk_max) goto head_bb;
10905
10906 <exit_bb> [incoming]
10907 V = B + ((range -/+ 1) / S +/- 1) * S [*]
10908
10909 [*] Needed if V live at end of loop
10910
10911 Note: CHUNKING & GWV mask are specified explicitly here. This is a
10912 transition, and will be specified by a more general mechanism shortly.
10913 */
10914
10915 static void
10916 expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
10917 {
10918 tree v = fd->loop.v;
10919 enum tree_code cond_code = fd->loop.cond_code;
10920 enum tree_code plus_code = PLUS_EXPR;
10921
10922 tree chunk_size = integer_minus_one_node;
10923 tree gwv = integer_zero_node;
10924 tree iter_type = TREE_TYPE (v);
10925 tree diff_type = iter_type;
10926 tree plus_type = iter_type;
10927 struct oacc_collapse *counts = NULL;
10928
10929 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
10930 == GF_OMP_FOR_KIND_OACC_LOOP);
10931 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
10932 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
10933
10934 if (POINTER_TYPE_P (iter_type))
10935 {
10936 plus_code = POINTER_PLUS_EXPR;
10937 plus_type = sizetype;
10938 }
10939 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
10940 diff_type = signed_type_for (diff_type);
10941
10942 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
10943 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
10944 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
10945 basic_block bottom_bb = NULL;
10946
10947 /* entry_bb has two sucessors; the branch edge is to the exit
10948 block, fallthrough edge to body. */
10949 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
10950 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
10951
10952 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
10953 body_bb, or to a block whose only successor is the body_bb. Its
10954 fallthrough successor is the final block (same as the branch
10955 successor of the entry_bb). */
10956 if (cont_bb)
10957 {
10958 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10959 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
10960
10961 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
10962 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
10963 }
10964 else
10965 gcc_assert (!gimple_in_ssa_p (cfun));
10966
10967 /* The exit block only has entry_bb and cont_bb as predecessors. */
10968 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
10969
10970 tree chunk_no;
10971 tree chunk_max = NULL_TREE;
10972 tree bound, offset;
10973 tree step = create_tmp_var (diff_type, ".step");
10974 bool up = cond_code == LT_EXPR;
10975 tree dir = build_int_cst (diff_type, up ? +1 : -1);
10976 bool chunking = !gimple_in_ssa_p (cfun);;
10977 bool negating;
10978
10979 /* SSA instances. */
10980 tree offset_incr = NULL_TREE;
10981 tree offset_init = NULL_TREE;
10982
10983 gimple_stmt_iterator gsi;
10984 gassign *ass;
10985 gcall *call;
10986 gimple *stmt;
10987 tree expr;
10988 location_t loc;
10989 edge split, be, fte;
10990
10991 /* Split the end of entry_bb to create head_bb. */
10992 split = split_block (entry_bb, last_stmt (entry_bb));
10993 basic_block head_bb = split->dest;
10994 entry_bb = split->src;
10995
10996 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
10997 gsi = gsi_last_bb (entry_bb);
10998 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
10999 loc = gimple_location (for_stmt);
11000
11001 if (gimple_in_ssa_p (cfun))
11002 {
11003 offset_init = gimple_omp_for_index (for_stmt, 0);
11004 gcc_assert (integer_zerop (fd->loop.n1));
11005 /* The SSA parallelizer does gang parallelism. */
11006 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11007 }
11008
11009 if (fd->collapse > 1)
11010 {
11011 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11012 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11013 TREE_TYPE (fd->loop.n2));
11014
11015 if (SSA_VAR_P (fd->loop.n2))
11016 {
11017 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11018 true, GSI_SAME_STMT);
11019 ass = gimple_build_assign (fd->loop.n2, total);
11020 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11021 }
11022
11023 }
11024
11025 tree b = fd->loop.n1;
11026 tree e = fd->loop.n2;
11027 tree s = fd->loop.step;
11028
11029 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11030 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11031
11032 /* Convert the step, avoiding possible unsigned->signed overflow. */
11033 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11034 if (negating)
11035 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11036 s = fold_convert (diff_type, s);
11037 if (negating)
11038 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11039 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11040
11041 if (!chunking)
11042 chunk_size = integer_zero_node;
11043 expr = fold_convert (diff_type, chunk_size);
11044 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11045 NULL_TREE, true, GSI_SAME_STMT);
11046 /* Determine the range, avoiding possible unsigned->signed overflow. */
11047 negating = !up && TYPE_UNSIGNED (iter_type);
11048 expr = fold_build2 (MINUS_EXPR, plus_type,
11049 fold_convert (plus_type, negating ? b : e),
11050 fold_convert (plus_type, negating ? e : b));
11051 expr = fold_convert (diff_type, expr);
11052 if (negating)
11053 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11054 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11055 NULL_TREE, true, GSI_SAME_STMT);
11056
11057 chunk_no = build_int_cst (diff_type, 0);
11058 if (chunking)
11059 {
11060 gcc_assert (!gimple_in_ssa_p (cfun));
11061
11062 expr = chunk_no;
11063 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11064 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11065
11066 ass = gimple_build_assign (chunk_no, expr);
11067 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11068
11069 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11070 build_int_cst (integer_type_node,
11071 IFN_GOACC_LOOP_CHUNKS),
11072 dir, range, s, chunk_size, gwv);
11073 gimple_call_set_lhs (call, chunk_max);
11074 gimple_set_location (call, loc);
11075 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11076 }
11077 else
11078 chunk_size = chunk_no;
11079
11080 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11081 build_int_cst (integer_type_node,
11082 IFN_GOACC_LOOP_STEP),
11083 dir, range, s, chunk_size, gwv);
11084 gimple_call_set_lhs (call, step);
11085 gimple_set_location (call, loc);
11086 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11087
11088 /* Remove the GIMPLE_OMP_FOR. */
11089 gsi_remove (&gsi, true);
11090
11091 /* Fixup edges from head_bb */
11092 be = BRANCH_EDGE (head_bb);
11093 fte = FALLTHRU_EDGE (head_bb);
11094 be->flags |= EDGE_FALSE_VALUE;
11095 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11096
11097 basic_block body_bb = fte->dest;
11098
11099 if (gimple_in_ssa_p (cfun))
11100 {
11101 gsi = gsi_last_bb (cont_bb);
11102 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11103
11104 offset = gimple_omp_continue_control_use (cont_stmt);
11105 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11106 }
11107 else
11108 {
11109 offset = create_tmp_var (diff_type, ".offset");
11110 offset_init = offset_incr = offset;
11111 }
11112 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11113
11114 /* Loop offset & bound go into head_bb. */
11115 gsi = gsi_start_bb (head_bb);
11116
11117 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11118 build_int_cst (integer_type_node,
11119 IFN_GOACC_LOOP_OFFSET),
11120 dir, range, s,
11121 chunk_size, gwv, chunk_no);
11122 gimple_call_set_lhs (call, offset_init);
11123 gimple_set_location (call, loc);
11124 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11125
11126 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11127 build_int_cst (integer_type_node,
11128 IFN_GOACC_LOOP_BOUND),
11129 dir, range, s,
11130 chunk_size, gwv, offset_init);
11131 gimple_call_set_lhs (call, bound);
11132 gimple_set_location (call, loc);
11133 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11134
11135 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11136 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11137 GSI_CONTINUE_LINKING);
11138
11139 /* V assignment goes into body_bb. */
11140 if (!gimple_in_ssa_p (cfun))
11141 {
11142 gsi = gsi_start_bb (body_bb);
11143
11144 expr = build2 (plus_code, iter_type, b,
11145 fold_convert (plus_type, offset));
11146 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11147 true, GSI_SAME_STMT);
11148 ass = gimple_build_assign (v, expr);
11149 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11150 if (fd->collapse > 1)
11151 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11152 }
11153
11154 /* Loop increment goes into cont_bb. If this is not a loop, we
11155 will have spawned threads as if it was, and each one will
11156 execute one iteration. The specification is not explicit about
11157 whether such constructs are ill-formed or not, and they can
11158 occur, especially when noreturn routines are involved. */
11159 if (cont_bb)
11160 {
11161 gsi = gsi_last_bb (cont_bb);
11162 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11163 loc = gimple_location (cont_stmt);
11164
11165 /* Increment offset. */
11166 if (gimple_in_ssa_p (cfun))
11167 expr= build2 (plus_code, iter_type, offset,
11168 fold_convert (plus_type, step));
11169 else
11170 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11171 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11172 true, GSI_SAME_STMT);
11173 ass = gimple_build_assign (offset_incr, expr);
11174 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11175 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11176 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11177
11178 /* Remove the GIMPLE_OMP_CONTINUE. */
11179 gsi_remove (&gsi, true);
11180
11181 /* Fixup edges from cont_bb */
11182 be = BRANCH_EDGE (cont_bb);
11183 fte = FALLTHRU_EDGE (cont_bb);
11184 be->flags |= EDGE_TRUE_VALUE;
11185 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11186
11187 if (chunking)
11188 {
11189 /* Split the beginning of exit_bb to make bottom_bb. We
11190 need to insert a nop at the start, because splitting is
11191 after a stmt, not before. */
11192 gsi = gsi_start_bb (exit_bb);
11193 stmt = gimple_build_nop ();
11194 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11195 split = split_block (exit_bb, stmt);
11196 bottom_bb = split->src;
11197 exit_bb = split->dest;
11198 gsi = gsi_last_bb (bottom_bb);
11199
11200 /* Chunk increment and test goes into bottom_bb. */
11201 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11202 build_int_cst (diff_type, 1));
11203 ass = gimple_build_assign (chunk_no, expr);
11204 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11205
11206 /* Chunk test at end of bottom_bb. */
11207 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11208 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11209 GSI_CONTINUE_LINKING);
11210
11211 /* Fixup edges from bottom_bb. */
11212 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11213 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11214 }
11215 }
11216
11217 gsi = gsi_last_bb (exit_bb);
11218 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11219 loc = gimple_location (gsi_stmt (gsi));
11220
11221 if (!gimple_in_ssa_p (cfun))
11222 {
11223 /* Insert the final value of V, in case it is live. This is the
11224 value for the only thread that survives past the join. */
11225 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11226 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11227 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11228 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11229 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11230 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11231 true, GSI_SAME_STMT);
11232 ass = gimple_build_assign (v, expr);
11233 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11234 }
11235
11236 /* Remove the OMP_RETURN. */
11237 gsi_remove (&gsi, true);
11238
11239 if (cont_bb)
11240 {
11241 /* We now have one or two nested loops. Update the loop
11242 structures. */
11243 struct loop *parent = entry_bb->loop_father;
11244 struct loop *body = body_bb->loop_father;
11245
11246 if (chunking)
11247 {
11248 struct loop *chunk_loop = alloc_loop ();
11249 chunk_loop->header = head_bb;
11250 chunk_loop->latch = bottom_bb;
11251 add_loop (chunk_loop, parent);
11252 parent = chunk_loop;
11253 }
11254 else if (parent != body)
11255 {
11256 gcc_assert (body->header == body_bb);
11257 gcc_assert (body->latch == cont_bb
11258 || single_pred (body->latch) == cont_bb);
11259 parent = NULL;
11260 }
11261
11262 if (parent)
11263 {
11264 struct loop *body_loop = alloc_loop ();
11265 body_loop->header = body_bb;
11266 body_loop->latch = cont_bb;
11267 add_loop (body_loop, parent);
11268 }
11269 }
11270 }
11271
11272 /* Expand the OMP loop defined by REGION. */
11273
11274 static void
11275 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
11276 {
11277 struct omp_for_data fd;
11278 struct omp_for_data_loop *loops;
11279
11280 loops
11281 = (struct omp_for_data_loop *)
11282 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
11283 * sizeof (struct omp_for_data_loop));
11284 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11285 &fd, loops);
11286 region->sched_kind = fd.sched_kind;
11287 region->sched_modifiers = fd.sched_modifiers;
11288
11289 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11290 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11291 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11292 if (region->cont)
11293 {
11294 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11295 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11296 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11297 }
11298 else
11299 /* If there isn't a continue then this is a degerate case where
11300 the introduction of abnormal edges during lowering will prevent
11301 original loops from being detected. Fix that up. */
11302 loops_state_set (LOOPS_NEED_FIXUP);
11303
11304 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
11305 expand_omp_simd (region, &fd);
11306 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11307 expand_cilk_for (region, &fd);
11308 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11309 {
11310 gcc_assert (!inner_stmt);
11311 expand_oacc_for (region, &fd);
11312 }
11313 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11314 {
11315 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11316 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11317 else
11318 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11319 }
11320 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
11321 && !fd.have_ordered)
11322 {
11323 if (fd.chunk_size == NULL)
11324 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
11325 else
11326 expand_omp_for_static_chunk (region, &fd, inner_stmt);
11327 }
11328 else
11329 {
11330 int fn_index, start_ix, next_ix;
11331
11332 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11333 == GF_OMP_FOR_KIND_FOR);
11334 if (fd.chunk_size == NULL
11335 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11336 fd.chunk_size = integer_zero_node;
11337 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
11338 switch (fd.sched_kind)
11339 {
11340 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11341 fn_index = 3;
11342 break;
11343 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11344 case OMP_CLAUSE_SCHEDULE_GUIDED:
11345 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11346 && !fd.ordered
11347 && !fd.have_ordered)
11348 {
11349 fn_index = 3 + fd.sched_kind;
11350 break;
11351 }
11352 /* FALLTHRU */
11353 default:
11354 fn_index = fd.sched_kind;
11355 break;
11356 }
11357 if (!fd.ordered)
11358 fn_index += fd.have_ordered * 6;
11359 if (fd.ordered)
11360 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11361 else
11362 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
11363 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
11364 if (fd.iter_type == long_long_unsigned_type_node)
11365 {
11366 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11367 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11368 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11369 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
11370 }
11371 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
11372 (enum built_in_function) next_ix, inner_stmt);
11373 }
11374
11375 if (gimple_in_ssa_p (cfun))
11376 update_ssa (TODO_update_ssa_only_virtuals);
11377 }
11378
11379
11380 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11381
11382 v = GOMP_sections_start (n);
11383 L0:
11384 switch (v)
11385 {
11386 case 0:
11387 goto L2;
11388 case 1:
11389 section 1;
11390 goto L1;
11391 case 2:
11392 ...
11393 case n:
11394 ...
11395 default:
11396 abort ();
11397 }
11398 L1:
11399 v = GOMP_sections_next ();
11400 goto L0;
11401 L2:
11402 reduction;
11403
11404 If this is a combined parallel sections, replace the call to
11405 GOMP_sections_start with call to GOMP_sections_next. */
11406
11407 static void
11408 expand_omp_sections (struct omp_region *region)
11409 {
11410 tree t, u, vin = NULL, vmain, vnext, l2;
11411 unsigned len;
11412 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
11413 gimple_stmt_iterator si, switch_si;
11414 gomp_sections *sections_stmt;
11415 gimple *stmt;
11416 gomp_continue *cont;
11417 edge_iterator ei;
11418 edge e;
11419 struct omp_region *inner;
11420 unsigned i, casei;
11421 bool exit_reachable = region->cont != NULL;
11422
11423 gcc_assert (region->exit != NULL);
11424 entry_bb = region->entry;
11425 l0_bb = single_succ (entry_bb);
11426 l1_bb = region->cont;
11427 l2_bb = region->exit;
11428 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11429 l2 = gimple_block_label (l2_bb);
11430 else
11431 {
11432 /* This can happen if there are reductions. */
11433 len = EDGE_COUNT (l0_bb->succs);
11434 gcc_assert (len > 0);
11435 e = EDGE_SUCC (l0_bb, len - 1);
11436 si = gsi_last_bb (e->dest);
11437 l2 = NULL_TREE;
11438 if (gsi_end_p (si)
11439 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11440 l2 = gimple_block_label (e->dest);
11441 else
11442 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11443 {
11444 si = gsi_last_bb (e->dest);
11445 if (gsi_end_p (si)
11446 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11447 {
11448 l2 = gimple_block_label (e->dest);
11449 break;
11450 }
11451 }
11452 }
11453 if (exit_reachable)
11454 default_bb = create_empty_bb (l1_bb->prev_bb);
11455 else
11456 default_bb = create_empty_bb (l0_bb);
11457
11458 /* We will build a switch() with enough cases for all the
11459 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11460 and a default case to abort if something goes wrong. */
11461 len = EDGE_COUNT (l0_bb->succs);
11462
11463 /* Use vec::quick_push on label_vec throughout, since we know the size
11464 in advance. */
11465 auto_vec<tree> label_vec (len);
11466
11467 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11468 GIMPLE_OMP_SECTIONS statement. */
11469 si = gsi_last_bb (entry_bb);
11470 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
11471 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11472 vin = gimple_omp_sections_control (sections_stmt);
11473 if (!is_combined_parallel (region))
11474 {
11475 /* If we are not inside a combined parallel+sections region,
11476 call GOMP_sections_start. */
11477 t = build_int_cst (unsigned_type_node, len - 1);
11478 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
11479 stmt = gimple_build_call (u, 1, t);
11480 }
11481 else
11482 {
11483 /* Otherwise, call GOMP_sections_next. */
11484 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11485 stmt = gimple_build_call (u, 0);
11486 }
11487 gimple_call_set_lhs (stmt, vin);
11488 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11489 gsi_remove (&si, true);
11490
11491 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11492 L0_BB. */
11493 switch_si = gsi_last_bb (l0_bb);
11494 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
11495 if (exit_reachable)
11496 {
11497 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
11498 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11499 vmain = gimple_omp_continue_control_use (cont);
11500 vnext = gimple_omp_continue_control_def (cont);
11501 }
11502 else
11503 {
11504 vmain = vin;
11505 vnext = NULL_TREE;
11506 }
11507
11508 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
11509 label_vec.quick_push (t);
11510 i = 1;
11511
11512 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11513 for (inner = region->inner, casei = 1;
11514 inner;
11515 inner = inner->next, i++, casei++)
11516 {
11517 basic_block s_entry_bb, s_exit_bb;
11518
11519 /* Skip optional reduction region. */
11520 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
11521 {
11522 --i;
11523 --casei;
11524 continue;
11525 }
11526
11527 s_entry_bb = inner->entry;
11528 s_exit_bb = inner->exit;
11529
11530 t = gimple_block_label (s_entry_bb);
11531 u = build_int_cst (unsigned_type_node, casei);
11532 u = build_case_label (u, NULL, t);
11533 label_vec.quick_push (u);
11534
11535 si = gsi_last_bb (s_entry_bb);
11536 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11537 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11538 gsi_remove (&si, true);
11539 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
11540
11541 if (s_exit_bb == NULL)
11542 continue;
11543
11544 si = gsi_last_bb (s_exit_bb);
11545 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11546 gsi_remove (&si, true);
11547
11548 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
11549 }
11550
11551 /* Error handling code goes in DEFAULT_BB. */
11552 t = gimple_block_label (default_bb);
11553 u = build_case_label (NULL, NULL, t);
11554 make_edge (l0_bb, default_bb, 0);
11555 add_bb_to_loop (default_bb, current_loops->tree_root);
11556
11557 stmt = gimple_build_switch (vmain, u, label_vec);
11558 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11559 gsi_remove (&switch_si, true);
11560
11561 si = gsi_start_bb (default_bb);
11562 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
11563 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
11564
11565 if (exit_reachable)
11566 {
11567 tree bfn_decl;
11568
11569 /* Code to get the next section goes in L1_BB. */
11570 si = gsi_last_bb (l1_bb);
11571 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
11572
11573 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11574 stmt = gimple_build_call (bfn_decl, 0);
11575 gimple_call_set_lhs (stmt, vnext);
11576 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11577 gsi_remove (&si, true);
11578
11579 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
11580 }
11581
11582 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11583 si = gsi_last_bb (l2_bb);
11584 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11585 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
11586 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11587 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
11588 else
11589 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11590 stmt = gimple_build_call (t, 0);
11591 if (gimple_omp_return_lhs (gsi_stmt (si)))
11592 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
11593 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11594 gsi_remove (&si, true);
11595
11596 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
11597 }
11598
11599
11600 /* Expand code for an OpenMP single directive. We've already expanded
11601 much of the code, here we simply place the GOMP_barrier call. */
11602
11603 static void
11604 expand_omp_single (struct omp_region *region)
11605 {
11606 basic_block entry_bb, exit_bb;
11607 gimple_stmt_iterator si;
11608
11609 entry_bb = region->entry;
11610 exit_bb = region->exit;
11611
11612 si = gsi_last_bb (entry_bb);
11613 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11614 gsi_remove (&si, true);
11615 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11616
11617 si = gsi_last_bb (exit_bb);
11618 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11619 {
11620 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11621 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11622 }
11623 gsi_remove (&si, true);
11624 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11625 }
11626
11627
11628 /* Generic expansion for OpenMP synchronization directives: master,
11629 ordered and critical. All we need to do here is remove the entry
11630 and exit markers for REGION. */
11631
11632 static void
11633 expand_omp_synch (struct omp_region *region)
11634 {
11635 basic_block entry_bb, exit_bb;
11636 gimple_stmt_iterator si;
11637
11638 entry_bb = region->entry;
11639 exit_bb = region->exit;
11640
11641 si = gsi_last_bb (entry_bb);
11642 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11643 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
11644 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
11645 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
11646 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11647 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
11648 gsi_remove (&si, true);
11649 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11650
11651 if (exit_bb)
11652 {
11653 si = gsi_last_bb (exit_bb);
11654 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11655 gsi_remove (&si, true);
11656 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11657 }
11658 }
11659
11660 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11661 operation as a normal volatile load. */
11662
11663 static bool
11664 expand_omp_atomic_load (basic_block load_bb, tree addr,
11665 tree loaded_val, int index)
11666 {
11667 enum built_in_function tmpbase;
11668 gimple_stmt_iterator gsi;
11669 basic_block store_bb;
11670 location_t loc;
11671 gimple *stmt;
11672 tree decl, call, type, itype;
11673
11674 gsi = gsi_last_bb (load_bb);
11675 stmt = gsi_stmt (gsi);
11676 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11677 loc = gimple_location (stmt);
11678
11679 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11680 is smaller than word size, then expand_atomic_load assumes that the load
11681 is atomic. We could avoid the builtin entirely in this case. */
11682
11683 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11684 decl = builtin_decl_explicit (tmpbase);
11685 if (decl == NULL_TREE)
11686 return false;
11687
11688 type = TREE_TYPE (loaded_val);
11689 itype = TREE_TYPE (TREE_TYPE (decl));
11690
11691 call = build_call_expr_loc (loc, decl, 2, addr,
11692 build_int_cst (NULL,
11693 gimple_omp_atomic_seq_cst_p (stmt)
11694 ? MEMMODEL_SEQ_CST
11695 : MEMMODEL_RELAXED));
11696 if (!useless_type_conversion_p (type, itype))
11697 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11698 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11699
11700 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11701 gsi_remove (&gsi, true);
11702
11703 store_bb = single_succ (load_bb);
11704 gsi = gsi_last_bb (store_bb);
11705 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11706 gsi_remove (&gsi, true);
11707
11708 if (gimple_in_ssa_p (cfun))
11709 update_ssa (TODO_update_ssa_no_phi);
11710
11711 return true;
11712 }
11713
11714 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11715 operation as a normal volatile store. */
11716
11717 static bool
11718 expand_omp_atomic_store (basic_block load_bb, tree addr,
11719 tree loaded_val, tree stored_val, int index)
11720 {
11721 enum built_in_function tmpbase;
11722 gimple_stmt_iterator gsi;
11723 basic_block store_bb = single_succ (load_bb);
11724 location_t loc;
11725 gimple *stmt;
11726 tree decl, call, type, itype;
11727 machine_mode imode;
11728 bool exchange;
11729
11730 gsi = gsi_last_bb (load_bb);
11731 stmt = gsi_stmt (gsi);
11732 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11733
11734 /* If the load value is needed, then this isn't a store but an exchange. */
11735 exchange = gimple_omp_atomic_need_value_p (stmt);
11736
11737 gsi = gsi_last_bb (store_bb);
11738 stmt = gsi_stmt (gsi);
11739 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
11740 loc = gimple_location (stmt);
11741
11742 /* ??? If the target does not implement atomic_store_optab[mode], and mode
11743 is smaller than word size, then expand_atomic_store assumes that the store
11744 is atomic. We could avoid the builtin entirely in this case. */
11745
11746 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
11747 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
11748 decl = builtin_decl_explicit (tmpbase);
11749 if (decl == NULL_TREE)
11750 return false;
11751
11752 type = TREE_TYPE (stored_val);
11753
11754 /* Dig out the type of the function's second argument. */
11755 itype = TREE_TYPE (decl);
11756 itype = TYPE_ARG_TYPES (itype);
11757 itype = TREE_CHAIN (itype);
11758 itype = TREE_VALUE (itype);
11759 imode = TYPE_MODE (itype);
11760
11761 if (exchange && !can_atomic_exchange_p (imode, true))
11762 return false;
11763
11764 if (!useless_type_conversion_p (itype, type))
11765 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
11766 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
11767 build_int_cst (NULL,
11768 gimple_omp_atomic_seq_cst_p (stmt)
11769 ? MEMMODEL_SEQ_CST
11770 : MEMMODEL_RELAXED));
11771 if (exchange)
11772 {
11773 if (!useless_type_conversion_p (type, itype))
11774 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11775 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11776 }
11777
11778 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11779 gsi_remove (&gsi, true);
11780
11781 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
11782 gsi = gsi_last_bb (load_bb);
11783 gsi_remove (&gsi, true);
11784
11785 if (gimple_in_ssa_p (cfun))
11786 update_ssa (TODO_update_ssa_no_phi);
11787
11788 return true;
11789 }
11790
11791 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11792 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
11793 size of the data type, and thus usable to find the index of the builtin
11794 decl. Returns false if the expression is not of the proper form. */
11795
11796 static bool
11797 expand_omp_atomic_fetch_op (basic_block load_bb,
11798 tree addr, tree loaded_val,
11799 tree stored_val, int index)
11800 {
11801 enum built_in_function oldbase, newbase, tmpbase;
11802 tree decl, itype, call;
11803 tree lhs, rhs;
11804 basic_block store_bb = single_succ (load_bb);
11805 gimple_stmt_iterator gsi;
11806 gimple *stmt;
11807 location_t loc;
11808 enum tree_code code;
11809 bool need_old, need_new;
11810 machine_mode imode;
11811 bool seq_cst;
11812
11813 /* We expect to find the following sequences:
11814
11815 load_bb:
11816 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
11817
11818 store_bb:
11819 val = tmp OP something; (or: something OP tmp)
11820 GIMPLE_OMP_STORE (val)
11821
11822 ???FIXME: Allow a more flexible sequence.
11823 Perhaps use data flow to pick the statements.
11824
11825 */
11826
11827 gsi = gsi_after_labels (store_bb);
11828 stmt = gsi_stmt (gsi);
11829 loc = gimple_location (stmt);
11830 if (!is_gimple_assign (stmt))
11831 return false;
11832 gsi_next (&gsi);
11833 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
11834 return false;
11835 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
11836 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
11837 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
11838 gcc_checking_assert (!need_old || !need_new);
11839
11840 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
11841 return false;
11842
11843 /* Check for one of the supported fetch-op operations. */
11844 code = gimple_assign_rhs_code (stmt);
11845 switch (code)
11846 {
11847 case PLUS_EXPR:
11848 case POINTER_PLUS_EXPR:
11849 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
11850 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
11851 break;
11852 case MINUS_EXPR:
11853 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
11854 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
11855 break;
11856 case BIT_AND_EXPR:
11857 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
11858 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
11859 break;
11860 case BIT_IOR_EXPR:
11861 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
11862 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
11863 break;
11864 case BIT_XOR_EXPR:
11865 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
11866 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
11867 break;
11868 default:
11869 return false;
11870 }
11871
11872 /* Make sure the expression is of the proper form. */
11873 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
11874 rhs = gimple_assign_rhs2 (stmt);
11875 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
11876 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
11877 rhs = gimple_assign_rhs1 (stmt);
11878 else
11879 return false;
11880
11881 tmpbase = ((enum built_in_function)
11882 ((need_new ? newbase : oldbase) + index + 1));
11883 decl = builtin_decl_explicit (tmpbase);
11884 if (decl == NULL_TREE)
11885 return false;
11886 itype = TREE_TYPE (TREE_TYPE (decl));
11887 imode = TYPE_MODE (itype);
11888
11889 /* We could test all of the various optabs involved, but the fact of the
11890 matter is that (with the exception of i486 vs i586 and xadd) all targets
11891 that support any atomic operaton optab also implements compare-and-swap.
11892 Let optabs.c take care of expanding any compare-and-swap loop. */
11893 if (!can_compare_and_swap_p (imode, true))
11894 return false;
11895
11896 gsi = gsi_last_bb (load_bb);
11897 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
11898
11899 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
11900 It only requires that the operation happen atomically. Thus we can
11901 use the RELAXED memory model. */
11902 call = build_call_expr_loc (loc, decl, 3, addr,
11903 fold_convert_loc (loc, itype, rhs),
11904 build_int_cst (NULL,
11905 seq_cst ? MEMMODEL_SEQ_CST
11906 : MEMMODEL_RELAXED));
11907
11908 if (need_old || need_new)
11909 {
11910 lhs = need_old ? loaded_val : stored_val;
11911 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
11912 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
11913 }
11914 else
11915 call = fold_convert_loc (loc, void_type_node, call);
11916 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11917 gsi_remove (&gsi, true);
11918
11919 gsi = gsi_last_bb (store_bb);
11920 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11921 gsi_remove (&gsi, true);
11922 gsi = gsi_last_bb (store_bb);
11923 gsi_remove (&gsi, true);
11924
11925 if (gimple_in_ssa_p (cfun))
11926 update_ssa (TODO_update_ssa_no_phi);
11927
11928 return true;
11929 }
11930
11931 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
11932
11933 oldval = *addr;
11934 repeat:
11935 newval = rhs; // with oldval replacing *addr in rhs
11936 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
11937 if (oldval != newval)
11938 goto repeat;
11939
11940 INDEX is log2 of the size of the data type, and thus usable to find the
11941 index of the builtin decl. */
11942
11943 static bool
11944 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
11945 tree addr, tree loaded_val, tree stored_val,
11946 int index)
11947 {
11948 tree loadedi, storedi, initial, new_storedi, old_vali;
11949 tree type, itype, cmpxchg, iaddr;
11950 gimple_stmt_iterator si;
11951 basic_block loop_header = single_succ (load_bb);
11952 gimple *phi, *stmt;
11953 edge e;
11954 enum built_in_function fncode;
11955
11956 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
11957 order to use the RELAXED memory model effectively. */
11958 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
11959 + index + 1);
11960 cmpxchg = builtin_decl_explicit (fncode);
11961 if (cmpxchg == NULL_TREE)
11962 return false;
11963 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
11964 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
11965
11966 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
11967 return false;
11968
11969 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
11970 si = gsi_last_bb (load_bb);
11971 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
11972
11973 /* For floating-point values, we'll need to view-convert them to integers
11974 so that we can perform the atomic compare and swap. Simplify the
11975 following code by always setting up the "i"ntegral variables. */
11976 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
11977 {
11978 tree iaddr_val;
11979
11980 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
11981 true));
11982 iaddr_val
11983 = force_gimple_operand_gsi (&si,
11984 fold_convert (TREE_TYPE (iaddr), addr),
11985 false, NULL_TREE, true, GSI_SAME_STMT);
11986 stmt = gimple_build_assign (iaddr, iaddr_val);
11987 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
11988 loadedi = create_tmp_var (itype);
11989 if (gimple_in_ssa_p (cfun))
11990 loadedi = make_ssa_name (loadedi);
11991 }
11992 else
11993 {
11994 iaddr = addr;
11995 loadedi = loaded_val;
11996 }
11997
11998 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11999 tree loaddecl = builtin_decl_explicit (fncode);
12000 if (loaddecl)
12001 initial
12002 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12003 build_call_expr (loaddecl, 2, iaddr,
12004 build_int_cst (NULL_TREE,
12005 MEMMODEL_RELAXED)));
12006 else
12007 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12008 build_int_cst (TREE_TYPE (iaddr), 0));
12009
12010 initial
12011 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12012 GSI_SAME_STMT);
12013
12014 /* Move the value to the LOADEDI temporary. */
12015 if (gimple_in_ssa_p (cfun))
12016 {
12017 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
12018 phi = create_phi_node (loadedi, loop_header);
12019 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12020 initial);
12021 }
12022 else
12023 gsi_insert_before (&si,
12024 gimple_build_assign (loadedi, initial),
12025 GSI_SAME_STMT);
12026 if (loadedi != loaded_val)
12027 {
12028 gimple_stmt_iterator gsi2;
12029 tree x;
12030
12031 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
12032 gsi2 = gsi_start_bb (loop_header);
12033 if (gimple_in_ssa_p (cfun))
12034 {
12035 gassign *stmt;
12036 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12037 true, GSI_SAME_STMT);
12038 stmt = gimple_build_assign (loaded_val, x);
12039 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
12040 }
12041 else
12042 {
12043 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12044 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12045 true, GSI_SAME_STMT);
12046 }
12047 }
12048 gsi_remove (&si, true);
12049
12050 si = gsi_last_bb (store_bb);
12051 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12052
12053 if (iaddr == addr)
12054 storedi = stored_val;
12055 else
12056 storedi =
12057 force_gimple_operand_gsi (&si,
12058 build1 (VIEW_CONVERT_EXPR, itype,
12059 stored_val), true, NULL_TREE, true,
12060 GSI_SAME_STMT);
12061
12062 /* Build the compare&swap statement. */
12063 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
12064 new_storedi = force_gimple_operand_gsi (&si,
12065 fold_convert (TREE_TYPE (loadedi),
12066 new_storedi),
12067 true, NULL_TREE,
12068 true, GSI_SAME_STMT);
12069
12070 if (gimple_in_ssa_p (cfun))
12071 old_vali = loadedi;
12072 else
12073 {
12074 old_vali = create_tmp_var (TREE_TYPE (loadedi));
12075 stmt = gimple_build_assign (old_vali, loadedi);
12076 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12077
12078 stmt = gimple_build_assign (loadedi, new_storedi);
12079 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12080 }
12081
12082 /* Note that we always perform the comparison as an integer, even for
12083 floating point. This allows the atomic operation to properly
12084 succeed even with NaNs and -0.0. */
12085 stmt = gimple_build_cond_empty
12086 (build2 (NE_EXPR, boolean_type_node,
12087 new_storedi, old_vali));
12088 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12089
12090 /* Update cfg. */
12091 e = single_succ_edge (store_bb);
12092 e->flags &= ~EDGE_FALLTHRU;
12093 e->flags |= EDGE_FALSE_VALUE;
12094
12095 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12096
12097 /* Copy the new value to loadedi (we already did that before the condition
12098 if we are not in SSA). */
12099 if (gimple_in_ssa_p (cfun))
12100 {
12101 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
12102 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
12103 }
12104
12105 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12106 gsi_remove (&si, true);
12107
12108 struct loop *loop = alloc_loop ();
12109 loop->header = loop_header;
12110 loop->latch = store_bb;
12111 add_loop (loop, loop_header->loop_father);
12112
12113 if (gimple_in_ssa_p (cfun))
12114 update_ssa (TODO_update_ssa_no_phi);
12115
12116 return true;
12117 }
12118
12119 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12120
12121 GOMP_atomic_start ();
12122 *addr = rhs;
12123 GOMP_atomic_end ();
12124
12125 The result is not globally atomic, but works so long as all parallel
12126 references are within #pragma omp atomic directives. According to
12127 responses received from omp@openmp.org, appears to be within spec.
12128 Which makes sense, since that's how several other compilers handle
12129 this situation as well.
12130 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12131 expanding. STORED_VAL is the operand of the matching
12132 GIMPLE_OMP_ATOMIC_STORE.
12133
12134 We replace
12135 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
12136 loaded_val = *addr;
12137
12138 and replace
12139 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
12140 *addr = stored_val;
12141 */
12142
12143 static bool
12144 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12145 tree addr, tree loaded_val, tree stored_val)
12146 {
12147 gimple_stmt_iterator si;
12148 gassign *stmt;
12149 tree t;
12150
12151 si = gsi_last_bb (load_bb);
12152 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12153
12154 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
12155 t = build_call_expr (t, 0);
12156 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12157
12158 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
12159 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12160 gsi_remove (&si, true);
12161
12162 si = gsi_last_bb (store_bb);
12163 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12164
12165 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12166 stored_val);
12167 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12168
12169 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
12170 t = build_call_expr (t, 0);
12171 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12172 gsi_remove (&si, true);
12173
12174 if (gimple_in_ssa_p (cfun))
12175 update_ssa (TODO_update_ssa_no_phi);
12176 return true;
12177 }
12178
12179 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12180 using expand_omp_atomic_fetch_op. If it failed, we try to
12181 call expand_omp_atomic_pipeline, and if it fails too, the
12182 ultimate fallback is wrapping the operation in a mutex
12183 (expand_omp_atomic_mutex). REGION is the atomic region built
12184 by build_omp_regions_1(). */
12185
12186 static void
12187 expand_omp_atomic (struct omp_region *region)
12188 {
12189 basic_block load_bb = region->entry, store_bb = region->exit;
12190 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12191 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
12192 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12193 tree addr = gimple_omp_atomic_load_rhs (load);
12194 tree stored_val = gimple_omp_atomic_store_val (store);
12195 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12196 HOST_WIDE_INT index;
12197
12198 /* Make sure the type is one of the supported sizes. */
12199 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
12200 index = exact_log2 (index);
12201 if (index >= 0 && index <= 4)
12202 {
12203 unsigned int align = TYPE_ALIGN_UNIT (type);
12204
12205 /* __sync builtins require strict data alignment. */
12206 if (exact_log2 (align) >= index)
12207 {
12208 /* Atomic load. */
12209 if (loaded_val == stored_val
12210 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12211 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12212 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12213 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
12214 return;
12215
12216 /* Atomic store. */
12217 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12218 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12219 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12220 && store_bb == single_succ (load_bb)
12221 && first_stmt (store_bb) == store
12222 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12223 stored_val, index))
12224 return;
12225
12226 /* When possible, use specialized atomic update functions. */
12227 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
12228 && store_bb == single_succ (load_bb)
12229 && expand_omp_atomic_fetch_op (load_bb, addr,
12230 loaded_val, stored_val, index))
12231 return;
12232
12233 /* If we don't have specialized __sync builtins, try and implement
12234 as a compare and swap loop. */
12235 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12236 loaded_val, stored_val, index))
12237 return;
12238 }
12239 }
12240
12241 /* The ultimate fallback is wrapping the operation in a mutex. */
12242 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12243 }
12244
12245
12246 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
12247 macro on gomp-constants.h. We do not check for overflow. */
12248
12249 static tree
12250 oacc_launch_pack (unsigned code, tree device, unsigned op)
12251 {
12252 tree res;
12253
12254 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12255 if (device)
12256 {
12257 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12258 device, build_int_cst (unsigned_type_node,
12259 GOMP_LAUNCH_DEVICE_SHIFT));
12260 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12261 }
12262 return res;
12263 }
12264
12265 /* Look for compute grid dimension clauses and convert to an attribute
12266 attached to FN. This permits the target-side code to (a) massage
12267 the dimensions, (b) emit that data and (c) optimize. Non-constant
12268 dimensions are pushed onto ARGS.
12269
12270 The attribute value is a TREE_LIST. A set of dimensions is
12271 represented as a list of INTEGER_CST. Those that are runtime
12272 exprs are represented as an INTEGER_CST of zero.
12273
12274 TOOO. Normally the attribute will just contain a single such list. If
12275 however it contains a list of lists, this will represent the use of
12276 device_type. Each member of the outer list is an assoc list of
12277 dimensions, keyed by the device type. The first entry will be the
12278 default. Well, that's the plan. */
12279
12280 #define OACC_FN_ATTRIB "oacc function"
12281
12282 /* Replace any existing oacc fn attribute with updated dimensions. */
12283
12284 void
12285 replace_oacc_fn_attrib (tree fn, tree dims)
12286 {
12287 tree ident = get_identifier (OACC_FN_ATTRIB);
12288 tree attribs = DECL_ATTRIBUTES (fn);
12289
12290 /* If we happen to be present as the first attrib, drop it. */
12291 if (attribs && TREE_PURPOSE (attribs) == ident)
12292 attribs = TREE_CHAIN (attribs);
12293 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12294 }
12295
12296 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12297 function attribute. Push any that are non-constant onto the ARGS
12298 list, along with an appropriate GOMP_LAUNCH_DIM tag. */
12299
12300 static void
12301 set_oacc_fn_attrib (tree fn, tree clauses, vec<tree> *args)
12302 {
12303 /* Must match GOMP_DIM ordering. */
12304 static const omp_clause_code ids[]
12305 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12306 OMP_CLAUSE_VECTOR_LENGTH };
12307 unsigned ix;
12308 tree dims[GOMP_DIM_MAX];
12309 tree attr = NULL_TREE;
12310 unsigned non_const = 0;
12311
12312 for (ix = GOMP_DIM_MAX; ix--;)
12313 {
12314 tree clause = find_omp_clause (clauses, ids[ix]);
12315 tree dim = NULL_TREE;
12316
12317 if (clause)
12318 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12319 dims[ix] = dim;
12320 if (dim && TREE_CODE (dim) != INTEGER_CST)
12321 {
12322 dim = integer_zero_node;
12323 non_const |= GOMP_DIM_MASK (ix);
12324 }
12325 attr = tree_cons (NULL_TREE, dim, attr);
12326 }
12327
12328 replace_oacc_fn_attrib (fn, attr);
12329
12330 if (non_const)
12331 {
12332 /* Push a dynamic argument set. */
12333 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12334 NULL_TREE, non_const));
12335 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12336 if (non_const & GOMP_DIM_MASK (ix))
12337 args->safe_push (dims[ix]);
12338 }
12339 }
12340
12341 /* Process the routine's dimension clauess to generate an attribute
12342 value. Issue diagnostics as appropriate. We default to SEQ
12343 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12344 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12345 can have a loop partitioned on it. non-zero indicates
12346 yes, zero indicates no. By construction once a non-zero has been
12347 reached, further inner dimensions must also be non-zero. We set
12348 TREE_VALUE to zero for the dimensions that may be partitioned and
12349 1 for the other ones -- if a loop is (erroneously) spawned at
12350 an outer level, we don't want to try and partition it. */
12351
12352 tree
12353 build_oacc_routine_dims (tree clauses)
12354 {
12355 /* Must match GOMP_DIM ordering. */
12356 static const omp_clause_code ids[] =
12357 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12358 int ix;
12359 int level = -1;
12360
12361 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12362 for (ix = GOMP_DIM_MAX + 1; ix--;)
12363 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12364 {
12365 if (level >= 0)
12366 error_at (OMP_CLAUSE_LOCATION (clauses),
12367 "multiple loop axes specified for routine");
12368 level = ix;
12369 break;
12370 }
12371
12372 /* Default to SEQ. */
12373 if (level < 0)
12374 level = GOMP_DIM_MAX;
12375
12376 tree dims = NULL_TREE;
12377
12378 for (ix = GOMP_DIM_MAX; ix--;)
12379 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12380 build_int_cst (integer_type_node, ix < level), dims);
12381
12382 return dims;
12383 }
12384
12385 /* Retrieve the oacc function attrib and return it. Non-oacc
12386 functions will return NULL. */
12387
12388 tree
12389 get_oacc_fn_attrib (tree fn)
12390 {
12391 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12392 }
12393
12394 /* Extract an oacc execution dimension from FN. FN must be an
12395 offloaded function or routine that has already had its execution
12396 dimensions lowered to the target-specific values. */
12397
12398 int
12399 get_oacc_fn_dim_size (tree fn, int axis)
12400 {
12401 tree attrs = get_oacc_fn_attrib (fn);
12402
12403 gcc_assert (axis < GOMP_DIM_MAX);
12404
12405 tree dims = TREE_VALUE (attrs);
12406 while (axis--)
12407 dims = TREE_CHAIN (dims);
12408
12409 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12410
12411 return size;
12412 }
12413
12414 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12415 IFN_GOACC_DIM_SIZE call. */
12416
12417 int
12418 get_oacc_ifn_dim_arg (const gimple *stmt)
12419 {
12420 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12421 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12422 tree arg = gimple_call_arg (stmt, 0);
12423 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12424
12425 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12426 return (int) axis;
12427 }
12428
12429 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
12430
12431 static void
12432 expand_omp_target (struct omp_region *region)
12433 {
12434 basic_block entry_bb, exit_bb, new_bb;
12435 struct function *child_cfun;
12436 tree child_fn, block, t;
12437 gimple_stmt_iterator gsi;
12438 gomp_target *entry_stmt;
12439 gimple *stmt;
12440 edge e;
12441 bool offloaded, data_region;
12442
12443 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
12444 new_bb = region->entry;
12445
12446 offloaded = is_gimple_omp_offloaded (entry_stmt);
12447 switch (gimple_omp_target_kind (entry_stmt))
12448 {
12449 case GF_OMP_TARGET_KIND_REGION:
12450 case GF_OMP_TARGET_KIND_UPDATE:
12451 case GF_OMP_TARGET_KIND_ENTER_DATA:
12452 case GF_OMP_TARGET_KIND_EXIT_DATA:
12453 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12454 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12455 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12456 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12457 data_region = false;
12458 break;
12459 case GF_OMP_TARGET_KIND_DATA:
12460 case GF_OMP_TARGET_KIND_OACC_DATA:
12461 data_region = true;
12462 break;
12463 default:
12464 gcc_unreachable ();
12465 }
12466
12467 child_fn = NULL_TREE;
12468 child_cfun = NULL;
12469 if (offloaded)
12470 {
12471 child_fn = gimple_omp_target_child_fn (entry_stmt);
12472 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
12473 }
12474
12475 /* Supported by expand_omp_taskreg, but not here. */
12476 if (child_cfun != NULL)
12477 gcc_checking_assert (!child_cfun->cfg);
12478 gcc_checking_assert (!gimple_in_ssa_p (cfun));
12479
12480 entry_bb = region->entry;
12481 exit_bb = region->exit;
12482
12483 if (offloaded)
12484 {
12485 unsigned srcidx, dstidx, num;
12486
12487 /* If the offloading region needs data sent from the parent
12488 function, then the very first statement (except possible
12489 tree profile counter updates) of the offloading body
12490 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
12491 &.OMP_DATA_O is passed as an argument to the child function,
12492 we need to replace it with the argument as seen by the child
12493 function.
12494
12495 In most cases, this will end up being the identity assignment
12496 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
12497 a function call that has been inlined, the original PARM_DECL
12498 .OMP_DATA_I may have been converted into a different local
12499 variable. In which case, we need to keep the assignment. */
12500 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
12501 if (data_arg)
12502 {
12503 basic_block entry_succ_bb = single_succ (entry_bb);
12504 gimple_stmt_iterator gsi;
12505 tree arg;
12506 gimple *tgtcopy_stmt = NULL;
12507 tree sender = TREE_VEC_ELT (data_arg, 0);
12508
12509 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
12510 {
12511 gcc_assert (!gsi_end_p (gsi));
12512 stmt = gsi_stmt (gsi);
12513 if (gimple_code (stmt) != GIMPLE_ASSIGN)
12514 continue;
12515
12516 if (gimple_num_ops (stmt) == 2)
12517 {
12518 tree arg = gimple_assign_rhs1 (stmt);
12519
12520 /* We're ignoring the subcode because we're
12521 effectively doing a STRIP_NOPS. */
12522
12523 if (TREE_CODE (arg) == ADDR_EXPR
12524 && TREE_OPERAND (arg, 0) == sender)
12525 {
12526 tgtcopy_stmt = stmt;
12527 break;
12528 }
12529 }
12530 }
12531
12532 gcc_assert (tgtcopy_stmt != NULL);
12533 arg = DECL_ARGUMENTS (child_fn);
12534
12535 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
12536 gsi_remove (&gsi, true);
12537 }
12538
12539 /* Declare local variables needed in CHILD_CFUN. */
12540 block = DECL_INITIAL (child_fn);
12541 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
12542 /* The gimplifier could record temporaries in the offloading block
12543 rather than in containing function's local_decls chain,
12544 which would mean cgraph missed finalizing them. Do it now. */
12545 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
12546 if (TREE_CODE (t) == VAR_DECL
12547 && TREE_STATIC (t)
12548 && !DECL_EXTERNAL (t))
12549 varpool_node::finalize_decl (t);
12550 DECL_SAVED_TREE (child_fn) = NULL;
12551 /* We'll create a CFG for child_fn, so no gimple body is needed. */
12552 gimple_set_body (child_fn, NULL);
12553 TREE_USED (block) = 1;
12554
12555 /* Reset DECL_CONTEXT on function arguments. */
12556 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
12557 DECL_CONTEXT (t) = child_fn;
12558
12559 /* Split ENTRY_BB at GIMPLE_*,
12560 so that it can be moved to the child function. */
12561 gsi = gsi_last_bb (entry_bb);
12562 stmt = gsi_stmt (gsi);
12563 gcc_assert (stmt
12564 && gimple_code (stmt) == gimple_code (entry_stmt));
12565 e = split_block (entry_bb, stmt);
12566 gsi_remove (&gsi, true);
12567 entry_bb = e->dest;
12568 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
12569
12570 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
12571 if (exit_bb)
12572 {
12573 gsi = gsi_last_bb (exit_bb);
12574 gcc_assert (!gsi_end_p (gsi)
12575 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
12576 stmt = gimple_build_return (NULL);
12577 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
12578 gsi_remove (&gsi, true);
12579 }
12580
12581 /* Move the offloading region into CHILD_CFUN. */
12582
12583 block = gimple_block (entry_stmt);
12584
12585 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
12586 if (exit_bb)
12587 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
12588 /* When the OMP expansion process cannot guarantee an up-to-date
12589 loop tree arrange for the child function to fixup loops. */
12590 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12591 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
12592
12593 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
12594 num = vec_safe_length (child_cfun->local_decls);
12595 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
12596 {
12597 t = (*child_cfun->local_decls)[srcidx];
12598 if (DECL_CONTEXT (t) == cfun->decl)
12599 continue;
12600 if (srcidx != dstidx)
12601 (*child_cfun->local_decls)[dstidx] = t;
12602 dstidx++;
12603 }
12604 if (dstidx != num)
12605 vec_safe_truncate (child_cfun->local_decls, dstidx);
12606
12607 /* Inform the callgraph about the new function. */
12608 child_cfun->curr_properties = cfun->curr_properties;
12609 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
12610 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
12611 cgraph_node *node = cgraph_node::get_create (child_fn);
12612 node->parallelized_function = 1;
12613 cgraph_node::add_new_function (child_fn, true);
12614
12615 #ifdef ENABLE_OFFLOADING
12616 /* Add the new function to the offload table. */
12617 vec_safe_push (offload_funcs, child_fn);
12618 #endif
12619
12620 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
12621 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
12622
12623 /* Fix the callgraph edges for child_cfun. Those for cfun will be
12624 fixed in a following pass. */
12625 push_cfun (child_cfun);
12626 if (need_asm)
12627 assign_assembler_name_if_neeeded (child_fn);
12628 cgraph_edge::rebuild_edges ();
12629
12630 #ifdef ENABLE_OFFLOADING
12631 /* Prevent IPA from removing child_fn as unreachable, since there are no
12632 refs from the parent function to child_fn in offload LTO mode. */
12633 cgraph_node::get (child_fn)->mark_force_output ();
12634 #endif
12635
12636 /* Some EH regions might become dead, see PR34608. If
12637 pass_cleanup_cfg isn't the first pass to happen with the
12638 new child, these dead EH edges might cause problems.
12639 Clean them up now. */
12640 if (flag_exceptions)
12641 {
12642 basic_block bb;
12643 bool changed = false;
12644
12645 FOR_EACH_BB_FN (bb, cfun)
12646 changed |= gimple_purge_dead_eh_edges (bb);
12647 if (changed)
12648 cleanup_tree_cfg ();
12649 }
12650 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
12651 verify_loop_structure ();
12652 pop_cfun ();
12653
12654 if (dump_file && !gimple_in_ssa_p (cfun))
12655 {
12656 omp_any_child_fn_dumped = true;
12657 dump_function_header (dump_file, child_fn, dump_flags);
12658 dump_function_to_file (child_fn, dump_file, dump_flags);
12659 }
12660 }
12661
12662 /* Emit a library call to launch the offloading region, or do data
12663 transfers. */
12664 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
12665 enum built_in_function start_ix;
12666 location_t clause_loc;
12667 unsigned int flags_i = 0;
12668
12669 switch (gimple_omp_target_kind (entry_stmt))
12670 {
12671 case GF_OMP_TARGET_KIND_REGION:
12672 start_ix = BUILT_IN_GOMP_TARGET;
12673 break;
12674 case GF_OMP_TARGET_KIND_DATA:
12675 start_ix = BUILT_IN_GOMP_TARGET_DATA;
12676 break;
12677 case GF_OMP_TARGET_KIND_UPDATE:
12678 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
12679 break;
12680 case GF_OMP_TARGET_KIND_ENTER_DATA:
12681 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12682 break;
12683 case GF_OMP_TARGET_KIND_EXIT_DATA:
12684 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
12685 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
12686 break;
12687 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
12688 case GF_OMP_TARGET_KIND_OACC_KERNELS:
12689 start_ix = BUILT_IN_GOACC_PARALLEL;
12690 break;
12691 case GF_OMP_TARGET_KIND_OACC_DATA:
12692 start_ix = BUILT_IN_GOACC_DATA_START;
12693 break;
12694 case GF_OMP_TARGET_KIND_OACC_UPDATE:
12695 start_ix = BUILT_IN_GOACC_UPDATE;
12696 break;
12697 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
12698 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
12699 break;
12700 default:
12701 gcc_unreachable ();
12702 }
12703
12704 clauses = gimple_omp_target_clauses (entry_stmt);
12705
12706 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
12707 library choose) and there is no conditional. */
12708 cond = NULL_TREE;
12709 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
12710
12711 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
12712 if (c)
12713 cond = OMP_CLAUSE_IF_EXPR (c);
12714
12715 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
12716 if (c)
12717 {
12718 /* Even if we pass it to all library function calls, it is currently only
12719 defined/used for the OpenMP target ones. */
12720 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
12721 || start_ix == BUILT_IN_GOMP_TARGET_DATA
12722 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
12723 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
12724
12725 device = OMP_CLAUSE_DEVICE_ID (c);
12726 clause_loc = OMP_CLAUSE_LOCATION (c);
12727 }
12728 else
12729 clause_loc = gimple_location (entry_stmt);
12730
12731 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
12732 if (c)
12733 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
12734
12735 /* Ensure 'device' is of the correct type. */
12736 device = fold_convert_loc (clause_loc, integer_type_node, device);
12737
12738 /* If we found the clause 'if (cond)', build
12739 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
12740 if (cond)
12741 {
12742 cond = gimple_boolify (cond);
12743
12744 basic_block cond_bb, then_bb, else_bb;
12745 edge e;
12746 tree tmp_var;
12747
12748 tmp_var = create_tmp_var (TREE_TYPE (device));
12749 if (offloaded)
12750 e = split_block_after_labels (new_bb);
12751 else
12752 {
12753 gsi = gsi_last_bb (new_bb);
12754 gsi_prev (&gsi);
12755 e = split_block (new_bb, gsi_stmt (gsi));
12756 }
12757 cond_bb = e->src;
12758 new_bb = e->dest;
12759 remove_edge (e);
12760
12761 then_bb = create_empty_bb (cond_bb);
12762 else_bb = create_empty_bb (then_bb);
12763 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
12764 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
12765
12766 stmt = gimple_build_cond_empty (cond);
12767 gsi = gsi_last_bb (cond_bb);
12768 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12769
12770 gsi = gsi_start_bb (then_bb);
12771 stmt = gimple_build_assign (tmp_var, device);
12772 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12773
12774 gsi = gsi_start_bb (else_bb);
12775 stmt = gimple_build_assign (tmp_var,
12776 build_int_cst (integer_type_node,
12777 GOMP_DEVICE_HOST_FALLBACK));
12778 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
12779
12780 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
12781 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
12782 add_bb_to_loop (then_bb, cond_bb->loop_father);
12783 add_bb_to_loop (else_bb, cond_bb->loop_father);
12784 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
12785 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
12786
12787 device = tmp_var;
12788 }
12789
12790 gsi = gsi_last_bb (new_bb);
12791 t = gimple_omp_target_data_arg (entry_stmt);
12792 if (t == NULL)
12793 {
12794 t1 = size_zero_node;
12795 t2 = build_zero_cst (ptr_type_node);
12796 t3 = t2;
12797 t4 = t2;
12798 }
12799 else
12800 {
12801 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
12802 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
12803 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
12804 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
12805 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
12806 }
12807
12808 gimple *g;
12809 bool tagging = false;
12810 /* The maximum number used by any start_ix, without varargs. */
12811 auto_vec<tree, 11> args;
12812 args.quick_push (device);
12813 if (offloaded)
12814 args.quick_push (build_fold_addr_expr (child_fn));
12815 args.quick_push (t1);
12816 args.quick_push (t2);
12817 args.quick_push (t3);
12818 args.quick_push (t4);
12819 switch (start_ix)
12820 {
12821 case BUILT_IN_GOACC_DATA_START:
12822 case BUILT_IN_GOMP_TARGET_DATA:
12823 break;
12824 case BUILT_IN_GOMP_TARGET:
12825 case BUILT_IN_GOMP_TARGET_UPDATE:
12826 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
12827 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
12828 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
12829 if (c)
12830 depend = OMP_CLAUSE_DECL (c);
12831 else
12832 depend = build_int_cst (ptr_type_node, 0);
12833 args.quick_push (depend);
12834 if (start_ix == BUILT_IN_GOMP_TARGET)
12835 {
12836 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12837 if (c)
12838 {
12839 t = fold_convert (integer_type_node,
12840 OMP_CLAUSE_NUM_TEAMS_EXPR (c));
12841 t = force_gimple_operand_gsi (&gsi, t, true, NULL,
12842 true, GSI_SAME_STMT);
12843 }
12844 else
12845 t = integer_minus_one_node;
12846 args.quick_push (t);
12847 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12848 if (c)
12849 {
12850 t = fold_convert (integer_type_node,
12851 OMP_CLAUSE_THREAD_LIMIT_EXPR (c));
12852 t = force_gimple_operand_gsi (&gsi, t, true, NULL,
12853 true, GSI_SAME_STMT);
12854 }
12855 else
12856 t = integer_minus_one_node;
12857 args.quick_push (t);
12858 }
12859 break;
12860 case BUILT_IN_GOACC_PARALLEL:
12861 {
12862 set_oacc_fn_attrib (child_fn, clauses, &args);
12863 tagging = true;
12864 }
12865 /* FALLTHRU */
12866 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
12867 case BUILT_IN_GOACC_UPDATE:
12868 {
12869 tree t_async = NULL_TREE;
12870
12871 /* If present, use the value specified by the respective
12872 clause, making sure that is of the correct type. */
12873 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
12874 if (c)
12875 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
12876 integer_type_node,
12877 OMP_CLAUSE_ASYNC_EXPR (c));
12878 else if (!tagging)
12879 /* Default values for t_async. */
12880 t_async = fold_convert_loc (gimple_location (entry_stmt),
12881 integer_type_node,
12882 build_int_cst (integer_type_node,
12883 GOMP_ASYNC_SYNC));
12884 if (tagging && t_async)
12885 {
12886 unsigned HOST_WIDE_INT i_async;
12887
12888 if (TREE_CODE (t_async) == INTEGER_CST)
12889 {
12890 /* See if we can pack the async arg in to the tag's
12891 operand. */
12892 i_async = TREE_INT_CST_LOW (t_async);
12893
12894 if (i_async < GOMP_LAUNCH_OP_MAX)
12895 t_async = NULL_TREE;
12896 }
12897 if (t_async)
12898 i_async = GOMP_LAUNCH_OP_MAX;
12899 args.safe_push (oacc_launch_pack
12900 (GOMP_LAUNCH_ASYNC, NULL_TREE, i_async));
12901 }
12902 if (t_async)
12903 args.safe_push (t_async);
12904
12905 /* Save the argument index, and ... */
12906 unsigned t_wait_idx = args.length ();
12907 unsigned num_waits = 0;
12908 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
12909 if (!tagging || c)
12910 /* ... push a placeholder. */
12911 args.safe_push (integer_zero_node);
12912
12913 for (; c; c = OMP_CLAUSE_CHAIN (c))
12914 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
12915 {
12916 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
12917 integer_type_node,
12918 OMP_CLAUSE_WAIT_EXPR (c)));
12919 num_waits++;
12920 }
12921
12922 if (!tagging || num_waits)
12923 {
12924 tree len;
12925
12926 /* Now that we know the number, update the placeholder. */
12927 if (tagging)
12928 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
12929 else
12930 len = build_int_cst (integer_type_node, num_waits);
12931 len = fold_convert_loc (gimple_location (entry_stmt),
12932 unsigned_type_node, len);
12933 args[t_wait_idx] = len;
12934 }
12935 }
12936 break;
12937 default:
12938 gcc_unreachable ();
12939 }
12940 if (tagging)
12941 /* Push terminal marker - zero. */
12942 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
12943
12944 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
12945 gimple_set_location (g, gimple_location (entry_stmt));
12946 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
12947 if (!offloaded)
12948 {
12949 g = gsi_stmt (gsi);
12950 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
12951 gsi_remove (&gsi, true);
12952 }
12953 if (data_region && region->exit)
12954 {
12955 gsi = gsi_last_bb (region->exit);
12956 g = gsi_stmt (gsi);
12957 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
12958 gsi_remove (&gsi, true);
12959 }
12960 }
12961
12962
12963 /* Expand the parallel region tree rooted at REGION. Expansion
12964 proceeds in depth-first order. Innermost regions are expanded
12965 first. This way, parallel regions that require a new function to
12966 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
12967 internal dependencies in their body. */
12968
12969 static void
12970 expand_omp (struct omp_region *region)
12971 {
12972 omp_any_child_fn_dumped = false;
12973 while (region)
12974 {
12975 location_t saved_location;
12976 gimple *inner_stmt = NULL;
12977
12978 /* First, determine whether this is a combined parallel+workshare
12979 region. */
12980 if (region->type == GIMPLE_OMP_PARALLEL)
12981 determine_parallel_type (region);
12982
12983 if (region->type == GIMPLE_OMP_FOR
12984 && gimple_omp_for_combined_p (last_stmt (region->entry)))
12985 inner_stmt = last_stmt (region->inner->entry);
12986
12987 if (region->inner)
12988 expand_omp (region->inner);
12989
12990 saved_location = input_location;
12991 if (gimple_has_location (last_stmt (region->entry)))
12992 input_location = gimple_location (last_stmt (region->entry));
12993
12994 switch (region->type)
12995 {
12996 case GIMPLE_OMP_PARALLEL:
12997 case GIMPLE_OMP_TASK:
12998 expand_omp_taskreg (region);
12999 break;
13000
13001 case GIMPLE_OMP_FOR:
13002 expand_omp_for (region, inner_stmt);
13003 break;
13004
13005 case GIMPLE_OMP_SECTIONS:
13006 expand_omp_sections (region);
13007 break;
13008
13009 case GIMPLE_OMP_SECTION:
13010 /* Individual omp sections are handled together with their
13011 parent GIMPLE_OMP_SECTIONS region. */
13012 break;
13013
13014 case GIMPLE_OMP_SINGLE:
13015 expand_omp_single (region);
13016 break;
13017
13018 case GIMPLE_OMP_ORDERED:
13019 {
13020 gomp_ordered *ord_stmt
13021 = as_a <gomp_ordered *> (last_stmt (region->entry));
13022 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13023 OMP_CLAUSE_DEPEND))
13024 {
13025 /* We'll expand these when expanding corresponding
13026 worksharing region with ordered(n) clause. */
13027 gcc_assert (region->outer
13028 && region->outer->type == GIMPLE_OMP_FOR);
13029 region->ord_stmt = ord_stmt;
13030 break;
13031 }
13032 }
13033 /* FALLTHRU */
13034 case GIMPLE_OMP_MASTER:
13035 case GIMPLE_OMP_TASKGROUP:
13036 case GIMPLE_OMP_CRITICAL:
13037 case GIMPLE_OMP_TEAMS:
13038 expand_omp_synch (region);
13039 break;
13040
13041 case GIMPLE_OMP_ATOMIC_LOAD:
13042 expand_omp_atomic (region);
13043 break;
13044
13045 case GIMPLE_OMP_TARGET:
13046 expand_omp_target (region);
13047 break;
13048
13049 default:
13050 gcc_unreachable ();
13051 }
13052
13053 input_location = saved_location;
13054 region = region->next;
13055 }
13056 if (omp_any_child_fn_dumped)
13057 {
13058 if (dump_file)
13059 dump_function_header (dump_file, current_function_decl, dump_flags);
13060 omp_any_child_fn_dumped = false;
13061 }
13062 }
13063
13064
13065 /* Helper for build_omp_regions. Scan the dominator tree starting at
13066 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13067 true, the function ends once a single tree is built (otherwise, whole
13068 forest of OMP constructs may be built). */
13069
13070 static void
13071 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13072 bool single_tree)
13073 {
13074 gimple_stmt_iterator gsi;
13075 gimple *stmt;
13076 basic_block son;
13077
13078 gsi = gsi_last_bb (bb);
13079 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
13080 {
13081 struct omp_region *region;
13082 enum gimple_code code;
13083
13084 stmt = gsi_stmt (gsi);
13085 code = gimple_code (stmt);
13086 if (code == GIMPLE_OMP_RETURN)
13087 {
13088 /* STMT is the return point out of region PARENT. Mark it
13089 as the exit point and make PARENT the immediately
13090 enclosing region. */
13091 gcc_assert (parent);
13092 region = parent;
13093 region->exit = bb;
13094 parent = parent->outer;
13095 }
13096 else if (code == GIMPLE_OMP_ATOMIC_STORE)
13097 {
13098 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13099 GIMPLE_OMP_RETURN, but matches with
13100 GIMPLE_OMP_ATOMIC_LOAD. */
13101 gcc_assert (parent);
13102 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
13103 region = parent;
13104 region->exit = bb;
13105 parent = parent->outer;
13106 }
13107 else if (code == GIMPLE_OMP_CONTINUE)
13108 {
13109 gcc_assert (parent);
13110 parent->cont = bb;
13111 }
13112 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
13113 {
13114 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13115 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
13116 }
13117 else
13118 {
13119 region = new_omp_region (bb, code, parent);
13120 /* Otherwise... */
13121 if (code == GIMPLE_OMP_TARGET)
13122 {
13123 switch (gimple_omp_target_kind (stmt))
13124 {
13125 case GF_OMP_TARGET_KIND_REGION:
13126 case GF_OMP_TARGET_KIND_DATA:
13127 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13128 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13129 case GF_OMP_TARGET_KIND_OACC_DATA:
13130 break;
13131 case GF_OMP_TARGET_KIND_UPDATE:
13132 case GF_OMP_TARGET_KIND_ENTER_DATA:
13133 case GF_OMP_TARGET_KIND_EXIT_DATA:
13134 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13135 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13136 /* ..., other than for those stand-alone directives... */
13137 region = NULL;
13138 break;
13139 default:
13140 gcc_unreachable ();
13141 }
13142 }
13143 else if (code == GIMPLE_OMP_ORDERED
13144 && find_omp_clause (gimple_omp_ordered_clauses
13145 (as_a <gomp_ordered *> (stmt)),
13146 OMP_CLAUSE_DEPEND))
13147 /* #pragma omp ordered depend is also just a stand-alone
13148 directive. */
13149 region = NULL;
13150 /* ..., this directive becomes the parent for a new region. */
13151 if (region)
13152 parent = region;
13153 }
13154 }
13155
13156 if (single_tree && !parent)
13157 return;
13158
13159 for (son = first_dom_son (CDI_DOMINATORS, bb);
13160 son;
13161 son = next_dom_son (CDI_DOMINATORS, son))
13162 build_omp_regions_1 (son, parent, single_tree);
13163 }
13164
13165 /* Builds the tree of OMP regions rooted at ROOT, storing it to
13166 root_omp_region. */
13167
13168 static void
13169 build_omp_regions_root (basic_block root)
13170 {
13171 gcc_assert (root_omp_region == NULL);
13172 build_omp_regions_1 (root, NULL, true);
13173 gcc_assert (root_omp_region != NULL);
13174 }
13175
13176 /* Expands omp construct (and its subconstructs) starting in HEAD. */
13177
13178 void
13179 omp_expand_local (basic_block head)
13180 {
13181 build_omp_regions_root (head);
13182 if (dump_file && (dump_flags & TDF_DETAILS))
13183 {
13184 fprintf (dump_file, "\nOMP region tree\n\n");
13185 dump_omp_region (dump_file, root_omp_region, 0);
13186 fprintf (dump_file, "\n");
13187 }
13188
13189 remove_exit_barriers (root_omp_region);
13190 expand_omp (root_omp_region);
13191
13192 free_omp_regions ();
13193 }
13194
13195 /* Scan the CFG and build a tree of OMP regions. Return the root of
13196 the OMP region tree. */
13197
13198 static void
13199 build_omp_regions (void)
13200 {
13201 gcc_assert (root_omp_region == NULL);
13202 calculate_dominance_info (CDI_DOMINATORS);
13203 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
13204 }
13205
13206 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
13207
13208 static unsigned int
13209 execute_expand_omp (void)
13210 {
13211 build_omp_regions ();
13212
13213 if (!root_omp_region)
13214 return 0;
13215
13216 if (dump_file)
13217 {
13218 fprintf (dump_file, "\nOMP region tree\n\n");
13219 dump_omp_region (dump_file, root_omp_region, 0);
13220 fprintf (dump_file, "\n");
13221 }
13222
13223 remove_exit_barriers (root_omp_region);
13224
13225 expand_omp (root_omp_region);
13226
13227 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13228 verify_loop_structure ();
13229 cleanup_tree_cfg ();
13230
13231 free_omp_regions ();
13232
13233 return 0;
13234 }
13235
13236 /* OMP expansion -- the default pass, run before creation of SSA form. */
13237
13238 namespace {
13239
13240 const pass_data pass_data_expand_omp =
13241 {
13242 GIMPLE_PASS, /* type */
13243 "ompexp", /* name */
13244 OPTGROUP_NONE, /* optinfo_flags */
13245 TV_NONE, /* tv_id */
13246 PROP_gimple_any, /* properties_required */
13247 PROP_gimple_eomp, /* properties_provided */
13248 0, /* properties_destroyed */
13249 0, /* todo_flags_start */
13250 0, /* todo_flags_finish */
13251 };
13252
13253 class pass_expand_omp : public gimple_opt_pass
13254 {
13255 public:
13256 pass_expand_omp (gcc::context *ctxt)
13257 : gimple_opt_pass (pass_data_expand_omp, ctxt)
13258 {}
13259
13260 /* opt_pass methods: */
13261 virtual unsigned int execute (function *)
13262 {
13263 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
13264 || flag_openmp_simd != 0)
13265 && !seen_error ());
13266
13267 /* This pass always runs, to provide PROP_gimple_eomp.
13268 But often, there is nothing to do. */
13269 if (!gate)
13270 return 0;
13271
13272 return execute_expand_omp ();
13273 }
13274
13275 }; // class pass_expand_omp
13276
13277 } // anon namespace
13278
13279 gimple_opt_pass *
13280 make_pass_expand_omp (gcc::context *ctxt)
13281 {
13282 return new pass_expand_omp (ctxt);
13283 }
13284
13285 namespace {
13286
13287 const pass_data pass_data_expand_omp_ssa =
13288 {
13289 GIMPLE_PASS, /* type */
13290 "ompexpssa", /* name */
13291 OPTGROUP_NONE, /* optinfo_flags */
13292 TV_NONE, /* tv_id */
13293 PROP_cfg | PROP_ssa, /* properties_required */
13294 PROP_gimple_eomp, /* properties_provided */
13295 0, /* properties_destroyed */
13296 0, /* todo_flags_start */
13297 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
13298 };
13299
13300 class pass_expand_omp_ssa : public gimple_opt_pass
13301 {
13302 public:
13303 pass_expand_omp_ssa (gcc::context *ctxt)
13304 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
13305 {}
13306
13307 /* opt_pass methods: */
13308 virtual bool gate (function *fun)
13309 {
13310 return !(fun->curr_properties & PROP_gimple_eomp);
13311 }
13312 virtual unsigned int execute (function *) { return execute_expand_omp (); }
13313
13314 }; // class pass_expand_omp_ssa
13315
13316 } // anon namespace
13317
13318 gimple_opt_pass *
13319 make_pass_expand_omp_ssa (gcc::context *ctxt)
13320 {
13321 return new pass_expand_omp_ssa (ctxt);
13322 }
13323 \f
13324 /* Routines to lower OMP directives into OMP-GIMPLE. */
13325
13326 /* If ctx is a worksharing context inside of a cancellable parallel
13327 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
13328 and conditional branch to parallel's cancel_label to handle
13329 cancellation in the implicit barrier. */
13330
13331 static void
13332 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
13333 {
13334 gimple *omp_return = gimple_seq_last_stmt (*body);
13335 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
13336 if (gimple_omp_return_nowait_p (omp_return))
13337 return;
13338 if (ctx->outer
13339 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
13340 && ctx->outer->cancellable)
13341 {
13342 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
13343 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
13344 tree lhs = create_tmp_var (c_bool_type);
13345 gimple_omp_return_set_lhs (omp_return, lhs);
13346 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
13347 gimple *g = gimple_build_cond (NE_EXPR, lhs,
13348 fold_convert (c_bool_type,
13349 boolean_false_node),
13350 ctx->outer->cancel_label, fallthru_label);
13351 gimple_seq_add_stmt (body, g);
13352 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
13353 }
13354 }
13355
13356 /* Lower the OpenMP sections directive in the current statement in GSI_P.
13357 CTX is the enclosing OMP context for the current statement. */
13358
13359 static void
13360 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13361 {
13362 tree block, control;
13363 gimple_stmt_iterator tgsi;
13364 gomp_sections *stmt;
13365 gimple *t;
13366 gbind *new_stmt, *bind;
13367 gimple_seq ilist, dlist, olist, new_body;
13368
13369 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
13370
13371 push_gimplify_context ();
13372
13373 dlist = NULL;
13374 ilist = NULL;
13375 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
13376 &ilist, &dlist, ctx, NULL);
13377
13378 new_body = gimple_omp_body (stmt);
13379 gimple_omp_set_body (stmt, NULL);
13380 tgsi = gsi_start (new_body);
13381 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
13382 {
13383 omp_context *sctx;
13384 gimple *sec_start;
13385
13386 sec_start = gsi_stmt (tgsi);
13387 sctx = maybe_lookup_ctx (sec_start);
13388 gcc_assert (sctx);
13389
13390 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
13391 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
13392 GSI_CONTINUE_LINKING);
13393 gimple_omp_set_body (sec_start, NULL);
13394
13395 if (gsi_one_before_end_p (tgsi))
13396 {
13397 gimple_seq l = NULL;
13398 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
13399 &l, ctx);
13400 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
13401 gimple_omp_section_set_last (sec_start);
13402 }
13403
13404 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
13405 GSI_CONTINUE_LINKING);
13406 }
13407
13408 block = make_node (BLOCK);
13409 bind = gimple_build_bind (NULL, new_body, block);
13410
13411 olist = NULL;
13412 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
13413
13414 block = make_node (BLOCK);
13415 new_stmt = gimple_build_bind (NULL, NULL, block);
13416 gsi_replace (gsi_p, new_stmt, true);
13417
13418 pop_gimplify_context (new_stmt);
13419 gimple_bind_append_vars (new_stmt, ctx->block_vars);
13420 BLOCK_VARS (block) = gimple_bind_vars (bind);
13421 if (BLOCK_VARS (block))
13422 TREE_USED (block) = 1;
13423
13424 new_body = NULL;
13425 gimple_seq_add_seq (&new_body, ilist);
13426 gimple_seq_add_stmt (&new_body, stmt);
13427 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
13428 gimple_seq_add_stmt (&new_body, bind);
13429
13430 control = create_tmp_var (unsigned_type_node, ".section");
13431 t = gimple_build_omp_continue (control, control);
13432 gimple_omp_sections_set_control (stmt, control);
13433 gimple_seq_add_stmt (&new_body, t);
13434
13435 gimple_seq_add_seq (&new_body, olist);
13436 if (ctx->cancellable)
13437 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
13438 gimple_seq_add_seq (&new_body, dlist);
13439
13440 new_body = maybe_catch_exception (new_body);
13441
13442 t = gimple_build_omp_return
13443 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
13444 OMP_CLAUSE_NOWAIT));
13445 gimple_seq_add_stmt (&new_body, t);
13446 maybe_add_implicit_barrier_cancel (ctx, &new_body);
13447
13448 gimple_bind_set_body (new_stmt, new_body);
13449 }
13450
13451
13452 /* A subroutine of lower_omp_single. Expand the simple form of
13453 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
13454
13455 if (GOMP_single_start ())
13456 BODY;
13457 [ GOMP_barrier (); ] -> unless 'nowait' is present.
13458
13459 FIXME. It may be better to delay expanding the logic of this until
13460 pass_expand_omp. The expanded logic may make the job more difficult
13461 to a synchronization analysis pass. */
13462
13463 static void
13464 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
13465 {
13466 location_t loc = gimple_location (single_stmt);
13467 tree tlabel = create_artificial_label (loc);
13468 tree flabel = create_artificial_label (loc);
13469 gimple *call, *cond;
13470 tree lhs, decl;
13471
13472 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
13473 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
13474 call = gimple_build_call (decl, 0);
13475 gimple_call_set_lhs (call, lhs);
13476 gimple_seq_add_stmt (pre_p, call);
13477
13478 cond = gimple_build_cond (EQ_EXPR, lhs,
13479 fold_convert_loc (loc, TREE_TYPE (lhs),
13480 boolean_true_node),
13481 tlabel, flabel);
13482 gimple_seq_add_stmt (pre_p, cond);
13483 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
13484 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
13485 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
13486 }
13487
13488
13489 /* A subroutine of lower_omp_single. Expand the simple form of
13490 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
13491
13492 #pragma omp single copyprivate (a, b, c)
13493
13494 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
13495
13496 {
13497 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
13498 {
13499 BODY;
13500 copyout.a = a;
13501 copyout.b = b;
13502 copyout.c = c;
13503 GOMP_single_copy_end (&copyout);
13504 }
13505 else
13506 {
13507 a = copyout_p->a;
13508 b = copyout_p->b;
13509 c = copyout_p->c;
13510 }
13511 GOMP_barrier ();
13512 }
13513
13514 FIXME. It may be better to delay expanding the logic of this until
13515 pass_expand_omp. The expanded logic may make the job more difficult
13516 to a synchronization analysis pass. */
13517
13518 static void
13519 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
13520 omp_context *ctx)
13521 {
13522 tree ptr_type, t, l0, l1, l2, bfn_decl;
13523 gimple_seq copyin_seq;
13524 location_t loc = gimple_location (single_stmt);
13525
13526 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
13527
13528 ptr_type = build_pointer_type (ctx->record_type);
13529 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
13530
13531 l0 = create_artificial_label (loc);
13532 l1 = create_artificial_label (loc);
13533 l2 = create_artificial_label (loc);
13534
13535 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
13536 t = build_call_expr_loc (loc, bfn_decl, 0);
13537 t = fold_convert_loc (loc, ptr_type, t);
13538 gimplify_assign (ctx->receiver_decl, t, pre_p);
13539
13540 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
13541 build_int_cst (ptr_type, 0));
13542 t = build3 (COND_EXPR, void_type_node, t,
13543 build_and_jump (&l0), build_and_jump (&l1));
13544 gimplify_and_add (t, pre_p);
13545
13546 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
13547
13548 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
13549
13550 copyin_seq = NULL;
13551 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
13552 &copyin_seq, ctx);
13553
13554 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
13555 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
13556 t = build_call_expr_loc (loc, bfn_decl, 1, t);
13557 gimplify_and_add (t, pre_p);
13558
13559 t = build_and_jump (&l2);
13560 gimplify_and_add (t, pre_p);
13561
13562 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
13563
13564 gimple_seq_add_seq (pre_p, copyin_seq);
13565
13566 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
13567 }
13568
13569
13570 /* Expand code for an OpenMP single directive. */
13571
13572 static void
13573 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13574 {
13575 tree block;
13576 gimple *t;
13577 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
13578 gbind *bind;
13579 gimple_seq bind_body, bind_body_tail = NULL, dlist;
13580
13581 push_gimplify_context ();
13582
13583 block = make_node (BLOCK);
13584 bind = gimple_build_bind (NULL, NULL, block);
13585 gsi_replace (gsi_p, bind, true);
13586 bind_body = NULL;
13587 dlist = NULL;
13588 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
13589 &bind_body, &dlist, ctx, NULL);
13590 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
13591
13592 gimple_seq_add_stmt (&bind_body, single_stmt);
13593
13594 if (ctx->record_type)
13595 lower_omp_single_copy (single_stmt, &bind_body, ctx);
13596 else
13597 lower_omp_single_simple (single_stmt, &bind_body);
13598
13599 gimple_omp_set_body (single_stmt, NULL);
13600
13601 gimple_seq_add_seq (&bind_body, dlist);
13602
13603 bind_body = maybe_catch_exception (bind_body);
13604
13605 t = gimple_build_omp_return
13606 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
13607 OMP_CLAUSE_NOWAIT));
13608 gimple_seq_add_stmt (&bind_body_tail, t);
13609 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
13610 if (ctx->record_type)
13611 {
13612 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
13613 tree clobber = build_constructor (ctx->record_type, NULL);
13614 TREE_THIS_VOLATILE (clobber) = 1;
13615 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
13616 clobber), GSI_SAME_STMT);
13617 }
13618 gimple_seq_add_seq (&bind_body, bind_body_tail);
13619 gimple_bind_set_body (bind, bind_body);
13620
13621 pop_gimplify_context (bind);
13622
13623 gimple_bind_append_vars (bind, ctx->block_vars);
13624 BLOCK_VARS (block) = ctx->block_vars;
13625 if (BLOCK_VARS (block))
13626 TREE_USED (block) = 1;
13627 }
13628
13629
13630 /* Expand code for an OpenMP master directive. */
13631
13632 static void
13633 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13634 {
13635 tree block, lab = NULL, x, bfn_decl;
13636 gimple *stmt = gsi_stmt (*gsi_p);
13637 gbind *bind;
13638 location_t loc = gimple_location (stmt);
13639 gimple_seq tseq;
13640
13641 push_gimplify_context ();
13642
13643 block = make_node (BLOCK);
13644 bind = gimple_build_bind (NULL, NULL, block);
13645 gsi_replace (gsi_p, bind, true);
13646 gimple_bind_add_stmt (bind, stmt);
13647
13648 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
13649 x = build_call_expr_loc (loc, bfn_decl, 0);
13650 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
13651 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
13652 tseq = NULL;
13653 gimplify_and_add (x, &tseq);
13654 gimple_bind_add_seq (bind, tseq);
13655
13656 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13657 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
13658 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13659 gimple_omp_set_body (stmt, NULL);
13660
13661 gimple_bind_add_stmt (bind, gimple_build_label (lab));
13662
13663 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13664
13665 pop_gimplify_context (bind);
13666
13667 gimple_bind_append_vars (bind, ctx->block_vars);
13668 BLOCK_VARS (block) = ctx->block_vars;
13669 }
13670
13671
13672 /* Expand code for an OpenMP taskgroup directive. */
13673
13674 static void
13675 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13676 {
13677 gimple *stmt = gsi_stmt (*gsi_p);
13678 gcall *x;
13679 gbind *bind;
13680 tree block = make_node (BLOCK);
13681
13682 bind = gimple_build_bind (NULL, NULL, block);
13683 gsi_replace (gsi_p, bind, true);
13684 gimple_bind_add_stmt (bind, stmt);
13685
13686 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
13687 0);
13688 gimple_bind_add_stmt (bind, x);
13689
13690 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13691 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13692 gimple_omp_set_body (stmt, NULL);
13693
13694 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13695
13696 gimple_bind_append_vars (bind, ctx->block_vars);
13697 BLOCK_VARS (block) = ctx->block_vars;
13698 }
13699
13700
13701 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
13702
13703 static void
13704 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
13705 omp_context *ctx)
13706 {
13707 struct omp_for_data fd;
13708 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
13709 return;
13710
13711 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
13712 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
13713 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
13714 if (!fd.ordered)
13715 return;
13716
13717 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13718 tree c = gimple_omp_ordered_clauses (ord_stmt);
13719 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
13720 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
13721 {
13722 /* Merge depend clauses from multiple adjacent
13723 #pragma omp ordered depend(sink:...) constructs
13724 into one #pragma omp ordered depend(sink:...), so that
13725 we can optimize them together. */
13726 gimple_stmt_iterator gsi = *gsi_p;
13727 gsi_next (&gsi);
13728 while (!gsi_end_p (gsi))
13729 {
13730 gimple *stmt = gsi_stmt (gsi);
13731 if (is_gimple_debug (stmt)
13732 || gimple_code (stmt) == GIMPLE_NOP)
13733 {
13734 gsi_next (&gsi);
13735 continue;
13736 }
13737 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
13738 break;
13739 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
13740 c = gimple_omp_ordered_clauses (ord_stmt2);
13741 if (c == NULL_TREE
13742 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
13743 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13744 break;
13745 while (*list_p)
13746 list_p = &OMP_CLAUSE_CHAIN (*list_p);
13747 *list_p = c;
13748 gsi_remove (&gsi, true);
13749 }
13750 }
13751
13752 /* Canonicalize sink dependence clauses into one folded clause if
13753 possible.
13754
13755 The basic algorithm is to create a sink vector whose first
13756 element is the GCD of all the first elements, and whose remaining
13757 elements are the minimum of the subsequent columns.
13758
13759 We ignore dependence vectors whose first element is zero because
13760 such dependencies are known to be executed by the same thread.
13761
13762 We take into account the direction of the loop, so a minimum
13763 becomes a maximum if the loop is iterating forwards. We also
13764 ignore sink clauses where the loop direction is unknown, or where
13765 the offsets are clearly invalid because they are not a multiple
13766 of the loop increment.
13767
13768 For example:
13769
13770 #pragma omp for ordered(2)
13771 for (i=0; i < N; ++i)
13772 for (j=0; j < M; ++j)
13773 {
13774 #pragma omp ordered \
13775 depend(sink:i-8,j-2) \
13776 depend(sink:i,j-1) \ // Completely ignored because i+0.
13777 depend(sink:i-4,j-3) \
13778 depend(sink:i-6,j-4)
13779 #pragma omp ordered depend(source)
13780 }
13781
13782 Folded clause is:
13783
13784 depend(sink:-gcd(8,4,6),-min(2,3,4))
13785 -or-
13786 depend(sink:-2,-2)
13787 */
13788
13789 /* FIXME: Computing GCD's where the first element is zero is
13790 non-trivial in the presence of collapsed loops. Do this later. */
13791 if (fd.collapse > 1)
13792 return;
13793
13794 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
13795 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
13796 tree folded_dep = NULL_TREE;
13797 /* TRUE if the first dimension's offset is negative. */
13798 bool neg_offset_p = false;
13799
13800 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
13801 unsigned int i;
13802 while ((c = *list_p) != NULL)
13803 {
13804 bool remove = false;
13805
13806 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
13807 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
13808 goto next_ordered_clause;
13809
13810 tree vec;
13811 for (vec = OMP_CLAUSE_DECL (c), i = 0;
13812 vec && TREE_CODE (vec) == TREE_LIST;
13813 vec = TREE_CHAIN (vec), ++i)
13814 {
13815 gcc_assert (i < len);
13816
13817 /* extract_omp_for_data has canonicalized the condition. */
13818 gcc_assert (fd.loops[i].cond_code == LT_EXPR
13819 || fd.loops[i].cond_code == GT_EXPR);
13820 bool forward = fd.loops[i].cond_code == LT_EXPR;
13821 bool maybe_lexically_later = true;
13822
13823 /* While the committee makes up its mind, bail if we have any
13824 non-constant steps. */
13825 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
13826 goto lower_omp_ordered_ret;
13827
13828 tree itype = TREE_TYPE (TREE_VALUE (vec));
13829 if (POINTER_TYPE_P (itype))
13830 itype = sizetype;
13831 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
13832 TYPE_PRECISION (itype),
13833 TYPE_SIGN (itype));
13834
13835 /* Ignore invalid offsets that are not multiples of the step. */
13836 if (!wi::multiple_of_p
13837 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
13838 UNSIGNED))
13839 {
13840 warning_at (OMP_CLAUSE_LOCATION (c), 0,
13841 "ignoring sink clause with offset that is not "
13842 "a multiple of the loop step");
13843 remove = true;
13844 goto next_ordered_clause;
13845 }
13846
13847 /* Calculate the first dimension. The first dimension of
13848 the folded dependency vector is the GCD of the first
13849 elements, while ignoring any first elements whose offset
13850 is 0. */
13851 if (i == 0)
13852 {
13853 /* Ignore dependence vectors whose first dimension is 0. */
13854 if (offset == 0)
13855 {
13856 remove = true;
13857 goto next_ordered_clause;
13858 }
13859 else
13860 {
13861 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
13862 {
13863 error_at (OMP_CLAUSE_LOCATION (c),
13864 "first offset must be in opposite direction "
13865 "of loop iterations");
13866 goto lower_omp_ordered_ret;
13867 }
13868 if (forward)
13869 offset = -offset;
13870 neg_offset_p = forward;
13871 /* Initialize the first time around. */
13872 if (folded_dep == NULL_TREE)
13873 {
13874 folded_dep = c;
13875 folded_deps[0] = offset;
13876 }
13877 else
13878 folded_deps[0] = wi::gcd (folded_deps[0],
13879 offset, UNSIGNED);
13880 }
13881 }
13882 /* Calculate minimum for the remaining dimensions. */
13883 else
13884 {
13885 folded_deps[len + i - 1] = offset;
13886 if (folded_dep == c)
13887 folded_deps[i] = offset;
13888 else if (maybe_lexically_later
13889 && !wi::eq_p (folded_deps[i], offset))
13890 {
13891 if (forward ^ wi::gts_p (folded_deps[i], offset))
13892 {
13893 unsigned int j;
13894 folded_dep = c;
13895 for (j = 1; j <= i; j++)
13896 folded_deps[j] = folded_deps[len + j - 1];
13897 }
13898 else
13899 maybe_lexically_later = false;
13900 }
13901 }
13902 }
13903 gcc_assert (i == len);
13904
13905 remove = true;
13906
13907 next_ordered_clause:
13908 if (remove)
13909 *list_p = OMP_CLAUSE_CHAIN (c);
13910 else
13911 list_p = &OMP_CLAUSE_CHAIN (c);
13912 }
13913
13914 if (folded_dep)
13915 {
13916 if (neg_offset_p)
13917 folded_deps[0] = -folded_deps[0];
13918
13919 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
13920 if (POINTER_TYPE_P (itype))
13921 itype = sizetype;
13922
13923 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
13924 = wide_int_to_tree (itype, folded_deps[0]);
13925 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
13926 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
13927 }
13928
13929 lower_omp_ordered_ret:
13930
13931 /* Ordered without clauses is #pragma omp threads, while we want
13932 a nop instead if we remove all clauses. */
13933 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
13934 gsi_replace (gsi_p, gimple_build_nop (), true);
13935 }
13936
13937
13938 /* Expand code for an OpenMP ordered directive. */
13939
13940 static void
13941 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
13942 {
13943 tree block;
13944 gimple *stmt = gsi_stmt (*gsi_p);
13945 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
13946 gcall *x;
13947 gbind *bind;
13948 bool simd
13949 = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt), OMP_CLAUSE_SIMD);
13950
13951 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13952 OMP_CLAUSE_DEPEND))
13953 {
13954 /* FIXME: This is needs to be moved to the expansion to verify various
13955 conditions only testable on cfg with dominators computed, and also
13956 all the depend clauses to be merged still might need to be available
13957 for the runtime checks. */
13958 if (0)
13959 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
13960 return;
13961 }
13962
13963 push_gimplify_context ();
13964
13965 block = make_node (BLOCK);
13966 bind = gimple_build_bind (NULL, NULL, block);
13967 gsi_replace (gsi_p, bind, true);
13968 gimple_bind_add_stmt (bind, stmt);
13969
13970 if (simd)
13971 {
13972 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 0);
13973 cfun->has_simduid_loops = true;
13974 }
13975 else
13976 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
13977 0);
13978 gimple_bind_add_stmt (bind, x);
13979
13980 lower_omp (gimple_omp_body_ptr (stmt), ctx);
13981 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
13982 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
13983 gimple_omp_set_body (stmt, NULL);
13984
13985 if (simd)
13986 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 0);
13987 else
13988 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
13989 0);
13990 gimple_bind_add_stmt (bind, x);
13991
13992 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
13993
13994 pop_gimplify_context (bind);
13995
13996 gimple_bind_append_vars (bind, ctx->block_vars);
13997 BLOCK_VARS (block) = gimple_bind_vars (bind);
13998 }
13999
14000
14001 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14002 substitution of a couple of function calls. But in the NAMED case,
14003 requires that languages coordinate a symbol name. It is therefore
14004 best put here in common code. */
14005
14006 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
14007
14008 static void
14009 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14010 {
14011 tree block;
14012 tree name, lock, unlock;
14013 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14014 gbind *bind;
14015 location_t loc = gimple_location (stmt);
14016 gimple_seq tbody;
14017
14018 name = gimple_omp_critical_name (stmt);
14019 if (name)
14020 {
14021 tree decl;
14022
14023 if (!critical_name_mutexes)
14024 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
14025
14026 tree *n = critical_name_mutexes->get (name);
14027 if (n == NULL)
14028 {
14029 char *new_str;
14030
14031 decl = create_tmp_var_raw (ptr_type_node);
14032
14033 new_str = ACONCAT ((".gomp_critical_user_",
14034 IDENTIFIER_POINTER (name), NULL));
14035 DECL_NAME (decl) = get_identifier (new_str);
14036 TREE_PUBLIC (decl) = 1;
14037 TREE_STATIC (decl) = 1;
14038 DECL_COMMON (decl) = 1;
14039 DECL_ARTIFICIAL (decl) = 1;
14040 DECL_IGNORED_P (decl) = 1;
14041
14042 varpool_node::finalize_decl (decl);
14043
14044 critical_name_mutexes->put (name, decl);
14045 }
14046 else
14047 decl = *n;
14048
14049 /* If '#pragma omp critical' is inside offloaded region or
14050 inside function marked as offloadable, the symbol must be
14051 marked as offloadable too. */
14052 omp_context *octx;
14053 if (cgraph_node::get (current_function_decl)->offloadable)
14054 varpool_node::get_create (decl)->offloadable = 1;
14055 else
14056 for (octx = ctx->outer; octx; octx = octx->outer)
14057 if (is_gimple_omp_offloaded (octx->stmt))
14058 {
14059 varpool_node::get_create (decl)->offloadable = 1;
14060 break;
14061 }
14062
14063 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
14064 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
14065
14066 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
14067 unlock = build_call_expr_loc (loc, unlock, 1,
14068 build_fold_addr_expr_loc (loc, decl));
14069 }
14070 else
14071 {
14072 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
14073 lock = build_call_expr_loc (loc, lock, 0);
14074
14075 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
14076 unlock = build_call_expr_loc (loc, unlock, 0);
14077 }
14078
14079 push_gimplify_context ();
14080
14081 block = make_node (BLOCK);
14082 bind = gimple_build_bind (NULL, NULL, block);
14083 gsi_replace (gsi_p, bind, true);
14084 gimple_bind_add_stmt (bind, stmt);
14085
14086 tbody = gimple_bind_body (bind);
14087 gimplify_and_add (lock, &tbody);
14088 gimple_bind_set_body (bind, tbody);
14089
14090 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14091 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14092 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14093 gimple_omp_set_body (stmt, NULL);
14094
14095 tbody = gimple_bind_body (bind);
14096 gimplify_and_add (unlock, &tbody);
14097 gimple_bind_set_body (bind, tbody);
14098
14099 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14100
14101 pop_gimplify_context (bind);
14102 gimple_bind_append_vars (bind, ctx->block_vars);
14103 BLOCK_VARS (block) = gimple_bind_vars (bind);
14104 }
14105
14106
14107 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14108 for a lastprivate clause. Given a loop control predicate of (V
14109 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14110 is appended to *DLIST, iterator initialization is appended to
14111 *BODY_P. */
14112
14113 static void
14114 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14115 gimple_seq *dlist, struct omp_context *ctx)
14116 {
14117 tree clauses, cond, vinit;
14118 enum tree_code cond_code;
14119 gimple_seq stmts;
14120
14121 cond_code = fd->loop.cond_code;
14122 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14123
14124 /* When possible, use a strict equality expression. This can let VRP
14125 type optimizations deduce the value and remove a copy. */
14126 if (tree_fits_shwi_p (fd->loop.step))
14127 {
14128 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
14129 if (step == 1 || step == -1)
14130 cond_code = EQ_EXPR;
14131 }
14132
14133 tree n2 = fd->loop.n2;
14134 if (fd->collapse > 1
14135 && TREE_CODE (n2) != INTEGER_CST
14136 && gimple_omp_for_combined_into_p (fd->for_stmt))
14137 {
14138 struct omp_context *taskreg_ctx = NULL;
14139 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14140 {
14141 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
14142 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14143 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
14144 {
14145 if (gimple_omp_for_combined_into_p (gfor))
14146 {
14147 gcc_assert (ctx->outer->outer
14148 && is_parallel_ctx (ctx->outer->outer));
14149 taskreg_ctx = ctx->outer->outer;
14150 }
14151 else
14152 {
14153 struct omp_for_data outer_fd;
14154 extract_omp_for_data (gfor, &outer_fd, NULL);
14155 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14156 }
14157 }
14158 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
14159 taskreg_ctx = ctx->outer->outer;
14160 }
14161 else if (is_taskreg_ctx (ctx->outer))
14162 taskreg_ctx = ctx->outer;
14163 if (taskreg_ctx)
14164 {
14165 int i;
14166 tree innerc
14167 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
14168 OMP_CLAUSE__LOOPTEMP_);
14169 gcc_assert (innerc);
14170 for (i = 0; i < fd->collapse; i++)
14171 {
14172 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14173 OMP_CLAUSE__LOOPTEMP_);
14174 gcc_assert (innerc);
14175 }
14176 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
14177 OMP_CLAUSE__LOOPTEMP_);
14178 if (innerc)
14179 n2 = fold_convert (TREE_TYPE (n2),
14180 lookup_decl (OMP_CLAUSE_DECL (innerc),
14181 taskreg_ctx));
14182 }
14183 }
14184 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
14185
14186 clauses = gimple_omp_for_clauses (fd->for_stmt);
14187 stmts = NULL;
14188 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
14189 if (!gimple_seq_empty_p (stmts))
14190 {
14191 gimple_seq_add_seq (&stmts, *dlist);
14192 *dlist = stmts;
14193
14194 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
14195 vinit = fd->loop.n1;
14196 if (cond_code == EQ_EXPR
14197 && tree_fits_shwi_p (fd->loop.n2)
14198 && ! integer_zerop (fd->loop.n2))
14199 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
14200 else
14201 vinit = unshare_expr (vinit);
14202
14203 /* Initialize the iterator variable, so that threads that don't execute
14204 any iterations don't execute the lastprivate clauses by accident. */
14205 gimplify_assign (fd->loop.v, vinit, body_p);
14206 }
14207 }
14208
14209
14210 /* Lower code for an OMP loop directive. */
14211
14212 static void
14213 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14214 {
14215 tree *rhs_p, block;
14216 struct omp_for_data fd, *fdp = NULL;
14217 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
14218 gbind *new_stmt;
14219 gimple_seq omp_for_body, body, dlist;
14220 gimple_seq oacc_head = NULL, oacc_tail = NULL;
14221 size_t i;
14222
14223 push_gimplify_context ();
14224
14225 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
14226
14227 block = make_node (BLOCK);
14228 new_stmt = gimple_build_bind (NULL, NULL, block);
14229 /* Replace at gsi right away, so that 'stmt' is no member
14230 of a sequence anymore as we're going to add to a different
14231 one below. */
14232 gsi_replace (gsi_p, new_stmt, true);
14233
14234 /* Move declaration of temporaries in the loop body before we make
14235 it go away. */
14236 omp_for_body = gimple_omp_body (stmt);
14237 if (!gimple_seq_empty_p (omp_for_body)
14238 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
14239 {
14240 gbind *inner_bind
14241 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
14242 tree vars = gimple_bind_vars (inner_bind);
14243 gimple_bind_append_vars (new_stmt, vars);
14244 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
14245 keep them on the inner_bind and it's block. */
14246 gimple_bind_set_vars (inner_bind, NULL_TREE);
14247 if (gimple_bind_block (inner_bind))
14248 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
14249 }
14250
14251 if (gimple_omp_for_combined_into_p (stmt))
14252 {
14253 extract_omp_for_data (stmt, &fd, NULL);
14254 fdp = &fd;
14255
14256 /* We need two temporaries with fd.loop.v type (istart/iend)
14257 and then (fd.collapse - 1) temporaries with the same
14258 type for count2 ... countN-1 vars if not constant. */
14259 size_t count = 2;
14260 tree type = fd.iter_type;
14261 if (fd.collapse > 1
14262 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
14263 count += fd.collapse - 1;
14264 bool taskreg_for
14265 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
14266 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
14267 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
14268 tree clauses = *pc;
14269 if (taskreg_for)
14270 outerc
14271 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
14272 OMP_CLAUSE__LOOPTEMP_);
14273 for (i = 0; i < count; i++)
14274 {
14275 tree temp;
14276 if (taskreg_for)
14277 {
14278 gcc_assert (outerc);
14279 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
14280 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
14281 OMP_CLAUSE__LOOPTEMP_);
14282 }
14283 else
14284 {
14285 temp = create_tmp_var (type);
14286 insert_decl_map (&ctx->outer->cb, temp, temp);
14287 }
14288 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
14289 OMP_CLAUSE_DECL (*pc) = temp;
14290 pc = &OMP_CLAUSE_CHAIN (*pc);
14291 }
14292 *pc = clauses;
14293 }
14294
14295 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
14296 dlist = NULL;
14297 body = NULL;
14298 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
14299 fdp);
14300 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
14301
14302 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14303
14304 /* Lower the header expressions. At this point, we can assume that
14305 the header is of the form:
14306
14307 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
14308
14309 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
14310 using the .omp_data_s mapping, if needed. */
14311 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
14312 {
14313 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
14314 if (!is_gimple_min_invariant (*rhs_p))
14315 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
14316
14317 rhs_p = gimple_omp_for_final_ptr (stmt, i);
14318 if (!is_gimple_min_invariant (*rhs_p))
14319 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
14320
14321 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
14322 if (!is_gimple_min_invariant (*rhs_p))
14323 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
14324 }
14325
14326 /* Once lowered, extract the bounds and clauses. */
14327 extract_omp_for_data (stmt, &fd, NULL);
14328
14329 if (is_gimple_omp_oacc (ctx->stmt)
14330 && !ctx_in_oacc_kernels_region (ctx))
14331 lower_oacc_head_tail (gimple_location (stmt),
14332 gimple_omp_for_clauses (stmt),
14333 &oacc_head, &oacc_tail, ctx);
14334
14335 /* Add OpenACC partitioning and reduction markers just before the loop */
14336 if (oacc_head)
14337 gimple_seq_add_seq (&body, oacc_head);
14338
14339 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
14340
14341 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
14342 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
14343 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
14344 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
14345 {
14346 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
14347 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
14348 OMP_CLAUSE_LINEAR_STEP (c)
14349 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
14350 ctx);
14351 }
14352
14353 gimple_seq_add_stmt (&body, stmt);
14354 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
14355
14356 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
14357 fd.loop.v));
14358
14359 /* After the loop, add exit clauses. */
14360 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
14361
14362 if (ctx->cancellable)
14363 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
14364
14365 gimple_seq_add_seq (&body, dlist);
14366
14367 body = maybe_catch_exception (body);
14368
14369 /* Region exit marker goes at the end of the loop body. */
14370 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
14371 maybe_add_implicit_barrier_cancel (ctx, &body);
14372
14373 /* Add OpenACC joining and reduction markers just after the loop. */
14374 if (oacc_tail)
14375 gimple_seq_add_seq (&body, oacc_tail);
14376
14377 pop_gimplify_context (new_stmt);
14378
14379 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14380 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
14381 if (BLOCK_VARS (block))
14382 TREE_USED (block) = 1;
14383
14384 gimple_bind_set_body (new_stmt, body);
14385 gimple_omp_set_body (stmt, NULL);
14386 gimple_omp_for_set_pre_body (stmt, NULL);
14387 }
14388
14389 /* Callback for walk_stmts. Check if the current statement only contains
14390 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
14391
14392 static tree
14393 check_combined_parallel (gimple_stmt_iterator *gsi_p,
14394 bool *handled_ops_p,
14395 struct walk_stmt_info *wi)
14396 {
14397 int *info = (int *) wi->info;
14398 gimple *stmt = gsi_stmt (*gsi_p);
14399
14400 *handled_ops_p = true;
14401 switch (gimple_code (stmt))
14402 {
14403 WALK_SUBSTMTS;
14404
14405 case GIMPLE_OMP_FOR:
14406 case GIMPLE_OMP_SECTIONS:
14407 *info = *info == 0 ? 1 : -1;
14408 break;
14409 default:
14410 *info = -1;
14411 break;
14412 }
14413 return NULL;
14414 }
14415
14416 struct omp_taskcopy_context
14417 {
14418 /* This field must be at the beginning, as we do "inheritance": Some
14419 callback functions for tree-inline.c (e.g., omp_copy_decl)
14420 receive a copy_body_data pointer that is up-casted to an
14421 omp_context pointer. */
14422 copy_body_data cb;
14423 omp_context *ctx;
14424 };
14425
14426 static tree
14427 task_copyfn_copy_decl (tree var, copy_body_data *cb)
14428 {
14429 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
14430
14431 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
14432 return create_tmp_var (TREE_TYPE (var));
14433
14434 return var;
14435 }
14436
14437 static tree
14438 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
14439 {
14440 tree name, new_fields = NULL, type, f;
14441
14442 type = lang_hooks.types.make_type (RECORD_TYPE);
14443 name = DECL_NAME (TYPE_NAME (orig_type));
14444 name = build_decl (gimple_location (tcctx->ctx->stmt),
14445 TYPE_DECL, name, type);
14446 TYPE_NAME (type) = name;
14447
14448 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
14449 {
14450 tree new_f = copy_node (f);
14451 DECL_CONTEXT (new_f) = type;
14452 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
14453 TREE_CHAIN (new_f) = new_fields;
14454 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14455 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
14456 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
14457 &tcctx->cb, NULL);
14458 new_fields = new_f;
14459 tcctx->cb.decl_map->put (f, new_f);
14460 }
14461 TYPE_FIELDS (type) = nreverse (new_fields);
14462 layout_type (type);
14463 return type;
14464 }
14465
14466 /* Create task copyfn. */
14467
14468 static void
14469 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
14470 {
14471 struct function *child_cfun;
14472 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
14473 tree record_type, srecord_type, bind, list;
14474 bool record_needs_remap = false, srecord_needs_remap = false;
14475 splay_tree_node n;
14476 struct omp_taskcopy_context tcctx;
14477 location_t loc = gimple_location (task_stmt);
14478
14479 child_fn = gimple_omp_task_copy_fn (task_stmt);
14480 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
14481 gcc_assert (child_cfun->cfg == NULL);
14482 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
14483
14484 /* Reset DECL_CONTEXT on function arguments. */
14485 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
14486 DECL_CONTEXT (t) = child_fn;
14487
14488 /* Populate the function. */
14489 push_gimplify_context ();
14490 push_cfun (child_cfun);
14491
14492 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
14493 TREE_SIDE_EFFECTS (bind) = 1;
14494 list = NULL;
14495 DECL_SAVED_TREE (child_fn) = bind;
14496 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
14497
14498 /* Remap src and dst argument types if needed. */
14499 record_type = ctx->record_type;
14500 srecord_type = ctx->srecord_type;
14501 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
14502 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14503 {
14504 record_needs_remap = true;
14505 break;
14506 }
14507 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
14508 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
14509 {
14510 srecord_needs_remap = true;
14511 break;
14512 }
14513
14514 if (record_needs_remap || srecord_needs_remap)
14515 {
14516 memset (&tcctx, '\0', sizeof (tcctx));
14517 tcctx.cb.src_fn = ctx->cb.src_fn;
14518 tcctx.cb.dst_fn = child_fn;
14519 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
14520 gcc_checking_assert (tcctx.cb.src_node);
14521 tcctx.cb.dst_node = tcctx.cb.src_node;
14522 tcctx.cb.src_cfun = ctx->cb.src_cfun;
14523 tcctx.cb.copy_decl = task_copyfn_copy_decl;
14524 tcctx.cb.eh_lp_nr = 0;
14525 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
14526 tcctx.cb.decl_map = new hash_map<tree, tree>;
14527 tcctx.ctx = ctx;
14528
14529 if (record_needs_remap)
14530 record_type = task_copyfn_remap_type (&tcctx, record_type);
14531 if (srecord_needs_remap)
14532 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
14533 }
14534 else
14535 tcctx.cb.decl_map = NULL;
14536
14537 arg = DECL_ARGUMENTS (child_fn);
14538 TREE_TYPE (arg) = build_pointer_type (record_type);
14539 sarg = DECL_CHAIN (arg);
14540 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
14541
14542 /* First pass: initialize temporaries used in record_type and srecord_type
14543 sizes and field offsets. */
14544 if (tcctx.cb.decl_map)
14545 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
14546 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14547 {
14548 tree *p;
14549
14550 decl = OMP_CLAUSE_DECL (c);
14551 p = tcctx.cb.decl_map->get (decl);
14552 if (p == NULL)
14553 continue;
14554 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14555 sf = (tree) n->value;
14556 sf = *tcctx.cb.decl_map->get (sf);
14557 src = build_simple_mem_ref_loc (loc, sarg);
14558 src = omp_build_component_ref (src, sf);
14559 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
14560 append_to_statement_list (t, &list);
14561 }
14562
14563 /* Second pass: copy shared var pointers and copy construct non-VLA
14564 firstprivate vars. */
14565 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
14566 switch (OMP_CLAUSE_CODE (c))
14567 {
14568 splay_tree_key key;
14569 case OMP_CLAUSE_SHARED:
14570 decl = OMP_CLAUSE_DECL (c);
14571 key = (splay_tree_key) decl;
14572 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
14573 key = (splay_tree_key) &DECL_UID (decl);
14574 n = splay_tree_lookup (ctx->field_map, key);
14575 if (n == NULL)
14576 break;
14577 f = (tree) n->value;
14578 if (tcctx.cb.decl_map)
14579 f = *tcctx.cb.decl_map->get (f);
14580 n = splay_tree_lookup (ctx->sfield_map, key);
14581 sf = (tree) n->value;
14582 if (tcctx.cb.decl_map)
14583 sf = *tcctx.cb.decl_map->get (sf);
14584 src = build_simple_mem_ref_loc (loc, sarg);
14585 src = omp_build_component_ref (src, sf);
14586 dst = build_simple_mem_ref_loc (loc, arg);
14587 dst = omp_build_component_ref (dst, f);
14588 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
14589 append_to_statement_list (t, &list);
14590 break;
14591 case OMP_CLAUSE_FIRSTPRIVATE:
14592 decl = OMP_CLAUSE_DECL (c);
14593 if (is_variable_sized (decl))
14594 break;
14595 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14596 if (n == NULL)
14597 break;
14598 f = (tree) n->value;
14599 if (tcctx.cb.decl_map)
14600 f = *tcctx.cb.decl_map->get (f);
14601 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14602 if (n != NULL)
14603 {
14604 sf = (tree) n->value;
14605 if (tcctx.cb.decl_map)
14606 sf = *tcctx.cb.decl_map->get (sf);
14607 src = build_simple_mem_ref_loc (loc, sarg);
14608 src = omp_build_component_ref (src, sf);
14609 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
14610 src = build_simple_mem_ref_loc (loc, src);
14611 }
14612 else
14613 src = decl;
14614 dst = build_simple_mem_ref_loc (loc, arg);
14615 dst = omp_build_component_ref (dst, f);
14616 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14617 append_to_statement_list (t, &list);
14618 break;
14619 case OMP_CLAUSE_PRIVATE:
14620 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
14621 break;
14622 decl = OMP_CLAUSE_DECL (c);
14623 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14624 f = (tree) n->value;
14625 if (tcctx.cb.decl_map)
14626 f = *tcctx.cb.decl_map->get (f);
14627 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
14628 if (n != NULL)
14629 {
14630 sf = (tree) n->value;
14631 if (tcctx.cb.decl_map)
14632 sf = *tcctx.cb.decl_map->get (sf);
14633 src = build_simple_mem_ref_loc (loc, sarg);
14634 src = omp_build_component_ref (src, sf);
14635 if (use_pointer_for_field (decl, NULL))
14636 src = build_simple_mem_ref_loc (loc, src);
14637 }
14638 else
14639 src = decl;
14640 dst = build_simple_mem_ref_loc (loc, arg);
14641 dst = omp_build_component_ref (dst, f);
14642 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
14643 append_to_statement_list (t, &list);
14644 break;
14645 default:
14646 break;
14647 }
14648
14649 /* Last pass: handle VLA firstprivates. */
14650 if (tcctx.cb.decl_map)
14651 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
14652 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
14653 {
14654 tree ind, ptr, df;
14655
14656 decl = OMP_CLAUSE_DECL (c);
14657 if (!is_variable_sized (decl))
14658 continue;
14659 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
14660 if (n == NULL)
14661 continue;
14662 f = (tree) n->value;
14663 f = *tcctx.cb.decl_map->get (f);
14664 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
14665 ind = DECL_VALUE_EXPR (decl);
14666 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
14667 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
14668 n = splay_tree_lookup (ctx->sfield_map,
14669 (splay_tree_key) TREE_OPERAND (ind, 0));
14670 sf = (tree) n->value;
14671 sf = *tcctx.cb.decl_map->get (sf);
14672 src = build_simple_mem_ref_loc (loc, sarg);
14673 src = omp_build_component_ref (src, sf);
14674 src = build_simple_mem_ref_loc (loc, src);
14675 dst = build_simple_mem_ref_loc (loc, arg);
14676 dst = omp_build_component_ref (dst, f);
14677 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
14678 append_to_statement_list (t, &list);
14679 n = splay_tree_lookup (ctx->field_map,
14680 (splay_tree_key) TREE_OPERAND (ind, 0));
14681 df = (tree) n->value;
14682 df = *tcctx.cb.decl_map->get (df);
14683 ptr = build_simple_mem_ref_loc (loc, arg);
14684 ptr = omp_build_component_ref (ptr, df);
14685 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
14686 build_fold_addr_expr_loc (loc, dst));
14687 append_to_statement_list (t, &list);
14688 }
14689
14690 t = build1 (RETURN_EXPR, void_type_node, NULL);
14691 append_to_statement_list (t, &list);
14692
14693 if (tcctx.cb.decl_map)
14694 delete tcctx.cb.decl_map;
14695 pop_gimplify_context (NULL);
14696 BIND_EXPR_BODY (bind) = list;
14697 pop_cfun ();
14698 }
14699
14700 static void
14701 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
14702 {
14703 tree c, clauses;
14704 gimple *g;
14705 size_t n_in = 0, n_out = 0, idx = 2, i;
14706
14707 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
14708 gcc_assert (clauses);
14709 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14710 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
14711 switch (OMP_CLAUSE_DEPEND_KIND (c))
14712 {
14713 case OMP_CLAUSE_DEPEND_IN:
14714 n_in++;
14715 break;
14716 case OMP_CLAUSE_DEPEND_OUT:
14717 case OMP_CLAUSE_DEPEND_INOUT:
14718 n_out++;
14719 break;
14720 case OMP_CLAUSE_DEPEND_SOURCE:
14721 case OMP_CLAUSE_DEPEND_SINK:
14722 /* FALLTHRU */
14723 default:
14724 gcc_unreachable ();
14725 }
14726 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
14727 tree array = create_tmp_var (type);
14728 TREE_ADDRESSABLE (array) = 1;
14729 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
14730 NULL_TREE);
14731 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
14732 gimple_seq_add_stmt (iseq, g);
14733 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
14734 NULL_TREE);
14735 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
14736 gimple_seq_add_stmt (iseq, g);
14737 for (i = 0; i < 2; i++)
14738 {
14739 if ((i ? n_in : n_out) == 0)
14740 continue;
14741 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
14742 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14743 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
14744 {
14745 tree t = OMP_CLAUSE_DECL (c);
14746 t = fold_convert (ptr_type_node, t);
14747 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
14748 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
14749 NULL_TREE, NULL_TREE);
14750 g = gimple_build_assign (r, t);
14751 gimple_seq_add_stmt (iseq, g);
14752 }
14753 }
14754 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
14755 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
14756 OMP_CLAUSE_CHAIN (c) = *pclauses;
14757 *pclauses = c;
14758 tree clobber = build_constructor (type, NULL);
14759 TREE_THIS_VOLATILE (clobber) = 1;
14760 g = gimple_build_assign (array, clobber);
14761 gimple_seq_add_stmt (oseq, g);
14762 }
14763
14764 /* Lower the OpenMP parallel or task directive in the current statement
14765 in GSI_P. CTX holds context information for the directive. */
14766
14767 static void
14768 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14769 {
14770 tree clauses;
14771 tree child_fn, t;
14772 gimple *stmt = gsi_stmt (*gsi_p);
14773 gbind *par_bind, *bind, *dep_bind = NULL;
14774 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
14775 location_t loc = gimple_location (stmt);
14776
14777 clauses = gimple_omp_taskreg_clauses (stmt);
14778 par_bind
14779 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
14780 par_body = gimple_bind_body (par_bind);
14781 child_fn = ctx->cb.dst_fn;
14782 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
14783 && !gimple_omp_parallel_combined_p (stmt))
14784 {
14785 struct walk_stmt_info wi;
14786 int ws_num = 0;
14787
14788 memset (&wi, 0, sizeof (wi));
14789 wi.info = &ws_num;
14790 wi.val_only = true;
14791 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
14792 if (ws_num == 1)
14793 gimple_omp_parallel_set_combined_p (stmt, true);
14794 }
14795 gimple_seq dep_ilist = NULL;
14796 gimple_seq dep_olist = NULL;
14797 if (gimple_code (stmt) == GIMPLE_OMP_TASK
14798 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
14799 {
14800 push_gimplify_context ();
14801 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
14802 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
14803 &dep_ilist, &dep_olist);
14804 }
14805
14806 if (ctx->srecord_type)
14807 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
14808
14809 push_gimplify_context ();
14810
14811 par_olist = NULL;
14812 par_ilist = NULL;
14813 par_rlist = NULL;
14814 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
14815 lower_omp (&par_body, ctx);
14816 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
14817 lower_reduction_clauses (clauses, &par_rlist, ctx);
14818
14819 /* Declare all the variables created by mapping and the variables
14820 declared in the scope of the parallel body. */
14821 record_vars_into (ctx->block_vars, child_fn);
14822 record_vars_into (gimple_bind_vars (par_bind), child_fn);
14823
14824 if (ctx->record_type)
14825 {
14826 ctx->sender_decl
14827 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
14828 : ctx->record_type, ".omp_data_o");
14829 DECL_NAMELESS (ctx->sender_decl) = 1;
14830 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
14831 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
14832 }
14833
14834 olist = NULL;
14835 ilist = NULL;
14836 lower_send_clauses (clauses, &ilist, &olist, ctx);
14837 lower_send_shared_vars (&ilist, &olist, ctx);
14838
14839 if (ctx->record_type)
14840 {
14841 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
14842 TREE_THIS_VOLATILE (clobber) = 1;
14843 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
14844 clobber));
14845 }
14846
14847 /* Once all the expansions are done, sequence all the different
14848 fragments inside gimple_omp_body. */
14849
14850 new_body = NULL;
14851
14852 if (ctx->record_type)
14853 {
14854 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
14855 /* fixup_child_record_type might have changed receiver_decl's type. */
14856 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
14857 gimple_seq_add_stmt (&new_body,
14858 gimple_build_assign (ctx->receiver_decl, t));
14859 }
14860
14861 gimple_seq_add_seq (&new_body, par_ilist);
14862 gimple_seq_add_seq (&new_body, par_body);
14863 gimple_seq_add_seq (&new_body, par_rlist);
14864 if (ctx->cancellable)
14865 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
14866 gimple_seq_add_seq (&new_body, par_olist);
14867 new_body = maybe_catch_exception (new_body);
14868 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
14869 gimple_seq_add_stmt (&new_body,
14870 gimple_build_omp_continue (integer_zero_node,
14871 integer_zero_node));
14872 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
14873 gimple_omp_set_body (stmt, new_body);
14874
14875 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
14876 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
14877 gimple_bind_add_seq (bind, ilist);
14878 gimple_bind_add_stmt (bind, stmt);
14879 gimple_bind_add_seq (bind, olist);
14880
14881 pop_gimplify_context (NULL);
14882
14883 if (dep_bind)
14884 {
14885 gimple_bind_add_seq (dep_bind, dep_ilist);
14886 gimple_bind_add_stmt (dep_bind, bind);
14887 gimple_bind_add_seq (dep_bind, dep_olist);
14888 pop_gimplify_context (dep_bind);
14889 }
14890 }
14891
14892 /* Lower the GIMPLE_OMP_TARGET in the current statement
14893 in GSI_P. CTX holds context information for the directive. */
14894
14895 static void
14896 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14897 {
14898 tree clauses;
14899 tree child_fn, t, c;
14900 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
14901 gbind *tgt_bind, *bind, *dep_bind = NULL;
14902 gimple_seq tgt_body, olist, ilist, fplist, new_body;
14903 location_t loc = gimple_location (stmt);
14904 bool offloaded, data_region;
14905 unsigned int map_cnt = 0;
14906 bool has_depend = false;
14907
14908 offloaded = is_gimple_omp_offloaded (stmt);
14909 switch (gimple_omp_target_kind (stmt))
14910 {
14911 case GF_OMP_TARGET_KIND_REGION:
14912 case GF_OMP_TARGET_KIND_UPDATE:
14913 case GF_OMP_TARGET_KIND_ENTER_DATA:
14914 case GF_OMP_TARGET_KIND_EXIT_DATA:
14915 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
14916 case GF_OMP_TARGET_KIND_OACC_KERNELS:
14917 case GF_OMP_TARGET_KIND_OACC_UPDATE:
14918 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
14919 data_region = false;
14920 break;
14921 case GF_OMP_TARGET_KIND_DATA:
14922 case GF_OMP_TARGET_KIND_OACC_DATA:
14923 data_region = true;
14924 break;
14925 default:
14926 gcc_unreachable ();
14927 }
14928
14929 clauses = gimple_omp_target_clauses (stmt);
14930
14931 gimple_seq dep_ilist = NULL;
14932 gimple_seq dep_olist = NULL;
14933 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
14934 {
14935 push_gimplify_context ();
14936 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
14937 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
14938 &dep_ilist, &dep_olist);
14939 has_depend = true;
14940 }
14941
14942 tgt_bind = NULL;
14943 tgt_body = NULL;
14944 if (offloaded)
14945 {
14946 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
14947 tgt_body = gimple_bind_body (tgt_bind);
14948 }
14949 else if (data_region)
14950 tgt_body = gimple_omp_body (stmt);
14951 child_fn = ctx->cb.dst_fn;
14952
14953 push_gimplify_context ();
14954 fplist = NULL;
14955
14956 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
14957 switch (OMP_CLAUSE_CODE (c))
14958 {
14959 tree var, x;
14960
14961 default:
14962 break;
14963 case OMP_CLAUSE_MAP:
14964 #if CHECKING_P
14965 /* First check what we're prepared to handle in the following. */
14966 switch (OMP_CLAUSE_MAP_KIND (c))
14967 {
14968 case GOMP_MAP_ALLOC:
14969 case GOMP_MAP_TO:
14970 case GOMP_MAP_FROM:
14971 case GOMP_MAP_TOFROM:
14972 case GOMP_MAP_POINTER:
14973 case GOMP_MAP_TO_PSET:
14974 case GOMP_MAP_FORCE_DEALLOC:
14975 case GOMP_MAP_RELEASE:
14976 case GOMP_MAP_ALWAYS_TO:
14977 case GOMP_MAP_ALWAYS_FROM:
14978 case GOMP_MAP_ALWAYS_TOFROM:
14979 case GOMP_MAP_FIRSTPRIVATE_POINTER:
14980 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
14981 case GOMP_MAP_STRUCT:
14982 case GOMP_MAP_ALWAYS_POINTER:
14983 break;
14984 case GOMP_MAP_FORCE_ALLOC:
14985 case GOMP_MAP_FORCE_TO:
14986 case GOMP_MAP_FORCE_FROM:
14987 case GOMP_MAP_FORCE_TOFROM:
14988 case GOMP_MAP_FORCE_PRESENT:
14989 case GOMP_MAP_FORCE_DEVICEPTR:
14990 gcc_assert (is_gimple_omp_oacc (stmt));
14991 break;
14992 default:
14993 gcc_unreachable ();
14994 }
14995 #endif
14996 /* FALLTHRU */
14997 case OMP_CLAUSE_TO:
14998 case OMP_CLAUSE_FROM:
14999 oacc_firstprivate:
15000 var = OMP_CLAUSE_DECL (c);
15001 if (!DECL_P (var))
15002 {
15003 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
15004 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15005 && (OMP_CLAUSE_MAP_KIND (c)
15006 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
15007 map_cnt++;
15008 continue;
15009 }
15010
15011 if (DECL_SIZE (var)
15012 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15013 {
15014 tree var2 = DECL_VALUE_EXPR (var);
15015 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15016 var2 = TREE_OPERAND (var2, 0);
15017 gcc_assert (DECL_P (var2));
15018 var = var2;
15019 }
15020
15021 if (offloaded
15022 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15023 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15024 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15025 {
15026 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15027 {
15028 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15029 && varpool_node::get_create (var)->offloadable)
15030 continue;
15031
15032 tree type = build_pointer_type (TREE_TYPE (var));
15033 tree new_var = lookup_decl (var, ctx);
15034 x = create_tmp_var_raw (type, get_name (new_var));
15035 gimple_add_tmp_var (x);
15036 x = build_simple_mem_ref (x);
15037 SET_DECL_VALUE_EXPR (new_var, x);
15038 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15039 }
15040 continue;
15041 }
15042
15043 if (!maybe_lookup_field (var, ctx))
15044 continue;
15045
15046 if (offloaded)
15047 {
15048 x = build_receiver_ref (var, true, ctx);
15049 tree new_var = lookup_decl (var, ctx);
15050
15051 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15052 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15053 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15054 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15055 x = build_simple_mem_ref (x);
15056 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15057 {
15058 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15059 if (is_reference (new_var))
15060 {
15061 /* Create a local object to hold the instance
15062 value. */
15063 tree type = TREE_TYPE (TREE_TYPE (new_var));
15064 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15065 tree inst = create_tmp_var (type, id);
15066 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15067 x = build_fold_addr_expr (inst);
15068 }
15069 gimplify_assign (new_var, x, &fplist);
15070 }
15071 else if (DECL_P (new_var))
15072 {
15073 SET_DECL_VALUE_EXPR (new_var, x);
15074 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15075 }
15076 else
15077 gcc_unreachable ();
15078 }
15079 map_cnt++;
15080 break;
15081
15082 case OMP_CLAUSE_FIRSTPRIVATE:
15083 if (is_oacc_parallel (ctx))
15084 goto oacc_firstprivate;
15085 map_cnt++;
15086 var = OMP_CLAUSE_DECL (c);
15087 if (!is_reference (var)
15088 && !is_gimple_reg_type (TREE_TYPE (var)))
15089 {
15090 tree new_var = lookup_decl (var, ctx);
15091 if (is_variable_sized (var))
15092 {
15093 tree pvar = DECL_VALUE_EXPR (var);
15094 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15095 pvar = TREE_OPERAND (pvar, 0);
15096 gcc_assert (DECL_P (pvar));
15097 tree new_pvar = lookup_decl (pvar, ctx);
15098 x = build_fold_indirect_ref (new_pvar);
15099 TREE_THIS_NOTRAP (x) = 1;
15100 }
15101 else
15102 x = build_receiver_ref (var, true, ctx);
15103 SET_DECL_VALUE_EXPR (new_var, x);
15104 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15105 }
15106 break;
15107
15108 case OMP_CLAUSE_PRIVATE:
15109 if (is_gimple_omp_oacc (ctx->stmt))
15110 break;
15111 var = OMP_CLAUSE_DECL (c);
15112 if (is_variable_sized (var))
15113 {
15114 tree new_var = lookup_decl (var, ctx);
15115 tree pvar = DECL_VALUE_EXPR (var);
15116 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15117 pvar = TREE_OPERAND (pvar, 0);
15118 gcc_assert (DECL_P (pvar));
15119 tree new_pvar = lookup_decl (pvar, ctx);
15120 x = build_fold_indirect_ref (new_pvar);
15121 TREE_THIS_NOTRAP (x) = 1;
15122 SET_DECL_VALUE_EXPR (new_var, x);
15123 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15124 }
15125 break;
15126
15127 case OMP_CLAUSE_USE_DEVICE_PTR:
15128 case OMP_CLAUSE_IS_DEVICE_PTR:
15129 var = OMP_CLAUSE_DECL (c);
15130 map_cnt++;
15131 if (is_variable_sized (var))
15132 {
15133 tree new_var = lookup_decl (var, ctx);
15134 tree pvar = DECL_VALUE_EXPR (var);
15135 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15136 pvar = TREE_OPERAND (pvar, 0);
15137 gcc_assert (DECL_P (pvar));
15138 tree new_pvar = lookup_decl (pvar, ctx);
15139 x = build_fold_indirect_ref (new_pvar);
15140 TREE_THIS_NOTRAP (x) = 1;
15141 SET_DECL_VALUE_EXPR (new_var, x);
15142 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15143 }
15144 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15145 {
15146 tree new_var = lookup_decl (var, ctx);
15147 tree type = build_pointer_type (TREE_TYPE (var));
15148 x = create_tmp_var_raw (type, get_name (new_var));
15149 gimple_add_tmp_var (x);
15150 x = build_simple_mem_ref (x);
15151 SET_DECL_VALUE_EXPR (new_var, x);
15152 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15153 }
15154 break;
15155 }
15156
15157 if (offloaded)
15158 {
15159 target_nesting_level++;
15160 lower_omp (&tgt_body, ctx);
15161 target_nesting_level--;
15162 }
15163 else if (data_region)
15164 lower_omp (&tgt_body, ctx);
15165
15166 if (offloaded)
15167 {
15168 /* Declare all the variables created by mapping and the variables
15169 declared in the scope of the target body. */
15170 record_vars_into (ctx->block_vars, child_fn);
15171 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
15172 }
15173
15174 olist = NULL;
15175 ilist = NULL;
15176 if (ctx->record_type)
15177 {
15178 ctx->sender_decl
15179 = create_tmp_var (ctx->record_type, ".omp_data_arr");
15180 DECL_NAMELESS (ctx->sender_decl) = 1;
15181 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15182 t = make_tree_vec (3);
15183 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
15184 TREE_VEC_ELT (t, 1)
15185 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
15186 ".omp_data_sizes");
15187 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
15188 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
15189 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
15190 tree tkind_type = short_unsigned_type_node;
15191 int talign_shift = 8;
15192 TREE_VEC_ELT (t, 2)
15193 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
15194 ".omp_data_kinds");
15195 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
15196 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
15197 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
15198 gimple_omp_target_set_data_arg (stmt, t);
15199
15200 vec<constructor_elt, va_gc> *vsize;
15201 vec<constructor_elt, va_gc> *vkind;
15202 vec_alloc (vsize, map_cnt);
15203 vec_alloc (vkind, map_cnt);
15204 unsigned int map_idx = 0;
15205
15206 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15207 switch (OMP_CLAUSE_CODE (c))
15208 {
15209 tree ovar, nc, s, purpose, var, x, type;
15210 unsigned int talign;
15211
15212 default:
15213 break;
15214
15215 case OMP_CLAUSE_MAP:
15216 case OMP_CLAUSE_TO:
15217 case OMP_CLAUSE_FROM:
15218 oacc_firstprivate_map:
15219 nc = c;
15220 ovar = OMP_CLAUSE_DECL (c);
15221 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15222 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15223 || (OMP_CLAUSE_MAP_KIND (c)
15224 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
15225 break;
15226 if (!DECL_P (ovar))
15227 {
15228 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15229 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
15230 {
15231 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
15232 == get_base_address (ovar));
15233 nc = OMP_CLAUSE_CHAIN (c);
15234 ovar = OMP_CLAUSE_DECL (nc);
15235 }
15236 else
15237 {
15238 tree x = build_sender_ref (ovar, ctx);
15239 tree v
15240 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
15241 gimplify_assign (x, v, &ilist);
15242 nc = NULL_TREE;
15243 }
15244 }
15245 else
15246 {
15247 if (DECL_SIZE (ovar)
15248 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
15249 {
15250 tree ovar2 = DECL_VALUE_EXPR (ovar);
15251 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
15252 ovar2 = TREE_OPERAND (ovar2, 0);
15253 gcc_assert (DECL_P (ovar2));
15254 ovar = ovar2;
15255 }
15256 if (!maybe_lookup_field (ovar, ctx))
15257 continue;
15258 }
15259
15260 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
15261 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
15262 talign = DECL_ALIGN_UNIT (ovar);
15263 if (nc)
15264 {
15265 var = lookup_decl_in_outer_ctx (ovar, ctx);
15266 x = build_sender_ref (ovar, ctx);
15267
15268 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15269 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15270 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15271 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
15272 {
15273 gcc_assert (offloaded);
15274 tree avar
15275 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
15276 mark_addressable (avar);
15277 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
15278 talign = DECL_ALIGN_UNIT (avar);
15279 avar = build_fold_addr_expr (avar);
15280 gimplify_assign (x, avar, &ilist);
15281 }
15282 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15283 {
15284 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15285 if (!is_reference (var))
15286 var = build_fold_addr_expr (var);
15287 else
15288 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15289 gimplify_assign (x, var, &ilist);
15290 }
15291 else if (is_gimple_reg (var))
15292 {
15293 gcc_assert (offloaded);
15294 tree avar = create_tmp_var (TREE_TYPE (var));
15295 mark_addressable (avar);
15296 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
15297 if (GOMP_MAP_COPY_TO_P (map_kind)
15298 || map_kind == GOMP_MAP_POINTER
15299 || map_kind == GOMP_MAP_TO_PSET
15300 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
15301 gimplify_assign (avar, var, &ilist);
15302 avar = build_fold_addr_expr (avar);
15303 gimplify_assign (x, avar, &ilist);
15304 if ((GOMP_MAP_COPY_FROM_P (map_kind)
15305 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
15306 && !TYPE_READONLY (TREE_TYPE (var)))
15307 {
15308 x = unshare_expr (x);
15309 x = build_simple_mem_ref (x);
15310 gimplify_assign (var, x, &olist);
15311 }
15312 }
15313 else
15314 {
15315 var = build_fold_addr_expr (var);
15316 gimplify_assign (x, var, &ilist);
15317 }
15318 }
15319 s = NULL_TREE;
15320 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15321 {
15322 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
15323 s = TREE_TYPE (ovar);
15324 if (TREE_CODE (s) == REFERENCE_TYPE)
15325 s = TREE_TYPE (s);
15326 s = TYPE_SIZE_UNIT (s);
15327 }
15328 else
15329 s = OMP_CLAUSE_SIZE (c);
15330 if (s == NULL_TREE)
15331 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15332 s = fold_convert (size_type_node, s);
15333 purpose = size_int (map_idx++);
15334 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15335 if (TREE_CODE (s) != INTEGER_CST)
15336 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15337
15338 unsigned HOST_WIDE_INT tkind, tkind_zero;
15339 switch (OMP_CLAUSE_CODE (c))
15340 {
15341 case OMP_CLAUSE_MAP:
15342 tkind = OMP_CLAUSE_MAP_KIND (c);
15343 tkind_zero = tkind;
15344 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
15345 switch (tkind)
15346 {
15347 case GOMP_MAP_ALLOC:
15348 case GOMP_MAP_TO:
15349 case GOMP_MAP_FROM:
15350 case GOMP_MAP_TOFROM:
15351 case GOMP_MAP_ALWAYS_TO:
15352 case GOMP_MAP_ALWAYS_FROM:
15353 case GOMP_MAP_ALWAYS_TOFROM:
15354 case GOMP_MAP_RELEASE:
15355 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
15356 break;
15357 case GOMP_MAP_DELETE:
15358 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
15359 default:
15360 break;
15361 }
15362 if (tkind_zero != tkind)
15363 {
15364 if (integer_zerop (s))
15365 tkind = tkind_zero;
15366 else if (integer_nonzerop (s))
15367 tkind_zero = tkind;
15368 }
15369 break;
15370 case OMP_CLAUSE_FIRSTPRIVATE:
15371 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
15372 tkind = GOMP_MAP_TO;
15373 tkind_zero = tkind;
15374 break;
15375 case OMP_CLAUSE_TO:
15376 tkind = GOMP_MAP_TO;
15377 tkind_zero = tkind;
15378 break;
15379 case OMP_CLAUSE_FROM:
15380 tkind = GOMP_MAP_FROM;
15381 tkind_zero = tkind;
15382 break;
15383 default:
15384 gcc_unreachable ();
15385 }
15386 gcc_checking_assert (tkind
15387 < (HOST_WIDE_INT_C (1U) << talign_shift));
15388 gcc_checking_assert (tkind_zero
15389 < (HOST_WIDE_INT_C (1U) << talign_shift));
15390 talign = ceil_log2 (talign);
15391 tkind |= talign << talign_shift;
15392 tkind_zero |= talign << talign_shift;
15393 gcc_checking_assert (tkind
15394 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15395 gcc_checking_assert (tkind_zero
15396 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15397 if (tkind == tkind_zero)
15398 x = build_int_cstu (tkind_type, tkind);
15399 else
15400 {
15401 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
15402 x = build3 (COND_EXPR, tkind_type,
15403 fold_build2 (EQ_EXPR, boolean_type_node,
15404 unshare_expr (s), size_zero_node),
15405 build_int_cstu (tkind_type, tkind_zero),
15406 build_int_cstu (tkind_type, tkind));
15407 }
15408 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
15409 if (nc && nc != c)
15410 c = nc;
15411 break;
15412
15413 case OMP_CLAUSE_FIRSTPRIVATE:
15414 if (is_oacc_parallel (ctx))
15415 goto oacc_firstprivate_map;
15416 ovar = OMP_CLAUSE_DECL (c);
15417 if (is_reference (ovar))
15418 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15419 else
15420 talign = DECL_ALIGN_UNIT (ovar);
15421 var = lookup_decl_in_outer_ctx (ovar, ctx);
15422 x = build_sender_ref (ovar, ctx);
15423 tkind = GOMP_MAP_FIRSTPRIVATE;
15424 type = TREE_TYPE (ovar);
15425 if (is_reference (ovar))
15426 type = TREE_TYPE (type);
15427 bool use_firstprivate_int, force_addr;
15428 use_firstprivate_int = false;
15429 force_addr = false;
15430 if ((INTEGRAL_TYPE_P (type)
15431 && TYPE_PRECISION (type) <= POINTER_SIZE)
15432 || TREE_CODE (type) == POINTER_TYPE)
15433 use_firstprivate_int = true;
15434 if (has_depend)
15435 {
15436 if (is_reference (var))
15437 use_firstprivate_int = false;
15438 else if (is_gimple_reg (var))
15439 {
15440 if (DECL_HAS_VALUE_EXPR_P (var))
15441 {
15442 tree v = get_base_address (var);
15443 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15444 {
15445 use_firstprivate_int = false;
15446 force_addr = true;
15447 }
15448 else
15449 switch (TREE_CODE (v))
15450 {
15451 case INDIRECT_REF:
15452 case MEM_REF:
15453 use_firstprivate_int = false;
15454 force_addr = true;
15455 break;
15456 default:
15457 break;
15458 }
15459 }
15460 }
15461 else
15462 use_firstprivate_int = false;
15463 }
15464 if (use_firstprivate_int)
15465 {
15466 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15467 tree t = var;
15468 if (is_reference (var))
15469 t = build_simple_mem_ref (var);
15470 if (TREE_CODE (type) != POINTER_TYPE)
15471 t = fold_convert (pointer_sized_int_node, t);
15472 t = fold_convert (TREE_TYPE (x), t);
15473 gimplify_assign (x, t, &ilist);
15474 }
15475 else if (is_reference (var))
15476 gimplify_assign (x, var, &ilist);
15477 else if (!force_addr && is_gimple_reg (var))
15478 {
15479 tree avar = create_tmp_var (TREE_TYPE (var));
15480 mark_addressable (avar);
15481 gimplify_assign (avar, var, &ilist);
15482 avar = build_fold_addr_expr (avar);
15483 gimplify_assign (x, avar, &ilist);
15484 }
15485 else
15486 {
15487 var = build_fold_addr_expr (var);
15488 gimplify_assign (x, var, &ilist);
15489 }
15490 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
15491 s = size_int (0);
15492 else if (is_reference (var))
15493 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
15494 else
15495 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
15496 s = fold_convert (size_type_node, s);
15497 purpose = size_int (map_idx++);
15498 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15499 if (TREE_CODE (s) != INTEGER_CST)
15500 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
15501
15502 gcc_checking_assert (tkind
15503 < (HOST_WIDE_INT_C (1U) << talign_shift));
15504 talign = ceil_log2 (talign);
15505 tkind |= talign << talign_shift;
15506 gcc_checking_assert (tkind
15507 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15508 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15509 build_int_cstu (tkind_type, tkind));
15510 break;
15511
15512 case OMP_CLAUSE_USE_DEVICE_PTR:
15513 case OMP_CLAUSE_IS_DEVICE_PTR:
15514 ovar = OMP_CLAUSE_DECL (c);
15515 var = lookup_decl_in_outer_ctx (ovar, ctx);
15516 x = build_sender_ref (ovar, ctx);
15517 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
15518 tkind = GOMP_MAP_USE_DEVICE_PTR;
15519 else
15520 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
15521 type = TREE_TYPE (ovar);
15522 if (TREE_CODE (type) == ARRAY_TYPE)
15523 var = build_fold_addr_expr (var);
15524 else
15525 {
15526 if (is_reference (ovar))
15527 {
15528 type = TREE_TYPE (type);
15529 if (TREE_CODE (type) != ARRAY_TYPE)
15530 var = build_simple_mem_ref (var);
15531 var = fold_convert (TREE_TYPE (x), var);
15532 }
15533 }
15534 gimplify_assign (x, var, &ilist);
15535 s = size_int (0);
15536 purpose = size_int (map_idx++);
15537 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
15538 gcc_checking_assert (tkind
15539 < (HOST_WIDE_INT_C (1U) << talign_shift));
15540 gcc_checking_assert (tkind
15541 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
15542 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
15543 build_int_cstu (tkind_type, tkind));
15544 break;
15545 }
15546
15547 gcc_assert (map_idx == map_cnt);
15548
15549 DECL_INITIAL (TREE_VEC_ELT (t, 1))
15550 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
15551 DECL_INITIAL (TREE_VEC_ELT (t, 2))
15552 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
15553 for (int i = 1; i <= 2; i++)
15554 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
15555 {
15556 gimple_seq initlist = NULL;
15557 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
15558 TREE_VEC_ELT (t, i)),
15559 &initlist, true, NULL_TREE);
15560 gimple_seq_add_seq (&ilist, initlist);
15561
15562 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
15563 NULL);
15564 TREE_THIS_VOLATILE (clobber) = 1;
15565 gimple_seq_add_stmt (&olist,
15566 gimple_build_assign (TREE_VEC_ELT (t, i),
15567 clobber));
15568 }
15569
15570 tree clobber = build_constructor (ctx->record_type, NULL);
15571 TREE_THIS_VOLATILE (clobber) = 1;
15572 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15573 clobber));
15574 }
15575
15576 /* Once all the expansions are done, sequence all the different
15577 fragments inside gimple_omp_body. */
15578
15579 new_body = NULL;
15580
15581 if (offloaded
15582 && ctx->record_type)
15583 {
15584 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15585 /* fixup_child_record_type might have changed receiver_decl's type. */
15586 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15587 gimple_seq_add_stmt (&new_body,
15588 gimple_build_assign (ctx->receiver_decl, t));
15589 }
15590 gimple_seq_add_seq (&new_body, fplist);
15591
15592 if (offloaded || data_region)
15593 {
15594 tree prev = NULL_TREE;
15595 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15596 switch (OMP_CLAUSE_CODE (c))
15597 {
15598 tree var, x;
15599 default:
15600 break;
15601 case OMP_CLAUSE_FIRSTPRIVATE:
15602 if (is_gimple_omp_oacc (ctx->stmt))
15603 break;
15604 var = OMP_CLAUSE_DECL (c);
15605 if (is_reference (var)
15606 || is_gimple_reg_type (TREE_TYPE (var)))
15607 {
15608 tree new_var = lookup_decl (var, ctx);
15609 tree type;
15610 type = TREE_TYPE (var);
15611 if (is_reference (var))
15612 type = TREE_TYPE (type);
15613 bool use_firstprivate_int;
15614 use_firstprivate_int = false;
15615 if ((INTEGRAL_TYPE_P (type)
15616 && TYPE_PRECISION (type) <= POINTER_SIZE)
15617 || TREE_CODE (type) == POINTER_TYPE)
15618 use_firstprivate_int = true;
15619 if (has_depend)
15620 {
15621 tree v = lookup_decl_in_outer_ctx (var, ctx);
15622 if (is_reference (v))
15623 use_firstprivate_int = false;
15624 else if (is_gimple_reg (v))
15625 {
15626 if (DECL_HAS_VALUE_EXPR_P (v))
15627 {
15628 v = get_base_address (v);
15629 if (DECL_P (v) && TREE_ADDRESSABLE (v))
15630 use_firstprivate_int = false;
15631 else
15632 switch (TREE_CODE (v))
15633 {
15634 case INDIRECT_REF:
15635 case MEM_REF:
15636 use_firstprivate_int = false;
15637 break;
15638 default:
15639 break;
15640 }
15641 }
15642 }
15643 else
15644 use_firstprivate_int = false;
15645 }
15646 if (use_firstprivate_int)
15647 {
15648 x = build_receiver_ref (var, false, ctx);
15649 if (TREE_CODE (type) != POINTER_TYPE)
15650 x = fold_convert (pointer_sized_int_node, x);
15651 x = fold_convert (type, x);
15652 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15653 fb_rvalue);
15654 if (is_reference (var))
15655 {
15656 tree v = create_tmp_var_raw (type, get_name (var));
15657 gimple_add_tmp_var (v);
15658 TREE_ADDRESSABLE (v) = 1;
15659 gimple_seq_add_stmt (&new_body,
15660 gimple_build_assign (v, x));
15661 x = build_fold_addr_expr (v);
15662 }
15663 gimple_seq_add_stmt (&new_body,
15664 gimple_build_assign (new_var, x));
15665 }
15666 else
15667 {
15668 x = build_receiver_ref (var, !is_reference (var), ctx);
15669 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15670 fb_rvalue);
15671 gimple_seq_add_stmt (&new_body,
15672 gimple_build_assign (new_var, x));
15673 }
15674 }
15675 else if (is_variable_sized (var))
15676 {
15677 tree pvar = DECL_VALUE_EXPR (var);
15678 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15679 pvar = TREE_OPERAND (pvar, 0);
15680 gcc_assert (DECL_P (pvar));
15681 tree new_var = lookup_decl (pvar, ctx);
15682 x = build_receiver_ref (var, false, ctx);
15683 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15684 gimple_seq_add_stmt (&new_body,
15685 gimple_build_assign (new_var, x));
15686 }
15687 break;
15688 case OMP_CLAUSE_PRIVATE:
15689 if (is_gimple_omp_oacc (ctx->stmt))
15690 break;
15691 var = OMP_CLAUSE_DECL (c);
15692 if (is_reference (var))
15693 {
15694 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15695 tree new_var = lookup_decl (var, ctx);
15696 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
15697 if (TREE_CONSTANT (x))
15698 {
15699 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
15700 get_name (var));
15701 gimple_add_tmp_var (x);
15702 TREE_ADDRESSABLE (x) = 1;
15703 x = build_fold_addr_expr_loc (clause_loc, x);
15704 }
15705 else
15706 {
15707 tree atmp
15708 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
15709 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
15710 tree al = size_int (TYPE_ALIGN (rtype));
15711 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
15712 }
15713
15714 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
15715 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15716 gimple_seq_add_stmt (&new_body,
15717 gimple_build_assign (new_var, x));
15718 }
15719 break;
15720 case OMP_CLAUSE_USE_DEVICE_PTR:
15721 case OMP_CLAUSE_IS_DEVICE_PTR:
15722 var = OMP_CLAUSE_DECL (c);
15723 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
15724 x = build_sender_ref (var, ctx);
15725 else
15726 x = build_receiver_ref (var, false, ctx);
15727 if (is_variable_sized (var))
15728 {
15729 tree pvar = DECL_VALUE_EXPR (var);
15730 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15731 pvar = TREE_OPERAND (pvar, 0);
15732 gcc_assert (DECL_P (pvar));
15733 tree new_var = lookup_decl (pvar, ctx);
15734 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15735 gimple_seq_add_stmt (&new_body,
15736 gimple_build_assign (new_var, x));
15737 }
15738 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15739 {
15740 tree new_var = lookup_decl (var, ctx);
15741 new_var = DECL_VALUE_EXPR (new_var);
15742 gcc_assert (TREE_CODE (new_var) == MEM_REF);
15743 new_var = TREE_OPERAND (new_var, 0);
15744 gcc_assert (DECL_P (new_var));
15745 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15746 gimple_seq_add_stmt (&new_body,
15747 gimple_build_assign (new_var, x));
15748 }
15749 else
15750 {
15751 tree type = TREE_TYPE (var);
15752 tree new_var = lookup_decl (var, ctx);
15753 if (is_reference (var))
15754 {
15755 type = TREE_TYPE (type);
15756 if (TREE_CODE (type) != ARRAY_TYPE)
15757 {
15758 tree v = create_tmp_var_raw (type, get_name (var));
15759 gimple_add_tmp_var (v);
15760 TREE_ADDRESSABLE (v) = 1;
15761 x = fold_convert (type, x);
15762 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
15763 fb_rvalue);
15764 gimple_seq_add_stmt (&new_body,
15765 gimple_build_assign (v, x));
15766 x = build_fold_addr_expr (v);
15767 }
15768 }
15769 x = fold_convert (TREE_TYPE (new_var), x);
15770 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15771 gimple_seq_add_stmt (&new_body,
15772 gimple_build_assign (new_var, x));
15773 }
15774 break;
15775 }
15776 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
15777 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
15778 are already handled. */
15779 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15780 switch (OMP_CLAUSE_CODE (c))
15781 {
15782 tree var;
15783 default:
15784 break;
15785 case OMP_CLAUSE_MAP:
15786 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15787 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
15788 {
15789 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15790 HOST_WIDE_INT offset = 0;
15791 gcc_assert (prev);
15792 var = OMP_CLAUSE_DECL (c);
15793 if (DECL_P (var)
15794 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
15795 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
15796 ctx))
15797 && varpool_node::get_create (var)->offloadable)
15798 break;
15799 if (TREE_CODE (var) == INDIRECT_REF
15800 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
15801 var = TREE_OPERAND (var, 0);
15802 if (TREE_CODE (var) == COMPONENT_REF)
15803 {
15804 var = get_addr_base_and_unit_offset (var, &offset);
15805 gcc_assert (var != NULL_TREE && DECL_P (var));
15806 }
15807 else if (DECL_SIZE (var)
15808 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15809 {
15810 tree var2 = DECL_VALUE_EXPR (var);
15811 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15812 var2 = TREE_OPERAND (var2, 0);
15813 gcc_assert (DECL_P (var2));
15814 var = var2;
15815 }
15816 tree new_var = lookup_decl (var, ctx), x;
15817 tree type = TREE_TYPE (new_var);
15818 bool is_ref;
15819 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
15820 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
15821 == COMPONENT_REF))
15822 {
15823 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
15824 is_ref = true;
15825 new_var = build2 (MEM_REF, type,
15826 build_fold_addr_expr (new_var),
15827 build_int_cst (build_pointer_type (type),
15828 offset));
15829 }
15830 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
15831 {
15832 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
15833 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
15834 new_var = build2 (MEM_REF, type,
15835 build_fold_addr_expr (new_var),
15836 build_int_cst (build_pointer_type (type),
15837 offset));
15838 }
15839 else
15840 is_ref = is_reference (var);
15841 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
15842 is_ref = false;
15843 bool ref_to_array = false;
15844 if (is_ref)
15845 {
15846 type = TREE_TYPE (type);
15847 if (TREE_CODE (type) == ARRAY_TYPE)
15848 {
15849 type = build_pointer_type (type);
15850 ref_to_array = true;
15851 }
15852 }
15853 else if (TREE_CODE (type) == ARRAY_TYPE)
15854 {
15855 tree decl2 = DECL_VALUE_EXPR (new_var);
15856 gcc_assert (TREE_CODE (decl2) == MEM_REF);
15857 decl2 = TREE_OPERAND (decl2, 0);
15858 gcc_assert (DECL_P (decl2));
15859 new_var = decl2;
15860 type = TREE_TYPE (new_var);
15861 }
15862 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
15863 x = fold_convert_loc (clause_loc, type, x);
15864 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
15865 {
15866 tree bias = OMP_CLAUSE_SIZE (c);
15867 if (DECL_P (bias))
15868 bias = lookup_decl (bias, ctx);
15869 bias = fold_convert_loc (clause_loc, sizetype, bias);
15870 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
15871 bias);
15872 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
15873 TREE_TYPE (x), x, bias);
15874 }
15875 if (ref_to_array)
15876 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
15877 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15878 if (is_ref && !ref_to_array)
15879 {
15880 tree t = create_tmp_var_raw (type, get_name (var));
15881 gimple_add_tmp_var (t);
15882 TREE_ADDRESSABLE (t) = 1;
15883 gimple_seq_add_stmt (&new_body,
15884 gimple_build_assign (t, x));
15885 x = build_fold_addr_expr_loc (clause_loc, t);
15886 }
15887 gimple_seq_add_stmt (&new_body,
15888 gimple_build_assign (new_var, x));
15889 prev = NULL_TREE;
15890 }
15891 else if (OMP_CLAUSE_CHAIN (c)
15892 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
15893 == OMP_CLAUSE_MAP
15894 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
15895 == GOMP_MAP_FIRSTPRIVATE_POINTER
15896 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
15897 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
15898 prev = c;
15899 break;
15900 case OMP_CLAUSE_PRIVATE:
15901 var = OMP_CLAUSE_DECL (c);
15902 if (is_variable_sized (var))
15903 {
15904 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
15905 tree new_var = lookup_decl (var, ctx);
15906 tree pvar = DECL_VALUE_EXPR (var);
15907 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15908 pvar = TREE_OPERAND (pvar, 0);
15909 gcc_assert (DECL_P (pvar));
15910 tree new_pvar = lookup_decl (pvar, ctx);
15911 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
15912 tree al = size_int (DECL_ALIGN (var));
15913 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
15914 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
15915 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
15916 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
15917 gimple_seq_add_stmt (&new_body,
15918 gimple_build_assign (new_pvar, x));
15919 }
15920 break;
15921 }
15922
15923 gimple_seq fork_seq = NULL;
15924 gimple_seq join_seq = NULL;
15925
15926 if (is_oacc_parallel (ctx))
15927 {
15928 /* If there are reductions on the offloaded region itself, treat
15929 them as a dummy GANG loop. */
15930 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
15931
15932 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
15933 false, NULL, NULL, &fork_seq, &join_seq, ctx);
15934 }
15935
15936 gimple_seq_add_seq (&new_body, fork_seq);
15937 gimple_seq_add_seq (&new_body, tgt_body);
15938 gimple_seq_add_seq (&new_body, join_seq);
15939
15940 if (offloaded)
15941 new_body = maybe_catch_exception (new_body);
15942
15943 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15944 gimple_omp_set_body (stmt, new_body);
15945 }
15946
15947 bind = gimple_build_bind (NULL, NULL,
15948 tgt_bind ? gimple_bind_block (tgt_bind)
15949 : NULL_TREE);
15950 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15951 gimple_bind_add_seq (bind, ilist);
15952 gimple_bind_add_stmt (bind, stmt);
15953 gimple_bind_add_seq (bind, olist);
15954
15955 pop_gimplify_context (NULL);
15956
15957 if (dep_bind)
15958 {
15959 gimple_bind_add_seq (dep_bind, dep_ilist);
15960 gimple_bind_add_stmt (dep_bind, bind);
15961 gimple_bind_add_seq (dep_bind, dep_olist);
15962 pop_gimplify_context (dep_bind);
15963 }
15964 }
15965
15966 /* Expand code for an OpenMP teams directive. */
15967
15968 static void
15969 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15970 {
15971 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
15972 push_gimplify_context ();
15973
15974 tree block = make_node (BLOCK);
15975 gbind *bind = gimple_build_bind (NULL, NULL, block);
15976 gsi_replace (gsi_p, bind, true);
15977 gimple_seq bind_body = NULL;
15978 gimple_seq dlist = NULL;
15979 gimple_seq olist = NULL;
15980
15981 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
15982 OMP_CLAUSE_NUM_TEAMS);
15983 if (num_teams == NULL_TREE)
15984 num_teams = build_int_cst (unsigned_type_node, 0);
15985 else
15986 {
15987 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
15988 num_teams = fold_convert (unsigned_type_node, num_teams);
15989 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
15990 }
15991 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
15992 OMP_CLAUSE_THREAD_LIMIT);
15993 if (thread_limit == NULL_TREE)
15994 thread_limit = build_int_cst (unsigned_type_node, 0);
15995 else
15996 {
15997 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
15998 thread_limit = fold_convert (unsigned_type_node, thread_limit);
15999 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16000 fb_rvalue);
16001 }
16002
16003 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16004 &bind_body, &dlist, ctx, NULL);
16005 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16006 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16007 gimple_seq_add_stmt (&bind_body, teams_stmt);
16008
16009 location_t loc = gimple_location (teams_stmt);
16010 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16011 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16012 gimple_set_location (call, loc);
16013 gimple_seq_add_stmt (&bind_body, call);
16014
16015 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16016 gimple_omp_set_body (teams_stmt, NULL);
16017 gimple_seq_add_seq (&bind_body, olist);
16018 gimple_seq_add_seq (&bind_body, dlist);
16019 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16020 gimple_bind_set_body (bind, bind_body);
16021
16022 pop_gimplify_context (bind);
16023
16024 gimple_bind_append_vars (bind, ctx->block_vars);
16025 BLOCK_VARS (block) = ctx->block_vars;
16026 if (BLOCK_VARS (block))
16027 TREE_USED (block) = 1;
16028 }
16029
16030
16031 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16032 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16033 of OMP context, but with task_shared_vars set. */
16034
16035 static tree
16036 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16037 void *data)
16038 {
16039 tree t = *tp;
16040
16041 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16042 if (TREE_CODE (t) == VAR_DECL && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
16043 return t;
16044
16045 if (task_shared_vars
16046 && DECL_P (t)
16047 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
16048 return t;
16049
16050 /* If a global variable has been privatized, TREE_CONSTANT on
16051 ADDR_EXPR might be wrong. */
16052 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
16053 recompute_tree_invariant_for_addr_expr (t);
16054
16055 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16056 return NULL_TREE;
16057 }
16058
16059 /* Data to be communicated between lower_omp_regimplify_operands and
16060 lower_omp_regimplify_operands_p. */
16061
16062 struct lower_omp_regimplify_operands_data
16063 {
16064 omp_context *ctx;
16065 vec<tree> *decls;
16066 };
16067
16068 /* Helper function for lower_omp_regimplify_operands. Find
16069 omp_member_access_dummy_var vars and adjust temporarily their
16070 DECL_VALUE_EXPRs if needed. */
16071
16072 static tree
16073 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16074 void *data)
16075 {
16076 tree t = omp_member_access_dummy_var (*tp);
16077 if (t)
16078 {
16079 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16080 lower_omp_regimplify_operands_data *ldata
16081 = (lower_omp_regimplify_operands_data *) wi->info;
16082 tree o = maybe_lookup_decl (t, ldata->ctx);
16083 if (o != t)
16084 {
16085 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16086 ldata->decls->safe_push (*tp);
16087 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16088 SET_DECL_VALUE_EXPR (*tp, v);
16089 }
16090 }
16091 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
16092 return NULL_TREE;
16093 }
16094
16095 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16096 of omp_member_access_dummy_var vars during regimplification. */
16097
16098 static void
16099 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16100 gimple_stmt_iterator *gsi_p)
16101 {
16102 auto_vec<tree, 10> decls;
16103 if (ctx)
16104 {
16105 struct walk_stmt_info wi;
16106 memset (&wi, '\0', sizeof (wi));
16107 struct lower_omp_regimplify_operands_data data;
16108 data.ctx = ctx;
16109 data.decls = &decls;
16110 wi.info = &data;
16111 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16112 }
16113 gimple_regimplify_operands (stmt, gsi_p);
16114 while (!decls.is_empty ())
16115 {
16116 tree t = decls.pop ();
16117 tree v = decls.pop ();
16118 SET_DECL_VALUE_EXPR (t, v);
16119 }
16120 }
16121
16122 static void
16123 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16124 {
16125 gimple *stmt = gsi_stmt (*gsi_p);
16126 struct walk_stmt_info wi;
16127 gcall *call_stmt;
16128
16129 if (gimple_has_location (stmt))
16130 input_location = gimple_location (stmt);
16131
16132 if (task_shared_vars)
16133 memset (&wi, '\0', sizeof (wi));
16134
16135 /* If we have issued syntax errors, avoid doing any heavy lifting.
16136 Just replace the OMP directives with a NOP to avoid
16137 confusing RTL expansion. */
16138 if (seen_error () && is_gimple_omp (stmt))
16139 {
16140 gsi_replace (gsi_p, gimple_build_nop (), true);
16141 return;
16142 }
16143
16144 switch (gimple_code (stmt))
16145 {
16146 case GIMPLE_COND:
16147 {
16148 gcond *cond_stmt = as_a <gcond *> (stmt);
16149 if ((ctx || task_shared_vars)
16150 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
16151 lower_omp_regimplify_p,
16152 ctx ? NULL : &wi, NULL)
16153 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
16154 lower_omp_regimplify_p,
16155 ctx ? NULL : &wi, NULL)))
16156 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
16157 }
16158 break;
16159 case GIMPLE_CATCH:
16160 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
16161 break;
16162 case GIMPLE_EH_FILTER:
16163 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
16164 break;
16165 case GIMPLE_TRY:
16166 lower_omp (gimple_try_eval_ptr (stmt), ctx);
16167 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
16168 break;
16169 case GIMPLE_TRANSACTION:
16170 lower_omp (gimple_transaction_body_ptr (
16171 as_a <gtransaction *> (stmt)),
16172 ctx);
16173 break;
16174 case GIMPLE_BIND:
16175 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
16176 break;
16177 case GIMPLE_OMP_PARALLEL:
16178 case GIMPLE_OMP_TASK:
16179 ctx = maybe_lookup_ctx (stmt);
16180 gcc_assert (ctx);
16181 if (ctx->cancellable)
16182 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
16183 lower_omp_taskreg (gsi_p, ctx);
16184 break;
16185 case GIMPLE_OMP_FOR:
16186 ctx = maybe_lookup_ctx (stmt);
16187 gcc_assert (ctx);
16188 if (ctx->cancellable)
16189 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
16190 lower_omp_for (gsi_p, ctx);
16191 break;
16192 case GIMPLE_OMP_SECTIONS:
16193 ctx = maybe_lookup_ctx (stmt);
16194 gcc_assert (ctx);
16195 if (ctx->cancellable)
16196 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
16197 lower_omp_sections (gsi_p, ctx);
16198 break;
16199 case GIMPLE_OMP_SINGLE:
16200 ctx = maybe_lookup_ctx (stmt);
16201 gcc_assert (ctx);
16202 lower_omp_single (gsi_p, ctx);
16203 break;
16204 case GIMPLE_OMP_MASTER:
16205 ctx = maybe_lookup_ctx (stmt);
16206 gcc_assert (ctx);
16207 lower_omp_master (gsi_p, ctx);
16208 break;
16209 case GIMPLE_OMP_TASKGROUP:
16210 ctx = maybe_lookup_ctx (stmt);
16211 gcc_assert (ctx);
16212 lower_omp_taskgroup (gsi_p, ctx);
16213 break;
16214 case GIMPLE_OMP_ORDERED:
16215 ctx = maybe_lookup_ctx (stmt);
16216 gcc_assert (ctx);
16217 lower_omp_ordered (gsi_p, ctx);
16218 break;
16219 case GIMPLE_OMP_CRITICAL:
16220 ctx = maybe_lookup_ctx (stmt);
16221 gcc_assert (ctx);
16222 lower_omp_critical (gsi_p, ctx);
16223 break;
16224 case GIMPLE_OMP_ATOMIC_LOAD:
16225 if ((ctx || task_shared_vars)
16226 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
16227 as_a <gomp_atomic_load *> (stmt)),
16228 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
16229 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
16230 break;
16231 case GIMPLE_OMP_TARGET:
16232 ctx = maybe_lookup_ctx (stmt);
16233 gcc_assert (ctx);
16234 lower_omp_target (gsi_p, ctx);
16235 break;
16236 case GIMPLE_OMP_TEAMS:
16237 ctx = maybe_lookup_ctx (stmt);
16238 gcc_assert (ctx);
16239 lower_omp_teams (gsi_p, ctx);
16240 break;
16241 case GIMPLE_CALL:
16242 tree fndecl;
16243 call_stmt = as_a <gcall *> (stmt);
16244 fndecl = gimple_call_fndecl (call_stmt);
16245 if (fndecl
16246 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
16247 switch (DECL_FUNCTION_CODE (fndecl))
16248 {
16249 case BUILT_IN_GOMP_BARRIER:
16250 if (ctx == NULL)
16251 break;
16252 /* FALLTHRU */
16253 case BUILT_IN_GOMP_CANCEL:
16254 case BUILT_IN_GOMP_CANCELLATION_POINT:
16255 omp_context *cctx;
16256 cctx = ctx;
16257 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
16258 cctx = cctx->outer;
16259 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
16260 if (!cctx->cancellable)
16261 {
16262 if (DECL_FUNCTION_CODE (fndecl)
16263 == BUILT_IN_GOMP_CANCELLATION_POINT)
16264 {
16265 stmt = gimple_build_nop ();
16266 gsi_replace (gsi_p, stmt, false);
16267 }
16268 break;
16269 }
16270 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
16271 {
16272 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
16273 gimple_call_set_fndecl (call_stmt, fndecl);
16274 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
16275 }
16276 tree lhs;
16277 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
16278 gimple_call_set_lhs (call_stmt, lhs);
16279 tree fallthru_label;
16280 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
16281 gimple *g;
16282 g = gimple_build_label (fallthru_label);
16283 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
16284 g = gimple_build_cond (NE_EXPR, lhs,
16285 fold_convert (TREE_TYPE (lhs),
16286 boolean_false_node),
16287 cctx->cancel_label, fallthru_label);
16288 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
16289 break;
16290 default:
16291 break;
16292 }
16293 /* FALLTHRU */
16294 default:
16295 if ((ctx || task_shared_vars)
16296 && walk_gimple_op (stmt, lower_omp_regimplify_p,
16297 ctx ? NULL : &wi))
16298 {
16299 /* Just remove clobbers, this should happen only if we have
16300 "privatized" local addressable variables in SIMD regions,
16301 the clobber isn't needed in that case and gimplifying address
16302 of the ARRAY_REF into a pointer and creating MEM_REF based
16303 clobber would create worse code than we get with the clobber
16304 dropped. */
16305 if (gimple_clobber_p (stmt))
16306 {
16307 gsi_replace (gsi_p, gimple_build_nop (), true);
16308 break;
16309 }
16310 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
16311 }
16312 break;
16313 }
16314 }
16315
16316 static void
16317 lower_omp (gimple_seq *body, omp_context *ctx)
16318 {
16319 location_t saved_location = input_location;
16320 gimple_stmt_iterator gsi;
16321 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
16322 lower_omp_1 (&gsi, ctx);
16323 /* During gimplification, we haven't folded statments inside offloading
16324 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
16325 if (target_nesting_level || taskreg_nesting_level)
16326 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
16327 fold_stmt (&gsi);
16328 input_location = saved_location;
16329 }
16330 \f
16331 /* Main entry point. */
16332
16333 static unsigned int
16334 execute_lower_omp (void)
16335 {
16336 gimple_seq body;
16337 int i;
16338 omp_context *ctx;
16339
16340 /* This pass always runs, to provide PROP_gimple_lomp.
16341 But often, there is nothing to do. */
16342 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
16343 && flag_openmp_simd == 0)
16344 return 0;
16345
16346 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
16347 delete_omp_context);
16348
16349 body = gimple_body (current_function_decl);
16350 scan_omp (&body, NULL);
16351 gcc_assert (taskreg_nesting_level == 0);
16352 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
16353 finish_taskreg_scan (ctx);
16354 taskreg_contexts.release ();
16355
16356 if (all_contexts->root)
16357 {
16358 if (task_shared_vars)
16359 push_gimplify_context ();
16360 lower_omp (&body, NULL);
16361 if (task_shared_vars)
16362 pop_gimplify_context (NULL);
16363 }
16364
16365 if (all_contexts)
16366 {
16367 splay_tree_delete (all_contexts);
16368 all_contexts = NULL;
16369 }
16370 BITMAP_FREE (task_shared_vars);
16371 return 0;
16372 }
16373
16374 namespace {
16375
16376 const pass_data pass_data_lower_omp =
16377 {
16378 GIMPLE_PASS, /* type */
16379 "omplower", /* name */
16380 OPTGROUP_NONE, /* optinfo_flags */
16381 TV_NONE, /* tv_id */
16382 PROP_gimple_any, /* properties_required */
16383 PROP_gimple_lomp, /* properties_provided */
16384 0, /* properties_destroyed */
16385 0, /* todo_flags_start */
16386 0, /* todo_flags_finish */
16387 };
16388
16389 class pass_lower_omp : public gimple_opt_pass
16390 {
16391 public:
16392 pass_lower_omp (gcc::context *ctxt)
16393 : gimple_opt_pass (pass_data_lower_omp, ctxt)
16394 {}
16395
16396 /* opt_pass methods: */
16397 virtual unsigned int execute (function *) { return execute_lower_omp (); }
16398
16399 }; // class pass_lower_omp
16400
16401 } // anon namespace
16402
16403 gimple_opt_pass *
16404 make_pass_lower_omp (gcc::context *ctxt)
16405 {
16406 return new pass_lower_omp (ctxt);
16407 }
16408 \f
16409 /* The following is a utility to diagnose structured block violations.
16410 It is not part of the "omplower" pass, as that's invoked too late. It
16411 should be invoked by the respective front ends after gimplification. */
16412
16413 static splay_tree all_labels;
16414
16415 /* Check for mismatched contexts and generate an error if needed. Return
16416 true if an error is detected. */
16417
16418 static bool
16419 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
16420 gimple *branch_ctx, gimple *label_ctx)
16421 {
16422 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
16423 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
16424
16425 if (label_ctx == branch_ctx)
16426 return false;
16427
16428 const char* kind = NULL;
16429
16430 if (flag_cilkplus)
16431 {
16432 if ((branch_ctx
16433 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
16434 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
16435 || (label_ctx
16436 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
16437 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
16438 kind = "Cilk Plus";
16439 }
16440 if (flag_openacc)
16441 {
16442 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
16443 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
16444 {
16445 gcc_checking_assert (kind == NULL);
16446 kind = "OpenACC";
16447 }
16448 }
16449 if (kind == NULL)
16450 {
16451 gcc_checking_assert (flag_openmp);
16452 kind = "OpenMP";
16453 }
16454
16455 /*
16456 Previously we kept track of the label's entire context in diagnose_sb_[12]
16457 so we could traverse it and issue a correct "exit" or "enter" error
16458 message upon a structured block violation.
16459
16460 We built the context by building a list with tree_cons'ing, but there is
16461 no easy counterpart in gimple tuples. It seems like far too much work
16462 for issuing exit/enter error messages. If someone really misses the
16463 distinct error message... patches welcome.
16464 */
16465
16466 #if 0
16467 /* Try to avoid confusing the user by producing and error message
16468 with correct "exit" or "enter" verbiage. We prefer "exit"
16469 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
16470 if (branch_ctx == NULL)
16471 exit_p = false;
16472 else
16473 {
16474 while (label_ctx)
16475 {
16476 if (TREE_VALUE (label_ctx) == branch_ctx)
16477 {
16478 exit_p = false;
16479 break;
16480 }
16481 label_ctx = TREE_CHAIN (label_ctx);
16482 }
16483 }
16484
16485 if (exit_p)
16486 error ("invalid exit from %s structured block", kind);
16487 else
16488 error ("invalid entry to %s structured block", kind);
16489 #endif
16490
16491 /* If it's obvious we have an invalid entry, be specific about the error. */
16492 if (branch_ctx == NULL)
16493 error ("invalid entry to %s structured block", kind);
16494 else
16495 {
16496 /* Otherwise, be vague and lazy, but efficient. */
16497 error ("invalid branch to/from %s structured block", kind);
16498 }
16499
16500 gsi_replace (gsi_p, gimple_build_nop (), false);
16501 return true;
16502 }
16503
16504 /* Pass 1: Create a minimal tree of structured blocks, and record
16505 where each label is found. */
16506
16507 static tree
16508 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16509 struct walk_stmt_info *wi)
16510 {
16511 gimple *context = (gimple *) wi->info;
16512 gimple *inner_context;
16513 gimple *stmt = gsi_stmt (*gsi_p);
16514
16515 *handled_ops_p = true;
16516
16517 switch (gimple_code (stmt))
16518 {
16519 WALK_SUBSTMTS;
16520
16521 case GIMPLE_OMP_PARALLEL:
16522 case GIMPLE_OMP_TASK:
16523 case GIMPLE_OMP_SECTIONS:
16524 case GIMPLE_OMP_SINGLE:
16525 case GIMPLE_OMP_SECTION:
16526 case GIMPLE_OMP_MASTER:
16527 case GIMPLE_OMP_ORDERED:
16528 case GIMPLE_OMP_CRITICAL:
16529 case GIMPLE_OMP_TARGET:
16530 case GIMPLE_OMP_TEAMS:
16531 case GIMPLE_OMP_TASKGROUP:
16532 /* The minimal context here is just the current OMP construct. */
16533 inner_context = stmt;
16534 wi->info = inner_context;
16535 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
16536 wi->info = context;
16537 break;
16538
16539 case GIMPLE_OMP_FOR:
16540 inner_context = stmt;
16541 wi->info = inner_context;
16542 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16543 walk them. */
16544 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
16545 diagnose_sb_1, NULL, wi);
16546 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
16547 wi->info = context;
16548 break;
16549
16550 case GIMPLE_LABEL:
16551 splay_tree_insert (all_labels,
16552 (splay_tree_key) gimple_label_label (
16553 as_a <glabel *> (stmt)),
16554 (splay_tree_value) context);
16555 break;
16556
16557 default:
16558 break;
16559 }
16560
16561 return NULL_TREE;
16562 }
16563
16564 /* Pass 2: Check each branch and see if its context differs from that of
16565 the destination label's context. */
16566
16567 static tree
16568 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
16569 struct walk_stmt_info *wi)
16570 {
16571 gimple *context = (gimple *) wi->info;
16572 splay_tree_node n;
16573 gimple *stmt = gsi_stmt (*gsi_p);
16574
16575 *handled_ops_p = true;
16576
16577 switch (gimple_code (stmt))
16578 {
16579 WALK_SUBSTMTS;
16580
16581 case GIMPLE_OMP_PARALLEL:
16582 case GIMPLE_OMP_TASK:
16583 case GIMPLE_OMP_SECTIONS:
16584 case GIMPLE_OMP_SINGLE:
16585 case GIMPLE_OMP_SECTION:
16586 case GIMPLE_OMP_MASTER:
16587 case GIMPLE_OMP_ORDERED:
16588 case GIMPLE_OMP_CRITICAL:
16589 case GIMPLE_OMP_TARGET:
16590 case GIMPLE_OMP_TEAMS:
16591 case GIMPLE_OMP_TASKGROUP:
16592 wi->info = stmt;
16593 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
16594 wi->info = context;
16595 break;
16596
16597 case GIMPLE_OMP_FOR:
16598 wi->info = stmt;
16599 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
16600 walk them. */
16601 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
16602 diagnose_sb_2, NULL, wi);
16603 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
16604 wi->info = context;
16605 break;
16606
16607 case GIMPLE_COND:
16608 {
16609 gcond *cond_stmt = as_a <gcond *> (stmt);
16610 tree lab = gimple_cond_true_label (cond_stmt);
16611 if (lab)
16612 {
16613 n = splay_tree_lookup (all_labels,
16614 (splay_tree_key) lab);
16615 diagnose_sb_0 (gsi_p, context,
16616 n ? (gimple *) n->value : NULL);
16617 }
16618 lab = gimple_cond_false_label (cond_stmt);
16619 if (lab)
16620 {
16621 n = splay_tree_lookup (all_labels,
16622 (splay_tree_key) lab);
16623 diagnose_sb_0 (gsi_p, context,
16624 n ? (gimple *) n->value : NULL);
16625 }
16626 }
16627 break;
16628
16629 case GIMPLE_GOTO:
16630 {
16631 tree lab = gimple_goto_dest (stmt);
16632 if (TREE_CODE (lab) != LABEL_DECL)
16633 break;
16634
16635 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
16636 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
16637 }
16638 break;
16639
16640 case GIMPLE_SWITCH:
16641 {
16642 gswitch *switch_stmt = as_a <gswitch *> (stmt);
16643 unsigned int i;
16644 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
16645 {
16646 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
16647 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
16648 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
16649 break;
16650 }
16651 }
16652 break;
16653
16654 case GIMPLE_RETURN:
16655 diagnose_sb_0 (gsi_p, context, NULL);
16656 break;
16657
16658 default:
16659 break;
16660 }
16661
16662 return NULL_TREE;
16663 }
16664
16665 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
16666 GIMPLE_* codes. */
16667 bool
16668 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
16669 int *region_idx)
16670 {
16671 gimple *last = last_stmt (bb);
16672 enum gimple_code code = gimple_code (last);
16673 struct omp_region *cur_region = *region;
16674 bool fallthru = false;
16675
16676 switch (code)
16677 {
16678 case GIMPLE_OMP_PARALLEL:
16679 case GIMPLE_OMP_TASK:
16680 case GIMPLE_OMP_FOR:
16681 case GIMPLE_OMP_SINGLE:
16682 case GIMPLE_OMP_TEAMS:
16683 case GIMPLE_OMP_MASTER:
16684 case GIMPLE_OMP_TASKGROUP:
16685 case GIMPLE_OMP_CRITICAL:
16686 case GIMPLE_OMP_SECTION:
16687 cur_region = new_omp_region (bb, code, cur_region);
16688 fallthru = true;
16689 break;
16690
16691 case GIMPLE_OMP_ORDERED:
16692 cur_region = new_omp_region (bb, code, cur_region);
16693 fallthru = true;
16694 if (find_omp_clause (gimple_omp_ordered_clauses
16695 (as_a <gomp_ordered *> (last)),
16696 OMP_CLAUSE_DEPEND))
16697 cur_region = cur_region->outer;
16698 break;
16699
16700 case GIMPLE_OMP_TARGET:
16701 cur_region = new_omp_region (bb, code, cur_region);
16702 fallthru = true;
16703 switch (gimple_omp_target_kind (last))
16704 {
16705 case GF_OMP_TARGET_KIND_REGION:
16706 case GF_OMP_TARGET_KIND_DATA:
16707 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
16708 case GF_OMP_TARGET_KIND_OACC_KERNELS:
16709 case GF_OMP_TARGET_KIND_OACC_DATA:
16710 break;
16711 case GF_OMP_TARGET_KIND_UPDATE:
16712 case GF_OMP_TARGET_KIND_ENTER_DATA:
16713 case GF_OMP_TARGET_KIND_EXIT_DATA:
16714 case GF_OMP_TARGET_KIND_OACC_UPDATE:
16715 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
16716 cur_region = cur_region->outer;
16717 break;
16718 default:
16719 gcc_unreachable ();
16720 }
16721 break;
16722
16723 case GIMPLE_OMP_SECTIONS:
16724 cur_region = new_omp_region (bb, code, cur_region);
16725 fallthru = true;
16726 break;
16727
16728 case GIMPLE_OMP_SECTIONS_SWITCH:
16729 fallthru = false;
16730 break;
16731
16732 case GIMPLE_OMP_ATOMIC_LOAD:
16733 case GIMPLE_OMP_ATOMIC_STORE:
16734 fallthru = true;
16735 break;
16736
16737 case GIMPLE_OMP_RETURN:
16738 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
16739 somewhere other than the next block. This will be
16740 created later. */
16741 cur_region->exit = bb;
16742 if (cur_region->type == GIMPLE_OMP_TASK)
16743 /* Add an edge corresponding to not scheduling the task
16744 immediately. */
16745 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
16746 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
16747 cur_region = cur_region->outer;
16748 break;
16749
16750 case GIMPLE_OMP_CONTINUE:
16751 cur_region->cont = bb;
16752 switch (cur_region->type)
16753 {
16754 case GIMPLE_OMP_FOR:
16755 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
16756 succs edges as abnormal to prevent splitting
16757 them. */
16758 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
16759 /* Make the loopback edge. */
16760 make_edge (bb, single_succ (cur_region->entry),
16761 EDGE_ABNORMAL);
16762
16763 /* Create an edge from GIMPLE_OMP_FOR to exit, which
16764 corresponds to the case that the body of the loop
16765 is not executed at all. */
16766 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
16767 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
16768 fallthru = false;
16769 break;
16770
16771 case GIMPLE_OMP_SECTIONS:
16772 /* Wire up the edges into and out of the nested sections. */
16773 {
16774 basic_block switch_bb = single_succ (cur_region->entry);
16775
16776 struct omp_region *i;
16777 for (i = cur_region->inner; i ; i = i->next)
16778 {
16779 gcc_assert (i->type == GIMPLE_OMP_SECTION);
16780 make_edge (switch_bb, i->entry, 0);
16781 make_edge (i->exit, bb, EDGE_FALLTHRU);
16782 }
16783
16784 /* Make the loopback edge to the block with
16785 GIMPLE_OMP_SECTIONS_SWITCH. */
16786 make_edge (bb, switch_bb, 0);
16787
16788 /* Make the edge from the switch to exit. */
16789 make_edge (switch_bb, bb->next_bb, 0);
16790 fallthru = false;
16791 }
16792 break;
16793
16794 case GIMPLE_OMP_TASK:
16795 fallthru = true;
16796 break;
16797
16798 default:
16799 gcc_unreachable ();
16800 }
16801 break;
16802
16803 default:
16804 gcc_unreachable ();
16805 }
16806
16807 if (*region != cur_region)
16808 {
16809 *region = cur_region;
16810 if (cur_region)
16811 *region_idx = cur_region->entry->index;
16812 else
16813 *region_idx = 0;
16814 }
16815
16816 return fallthru;
16817 }
16818
16819 static unsigned int
16820 diagnose_omp_structured_block_errors (void)
16821 {
16822 struct walk_stmt_info wi;
16823 gimple_seq body = gimple_body (current_function_decl);
16824
16825 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
16826
16827 memset (&wi, 0, sizeof (wi));
16828 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
16829
16830 memset (&wi, 0, sizeof (wi));
16831 wi.want_locations = true;
16832 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
16833
16834 gimple_set_body (current_function_decl, body);
16835
16836 splay_tree_delete (all_labels);
16837 all_labels = NULL;
16838
16839 return 0;
16840 }
16841
16842 namespace {
16843
16844 const pass_data pass_data_diagnose_omp_blocks =
16845 {
16846 GIMPLE_PASS, /* type */
16847 "*diagnose_omp_blocks", /* name */
16848 OPTGROUP_NONE, /* optinfo_flags */
16849 TV_NONE, /* tv_id */
16850 PROP_gimple_any, /* properties_required */
16851 0, /* properties_provided */
16852 0, /* properties_destroyed */
16853 0, /* todo_flags_start */
16854 0, /* todo_flags_finish */
16855 };
16856
16857 class pass_diagnose_omp_blocks : public gimple_opt_pass
16858 {
16859 public:
16860 pass_diagnose_omp_blocks (gcc::context *ctxt)
16861 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
16862 {}
16863
16864 /* opt_pass methods: */
16865 virtual bool gate (function *)
16866 {
16867 return flag_cilkplus || flag_openacc || flag_openmp;
16868 }
16869 virtual unsigned int execute (function *)
16870 {
16871 return diagnose_omp_structured_block_errors ();
16872 }
16873
16874 }; // class pass_diagnose_omp_blocks
16875
16876 } // anon namespace
16877
16878 gimple_opt_pass *
16879 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
16880 {
16881 return new pass_diagnose_omp_blocks (ctxt);
16882 }
16883 \f
16884 /* SIMD clone supporting code. */
16885
16886 /* Allocate a fresh `simd_clone' and return it. NARGS is the number
16887 of arguments to reserve space for. */
16888
16889 static struct cgraph_simd_clone *
16890 simd_clone_struct_alloc (int nargs)
16891 {
16892 struct cgraph_simd_clone *clone_info;
16893 size_t len = (sizeof (struct cgraph_simd_clone)
16894 + nargs * sizeof (struct cgraph_simd_clone_arg));
16895 clone_info = (struct cgraph_simd_clone *)
16896 ggc_internal_cleared_alloc (len);
16897 return clone_info;
16898 }
16899
16900 /* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
16901
16902 static inline void
16903 simd_clone_struct_copy (struct cgraph_simd_clone *to,
16904 struct cgraph_simd_clone *from)
16905 {
16906 memcpy (to, from, (sizeof (struct cgraph_simd_clone)
16907 + ((from->nargs - from->inbranch)
16908 * sizeof (struct cgraph_simd_clone_arg))));
16909 }
16910
16911 /* Return vector of parameter types of function FNDECL. This uses
16912 TYPE_ARG_TYPES if available, otherwise falls back to types of
16913 DECL_ARGUMENTS types. */
16914
16915 vec<tree>
16916 simd_clone_vector_of_formal_parm_types (tree fndecl)
16917 {
16918 if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
16919 return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
16920 vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
16921 unsigned int i;
16922 tree arg;
16923 FOR_EACH_VEC_ELT (args, i, arg)
16924 args[i] = TREE_TYPE (args[i]);
16925 return args;
16926 }
16927
16928 /* Given a simd function in NODE, extract the simd specific
16929 information from the OMP clauses passed in CLAUSES, and return
16930 the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
16931 is set to TRUE if the `inbranch' or `notinbranch' clause specified,
16932 otherwise set to FALSE. */
16933
16934 static struct cgraph_simd_clone *
16935 simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
16936 bool *inbranch_specified)
16937 {
16938 vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
16939 tree t;
16940 int n;
16941 *inbranch_specified = false;
16942
16943 n = args.length ();
16944 if (n > 0 && args.last () == void_type_node)
16945 n--;
16946
16947 /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
16948 be cloned have a distinctive artificial label in addition to "omp
16949 declare simd". */
16950 bool cilk_clone
16951 = (flag_cilkplus
16952 && lookup_attribute ("cilk simd function",
16953 DECL_ATTRIBUTES (node->decl)));
16954
16955 /* Allocate one more than needed just in case this is an in-branch
16956 clone which will require a mask argument. */
16957 struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
16958 clone_info->nargs = n;
16959 clone_info->cilk_elemental = cilk_clone;
16960
16961 if (!clauses)
16962 {
16963 args.release ();
16964 return clone_info;
16965 }
16966 clauses = TREE_VALUE (clauses);
16967 if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
16968 return clone_info;
16969
16970 for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
16971 {
16972 switch (OMP_CLAUSE_CODE (t))
16973 {
16974 case OMP_CLAUSE_INBRANCH:
16975 clone_info->inbranch = 1;
16976 *inbranch_specified = true;
16977 break;
16978 case OMP_CLAUSE_NOTINBRANCH:
16979 clone_info->inbranch = 0;
16980 *inbranch_specified = true;
16981 break;
16982 case OMP_CLAUSE_SIMDLEN:
16983 clone_info->simdlen
16984 = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
16985 break;
16986 case OMP_CLAUSE_LINEAR:
16987 {
16988 tree decl = OMP_CLAUSE_DECL (t);
16989 tree step = OMP_CLAUSE_LINEAR_STEP (t);
16990 int argno = TREE_INT_CST_LOW (decl);
16991 if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
16992 {
16993 enum cgraph_simd_clone_arg_type arg_type;
16994 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
16995 switch (OMP_CLAUSE_LINEAR_KIND (t))
16996 {
16997 case OMP_CLAUSE_LINEAR_REF:
16998 arg_type
16999 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP;
17000 break;
17001 case OMP_CLAUSE_LINEAR_UVAL:
17002 arg_type
17003 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP;
17004 break;
17005 case OMP_CLAUSE_LINEAR_VAL:
17006 case OMP_CLAUSE_LINEAR_DEFAULT:
17007 arg_type
17008 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP;
17009 break;
17010 default:
17011 gcc_unreachable ();
17012 }
17013 else
17014 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
17015 clone_info->args[argno].arg_type = arg_type;
17016 clone_info->args[argno].linear_step = tree_to_shwi (step);
17017 gcc_assert (clone_info->args[argno].linear_step >= 0
17018 && clone_info->args[argno].linear_step < n);
17019 }
17020 else
17021 {
17022 if (POINTER_TYPE_P (args[argno]))
17023 step = fold_convert (ssizetype, step);
17024 if (!tree_fits_shwi_p (step))
17025 {
17026 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17027 "ignoring large linear step");
17028 args.release ();
17029 return NULL;
17030 }
17031 else if (integer_zerop (step))
17032 {
17033 warning_at (OMP_CLAUSE_LOCATION (t), 0,
17034 "ignoring zero linear step");
17035 args.release ();
17036 return NULL;
17037 }
17038 else
17039 {
17040 enum cgraph_simd_clone_arg_type arg_type;
17041 if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
17042 switch (OMP_CLAUSE_LINEAR_KIND (t))
17043 {
17044 case OMP_CLAUSE_LINEAR_REF:
17045 arg_type
17046 = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
17047 break;
17048 case OMP_CLAUSE_LINEAR_UVAL:
17049 arg_type
17050 = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
17051 break;
17052 case OMP_CLAUSE_LINEAR_VAL:
17053 case OMP_CLAUSE_LINEAR_DEFAULT:
17054 arg_type
17055 = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
17056 break;
17057 default:
17058 gcc_unreachable ();
17059 }
17060 else
17061 arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
17062 clone_info->args[argno].arg_type = arg_type;
17063 clone_info->args[argno].linear_step = tree_to_shwi (step);
17064 }
17065 }
17066 break;
17067 }
17068 case OMP_CLAUSE_UNIFORM:
17069 {
17070 tree decl = OMP_CLAUSE_DECL (t);
17071 int argno = tree_to_uhwi (decl);
17072 clone_info->args[argno].arg_type
17073 = SIMD_CLONE_ARG_TYPE_UNIFORM;
17074 break;
17075 }
17076 case OMP_CLAUSE_ALIGNED:
17077 {
17078 tree decl = OMP_CLAUSE_DECL (t);
17079 int argno = tree_to_uhwi (decl);
17080 clone_info->args[argno].alignment
17081 = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
17082 break;
17083 }
17084 default:
17085 break;
17086 }
17087 }
17088 args.release ();
17089 return clone_info;
17090 }
17091
17092 /* Given a SIMD clone in NODE, calculate the characteristic data
17093 type and return the coresponding type. The characteristic data
17094 type is computed as described in the Intel Vector ABI. */
17095
17096 static tree
17097 simd_clone_compute_base_data_type (struct cgraph_node *node,
17098 struct cgraph_simd_clone *clone_info)
17099 {
17100 tree type = integer_type_node;
17101 tree fndecl = node->decl;
17102
17103 /* a) For non-void function, the characteristic data type is the
17104 return type. */
17105 if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
17106 type = TREE_TYPE (TREE_TYPE (fndecl));
17107
17108 /* b) If the function has any non-uniform, non-linear parameters,
17109 then the characteristic data type is the type of the first
17110 such parameter. */
17111 else
17112 {
17113 vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
17114 for (unsigned int i = 0; i < clone_info->nargs; ++i)
17115 if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
17116 {
17117 type = map[i];
17118 break;
17119 }
17120 map.release ();
17121 }
17122
17123 /* c) If the characteristic data type determined by a) or b) above
17124 is struct, union, or class type which is pass-by-value (except
17125 for the type that maps to the built-in complex data type), the
17126 characteristic data type is int. */
17127 if (RECORD_OR_UNION_TYPE_P (type)
17128 && !aggregate_value_p (type, NULL)
17129 && TREE_CODE (type) != COMPLEX_TYPE)
17130 return integer_type_node;
17131
17132 /* d) If none of the above three classes is applicable, the
17133 characteristic data type is int. */
17134
17135 return type;
17136
17137 /* e) For Intel Xeon Phi native and offload compilation, if the
17138 resulting characteristic data type is 8-bit or 16-bit integer
17139 data type, the characteristic data type is int. */
17140 /* Well, we don't handle Xeon Phi yet. */
17141 }
17142
17143 static tree
17144 simd_clone_mangle (struct cgraph_node *node,
17145 struct cgraph_simd_clone *clone_info)
17146 {
17147 char vecsize_mangle = clone_info->vecsize_mangle;
17148 char mask = clone_info->inbranch ? 'M' : 'N';
17149 unsigned int simdlen = clone_info->simdlen;
17150 unsigned int n;
17151 pretty_printer pp;
17152
17153 gcc_assert (vecsize_mangle && simdlen);
17154
17155 pp_string (&pp, "_ZGV");
17156 pp_character (&pp, vecsize_mangle);
17157 pp_character (&pp, mask);
17158 pp_decimal_int (&pp, simdlen);
17159
17160 for (n = 0; n < clone_info->nargs; ++n)
17161 {
17162 struct cgraph_simd_clone_arg arg = clone_info->args[n];
17163
17164 switch (arg.arg_type)
17165 {
17166 case SIMD_CLONE_ARG_TYPE_UNIFORM:
17167 pp_character (&pp, 'u');
17168 break;
17169 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
17170 pp_character (&pp, 'l');
17171 goto mangle_linear;
17172 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
17173 pp_character (&pp, 'R');
17174 goto mangle_linear;
17175 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17176 pp_character (&pp, 'L');
17177 goto mangle_linear;
17178 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17179 pp_character (&pp, 'U');
17180 goto mangle_linear;
17181 mangle_linear:
17182 gcc_assert (arg.linear_step != 0);
17183 if (arg.linear_step > 1)
17184 pp_unsigned_wide_integer (&pp, arg.linear_step);
17185 else if (arg.linear_step < 0)
17186 {
17187 pp_character (&pp, 'n');
17188 pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
17189 arg.linear_step));
17190 }
17191 break;
17192 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
17193 pp_string (&pp, "ls");
17194 pp_unsigned_wide_integer (&pp, arg.linear_step);
17195 break;
17196 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
17197 pp_string (&pp, "Rs");
17198 pp_unsigned_wide_integer (&pp, arg.linear_step);
17199 break;
17200 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
17201 pp_string (&pp, "Ls");
17202 pp_unsigned_wide_integer (&pp, arg.linear_step);
17203 break;
17204 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
17205 pp_string (&pp, "Us");
17206 pp_unsigned_wide_integer (&pp, arg.linear_step);
17207 break;
17208 default:
17209 pp_character (&pp, 'v');
17210 }
17211 if (arg.alignment)
17212 {
17213 pp_character (&pp, 'a');
17214 pp_decimal_int (&pp, arg.alignment);
17215 }
17216 }
17217
17218 pp_underscore (&pp);
17219 const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
17220 if (*str == '*')
17221 ++str;
17222 pp_string (&pp, str);
17223 str = pp_formatted_text (&pp);
17224
17225 /* If there already is a SIMD clone with the same mangled name, don't
17226 add another one. This can happen e.g. for
17227 #pragma omp declare simd
17228 #pragma omp declare simd simdlen(8)
17229 int foo (int, int);
17230 if the simdlen is assumed to be 8 for the first one, etc. */
17231 for (struct cgraph_node *clone = node->simd_clones; clone;
17232 clone = clone->simdclone->next_clone)
17233 if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
17234 str) == 0)
17235 return NULL_TREE;
17236
17237 return get_identifier (str);
17238 }
17239
17240 /* Create a simd clone of OLD_NODE and return it. */
17241
17242 static struct cgraph_node *
17243 simd_clone_create (struct cgraph_node *old_node)
17244 {
17245 struct cgraph_node *new_node;
17246 if (old_node->definition)
17247 {
17248 if (!old_node->has_gimple_body_p ())
17249 return NULL;
17250 old_node->get_body ();
17251 new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
17252 false, NULL, NULL,
17253 "simdclone");
17254 }
17255 else
17256 {
17257 tree old_decl = old_node->decl;
17258 tree new_decl = copy_node (old_node->decl);
17259 DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
17260 SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
17261 SET_DECL_RTL (new_decl, NULL);
17262 DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
17263 DECL_STATIC_DESTRUCTOR (new_decl) = 0;
17264 new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
17265 if (old_node->in_other_partition)
17266 new_node->in_other_partition = 1;
17267 symtab->call_cgraph_insertion_hooks (new_node);
17268 }
17269 if (new_node == NULL)
17270 return new_node;
17271
17272 TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
17273
17274 /* The function cgraph_function_versioning () will force the new
17275 symbol local. Undo this, and inherit external visability from
17276 the old node. */
17277 new_node->local.local = old_node->local.local;
17278 new_node->externally_visible = old_node->externally_visible;
17279
17280 return new_node;
17281 }
17282
17283 /* Adjust the return type of the given function to its appropriate
17284 vector counterpart. Returns a simd array to be used throughout the
17285 function as a return value. */
17286
17287 static tree
17288 simd_clone_adjust_return_type (struct cgraph_node *node)
17289 {
17290 tree fndecl = node->decl;
17291 tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
17292 unsigned int veclen;
17293 tree t;
17294
17295 /* Adjust the function return type. */
17296 if (orig_rettype == void_type_node)
17297 return NULL_TREE;
17298 TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
17299 t = TREE_TYPE (TREE_TYPE (fndecl));
17300 if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
17301 veclen = node->simdclone->vecsize_int;
17302 else
17303 veclen = node->simdclone->vecsize_float;
17304 veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
17305 if (veclen > node->simdclone->simdlen)
17306 veclen = node->simdclone->simdlen;
17307 if (POINTER_TYPE_P (t))
17308 t = pointer_sized_int_node;
17309 if (veclen == node->simdclone->simdlen)
17310 t = build_vector_type (t, node->simdclone->simdlen);
17311 else
17312 {
17313 t = build_vector_type (t, veclen);
17314 t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
17315 }
17316 TREE_TYPE (TREE_TYPE (fndecl)) = t;
17317 if (!node->definition)
17318 return NULL_TREE;
17319
17320 t = DECL_RESULT (fndecl);
17321 /* Adjust the DECL_RESULT. */
17322 gcc_assert (TREE_TYPE (t) != void_type_node);
17323 TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
17324 relayout_decl (t);
17325
17326 tree atype = build_array_type_nelts (orig_rettype,
17327 node->simdclone->simdlen);
17328 if (veclen != node->simdclone->simdlen)
17329 return build1 (VIEW_CONVERT_EXPR, atype, t);
17330
17331 /* Set up a SIMD array to use as the return value. */
17332 tree retval = create_tmp_var_raw (atype, "retval");
17333 gimple_add_tmp_var (retval);
17334 return retval;
17335 }
17336
17337 /* Each vector argument has a corresponding array to be used locally
17338 as part of the eventual loop. Create such temporary array and
17339 return it.
17340
17341 PREFIX is the prefix to be used for the temporary.
17342
17343 TYPE is the inner element type.
17344
17345 SIMDLEN is the number of elements. */
17346
17347 static tree
17348 create_tmp_simd_array (const char *prefix, tree type, int simdlen)
17349 {
17350 tree atype = build_array_type_nelts (type, simdlen);
17351 tree avar = create_tmp_var_raw (atype, prefix);
17352 gimple_add_tmp_var (avar);
17353 return avar;
17354 }
17355
17356 /* Modify the function argument types to their corresponding vector
17357 counterparts if appropriate. Also, create one array for each simd
17358 argument to be used locally when using the function arguments as
17359 part of the loop.
17360
17361 NODE is the function whose arguments are to be adjusted.
17362
17363 Returns an adjustment vector that will be filled describing how the
17364 argument types will be adjusted. */
17365
17366 static ipa_parm_adjustment_vec
17367 simd_clone_adjust_argument_types (struct cgraph_node *node)
17368 {
17369 vec<tree> args;
17370 ipa_parm_adjustment_vec adjustments;
17371
17372 if (node->definition)
17373 args = ipa_get_vector_of_formal_parms (node->decl);
17374 else
17375 args = simd_clone_vector_of_formal_parm_types (node->decl);
17376 adjustments.create (args.length ());
17377 unsigned i, j, veclen;
17378 struct ipa_parm_adjustment adj;
17379 for (i = 0; i < node->simdclone->nargs; ++i)
17380 {
17381 memset (&adj, 0, sizeof (adj));
17382 tree parm = args[i];
17383 tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
17384 adj.base_index = i;
17385 adj.base = parm;
17386
17387 node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE;
17388 node->simdclone->args[i].orig_type = parm_type;
17389
17390 switch (node->simdclone->args[i].arg_type)
17391 {
17392 default:
17393 /* No adjustment necessary for scalar arguments. */
17394 adj.op = IPA_PARM_OP_COPY;
17395 break;
17396 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17397 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
17398 if (node->definition)
17399 node->simdclone->args[i].simd_array
17400 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17401 TREE_TYPE (parm_type),
17402 node->simdclone->simdlen);
17403 adj.op = IPA_PARM_OP_COPY;
17404 break;
17405 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17406 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
17407 case SIMD_CLONE_ARG_TYPE_VECTOR:
17408 if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
17409 veclen = node->simdclone->vecsize_int;
17410 else
17411 veclen = node->simdclone->vecsize_float;
17412 veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
17413 if (veclen > node->simdclone->simdlen)
17414 veclen = node->simdclone->simdlen;
17415 adj.arg_prefix = "simd";
17416 if (POINTER_TYPE_P (parm_type))
17417 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17418 else
17419 adj.type = build_vector_type (parm_type, veclen);
17420 node->simdclone->args[i].vector_type = adj.type;
17421 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17422 {
17423 adjustments.safe_push (adj);
17424 if (j == veclen)
17425 {
17426 memset (&adj, 0, sizeof (adj));
17427 adj.op = IPA_PARM_OP_NEW;
17428 adj.arg_prefix = "simd";
17429 adj.base_index = i;
17430 adj.type = node->simdclone->args[i].vector_type;
17431 }
17432 }
17433
17434 if (node->definition)
17435 node->simdclone->args[i].simd_array
17436 = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
17437 parm_type, node->simdclone->simdlen);
17438 }
17439 adjustments.safe_push (adj);
17440 }
17441
17442 if (node->simdclone->inbranch)
17443 {
17444 tree base_type
17445 = simd_clone_compute_base_data_type (node->simdclone->origin,
17446 node->simdclone);
17447
17448 memset (&adj, 0, sizeof (adj));
17449 adj.op = IPA_PARM_OP_NEW;
17450 adj.arg_prefix = "mask";
17451
17452 adj.base_index = i;
17453 if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
17454 veclen = node->simdclone->vecsize_int;
17455 else
17456 veclen = node->simdclone->vecsize_float;
17457 veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
17458 if (veclen > node->simdclone->simdlen)
17459 veclen = node->simdclone->simdlen;
17460 if (POINTER_TYPE_P (base_type))
17461 adj.type = build_vector_type (pointer_sized_int_node, veclen);
17462 else
17463 adj.type = build_vector_type (base_type, veclen);
17464 adjustments.safe_push (adj);
17465
17466 for (j = veclen; j < node->simdclone->simdlen; j += veclen)
17467 adjustments.safe_push (adj);
17468
17469 /* We have previously allocated one extra entry for the mask. Use
17470 it and fill it. */
17471 struct cgraph_simd_clone *sc = node->simdclone;
17472 sc->nargs++;
17473 if (node->definition)
17474 {
17475 sc->args[i].orig_arg
17476 = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
17477 sc->args[i].simd_array
17478 = create_tmp_simd_array ("mask", base_type, sc->simdlen);
17479 }
17480 sc->args[i].orig_type = base_type;
17481 sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
17482 }
17483
17484 if (node->definition)
17485 ipa_modify_formal_parameters (node->decl, adjustments);
17486 else
17487 {
17488 tree new_arg_types = NULL_TREE, new_reversed;
17489 bool last_parm_void = false;
17490 if (args.length () > 0 && args.last () == void_type_node)
17491 last_parm_void = true;
17492
17493 gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
17494 j = adjustments.length ();
17495 for (i = 0; i < j; i++)
17496 {
17497 struct ipa_parm_adjustment *adj = &adjustments[i];
17498 tree ptype;
17499 if (adj->op == IPA_PARM_OP_COPY)
17500 ptype = args[adj->base_index];
17501 else
17502 ptype = adj->type;
17503 new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
17504 }
17505 new_reversed = nreverse (new_arg_types);
17506 if (last_parm_void)
17507 {
17508 if (new_reversed)
17509 TREE_CHAIN (new_arg_types) = void_list_node;
17510 else
17511 new_reversed = void_list_node;
17512 }
17513
17514 tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
17515 TYPE_ARG_TYPES (new_type) = new_reversed;
17516 TREE_TYPE (node->decl) = new_type;
17517
17518 adjustments.release ();
17519 }
17520 args.release ();
17521 return adjustments;
17522 }
17523
17524 /* Initialize and copy the function arguments in NODE to their
17525 corresponding local simd arrays. Returns a fresh gimple_seq with
17526 the instruction sequence generated. */
17527
17528 static gimple_seq
17529 simd_clone_init_simd_arrays (struct cgraph_node *node,
17530 ipa_parm_adjustment_vec adjustments)
17531 {
17532 gimple_seq seq = NULL;
17533 unsigned i = 0, j = 0, k;
17534
17535 for (tree arg = DECL_ARGUMENTS (node->decl);
17536 arg;
17537 arg = DECL_CHAIN (arg), i++, j++)
17538 {
17539 if (adjustments[j].op == IPA_PARM_OP_COPY
17540 || POINTER_TYPE_P (TREE_TYPE (arg)))
17541 continue;
17542
17543 node->simdclone->args[i].vector_arg = arg;
17544
17545 tree array = node->simdclone->args[i].simd_array;
17546 if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
17547 {
17548 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17549 tree ptr = build_fold_addr_expr (array);
17550 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17551 build_int_cst (ptype, 0));
17552 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17553 gimplify_and_add (t, &seq);
17554 }
17555 else
17556 {
17557 unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
17558 tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
17559 for (k = 0; k < node->simdclone->simdlen; k += simdlen)
17560 {
17561 tree ptr = build_fold_addr_expr (array);
17562 int elemsize;
17563 if (k)
17564 {
17565 arg = DECL_CHAIN (arg);
17566 j++;
17567 }
17568 elemsize
17569 = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
17570 tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
17571 build_int_cst (ptype, k * elemsize));
17572 t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
17573 gimplify_and_add (t, &seq);
17574 }
17575 }
17576 }
17577 return seq;
17578 }
17579
17580 /* Callback info for ipa_simd_modify_stmt_ops below. */
17581
17582 struct modify_stmt_info {
17583 ipa_parm_adjustment_vec adjustments;
17584 gimple *stmt;
17585 /* True if the parent statement was modified by
17586 ipa_simd_modify_stmt_ops. */
17587 bool modified;
17588 };
17589
17590 /* Callback for walk_gimple_op.
17591
17592 Adjust operands from a given statement as specified in the
17593 adjustments vector in the callback data. */
17594
17595 static tree
17596 ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
17597 {
17598 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17599 struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
17600 tree *orig_tp = tp;
17601 if (TREE_CODE (*tp) == ADDR_EXPR)
17602 tp = &TREE_OPERAND (*tp, 0);
17603 struct ipa_parm_adjustment *cand = NULL;
17604 if (TREE_CODE (*tp) == PARM_DECL)
17605 cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
17606 else
17607 {
17608 if (TYPE_P (*tp))
17609 *walk_subtrees = 0;
17610 }
17611
17612 tree repl = NULL_TREE;
17613 if (cand)
17614 repl = unshare_expr (cand->new_decl);
17615 else
17616 {
17617 if (tp != orig_tp)
17618 {
17619 *walk_subtrees = 0;
17620 bool modified = info->modified;
17621 info->modified = false;
17622 walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
17623 if (!info->modified)
17624 {
17625 info->modified = modified;
17626 return NULL_TREE;
17627 }
17628 info->modified = modified;
17629 repl = *tp;
17630 }
17631 else
17632 return NULL_TREE;
17633 }
17634
17635 if (tp != orig_tp)
17636 {
17637 repl = build_fold_addr_expr (repl);
17638 gimple *stmt;
17639 if (is_gimple_debug (info->stmt))
17640 {
17641 tree vexpr = make_node (DEBUG_EXPR_DECL);
17642 stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
17643 DECL_ARTIFICIAL (vexpr) = 1;
17644 TREE_TYPE (vexpr) = TREE_TYPE (repl);
17645 DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
17646 repl = vexpr;
17647 }
17648 else
17649 {
17650 stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
17651 repl = gimple_assign_lhs (stmt);
17652 }
17653 gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
17654 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
17655 *orig_tp = repl;
17656 }
17657 else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
17658 {
17659 tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
17660 *tp = vce;
17661 }
17662 else
17663 *tp = repl;
17664
17665 info->modified = true;
17666 return NULL_TREE;
17667 }
17668
17669 /* Traverse the function body and perform all modifications as
17670 described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
17671 modified such that the replacement/reduction value will now be an
17672 offset into the corresponding simd_array.
17673
17674 This function will replace all function argument uses with their
17675 corresponding simd array elements, and ajust the return values
17676 accordingly. */
17677
17678 static void
17679 ipa_simd_modify_function_body (struct cgraph_node *node,
17680 ipa_parm_adjustment_vec adjustments,
17681 tree retval_array, tree iter)
17682 {
17683 basic_block bb;
17684 unsigned int i, j, l;
17685
17686 /* Re-use the adjustments array, but this time use it to replace
17687 every function argument use to an offset into the corresponding
17688 simd_array. */
17689 for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
17690 {
17691 if (!node->simdclone->args[i].vector_arg)
17692 continue;
17693
17694 tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
17695 tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
17696 adjustments[j].new_decl
17697 = build4 (ARRAY_REF,
17698 basetype,
17699 node->simdclone->args[i].simd_array,
17700 iter,
17701 NULL_TREE, NULL_TREE);
17702 if (adjustments[j].op == IPA_PARM_OP_NONE
17703 && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
17704 j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
17705 }
17706
17707 l = adjustments.length ();
17708 for (i = 1; i < num_ssa_names; i++)
17709 {
17710 tree name = ssa_name (i);
17711 if (name
17712 && SSA_NAME_VAR (name)
17713 && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
17714 {
17715 for (j = 0; j < l; j++)
17716 if (SSA_NAME_VAR (name) == adjustments[j].base
17717 && adjustments[j].new_decl)
17718 {
17719 tree base_var;
17720 if (adjustments[j].new_ssa_base == NULL_TREE)
17721 {
17722 base_var
17723 = copy_var_decl (adjustments[j].base,
17724 DECL_NAME (adjustments[j].base),
17725 TREE_TYPE (adjustments[j].base));
17726 adjustments[j].new_ssa_base = base_var;
17727 }
17728 else
17729 base_var = adjustments[j].new_ssa_base;
17730 if (SSA_NAME_IS_DEFAULT_DEF (name))
17731 {
17732 bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17733 gimple_stmt_iterator gsi = gsi_after_labels (bb);
17734 tree new_decl = unshare_expr (adjustments[j].new_decl);
17735 set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
17736 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17737 SSA_NAME_IS_DEFAULT_DEF (name) = 0;
17738 gimple *stmt = gimple_build_assign (name, new_decl);
17739 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
17740 }
17741 else
17742 SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
17743 }
17744 }
17745 }
17746
17747 struct modify_stmt_info info;
17748 info.adjustments = adjustments;
17749
17750 FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
17751 {
17752 gimple_stmt_iterator gsi;
17753
17754 gsi = gsi_start_bb (bb);
17755 while (!gsi_end_p (gsi))
17756 {
17757 gimple *stmt = gsi_stmt (gsi);
17758 info.stmt = stmt;
17759 struct walk_stmt_info wi;
17760
17761 memset (&wi, 0, sizeof (wi));
17762 info.modified = false;
17763 wi.info = &info;
17764 walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
17765
17766 if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
17767 {
17768 tree retval = gimple_return_retval (return_stmt);
17769 if (!retval)
17770 {
17771 gsi_remove (&gsi, true);
17772 continue;
17773 }
17774
17775 /* Replace `return foo' with `retval_array[iter] = foo'. */
17776 tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
17777 retval_array, iter, NULL, NULL);
17778 stmt = gimple_build_assign (ref, retval);
17779 gsi_replace (&gsi, stmt, true);
17780 info.modified = true;
17781 }
17782
17783 if (info.modified)
17784 {
17785 update_stmt (stmt);
17786 if (maybe_clean_eh_stmt (stmt))
17787 gimple_purge_dead_eh_edges (gimple_bb (stmt));
17788 }
17789 gsi_next (&gsi);
17790 }
17791 }
17792 }
17793
17794 /* Helper function of simd_clone_adjust, return linear step addend
17795 of Ith argument. */
17796
17797 static tree
17798 simd_clone_linear_addend (struct cgraph_node *node, unsigned int i,
17799 tree addtype, basic_block entry_bb)
17800 {
17801 tree ptype = NULL_TREE;
17802 switch (node->simdclone->args[i].arg_type)
17803 {
17804 case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
17805 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
17806 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
17807 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
17808 return build_int_cst (addtype, node->simdclone->args[i].linear_step);
17809 case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
17810 case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
17811 ptype = TREE_TYPE (node->simdclone->args[i].orig_arg);
17812 break;
17813 case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
17814 case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
17815 ptype = TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg));
17816 break;
17817 default:
17818 gcc_unreachable ();
17819 }
17820
17821 unsigned int idx = node->simdclone->args[i].linear_step;
17822 tree arg = node->simdclone->args[idx].orig_arg;
17823 gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
17824 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
17825 gimple *g;
17826 tree ret;
17827 if (is_gimple_reg (arg))
17828 ret = get_or_create_ssa_default_def (cfun, arg);
17829 else
17830 {
17831 g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
17832 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17833 ret = gimple_assign_lhs (g);
17834 }
17835 if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
17836 {
17837 g = gimple_build_assign (make_ssa_name (TREE_TYPE (TREE_TYPE (arg))),
17838 build_simple_mem_ref (ret));
17839 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17840 ret = gimple_assign_lhs (g);
17841 }
17842 if (!useless_type_conversion_p (addtype, TREE_TYPE (ret)))
17843 {
17844 g = gimple_build_assign (make_ssa_name (addtype), NOP_EXPR, ret);
17845 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17846 ret = gimple_assign_lhs (g);
17847 }
17848 if (POINTER_TYPE_P (ptype))
17849 {
17850 tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptype));
17851 if (size && TREE_CODE (size) == INTEGER_CST)
17852 {
17853 g = gimple_build_assign (make_ssa_name (addtype), MULT_EXPR,
17854 ret, fold_convert (addtype, size));
17855 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
17856 ret = gimple_assign_lhs (g);
17857 }
17858 }
17859 return ret;
17860 }
17861
17862 /* Adjust the argument types in NODE to their appropriate vector
17863 counterparts. */
17864
17865 static void
17866 simd_clone_adjust (struct cgraph_node *node)
17867 {
17868 push_cfun (DECL_STRUCT_FUNCTION (node->decl));
17869
17870 targetm.simd_clone.adjust (node);
17871
17872 tree retval = simd_clone_adjust_return_type (node);
17873 ipa_parm_adjustment_vec adjustments
17874 = simd_clone_adjust_argument_types (node);
17875
17876 push_gimplify_context ();
17877
17878 gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
17879
17880 /* Adjust all uses of vector arguments accordingly. Adjust all
17881 return values accordingly. */
17882 tree iter = create_tmp_var (unsigned_type_node, "iter");
17883 tree iter1 = make_ssa_name (iter);
17884 tree iter2 = make_ssa_name (iter);
17885 ipa_simd_modify_function_body (node, adjustments, retval, iter1);
17886
17887 /* Initialize the iteration variable. */
17888 basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
17889 basic_block body_bb = split_block_after_labels (entry_bb)->dest;
17890 gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
17891 /* Insert the SIMD array and iv initialization at function
17892 entry. */
17893 gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
17894
17895 pop_gimplify_context (NULL);
17896
17897 /* Create a new BB right before the original exit BB, to hold the
17898 iteration increment and the condition/branch. */
17899 basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
17900 basic_block incr_bb = create_empty_bb (orig_exit);
17901 add_bb_to_loop (incr_bb, body_bb->loop_father);
17902 /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
17903 flag. Set it now to be a FALLTHRU_EDGE. */
17904 gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
17905 EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
17906 for (unsigned i = 0;
17907 i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
17908 {
17909 edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
17910 redirect_edge_succ (e, incr_bb);
17911 }
17912 edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
17913 e->probability = REG_BR_PROB_BASE;
17914 gsi = gsi_last_bb (incr_bb);
17915 gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
17916 build_int_cst (unsigned_type_node, 1));
17917 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17918
17919 /* Mostly annotate the loop for the vectorizer (the rest is done below). */
17920 struct loop *loop = alloc_loop ();
17921 cfun->has_force_vectorize_loops = true;
17922 loop->safelen = node->simdclone->simdlen;
17923 loop->force_vectorize = true;
17924 loop->header = body_bb;
17925
17926 /* Branch around the body if the mask applies. */
17927 if (node->simdclone->inbranch)
17928 {
17929 gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
17930 tree mask_array
17931 = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
17932 tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
17933 tree aref = build4 (ARRAY_REF,
17934 TREE_TYPE (TREE_TYPE (mask_array)),
17935 mask_array, iter1,
17936 NULL, NULL);
17937 g = gimple_build_assign (mask, aref);
17938 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17939 int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
17940 if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
17941 {
17942 aref = build1 (VIEW_CONVERT_EXPR,
17943 build_nonstandard_integer_type (bitsize, 0), mask);
17944 mask = make_ssa_name (TREE_TYPE (aref));
17945 g = gimple_build_assign (mask, aref);
17946 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17947 }
17948
17949 g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
17950 NULL, NULL);
17951 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17952 make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
17953 FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
17954 }
17955
17956 /* Generate the condition. */
17957 g = gimple_build_cond (LT_EXPR,
17958 iter2,
17959 build_int_cst (unsigned_type_node,
17960 node->simdclone->simdlen),
17961 NULL, NULL);
17962 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
17963 e = split_block (incr_bb, gsi_stmt (gsi));
17964 basic_block latch_bb = e->dest;
17965 basic_block new_exit_bb;
17966 new_exit_bb = split_block_after_labels (latch_bb)->dest;
17967 loop->latch = latch_bb;
17968
17969 redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
17970
17971 make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
17972 /* The successor of incr_bb is already pointing to latch_bb; just
17973 change the flags.
17974 make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
17975 FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
17976
17977 gphi *phi = create_phi_node (iter1, body_bb);
17978 edge preheader_edge = find_edge (entry_bb, body_bb);
17979 edge latch_edge = single_succ_edge (latch_bb);
17980 add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
17981 UNKNOWN_LOCATION);
17982 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
17983
17984 /* Generate the new return. */
17985 gsi = gsi_last_bb (new_exit_bb);
17986 if (retval
17987 && TREE_CODE (retval) == VIEW_CONVERT_EXPR
17988 && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
17989 retval = TREE_OPERAND (retval, 0);
17990 else if (retval)
17991 {
17992 retval = build1 (VIEW_CONVERT_EXPR,
17993 TREE_TYPE (TREE_TYPE (node->decl)),
17994 retval);
17995 retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
17996 false, GSI_CONTINUE_LINKING);
17997 }
17998 g = gimple_build_return (retval);
17999 gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
18000
18001 /* Handle aligned clauses by replacing default defs of the aligned
18002 uniform args with __builtin_assume_aligned (arg_N(D), alignment)
18003 lhs. Handle linear by adding PHIs. */
18004 for (unsigned i = 0; i < node->simdclone->nargs; i++)
18005 if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
18006 && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
18007 || !is_gimple_reg_type
18008 (TREE_TYPE (node->simdclone->args[i].orig_arg))))
18009 {
18010 tree orig_arg = node->simdclone->args[i].orig_arg;
18011 if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
18012 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
18013 else
18014 {
18015 iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
18016 gimple_add_tmp_var (iter1);
18017 }
18018 gsi = gsi_after_labels (entry_bb);
18019 g = gimple_build_assign (iter1, orig_arg);
18020 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18021 gsi = gsi_after_labels (body_bb);
18022 g = gimple_build_assign (orig_arg, iter1);
18023 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18024 }
18025 else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
18026 && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
18027 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
18028 == REFERENCE_TYPE
18029 && TREE_ADDRESSABLE
18030 (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
18031 {
18032 tree orig_arg = node->simdclone->args[i].orig_arg;
18033 tree def = ssa_default_def (cfun, orig_arg);
18034 if (def && !has_zero_uses (def))
18035 {
18036 iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
18037 gimple_add_tmp_var (iter1);
18038 gsi = gsi_after_labels (entry_bb);
18039 g = gimple_build_assign (iter1, build_simple_mem_ref (def));
18040 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18041 gsi = gsi_after_labels (body_bb);
18042 g = gimple_build_assign (build_simple_mem_ref (def), iter1);
18043 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18044 }
18045 }
18046 else if (node->simdclone->args[i].alignment
18047 && node->simdclone->args[i].arg_type
18048 == SIMD_CLONE_ARG_TYPE_UNIFORM
18049 && (node->simdclone->args[i].alignment
18050 & (node->simdclone->args[i].alignment - 1)) == 0
18051 && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
18052 == POINTER_TYPE)
18053 {
18054 unsigned int alignment = node->simdclone->args[i].alignment;
18055 tree orig_arg = node->simdclone->args[i].orig_arg;
18056 tree def = ssa_default_def (cfun, orig_arg);
18057 if (def && !has_zero_uses (def))
18058 {
18059 tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
18060 gimple_seq seq = NULL;
18061 bool need_cvt = false;
18062 gcall *call
18063 = gimple_build_call (fn, 2, def, size_int (alignment));
18064 g = call;
18065 if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
18066 ptr_type_node))
18067 need_cvt = true;
18068 tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
18069 gimple_call_set_lhs (g, t);
18070 gimple_seq_add_stmt_without_update (&seq, g);
18071 if (need_cvt)
18072 {
18073 t = make_ssa_name (orig_arg);
18074 g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
18075 gimple_seq_add_stmt_without_update (&seq, g);
18076 }
18077 gsi_insert_seq_on_edge_immediate
18078 (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
18079
18080 entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
18081 int freq = compute_call_stmt_bb_frequency (current_function_decl,
18082 entry_bb);
18083 node->create_edge (cgraph_node::get_create (fn),
18084 call, entry_bb->count, freq);
18085
18086 imm_use_iterator iter;
18087 use_operand_p use_p;
18088 gimple *use_stmt;
18089 tree repl = gimple_get_lhs (g);
18090 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18091 if (is_gimple_debug (use_stmt) || use_stmt == call)
18092 continue;
18093 else
18094 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18095 SET_USE (use_p, repl);
18096 }
18097 }
18098 else if ((node->simdclone->args[i].arg_type
18099 == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
18100 || (node->simdclone->args[i].arg_type
18101 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP)
18102 || (node->simdclone->args[i].arg_type
18103 == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
18104 || (node->simdclone->args[i].arg_type
18105 == SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP))
18106 {
18107 tree orig_arg = node->simdclone->args[i].orig_arg;
18108 gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18109 || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
18110 tree def = NULL_TREE;
18111 if (TREE_ADDRESSABLE (orig_arg))
18112 {
18113 def = make_ssa_name (TREE_TYPE (orig_arg));
18114 iter1 = make_ssa_name (TREE_TYPE (orig_arg));
18115 iter2 = make_ssa_name (TREE_TYPE (orig_arg));
18116 gsi = gsi_after_labels (entry_bb);
18117 g = gimple_build_assign (def, orig_arg);
18118 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18119 }
18120 else
18121 {
18122 def = ssa_default_def (cfun, orig_arg);
18123 if (!def || has_zero_uses (def))
18124 def = NULL_TREE;
18125 else
18126 {
18127 iter1 = make_ssa_name (orig_arg);
18128 iter2 = make_ssa_name (orig_arg);
18129 }
18130 }
18131 if (def)
18132 {
18133 phi = create_phi_node (iter1, body_bb);
18134 add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
18135 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18136 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18137 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18138 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
18139 ? TREE_TYPE (orig_arg) : sizetype;
18140 tree addcst = simd_clone_linear_addend (node, i, addtype,
18141 entry_bb);
18142 gsi = gsi_last_bb (incr_bb);
18143 g = gimple_build_assign (iter2, code, iter1, addcst);
18144 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18145
18146 imm_use_iterator iter;
18147 use_operand_p use_p;
18148 gimple *use_stmt;
18149 if (TREE_ADDRESSABLE (orig_arg))
18150 {
18151 gsi = gsi_after_labels (body_bb);
18152 g = gimple_build_assign (orig_arg, iter1);
18153 gsi_insert_before (&gsi, g, GSI_NEW_STMT);
18154 }
18155 else
18156 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18157 if (use_stmt == phi)
18158 continue;
18159 else
18160 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18161 SET_USE (use_p, iter1);
18162 }
18163 }
18164 else if (node->simdclone->args[i].arg_type
18165 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
18166 || (node->simdclone->args[i].arg_type
18167 == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP))
18168 {
18169 tree orig_arg = node->simdclone->args[i].orig_arg;
18170 tree def = ssa_default_def (cfun, orig_arg);
18171 gcc_assert (!TREE_ADDRESSABLE (orig_arg)
18172 && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
18173 if (def && !has_zero_uses (def))
18174 {
18175 tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
18176 iter1 = make_ssa_name (orig_arg);
18177 iter2 = make_ssa_name (orig_arg);
18178 tree iter3 = make_ssa_name (rtype);
18179 tree iter4 = make_ssa_name (rtype);
18180 tree iter5 = make_ssa_name (rtype);
18181 gsi = gsi_after_labels (entry_bb);
18182 gimple *load
18183 = gimple_build_assign (iter3, build_simple_mem_ref (def));
18184 gsi_insert_before (&gsi, load, GSI_NEW_STMT);
18185
18186 tree array = node->simdclone->args[i].simd_array;
18187 TREE_ADDRESSABLE (array) = 1;
18188 tree ptr = build_fold_addr_expr (array);
18189 phi = create_phi_node (iter1, body_bb);
18190 add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
18191 add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
18192 g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
18193 TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
18194 gsi = gsi_last_bb (incr_bb);
18195 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18196
18197 phi = create_phi_node (iter4, body_bb);
18198 add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
18199 add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
18200 enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18201 ? PLUS_EXPR : POINTER_PLUS_EXPR;
18202 tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
18203 ? TREE_TYPE (iter3) : sizetype;
18204 tree addcst = simd_clone_linear_addend (node, i, addtype,
18205 entry_bb);
18206 g = gimple_build_assign (iter5, code, iter4, addcst);
18207 gsi = gsi_last_bb (incr_bb);
18208 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18209
18210 g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
18211 gsi = gsi_after_labels (body_bb);
18212 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18213
18214 imm_use_iterator iter;
18215 use_operand_p use_p;
18216 gimple *use_stmt;
18217 FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
18218 if (use_stmt == load)
18219 continue;
18220 else
18221 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
18222 SET_USE (use_p, iter1);
18223
18224 if (!TYPE_READONLY (rtype))
18225 {
18226 tree v = make_ssa_name (rtype);
18227 tree aref = build4 (ARRAY_REF, rtype, array,
18228 size_zero_node, NULL_TREE,
18229 NULL_TREE);
18230 gsi = gsi_after_labels (new_exit_bb);
18231 g = gimple_build_assign (v, aref);
18232 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18233 g = gimple_build_assign (build_simple_mem_ref (def), v);
18234 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
18235 }
18236 }
18237 }
18238
18239 calculate_dominance_info (CDI_DOMINATORS);
18240 add_loop (loop, loop->header->loop_father);
18241 update_ssa (TODO_update_ssa);
18242
18243 pop_cfun ();
18244 }
18245
18246 /* If the function in NODE is tagged as an elemental SIMD function,
18247 create the appropriate SIMD clones. */
18248
18249 static void
18250 expand_simd_clones (struct cgraph_node *node)
18251 {
18252 tree attr = lookup_attribute ("omp declare simd",
18253 DECL_ATTRIBUTES (node->decl));
18254 if (attr == NULL_TREE
18255 || node->global.inlined_to
18256 || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
18257 return;
18258
18259 /* Ignore
18260 #pragma omp declare simd
18261 extern int foo ();
18262 in C, there we don't know the argument types at all. */
18263 if (!node->definition
18264 && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
18265 return;
18266
18267 do
18268 {
18269 /* Start with parsing the "omp declare simd" attribute(s). */
18270 bool inbranch_clause_specified;
18271 struct cgraph_simd_clone *clone_info
18272 = simd_clone_clauses_extract (node, TREE_VALUE (attr),
18273 &inbranch_clause_specified);
18274 if (clone_info == NULL)
18275 continue;
18276
18277 int orig_simdlen = clone_info->simdlen;
18278 tree base_type = simd_clone_compute_base_data_type (node, clone_info);
18279 /* The target can return 0 (no simd clones should be created),
18280 1 (just one ISA of simd clones should be created) or higher
18281 count of ISA variants. In that case, clone_info is initialized
18282 for the first ISA variant. */
18283 int count
18284 = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
18285 base_type, 0);
18286 if (count == 0)
18287 continue;
18288
18289 /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
18290 also create one inbranch and one !inbranch clone of it. */
18291 for (int i = 0; i < count * 2; i++)
18292 {
18293 struct cgraph_simd_clone *clone = clone_info;
18294 if (inbranch_clause_specified && (i & 1) != 0)
18295 continue;
18296
18297 if (i != 0)
18298 {
18299 clone = simd_clone_struct_alloc (clone_info->nargs
18300 + ((i & 1) != 0));
18301 simd_clone_struct_copy (clone, clone_info);
18302 /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
18303 and simd_clone_adjust_argument_types did to the first
18304 clone's info. */
18305 clone->nargs -= clone_info->inbranch;
18306 clone->simdlen = orig_simdlen;
18307 /* And call the target hook again to get the right ISA. */
18308 targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
18309 base_type,
18310 i / 2);
18311 if ((i & 1) != 0)
18312 clone->inbranch = 1;
18313 }
18314
18315 /* simd_clone_mangle might fail if such a clone has been created
18316 already. */
18317 tree id = simd_clone_mangle (node, clone);
18318 if (id == NULL_TREE)
18319 continue;
18320
18321 /* Only when we are sure we want to create the clone actually
18322 clone the function (or definitions) or create another
18323 extern FUNCTION_DECL (for prototypes without definitions). */
18324 struct cgraph_node *n = simd_clone_create (node);
18325 if (n == NULL)
18326 continue;
18327
18328 n->simdclone = clone;
18329 clone->origin = node;
18330 clone->next_clone = NULL;
18331 if (node->simd_clones == NULL)
18332 {
18333 clone->prev_clone = n;
18334 node->simd_clones = n;
18335 }
18336 else
18337 {
18338 clone->prev_clone = node->simd_clones->simdclone->prev_clone;
18339 clone->prev_clone->simdclone->next_clone = n;
18340 node->simd_clones->simdclone->prev_clone = n;
18341 }
18342 symtab->change_decl_assembler_name (n->decl, id);
18343 /* And finally adjust the return type, parameters and for
18344 definitions also function body. */
18345 if (node->definition)
18346 simd_clone_adjust (n);
18347 else
18348 {
18349 simd_clone_adjust_return_type (n);
18350 simd_clone_adjust_argument_types (n);
18351 }
18352 }
18353 }
18354 while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
18355 }
18356
18357 /* Entry point for IPA simd clone creation pass. */
18358
18359 static unsigned int
18360 ipa_omp_simd_clone (void)
18361 {
18362 struct cgraph_node *node;
18363 FOR_EACH_FUNCTION (node)
18364 expand_simd_clones (node);
18365 return 0;
18366 }
18367
18368 namespace {
18369
18370 const pass_data pass_data_omp_simd_clone =
18371 {
18372 SIMPLE_IPA_PASS, /* type */
18373 "simdclone", /* name */
18374 OPTGROUP_NONE, /* optinfo_flags */
18375 TV_NONE, /* tv_id */
18376 ( PROP_ssa | PROP_cfg ), /* properties_required */
18377 0, /* properties_provided */
18378 0, /* properties_destroyed */
18379 0, /* todo_flags_start */
18380 0, /* todo_flags_finish */
18381 };
18382
18383 class pass_omp_simd_clone : public simple_ipa_opt_pass
18384 {
18385 public:
18386 pass_omp_simd_clone(gcc::context *ctxt)
18387 : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
18388 {}
18389
18390 /* opt_pass methods: */
18391 virtual bool gate (function *);
18392 virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
18393 };
18394
18395 bool
18396 pass_omp_simd_clone::gate (function *)
18397 {
18398 return ((flag_openmp || flag_openmp_simd
18399 || flag_cilkplus
18400 || (in_lto_p && !flag_wpa))
18401 && (targetm.simd_clone.compute_vecsize_and_simdlen != NULL));
18402 }
18403
18404 } // anon namespace
18405
18406 simple_ipa_opt_pass *
18407 make_pass_omp_simd_clone (gcc::context *ctxt)
18408 {
18409 return new pass_omp_simd_clone (ctxt);
18410 }
18411
18412 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18413 adds their addresses and sizes to constructor-vector V_CTOR. */
18414 static void
18415 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18416 vec<constructor_elt, va_gc> *v_ctor)
18417 {
18418 unsigned len = vec_safe_length (v_decls);
18419 for (unsigned i = 0; i < len; i++)
18420 {
18421 tree it = (*v_decls)[i];
18422 bool is_function = TREE_CODE (it) != VAR_DECL;
18423
18424 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, build_fold_addr_expr (it));
18425 if (!is_function)
18426 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE,
18427 fold_convert (const_ptr_type_node,
18428 DECL_SIZE_UNIT (it)));
18429 }
18430 }
18431
18432 /* Create new symbols containing (address, size) pairs for global variables,
18433 marked with "omp declare target" attribute, as well as addresses for the
18434 functions, which are outlined offloading regions. */
18435 void
18436 omp_finish_file (void)
18437 {
18438 unsigned num_funcs = vec_safe_length (offload_funcs);
18439 unsigned num_vars = vec_safe_length (offload_vars);
18440
18441 if (num_funcs == 0 && num_vars == 0)
18442 return;
18443
18444 if (targetm_common.have_named_sections)
18445 {
18446 vec<constructor_elt, va_gc> *v_f, *v_v;
18447 vec_alloc (v_f, num_funcs);
18448 vec_alloc (v_v, num_vars * 2);
18449
18450 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18451 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18452
18453 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18454 num_vars * 2);
18455 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18456 num_funcs);
18457 TYPE_ALIGN (vars_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18458 TYPE_ALIGN (funcs_decl_type) = TYPE_ALIGN (pointer_sized_int_node);
18459 tree ctor_v = build_constructor (vars_decl_type, v_v);
18460 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18461 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18462 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18463 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18464 get_identifier (".offload_func_table"),
18465 funcs_decl_type);
18466 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18467 get_identifier (".offload_var_table"),
18468 vars_decl_type);
18469 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18470 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18471 otherwise a joint table in a binary will contain padding between
18472 tables from multiple object files. */
18473 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18474 DECL_ALIGN (funcs_decl) = TYPE_ALIGN (funcs_decl_type);
18475 DECL_ALIGN (vars_decl) = TYPE_ALIGN (vars_decl_type);
18476 DECL_INITIAL (funcs_decl) = ctor_f;
18477 DECL_INITIAL (vars_decl) = ctor_v;
18478 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18479 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18480
18481 varpool_node::finalize_decl (vars_decl);
18482 varpool_node::finalize_decl (funcs_decl);
18483 }
18484 else
18485 {
18486 for (unsigned i = 0; i < num_funcs; i++)
18487 {
18488 tree it = (*offload_funcs)[i];
18489 targetm.record_offload_symbol (it);
18490 }
18491 for (unsigned i = 0; i < num_vars; i++)
18492 {
18493 tree it = (*offload_vars)[i];
18494 targetm.record_offload_symbol (it);
18495 }
18496 }
18497 }
18498
18499 /* Find the number of threads (POS = false), or thread number (POS =
18500 true) for an OpenACC region partitioned as MASK. Setup code
18501 required for the calculation is added to SEQ. */
18502
18503 static tree
18504 oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18505 {
18506 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18507 unsigned ix;
18508
18509 /* Start at gang level, and examine relevant dimension indices. */
18510 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18511 if (GOMP_DIM_MASK (ix) & mask)
18512 {
18513 tree arg = build_int_cst (unsigned_type_node, ix);
18514
18515 if (res)
18516 {
18517 /* We had an outer index, so scale that by the size of
18518 this dimension. */
18519 tree n = create_tmp_var (integer_type_node);
18520 gimple *call
18521 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18522
18523 gimple_call_set_lhs (call, n);
18524 gimple_seq_add_stmt (seq, call);
18525 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18526 }
18527 if (pos)
18528 {
18529 /* Determine index in this dimension. */
18530 tree id = create_tmp_var (integer_type_node);
18531 gimple *call = gimple_build_call_internal
18532 (IFN_GOACC_DIM_POS, 1, arg);
18533
18534 gimple_call_set_lhs (call, id);
18535 gimple_seq_add_stmt (seq, call);
18536 if (res)
18537 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18538 else
18539 res = id;
18540 }
18541 }
18542
18543 if (res == NULL_TREE)
18544 res = integer_zero_node;
18545
18546 return res;
18547 }
18548
18549 /* Transform IFN_GOACC_LOOP calls to actual code. See
18550 expand_oacc_for for where these are generated. At the vector
18551 level, we stride loops, such that each member of a warp will
18552 operate on adjacent iterations. At the worker and gang level,
18553 each gang/warp executes a set of contiguous iterations. Chunking
18554 can override this such that each iteration engine executes a
18555 contiguous chunk, and then moves on to stride to the next chunk. */
18556
18557 static void
18558 oacc_xform_loop (gcall *call)
18559 {
18560 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18561 enum ifn_goacc_loop_kind code
18562 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18563 tree dir = gimple_call_arg (call, 1);
18564 tree range = gimple_call_arg (call, 2);
18565 tree step = gimple_call_arg (call, 3);
18566 tree chunk_size = NULL_TREE;
18567 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18568 tree lhs = gimple_call_lhs (call);
18569 tree type = TREE_TYPE (lhs);
18570 tree diff_type = TREE_TYPE (range);
18571 tree r = NULL_TREE;
18572 gimple_seq seq = NULL;
18573 bool chunking = false, striding = true;
18574 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18575 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18576
18577 #ifdef ACCEL_COMPILER
18578 chunk_size = gimple_call_arg (call, 4);
18579 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18580 || integer_zerop (chunk_size)) /* Default (also static). */
18581 {
18582 /* If we're at the gang level, we want each to execute a
18583 contiguous run of iterations. Otherwise we want each element
18584 to stride. */
18585 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18586 chunking = false;
18587 }
18588 else
18589 {
18590 /* Chunk of size 1 is striding. */
18591 striding = integer_onep (chunk_size);
18592 chunking = !striding;
18593 }
18594 #endif
18595
18596 /* striding=true, chunking=true
18597 -> invalid.
18598 striding=true, chunking=false
18599 -> chunks=1
18600 striding=false,chunking=true
18601 -> chunks=ceil (range/(chunksize*threads*step))
18602 striding=false,chunking=false
18603 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18604 push_gimplify_context (true);
18605
18606 switch (code)
18607 {
18608 default: gcc_unreachable ();
18609
18610 case IFN_GOACC_LOOP_CHUNKS:
18611 if (!chunking)
18612 r = build_int_cst (type, 1);
18613 else
18614 {
18615 /* chunk_max
18616 = (range - dir) / (chunks * step * num_threads) + dir */
18617 tree per = oacc_thread_numbers (false, mask, &seq);
18618 per = fold_convert (type, per);
18619 chunk_size = fold_convert (type, chunk_size);
18620 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18621 per = fold_build2 (MULT_EXPR, type, per, step);
18622 r = build2 (MINUS_EXPR, type, range, dir);
18623 r = build2 (PLUS_EXPR, type, r, per);
18624 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18625 }
18626 break;
18627
18628 case IFN_GOACC_LOOP_STEP:
18629 {
18630 /* If striding, step by the entire compute volume, otherwise
18631 step by the inner volume. */
18632 unsigned volume = striding ? mask : inner_mask;
18633
18634 r = oacc_thread_numbers (false, volume, &seq);
18635 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18636 }
18637 break;
18638
18639 case IFN_GOACC_LOOP_OFFSET:
18640 if (striding)
18641 {
18642 r = oacc_thread_numbers (true, mask, &seq);
18643 r = fold_convert (diff_type, r);
18644 }
18645 else
18646 {
18647 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18648 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18649 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18650 inner_size, outer_size);
18651
18652 volume = fold_convert (diff_type, volume);
18653 if (chunking)
18654 chunk_size = fold_convert (diff_type, chunk_size);
18655 else
18656 {
18657 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18658
18659 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18660 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18661 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18662 }
18663
18664 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18665 fold_convert (diff_type, inner_size));
18666 r = oacc_thread_numbers (true, outer_mask, &seq);
18667 r = fold_convert (diff_type, r);
18668 r = build2 (MULT_EXPR, diff_type, r, span);
18669
18670 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18671 inner = fold_convert (diff_type, inner);
18672 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18673
18674 if (chunking)
18675 {
18676 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18677 tree per
18678 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18679 per = build2 (MULT_EXPR, diff_type, per, chunk);
18680
18681 r = build2 (PLUS_EXPR, diff_type, r, per);
18682 }
18683 }
18684 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18685 if (type != diff_type)
18686 r = fold_convert (type, r);
18687 break;
18688
18689 case IFN_GOACC_LOOP_BOUND:
18690 if (striding)
18691 r = range;
18692 else
18693 {
18694 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18695 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18696 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18697 inner_size, outer_size);
18698
18699 volume = fold_convert (diff_type, volume);
18700 if (chunking)
18701 chunk_size = fold_convert (diff_type, chunk_size);
18702 else
18703 {
18704 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18705
18706 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18707 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18708 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18709 }
18710
18711 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18712 fold_convert (diff_type, inner_size));
18713
18714 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18715
18716 tree offset = gimple_call_arg (call, 6);
18717 r = build2 (PLUS_EXPR, diff_type, r,
18718 fold_convert (diff_type, offset));
18719 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18720 diff_type, r, range);
18721 }
18722 if (diff_type != type)
18723 r = fold_convert (type, r);
18724 break;
18725 }
18726
18727 gimplify_assign (lhs, r, &seq);
18728
18729 pop_gimplify_context (NULL);
18730
18731 gsi_replace_with_seq (&gsi, seq, true);
18732 }
18733
18734 /* Validate and update the dimensions for offloaded FN. ATTRS is the
18735 raw attribute. DIMS is an array of dimensions, which is returned.
18736 Returns the function level dimensionality -- the level at which an
18737 offload routine wishes to partition a loop. */
18738
18739 static int
18740 oacc_validate_dims (tree fn, tree attrs, int *dims)
18741 {
18742 tree purpose[GOMP_DIM_MAX];
18743 unsigned ix;
18744 tree pos = TREE_VALUE (attrs);
18745 int fn_level = -1;
18746
18747 /* Make sure the attribute creator attached the dimension
18748 information. */
18749 gcc_assert (pos);
18750
18751 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18752 {
18753 purpose[ix] = TREE_PURPOSE (pos);
18754
18755 if (purpose[ix])
18756 {
18757 if (integer_zerop (purpose[ix]))
18758 fn_level = ix + 1;
18759 else if (fn_level < 0)
18760 fn_level = ix;
18761 }
18762
18763 tree val = TREE_VALUE (pos);
18764 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18765 pos = TREE_CHAIN (pos);
18766 }
18767
18768 bool changed = targetm.goacc.validate_dims (fn, dims, fn_level);
18769
18770 /* Default anything left to 1. */
18771 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18772 if (dims[ix] < 0)
18773 {
18774 dims[ix] = 1;
18775 changed = true;
18776 }
18777
18778 if (changed)
18779 {
18780 /* Replace the attribute with new values. */
18781 pos = NULL_TREE;
18782 for (ix = GOMP_DIM_MAX; ix--;)
18783 pos = tree_cons (purpose[ix],
18784 build_int_cst (integer_type_node, dims[ix]),
18785 pos);
18786 replace_oacc_fn_attrib (fn, pos);
18787 }
18788
18789 return fn_level;
18790 }
18791
18792 /* Create an empty OpenACC loop structure at LOC. */
18793
18794 static oacc_loop *
18795 new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18796 {
18797 oacc_loop *loop = XCNEW (oacc_loop);
18798
18799 loop->parent = parent;
18800 loop->child = loop->sibling = NULL;
18801
18802 if (parent)
18803 {
18804 loop->sibling = parent->child;
18805 parent->child = loop;
18806 }
18807
18808 loop->loc = loc;
18809 loop->marker = NULL;
18810 memset (loop->heads, 0, sizeof (loop->heads));
18811 memset (loop->tails, 0, sizeof (loop->tails));
18812 loop->routine = NULL_TREE;
18813
18814 loop->mask = loop->flags = 0;
18815 loop->chunk_size = 0;
18816 loop->head_end = NULL;
18817
18818 return loop;
18819 }
18820
18821 /* Create an outermost, dummy OpenACC loop for offloaded function
18822 DECL. */
18823
18824 static oacc_loop *
18825 new_oacc_loop_outer (tree decl)
18826 {
18827 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
18828 }
18829
18830 /* Start a new OpenACC loop structure beginning at head marker HEAD.
18831 Link into PARENT loop. Return the new loop. */
18832
18833 static oacc_loop *
18834 new_oacc_loop (oacc_loop *parent, gcall *marker)
18835 {
18836 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
18837
18838 loop->marker = marker;
18839
18840 /* TODO: This is where device_type flattening would occur for the loop
18841 flags. */
18842
18843 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
18844
18845 tree chunk_size = integer_zero_node;
18846 if (loop->flags & OLF_GANG_STATIC)
18847 chunk_size = gimple_call_arg (marker, 4);
18848 loop->chunk_size = chunk_size;
18849
18850 return loop;
18851 }
18852
18853 /* Create a dummy loop encompassing a call to a openACC routine.
18854 Extract the routine's partitioning requirements. */
18855
18856 static void
18857 new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
18858 {
18859 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
18860 int dims[GOMP_DIM_MAX];
18861 int level = oacc_validate_dims (decl, attrs, dims);
18862
18863 gcc_assert (level >= 0);
18864
18865 loop->marker = call;
18866 loop->routine = decl;
18867 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
18868 ^ (GOMP_DIM_MASK (level) - 1));
18869 }
18870
18871 /* Finish off the current OpenACC loop ending at tail marker TAIL.
18872 Return the parent loop. */
18873
18874 static oacc_loop *
18875 finish_oacc_loop (oacc_loop *loop)
18876 {
18877 return loop->parent;
18878 }
18879
18880 /* Free all OpenACC loop structures within LOOP (inclusive). */
18881
18882 static void
18883 free_oacc_loop (oacc_loop *loop)
18884 {
18885 if (loop->sibling)
18886 free_oacc_loop (loop->sibling);
18887 if (loop->child)
18888 free_oacc_loop (loop->child);
18889
18890 free (loop);
18891 }
18892
18893 /* Dump out the OpenACC loop head or tail beginning at FROM. */
18894
18895 static void
18896 dump_oacc_loop_part (FILE *file, gcall *from, int depth,
18897 const char *title, int level)
18898 {
18899 enum ifn_unique_kind kind
18900 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
18901
18902 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
18903 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
18904 {
18905 gimple *stmt = gsi_stmt (gsi);
18906
18907 if (is_gimple_call (stmt)
18908 && gimple_call_internal_p (stmt)
18909 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
18910 {
18911 enum ifn_unique_kind k
18912 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
18913 (gimple_call_arg (stmt, 0)));
18914
18915 if (k == kind && stmt != from)
18916 break;
18917 }
18918 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
18919
18920 gsi_next (&gsi);
18921 while (gsi_end_p (gsi))
18922 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
18923 }
18924 }
18925
18926 /* Dump OpenACC loops LOOP, its siblings and its children. */
18927
18928 static void
18929 dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
18930 {
18931 int ix;
18932
18933 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
18934 loop->flags, loop->mask,
18935 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
18936
18937 if (loop->marker)
18938 print_gimple_stmt (file, loop->marker, depth * 2, 0);
18939
18940 if (loop->routine)
18941 fprintf (file, "%*sRoutine %s:%u:%s\n",
18942 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
18943 DECL_SOURCE_LINE (loop->routine),
18944 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
18945
18946 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18947 if (loop->heads[ix])
18948 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
18949 for (ix = GOMP_DIM_MAX; ix--;)
18950 if (loop->tails[ix])
18951 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
18952
18953 if (loop->child)
18954 dump_oacc_loop (file, loop->child, depth + 1);
18955 if (loop->sibling)
18956 dump_oacc_loop (file, loop->sibling, depth);
18957 }
18958
18959 void debug_oacc_loop (oacc_loop *);
18960
18961 /* Dump loops to stderr. */
18962
18963 DEBUG_FUNCTION void
18964 debug_oacc_loop (oacc_loop *loop)
18965 {
18966 dump_oacc_loop (stderr, loop, 0);
18967 }
18968
18969 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
18970 structures as we go. By construction these loops are properly
18971 nested. */
18972
18973 static void
18974 oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
18975 {
18976 int marker = 0;
18977 int remaining = 0;
18978
18979 if (bb->flags & BB_VISITED)
18980 return;
18981
18982 follow:
18983 bb->flags |= BB_VISITED;
18984
18985 /* Scan for loop markers. */
18986 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
18987 gsi_next (&gsi))
18988 {
18989 gimple *stmt = gsi_stmt (gsi);
18990
18991 if (!is_gimple_call (stmt))
18992 continue;
18993
18994 gcall *call = as_a <gcall *> (stmt);
18995
18996 /* If this is a routine, make a dummy loop for it. */
18997 if (tree decl = gimple_call_fndecl (call))
18998 if (tree attrs = get_oacc_fn_attrib (decl))
18999 {
19000 gcc_assert (!marker);
19001 new_oacc_loop_routine (loop, call, decl, attrs);
19002 }
19003
19004 if (!gimple_call_internal_p (call))
19005 continue;
19006
19007 if (gimple_call_internal_fn (call) != IFN_UNIQUE)
19008 continue;
19009
19010 enum ifn_unique_kind kind
19011 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19012 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19013 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19014 {
19015 if (gimple_call_num_args (call) == 2)
19016 {
19017 gcc_assert (marker && !remaining);
19018 marker = 0;
19019 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19020 loop = finish_oacc_loop (loop);
19021 else
19022 loop->head_end = call;
19023 }
19024 else
19025 {
19026 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19027
19028 if (!marker)
19029 {
19030 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19031 loop = new_oacc_loop (loop, call);
19032 remaining = count;
19033 }
19034 gcc_assert (count == remaining);
19035 if (remaining)
19036 {
19037 remaining--;
19038 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19039 loop->heads[marker] = call;
19040 else
19041 loop->tails[remaining] = call;
19042 }
19043 marker++;
19044 }
19045 }
19046 }
19047 if (remaining || marker)
19048 {
19049 bb = single_succ (bb);
19050 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19051 goto follow;
19052 }
19053
19054 /* Walk successor blocks. */
19055 edge e;
19056 edge_iterator ei;
19057
19058 FOR_EACH_EDGE (e, ei, bb->succs)
19059 oacc_loop_discover_walk (loop, e->dest);
19060 }
19061
19062 /* LOOP is the first sibling. Reverse the order in place and return
19063 the new first sibling. Recurse to child loops. */
19064
19065 static oacc_loop *
19066 oacc_loop_sibling_nreverse (oacc_loop *loop)
19067 {
19068 oacc_loop *last = NULL;
19069 do
19070 {
19071 if (loop->child)
19072 loop->child = oacc_loop_sibling_nreverse (loop->child);
19073
19074 oacc_loop *next = loop->sibling;
19075 loop->sibling = last;
19076 last = loop;
19077 loop = next;
19078 }
19079 while (loop);
19080
19081 return last;
19082 }
19083
19084 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19085 the current function. */
19086
19087 static oacc_loop *
19088 oacc_loop_discovery ()
19089 {
19090 basic_block bb;
19091
19092 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19093 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19094
19095 /* The siblings were constructed in reverse order, reverse them so
19096 that diagnostics come out in an unsurprising order. */
19097 top = oacc_loop_sibling_nreverse (top);
19098
19099 /* Reset the visited flags. */
19100 FOR_ALL_BB_FN (bb, cfun)
19101 bb->flags &= ~BB_VISITED;
19102
19103 return top;
19104 }
19105
19106 /* Transform the abstract internal function markers starting at FROM
19107 to be for partitioning level LEVEL. Stop when we meet another HEAD
19108 or TAIL marker. */
19109
19110 static void
19111 oacc_loop_xform_head_tail (gcall *from, int level)
19112 {
19113 enum ifn_unique_kind kind
19114 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19115 tree replacement = build_int_cst (unsigned_type_node, level);
19116
19117 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19118 {
19119 gimple *stmt = gsi_stmt (gsi);
19120
19121 if (is_gimple_call (stmt)
19122 && gimple_call_internal_p (stmt)
19123 && gimple_call_internal_fn (stmt) == IFN_UNIQUE)
19124 {
19125 enum ifn_unique_kind k
19126 = ((enum ifn_unique_kind)
19127 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19128
19129 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19130 *gimple_call_arg_ptr (stmt, 2) = replacement;
19131 else if (k == kind && stmt != from)
19132 break;
19133 }
19134 else if (is_gimple_call (stmt)
19135 && gimple_call_internal_p (stmt)
19136 && gimple_call_internal_fn (stmt) == IFN_GOACC_REDUCTION)
19137 *gimple_call_arg_ptr (stmt, 3) = replacement;
19138
19139 gsi_next (&gsi);
19140 while (gsi_end_p (gsi))
19141 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19142 }
19143 }
19144
19145 /* Transform the IFN_GOACC_LOOP internal functions by providing the
19146 determined partitioning mask and chunking argument. */
19147
19148 static void
19149 oacc_loop_xform_loop (gcall *end_marker, tree mask_arg, tree chunk_arg)
19150 {
19151 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19152
19153 for (;;)
19154 {
19155 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19156 {
19157 gimple *stmt = gsi_stmt (gsi);
19158
19159 if (!is_gimple_call (stmt))
19160 continue;
19161
19162 gcall *call = as_a <gcall *> (stmt);
19163
19164 if (!gimple_call_internal_p (call))
19165 continue;
19166
19167 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19168 continue;
19169
19170 *gimple_call_arg_ptr (call, 5) = mask_arg;
19171 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19172 if (TREE_INT_CST_LOW (gimple_call_arg (call, 0))
19173 == IFN_GOACC_LOOP_BOUND)
19174 return;
19175 }
19176
19177 /* If we didn't see LOOP_BOUND, it should be in the single
19178 successor block. */
19179 basic_block bb = single_succ (gsi_bb (gsi));
19180 gsi = gsi_start_bb (bb);
19181 }
19182 }
19183
19184 /* Process the discovered OpenACC loops, setting the correct
19185 partitioning level etc. */
19186
19187 static void
19188 oacc_loop_process (oacc_loop *loop)
19189 {
19190 if (loop->child)
19191 oacc_loop_process (loop->child);
19192
19193 if (loop->mask && !loop->routine)
19194 {
19195 int ix;
19196 unsigned mask = loop->mask;
19197 unsigned dim = GOMP_DIM_GANG;
19198 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19199 tree chunk_arg = loop->chunk_size;
19200
19201 oacc_loop_xform_loop (loop->head_end, mask_arg, chunk_arg);
19202
19203 for (ix = 0; ix != GOMP_DIM_MAX && loop->heads[ix]; ix++)
19204 {
19205 gcc_assert (mask);
19206
19207 while (!(GOMP_DIM_MASK (dim) & mask))
19208 dim++;
19209
19210 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19211 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19212
19213 mask ^= GOMP_DIM_MASK (dim);
19214 }
19215 }
19216
19217 if (loop->sibling)
19218 oacc_loop_process (loop->sibling);
19219 }
19220
19221 /* Walk the OpenACC loop heirarchy checking and assigning the
19222 programmer-specified partitionings. OUTER_MASK is the partitioning
19223 this loop is contained within. Return partitiong mask used within
19224 this loop nest. */
19225
19226 static unsigned
19227 oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19228 {
19229 unsigned this_mask = loop->mask;
19230 bool has_auto = false;
19231 bool noisy = true;
19232
19233 #ifdef ACCEL_COMPILER
19234 /* When device_type is supported, we want the device compiler to be
19235 noisy, if the loop parameters are device_type-specific. */
19236 noisy = false;
19237 #endif
19238
19239 if (!loop->routine)
19240 {
19241 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19242 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19243
19244 this_mask = ((loop->flags >> OLF_DIM_BASE)
19245 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19246
19247 if ((this_mask != 0) + auto_par + seq_par > 1)
19248 {
19249 if (noisy)
19250 error_at (loop->loc,
19251 seq_par
19252 ? "%<seq%> overrides other OpenACC loop specifiers"
19253 : "%<auto%> conflicts with other OpenACC loop specifiers");
19254 auto_par = false;
19255 loop->flags &= ~OLF_AUTO;
19256 if (seq_par)
19257 {
19258 loop->flags &=
19259 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19260 this_mask = 0;
19261 }
19262 }
19263 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19264 has_auto = true;
19265 }
19266
19267 if (this_mask & outer_mask)
19268 {
19269 const oacc_loop *outer;
19270 for (outer = loop->parent; outer; outer = outer->parent)
19271 if (outer->mask & this_mask)
19272 break;
19273
19274 if (noisy)
19275 {
19276 if (outer)
19277 {
19278 error_at (loop->loc,
19279 "%s uses same OpenACC parallelism as containing loop",
19280 loop->routine ? "routine call" : "inner loop");
19281 inform (outer->loc, "containing loop here");
19282 }
19283 else
19284 error_at (loop->loc,
19285 "%s uses OpenACC parallelism disallowed by containing routine",
19286 loop->routine ? "routine call" : "loop");
19287
19288 if (loop->routine)
19289 inform (DECL_SOURCE_LOCATION (loop->routine),
19290 "routine %qD declared here", loop->routine);
19291 }
19292 this_mask &= ~outer_mask;
19293 }
19294 else
19295 {
19296 unsigned outermost = this_mask & -this_mask;
19297
19298 if (outermost && outermost <= outer_mask)
19299 {
19300 if (noisy)
19301 {
19302 error_at (loop->loc,
19303 "incorrectly nested OpenACC loop parallelism");
19304
19305 const oacc_loop *outer;
19306 for (outer = loop->parent;
19307 outer->flags && outer->flags < outermost;
19308 outer = outer->parent)
19309 continue;
19310 inform (outer->loc, "containing loop here");
19311 }
19312
19313 this_mask &= ~outermost;
19314 }
19315 }
19316
19317 loop->mask = this_mask;
19318
19319 if (loop->child
19320 && oacc_loop_fixed_partitions (loop->child, outer_mask | this_mask))
19321 has_auto = true;
19322
19323 if (loop->sibling
19324 && oacc_loop_fixed_partitions (loop->sibling, outer_mask))
19325 has_auto = true;
19326
19327 return has_auto;
19328 }
19329
19330 /* Walk the OpenACC loop heirarchy to check and assign partitioning
19331 axes. */
19332
19333 static void
19334 oacc_loop_partition (oacc_loop *loop, int fn_level)
19335 {
19336 unsigned outer_mask = 0;
19337
19338 if (fn_level >= 0)
19339 outer_mask = GOMP_DIM_MASK (fn_level) - 1;
19340
19341 oacc_loop_fixed_partitions (loop, outer_mask);
19342 }
19343
19344 /* Default fork/join early expander. Delete the function calls if
19345 there is no RTL expander. */
19346
19347 bool
19348 default_goacc_fork_join (gcall *ARG_UNUSED (call),
19349 const int *ARG_UNUSED (dims), bool is_fork)
19350 {
19351 if (is_fork)
19352 return targetm.have_oacc_fork ();
19353 else
19354 return targetm.have_oacc_join ();
19355 }
19356
19357 /* Default goacc.reduction early expander.
19358
19359 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19360 If RES_PTR is not integer-zerop:
19361 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19362 TEARDOWN - emit '*RES_PTR = VAR'
19363 If LHS is not NULL
19364 emit 'LHS = VAR' */
19365
19366 void
19367 default_goacc_reduction (gcall *call)
19368 {
19369 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19370 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19371 tree lhs = gimple_call_lhs (call);
19372 tree var = gimple_call_arg (call, 2);
19373 gimple_seq seq = NULL;
19374
19375 if (code == IFN_GOACC_REDUCTION_SETUP
19376 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19377 {
19378 /* Setup and Teardown need to copy from/to the receiver object,
19379 if there is one. */
19380 tree ref_to_res = gimple_call_arg (call, 1);
19381
19382 if (!integer_zerop (ref_to_res))
19383 {
19384 tree dst = build_simple_mem_ref (ref_to_res);
19385 tree src = var;
19386
19387 if (code == IFN_GOACC_REDUCTION_SETUP)
19388 {
19389 src = dst;
19390 dst = lhs;
19391 lhs = NULL;
19392 }
19393 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19394 }
19395 }
19396
19397 /* Copy VAR to LHS, if there is an LHS. */
19398 if (lhs)
19399 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19400
19401 gsi_replace_with_seq (&gsi, seq, true);
19402 }
19403
19404 /* Main entry point for oacc transformations which run on the device
19405 compiler after LTO, so we know what the target device is at this
19406 point (including the host fallback). */
19407
19408 static unsigned int
19409 execute_oacc_device_lower ()
19410 {
19411 tree attrs = get_oacc_fn_attrib (current_function_decl);
19412 int dims[GOMP_DIM_MAX];
19413
19414 if (!attrs)
19415 /* Not an offloaded function. */
19416 return 0;
19417
19418 int fn_level = oacc_validate_dims (current_function_decl, attrs, dims);
19419
19420 /* Discover, partition and process the loops. */
19421 oacc_loop *loops = oacc_loop_discovery ();
19422 oacc_loop_partition (loops, fn_level);
19423 oacc_loop_process (loops);
19424 if (dump_file)
19425 {
19426 fprintf (dump_file, "OpenACC loops\n");
19427 dump_oacc_loop (dump_file, loops, 0);
19428 fprintf (dump_file, "\n");
19429 }
19430
19431 /* Offloaded targets may introduce new basic blocks, which require
19432 dominance information to update SSA. */
19433 calculate_dominance_info (CDI_DOMINATORS);
19434
19435 /* Now lower internal loop functions to target-specific code
19436 sequences. */
19437 basic_block bb;
19438 FOR_ALL_BB_FN (bb, cfun)
19439 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19440 {
19441 gimple *stmt = gsi_stmt (gsi);
19442 if (!is_gimple_call (stmt))
19443 {
19444 gsi_next (&gsi);
19445 continue;
19446 }
19447
19448 gcall *call = as_a <gcall *> (stmt);
19449 if (!gimple_call_internal_p (call))
19450 {
19451 gsi_next (&gsi);
19452 continue;
19453 }
19454
19455 /* Rewind to allow rescan. */
19456 gsi_prev (&gsi);
19457 bool rescan = false, remove = false;
19458 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19459
19460 switch (ifn_code)
19461 {
19462 default: break;
19463
19464 case IFN_GOACC_LOOP:
19465 oacc_xform_loop (call);
19466 rescan = true;
19467 break;
19468
19469 case IFN_GOACC_REDUCTION:
19470 /* Mark the function for SSA renaming. */
19471 mark_virtual_operands_for_renaming (cfun);
19472
19473 /* If the level is -1, this ended up being an unused
19474 axis. Handle as a default. */
19475 if (integer_minus_onep (gimple_call_arg (call, 3)))
19476 default_goacc_reduction (call);
19477 else
19478 targetm.goacc.reduction (call);
19479 rescan = true;
19480 break;
19481
19482 case IFN_UNIQUE:
19483 {
19484 enum ifn_unique_kind kind
19485 = ((enum ifn_unique_kind)
19486 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19487
19488 switch (kind)
19489 {
19490 default:
19491 gcc_unreachable ();
19492
19493 case IFN_UNIQUE_OACC_FORK:
19494 case IFN_UNIQUE_OACC_JOIN:
19495 if (integer_minus_onep (gimple_call_arg (call, 2)))
19496 remove = true;
19497 else if (!targetm.goacc.fork_join
19498 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19499 remove = true;
19500 break;
19501
19502 case IFN_UNIQUE_OACC_HEAD_MARK:
19503 case IFN_UNIQUE_OACC_TAIL_MARK:
19504 remove = true;
19505 break;
19506 }
19507 break;
19508 }
19509 }
19510
19511 if (gsi_end_p (gsi))
19512 /* We rewound past the beginning of the BB. */
19513 gsi = gsi_start_bb (bb);
19514 else
19515 /* Undo the rewind. */
19516 gsi_next (&gsi);
19517
19518 if (remove)
19519 {
19520 if (gimple_vdef (call))
19521 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19522 if (gimple_call_lhs (call))
19523 {
19524 /* Propagate the data dependency var. */
19525 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19526 gimple_call_arg (call, 1));
19527 gsi_replace (&gsi, ass, false);
19528 }
19529 else
19530 gsi_remove (&gsi, true);
19531 }
19532 else if (!rescan)
19533 /* If not rescanning, advance over the call. */
19534 gsi_next (&gsi);
19535 }
19536
19537 free_oacc_loop (loops);
19538
19539 return 0;
19540 }
19541
19542 /* Default launch dimension validator. Force everything to 1. A
19543 backend that wants to provide larger dimensions must override this
19544 hook. */
19545
19546 bool
19547 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19548 int ARG_UNUSED (fn_level))
19549 {
19550 bool changed = false;
19551
19552 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19553 {
19554 if (dims[ix] != 1)
19555 {
19556 dims[ix] = 1;
19557 changed = true;
19558 }
19559 }
19560
19561 return changed;
19562 }
19563
19564 /* Default dimension bound is unknown on accelerator and 1 on host. */
19565
19566 int
19567 default_goacc_dim_limit (int ARG_UNUSED (axis))
19568 {
19569 #ifdef ACCEL_COMPILER
19570 return 0;
19571 #else
19572 return 1;
19573 #endif
19574 }
19575
19576 namespace {
19577
19578 const pass_data pass_data_oacc_device_lower =
19579 {
19580 GIMPLE_PASS, /* type */
19581 "oaccdevlow", /* name */
19582 OPTGROUP_NONE, /* optinfo_flags */
19583 TV_NONE, /* tv_id */
19584 PROP_cfg, /* properties_required */
19585 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19586 0, /* properties_destroyed */
19587 0, /* todo_flags_start */
19588 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19589 };
19590
19591 class pass_oacc_device_lower : public gimple_opt_pass
19592 {
19593 public:
19594 pass_oacc_device_lower (gcc::context *ctxt)
19595 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19596 {}
19597
19598 /* opt_pass methods: */
19599 virtual unsigned int execute (function *)
19600 {
19601 bool gate = flag_openacc != 0;
19602
19603 if (!gate)
19604 return 0;
19605
19606 return execute_oacc_device_lower ();
19607 }
19608
19609 }; // class pass_oacc_device_lower
19610
19611 } // anon namespace
19612
19613 gimple_opt_pass *
19614 make_pass_oacc_device_lower (gcc::context *ctxt)
19615 {
19616 return new pass_oacc_device_lower (ctxt);
19617 }
19618
19619 #include "gt-omp-low.h"