loop splitting
[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-2016 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 "memmodel.h"
29 #include "backend.h"
30 #include "target.h"
31 #include "rtl.h"
32 #include "tree.h"
33 #include "gimple.h"
34 #include "cfghooks.h"
35 #include "alloc-pool.h"
36 #include "tree-pass.h"
37 #include "ssa.h"
38 #include "expmed.h"
39 #include "optabs.h"
40 #include "emit-rtl.h"
41 #include "cgraph.h"
42 #include "pretty-print.h"
43 #include "diagnostic-core.h"
44 #include "alias.h"
45 #include "fold-const.h"
46 #include "stor-layout.h"
47 #include "cfganal.h"
48 #include "internal-fn.h"
49 #include "gimple-fold.h"
50 #include "gimplify.h"
51 #include "gimple-iterator.h"
52 #include "gimplify-me.h"
53 #include "gimple-walk.h"
54 #include "tree-iterator.h"
55 #include "tree-inline.h"
56 #include "langhooks.h"
57 #include "tree-cfg.h"
58 #include "tree-into-ssa.h"
59 #include "flags.h"
60 #include "dojump.h"
61 #include "explow.h"
62 #include "calls.h"
63 #include "varasm.h"
64 #include "stmt.h"
65 #include "expr.h"
66 #include "tree-dfa.h"
67 #include "tree-ssa.h"
68 #include "except.h"
69 #include "splay-tree.h"
70 #include "cfgloop.h"
71 #include "common/common-target.h"
72 #include "omp-low.h"
73 #include "gimple-low.h"
74 #include "tree-cfgcleanup.h"
75 #include "symbol-summary.h"
76 #include "ipa-prop.h"
77 #include "tree-nested.h"
78 #include "tree-eh.h"
79 #include "cilk.h"
80 #include "context.h"
81 #include "lto-section-names.h"
82 #include "gomp-constants.h"
83 #include "gimple-pretty-print.h"
84 #include "symbol-summary.h"
85 #include "hsa.h"
86 #include "params.h"
87
88 /* Lowering of OMP parallel and workshare constructs proceeds in two
89 phases. The first phase scans the function looking for OMP statements
90 and then for variables that must be replaced to satisfy data sharing
91 clauses. The second phase expands code for the constructs, as well as
92 re-gimplifying things when variables have been replaced with complex
93 expressions.
94
95 Final code generation is done by pass_expand_omp. The flowgraph is
96 scanned for regions which are then moved to a new
97 function, to be invoked by the thread library, or offloaded. */
98
99 /* OMP region information. Every parallel and workshare
100 directive is enclosed between two markers, the OMP_* directive
101 and a corresponding GIMPLE_OMP_RETURN statement. */
102
103 struct omp_region
104 {
105 /* The enclosing region. */
106 struct omp_region *outer;
107
108 /* First child region. */
109 struct omp_region *inner;
110
111 /* Next peer region. */
112 struct omp_region *next;
113
114 /* Block containing the omp directive as its last stmt. */
115 basic_block entry;
116
117 /* Block containing the GIMPLE_OMP_RETURN as its last stmt. */
118 basic_block exit;
119
120 /* Block containing the GIMPLE_OMP_CONTINUE as its last stmt. */
121 basic_block cont;
122
123 /* If this is a combined parallel+workshare region, this is a list
124 of additional arguments needed by the combined parallel+workshare
125 library call. */
126 vec<tree, va_gc> *ws_args;
127
128 /* The code for the omp directive of this region. */
129 enum gimple_code type;
130
131 /* Schedule kind, only used for GIMPLE_OMP_FOR type regions. */
132 enum omp_clause_schedule_kind sched_kind;
133
134 /* Schedule modifiers. */
135 unsigned char sched_modifiers;
136
137 /* True if this is a combined parallel+workshare region. */
138 bool is_combined_parallel;
139
140 /* The ordered stmt if type is GIMPLE_OMP_ORDERED and it has
141 a depend clause. */
142 gomp_ordered *ord_stmt;
143 };
144
145 /* Context structure. Used to store information about each parallel
146 directive in the code. */
147
148 struct omp_context
149 {
150 /* This field must be at the beginning, as we do "inheritance": Some
151 callback functions for tree-inline.c (e.g., omp_copy_decl)
152 receive a copy_body_data pointer that is up-casted to an
153 omp_context pointer. */
154 copy_body_data cb;
155
156 /* The tree of contexts corresponding to the encountered constructs. */
157 struct omp_context *outer;
158 gimple *stmt;
159
160 /* Map variables to fields in a structure that allows communication
161 between sending and receiving threads. */
162 splay_tree field_map;
163 tree record_type;
164 tree sender_decl;
165 tree receiver_decl;
166
167 /* These are used just by task contexts, if task firstprivate fn is
168 needed. srecord_type is used to communicate from the thread
169 that encountered the task construct to task firstprivate fn,
170 record_type is allocated by GOMP_task, initialized by task firstprivate
171 fn and passed to the task body fn. */
172 splay_tree sfield_map;
173 tree srecord_type;
174
175 /* A chain of variables to add to the top-level block surrounding the
176 construct. In the case of a parallel, this is in the child function. */
177 tree block_vars;
178
179 /* Label to which GOMP_cancel{,llation_point} and explicit and implicit
180 barriers should jump to during omplower pass. */
181 tree cancel_label;
182
183 /* What to do with variables with implicitly determined sharing
184 attributes. */
185 enum omp_clause_default_kind default_kind;
186
187 /* Nesting depth of this context. Used to beautify error messages re
188 invalid gotos. The outermost ctx is depth 1, with depth 0 being
189 reserved for the main body of the function. */
190 int depth;
191
192 /* True if this parallel directive is nested within another. */
193 bool is_nested;
194
195 /* True if this construct can be cancelled. */
196 bool cancellable;
197 };
198
199 /* A structure holding the elements of:
200 for (V = N1; V cond N2; V += STEP) [...] */
201
202 struct omp_for_data_loop
203 {
204 tree v, n1, n2, step;
205 enum tree_code cond_code;
206 };
207
208 /* A structure describing the main elements of a parallel loop. */
209
210 struct omp_for_data
211 {
212 struct omp_for_data_loop loop;
213 tree chunk_size;
214 gomp_for *for_stmt;
215 tree pre, iter_type;
216 int collapse;
217 int ordered;
218 bool have_nowait, have_ordered, simd_schedule;
219 unsigned char sched_modifiers;
220 enum omp_clause_schedule_kind sched_kind;
221 struct omp_for_data_loop *loops;
222 };
223
224 /* Describe the OpenACC looping structure of a function. The entire
225 function is held in a 'NULL' loop. */
226
227 struct oacc_loop
228 {
229 oacc_loop *parent; /* Containing loop. */
230
231 oacc_loop *child; /* First inner loop. */
232
233 oacc_loop *sibling; /* Next loop within same parent. */
234
235 location_t loc; /* Location of the loop start. */
236
237 gcall *marker; /* Initial head marker. */
238
239 gcall *heads[GOMP_DIM_MAX]; /* Head marker functions. */
240 gcall *tails[GOMP_DIM_MAX]; /* Tail marker functions. */
241
242 tree routine; /* Pseudo-loop enclosing a routine. */
243
244 unsigned mask; /* Partitioning mask. */
245 unsigned inner; /* Partitioning of inner loops. */
246 unsigned flags; /* Partitioning flags. */
247 unsigned ifns; /* Contained loop abstraction functions. */
248 tree chunk_size; /* Chunk size. */
249 gcall *head_end; /* Final marker of head sequence. */
250 };
251
252 /* Flags for an OpenACC loop. */
253
254 enum oacc_loop_flags {
255 OLF_SEQ = 1u << 0, /* Explicitly sequential */
256 OLF_AUTO = 1u << 1, /* Compiler chooses axes. */
257 OLF_INDEPENDENT = 1u << 2, /* Iterations are known independent. */
258 OLF_GANG_STATIC = 1u << 3, /* Gang partitioning is static (has op). */
259
260 /* Explicitly specified loop axes. */
261 OLF_DIM_BASE = 4,
262 OLF_DIM_GANG = 1u << (OLF_DIM_BASE + GOMP_DIM_GANG),
263 OLF_DIM_WORKER = 1u << (OLF_DIM_BASE + GOMP_DIM_WORKER),
264 OLF_DIM_VECTOR = 1u << (OLF_DIM_BASE + GOMP_DIM_VECTOR),
265
266 OLF_MAX = OLF_DIM_BASE + GOMP_DIM_MAX
267 };
268
269
270 static splay_tree all_contexts;
271 static int taskreg_nesting_level;
272 static int target_nesting_level;
273 static struct omp_region *root_omp_region;
274 static bitmap task_shared_vars;
275 static vec<omp_context *> taskreg_contexts;
276 static bool omp_any_child_fn_dumped;
277
278 static void scan_omp (gimple_seq *, omp_context *);
279 static tree scan_omp_1_op (tree *, int *, void *);
280 static gphi *find_phi_with_arg_on_edge (tree, edge);
281
282 #define WALK_SUBSTMTS \
283 case GIMPLE_BIND: \
284 case GIMPLE_TRY: \
285 case GIMPLE_CATCH: \
286 case GIMPLE_EH_FILTER: \
287 case GIMPLE_TRANSACTION: \
288 /* The sub-statements for these should be walked. */ \
289 *handled_ops_p = false; \
290 break;
291
292 /* Return true if CTX corresponds to an oacc parallel region. */
293
294 static bool
295 is_oacc_parallel (omp_context *ctx)
296 {
297 enum gimple_code outer_type = gimple_code (ctx->stmt);
298 return ((outer_type == GIMPLE_OMP_TARGET)
299 && (gimple_omp_target_kind (ctx->stmt)
300 == GF_OMP_TARGET_KIND_OACC_PARALLEL));
301 }
302
303 /* Return true if CTX corresponds to an oacc kernels region. */
304
305 static bool
306 is_oacc_kernels (omp_context *ctx)
307 {
308 enum gimple_code outer_type = gimple_code (ctx->stmt);
309 return ((outer_type == GIMPLE_OMP_TARGET)
310 && (gimple_omp_target_kind (ctx->stmt)
311 == GF_OMP_TARGET_KIND_OACC_KERNELS));
312 }
313
314 /* If DECL is the artificial dummy VAR_DECL created for non-static
315 data member privatization, return the underlying "this" parameter,
316 otherwise return NULL. */
317
318 tree
319 omp_member_access_dummy_var (tree decl)
320 {
321 if (!VAR_P (decl)
322 || !DECL_ARTIFICIAL (decl)
323 || !DECL_IGNORED_P (decl)
324 || !DECL_HAS_VALUE_EXPR_P (decl)
325 || !lang_hooks.decls.omp_disregard_value_expr (decl, false))
326 return NULL_TREE;
327
328 tree v = DECL_VALUE_EXPR (decl);
329 if (TREE_CODE (v) != COMPONENT_REF)
330 return NULL_TREE;
331
332 while (1)
333 switch (TREE_CODE (v))
334 {
335 case COMPONENT_REF:
336 case MEM_REF:
337 case INDIRECT_REF:
338 CASE_CONVERT:
339 case POINTER_PLUS_EXPR:
340 v = TREE_OPERAND (v, 0);
341 continue;
342 case PARM_DECL:
343 if (DECL_CONTEXT (v) == current_function_decl
344 && DECL_ARTIFICIAL (v)
345 && TREE_CODE (TREE_TYPE (v)) == POINTER_TYPE)
346 return v;
347 return NULL_TREE;
348 default:
349 return NULL_TREE;
350 }
351 }
352
353 /* Helper for unshare_and_remap, called through walk_tree. */
354
355 static tree
356 unshare_and_remap_1 (tree *tp, int *walk_subtrees, void *data)
357 {
358 tree *pair = (tree *) data;
359 if (*tp == pair[0])
360 {
361 *tp = unshare_expr (pair[1]);
362 *walk_subtrees = 0;
363 }
364 else if (IS_TYPE_OR_DECL_P (*tp))
365 *walk_subtrees = 0;
366 return NULL_TREE;
367 }
368
369 /* Return unshare_expr (X) with all occurrences of FROM
370 replaced with TO. */
371
372 static tree
373 unshare_and_remap (tree x, tree from, tree to)
374 {
375 tree pair[2] = { from, to };
376 x = unshare_expr (x);
377 walk_tree (&x, unshare_and_remap_1, pair, NULL);
378 return x;
379 }
380
381 /* Holds offload tables with decls. */
382 vec<tree, va_gc> *offload_funcs, *offload_vars;
383
384 /* Convenience function for calling scan_omp_1_op on tree operands. */
385
386 static inline tree
387 scan_omp_op (tree *tp, omp_context *ctx)
388 {
389 struct walk_stmt_info wi;
390
391 memset (&wi, 0, sizeof (wi));
392 wi.info = ctx;
393 wi.want_locations = true;
394
395 return walk_tree (tp, scan_omp_1_op, &wi, NULL);
396 }
397
398 static void lower_omp (gimple_seq *, omp_context *);
399 static tree lookup_decl_in_outer_ctx (tree, omp_context *);
400 static tree maybe_lookup_decl_in_outer_ctx (tree, omp_context *);
401
402 /* Find an OMP clause of type KIND within CLAUSES. */
403
404 tree
405 find_omp_clause (tree clauses, enum omp_clause_code kind)
406 {
407 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
408 if (OMP_CLAUSE_CODE (clauses) == kind)
409 return clauses;
410
411 return NULL_TREE;
412 }
413
414 /* Return true if CTX is for an omp parallel. */
415
416 static inline bool
417 is_parallel_ctx (omp_context *ctx)
418 {
419 return gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL;
420 }
421
422
423 /* Return true if CTX is for an omp task. */
424
425 static inline bool
426 is_task_ctx (omp_context *ctx)
427 {
428 return gimple_code (ctx->stmt) == GIMPLE_OMP_TASK;
429 }
430
431
432 /* Return true if CTX is for an omp taskloop. */
433
434 static inline bool
435 is_taskloop_ctx (omp_context *ctx)
436 {
437 return gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
438 && gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP;
439 }
440
441
442 /* Return true if CTX is for an omp parallel or omp task. */
443
444 static inline bool
445 is_taskreg_ctx (omp_context *ctx)
446 {
447 return is_parallel_ctx (ctx) || is_task_ctx (ctx);
448 }
449
450
451 /* Return true if REGION is a combined parallel+workshare region. */
452
453 static inline bool
454 is_combined_parallel (struct omp_region *region)
455 {
456 return region->is_combined_parallel;
457 }
458
459 /* Adjust *COND_CODE and *N2 so that the former is either LT_EXPR or
460 GT_EXPR. */
461
462 static void
463 adjust_for_condition (location_t loc, enum tree_code *cond_code, tree *n2)
464 {
465 switch (*cond_code)
466 {
467 case LT_EXPR:
468 case GT_EXPR:
469 case NE_EXPR:
470 break;
471 case LE_EXPR:
472 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
473 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, 1);
474 else
475 *n2 = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (*n2), *n2,
476 build_int_cst (TREE_TYPE (*n2), 1));
477 *cond_code = LT_EXPR;
478 break;
479 case GE_EXPR:
480 if (POINTER_TYPE_P (TREE_TYPE (*n2)))
481 *n2 = fold_build_pointer_plus_hwi_loc (loc, *n2, -1);
482 else
483 *n2 = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (*n2), *n2,
484 build_int_cst (TREE_TYPE (*n2), 1));
485 *cond_code = GT_EXPR;
486 break;
487 default:
488 gcc_unreachable ();
489 }
490 }
491
492 /* Return the looping step from INCR, extracted from the step of a gimple omp
493 for statement. */
494
495 static tree
496 get_omp_for_step_from_incr (location_t loc, tree incr)
497 {
498 tree step;
499 switch (TREE_CODE (incr))
500 {
501 case PLUS_EXPR:
502 step = TREE_OPERAND (incr, 1);
503 break;
504 case POINTER_PLUS_EXPR:
505 step = fold_convert (ssizetype, TREE_OPERAND (incr, 1));
506 break;
507 case MINUS_EXPR:
508 step = TREE_OPERAND (incr, 1);
509 step = fold_build1_loc (loc, NEGATE_EXPR, TREE_TYPE (step), step);
510 break;
511 default:
512 gcc_unreachable ();
513 }
514 return step;
515 }
516
517 /* Extract the header elements of parallel loop FOR_STMT and store
518 them into *FD. */
519
520 static void
521 extract_omp_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
522 struct omp_for_data_loop *loops)
523 {
524 tree t, var, *collapse_iter, *collapse_count;
525 tree count = NULL_TREE, iter_type = long_integer_type_node;
526 struct omp_for_data_loop *loop;
527 int i;
528 struct omp_for_data_loop dummy_loop;
529 location_t loc = gimple_location (for_stmt);
530 bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
531 bool distribute = gimple_omp_for_kind (for_stmt)
532 == GF_OMP_FOR_KIND_DISTRIBUTE;
533 bool taskloop = gimple_omp_for_kind (for_stmt)
534 == GF_OMP_FOR_KIND_TASKLOOP;
535 tree iterv, countv;
536
537 fd->for_stmt = for_stmt;
538 fd->pre = NULL;
539 if (gimple_omp_for_collapse (for_stmt) > 1)
540 fd->loops = loops;
541 else
542 fd->loops = &fd->loop;
543
544 fd->have_nowait = distribute || simd;
545 fd->have_ordered = false;
546 fd->collapse = 1;
547 fd->ordered = 0;
548 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
549 fd->sched_modifiers = 0;
550 fd->chunk_size = NULL_TREE;
551 fd->simd_schedule = false;
552 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
553 fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
554 collapse_iter = NULL;
555 collapse_count = NULL;
556
557 for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
558 switch (OMP_CLAUSE_CODE (t))
559 {
560 case OMP_CLAUSE_NOWAIT:
561 fd->have_nowait = true;
562 break;
563 case OMP_CLAUSE_ORDERED:
564 fd->have_ordered = true;
565 if (OMP_CLAUSE_ORDERED_EXPR (t))
566 fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
567 break;
568 case OMP_CLAUSE_SCHEDULE:
569 gcc_assert (!distribute && !taskloop);
570 fd->sched_kind
571 = (enum omp_clause_schedule_kind)
572 (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
573 fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
574 & ~OMP_CLAUSE_SCHEDULE_MASK);
575 fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
576 fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
577 break;
578 case OMP_CLAUSE_DIST_SCHEDULE:
579 gcc_assert (distribute);
580 fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
581 break;
582 case OMP_CLAUSE_COLLAPSE:
583 fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
584 if (fd->collapse > 1)
585 {
586 collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
587 collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
588 }
589 break;
590 default:
591 break;
592 }
593 if (fd->ordered && fd->collapse == 1 && loops != NULL)
594 {
595 fd->loops = loops;
596 iterv = NULL_TREE;
597 countv = NULL_TREE;
598 collapse_iter = &iterv;
599 collapse_count = &countv;
600 }
601
602 /* FIXME: for now map schedule(auto) to schedule(static).
603 There should be analysis to determine whether all iterations
604 are approximately the same amount of work (then schedule(static)
605 is best) or if it varies (then schedule(dynamic,N) is better). */
606 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
607 {
608 fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
609 gcc_assert (fd->chunk_size == NULL);
610 }
611 gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
612 if (taskloop)
613 fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
614 if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
615 gcc_assert (fd->chunk_size == NULL);
616 else if (fd->chunk_size == NULL)
617 {
618 /* We only need to compute a default chunk size for ordered
619 static loops and dynamic loops. */
620 if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
621 || fd->have_ordered)
622 fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
623 ? integer_zero_node : integer_one_node;
624 }
625
626 int cnt = fd->ordered ? fd->ordered : fd->collapse;
627 for (i = 0; i < cnt; i++)
628 {
629 if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
630 loop = &fd->loop;
631 else if (loops != NULL)
632 loop = loops + i;
633 else
634 loop = &dummy_loop;
635
636 loop->v = gimple_omp_for_index (for_stmt, i);
637 gcc_assert (SSA_VAR_P (loop->v));
638 gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
639 || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
640 var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
641 loop->n1 = gimple_omp_for_initial (for_stmt, i);
642
643 loop->cond_code = gimple_omp_for_cond (for_stmt, i);
644 loop->n2 = gimple_omp_for_final (for_stmt, i);
645 gcc_assert (loop->cond_code != NE_EXPR
646 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKSIMD
647 || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKFOR);
648 adjust_for_condition (loc, &loop->cond_code, &loop->n2);
649
650 t = gimple_omp_for_incr (for_stmt, i);
651 gcc_assert (TREE_OPERAND (t, 0) == var);
652 loop->step = get_omp_for_step_from_incr (loc, t);
653
654 if (simd
655 || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
656 && !fd->have_ordered))
657 {
658 if (fd->collapse == 1)
659 iter_type = TREE_TYPE (loop->v);
660 else if (i == 0
661 || TYPE_PRECISION (iter_type)
662 < TYPE_PRECISION (TREE_TYPE (loop->v)))
663 iter_type
664 = build_nonstandard_integer_type
665 (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
666 }
667 else if (iter_type != long_long_unsigned_type_node)
668 {
669 if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
670 iter_type = long_long_unsigned_type_node;
671 else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
672 && TYPE_PRECISION (TREE_TYPE (loop->v))
673 >= TYPE_PRECISION (iter_type))
674 {
675 tree n;
676
677 if (loop->cond_code == LT_EXPR)
678 n = fold_build2_loc (loc,
679 PLUS_EXPR, TREE_TYPE (loop->v),
680 loop->n2, loop->step);
681 else
682 n = loop->n1;
683 if (TREE_CODE (n) != INTEGER_CST
684 || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
685 iter_type = long_long_unsigned_type_node;
686 }
687 else if (TYPE_PRECISION (TREE_TYPE (loop->v))
688 > TYPE_PRECISION (iter_type))
689 {
690 tree n1, n2;
691
692 if (loop->cond_code == LT_EXPR)
693 {
694 n1 = loop->n1;
695 n2 = fold_build2_loc (loc,
696 PLUS_EXPR, TREE_TYPE (loop->v),
697 loop->n2, loop->step);
698 }
699 else
700 {
701 n1 = fold_build2_loc (loc,
702 MINUS_EXPR, TREE_TYPE (loop->v),
703 loop->n2, loop->step);
704 n2 = loop->n1;
705 }
706 if (TREE_CODE (n1) != INTEGER_CST
707 || TREE_CODE (n2) != INTEGER_CST
708 || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
709 || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
710 iter_type = long_long_unsigned_type_node;
711 }
712 }
713
714 if (i >= fd->collapse)
715 continue;
716
717 if (collapse_count && *collapse_count == NULL)
718 {
719 t = fold_binary (loop->cond_code, boolean_type_node,
720 fold_convert (TREE_TYPE (loop->v), loop->n1),
721 fold_convert (TREE_TYPE (loop->v), loop->n2));
722 if (t && integer_zerop (t))
723 count = build_zero_cst (long_long_unsigned_type_node);
724 else if ((i == 0 || count != NULL_TREE)
725 && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
726 && TREE_CONSTANT (loop->n1)
727 && TREE_CONSTANT (loop->n2)
728 && TREE_CODE (loop->step) == INTEGER_CST)
729 {
730 tree itype = TREE_TYPE (loop->v);
731
732 if (POINTER_TYPE_P (itype))
733 itype = signed_type_for (itype);
734 t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
735 t = fold_build2_loc (loc,
736 PLUS_EXPR, itype,
737 fold_convert_loc (loc, itype, loop->step), t);
738 t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
739 fold_convert_loc (loc, itype, loop->n2));
740 t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
741 fold_convert_loc (loc, itype, loop->n1));
742 if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
743 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
744 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
745 fold_build1_loc (loc, NEGATE_EXPR, itype,
746 fold_convert_loc (loc, itype,
747 loop->step)));
748 else
749 t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
750 fold_convert_loc (loc, itype, loop->step));
751 t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
752 if (count != NULL_TREE)
753 count = fold_build2_loc (loc,
754 MULT_EXPR, long_long_unsigned_type_node,
755 count, t);
756 else
757 count = t;
758 if (TREE_CODE (count) != INTEGER_CST)
759 count = NULL_TREE;
760 }
761 else if (count && !integer_zerop (count))
762 count = NULL_TREE;
763 }
764 }
765
766 if (count
767 && !simd
768 && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
769 || fd->have_ordered))
770 {
771 if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
772 iter_type = long_long_unsigned_type_node;
773 else
774 iter_type = long_integer_type_node;
775 }
776 else if (collapse_iter && *collapse_iter != NULL)
777 iter_type = TREE_TYPE (*collapse_iter);
778 fd->iter_type = iter_type;
779 if (collapse_iter && *collapse_iter == NULL)
780 *collapse_iter = create_tmp_var (iter_type, ".iter");
781 if (collapse_count && *collapse_count == NULL)
782 {
783 if (count)
784 *collapse_count = fold_convert_loc (loc, iter_type, count);
785 else
786 *collapse_count = create_tmp_var (iter_type, ".count");
787 }
788
789 if (fd->collapse > 1 || (fd->ordered && loops))
790 {
791 fd->loop.v = *collapse_iter;
792 fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
793 fd->loop.n2 = *collapse_count;
794 fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
795 fd->loop.cond_code = LT_EXPR;
796 }
797 else if (loops)
798 loops[0] = fd->loop;
799 }
800
801
802 /* Given two blocks PAR_ENTRY_BB and WS_ENTRY_BB such that WS_ENTRY_BB
803 is the immediate dominator of PAR_ENTRY_BB, return true if there
804 are no data dependencies that would prevent expanding the parallel
805 directive at PAR_ENTRY_BB as a combined parallel+workshare region.
806
807 When expanding a combined parallel+workshare region, the call to
808 the child function may need additional arguments in the case of
809 GIMPLE_OMP_FOR regions. In some cases, these arguments are
810 computed out of variables passed in from the parent to the child
811 via 'struct .omp_data_s'. For instance:
812
813 #pragma omp parallel for schedule (guided, i * 4)
814 for (j ...)
815
816 Is lowered into:
817
818 # BLOCK 2 (PAR_ENTRY_BB)
819 .omp_data_o.i = i;
820 #pragma omp parallel [child fn: bar.omp_fn.0 ( ..., D.1598)
821
822 # BLOCK 3 (WS_ENTRY_BB)
823 .omp_data_i = &.omp_data_o;
824 D.1667 = .omp_data_i->i;
825 D.1598 = D.1667 * 4;
826 #pragma omp for schedule (guided, D.1598)
827
828 When we outline the parallel region, the call to the child function
829 'bar.omp_fn.0' will need the value D.1598 in its argument list, but
830 that value is computed *after* the call site. So, in principle we
831 cannot do the transformation.
832
833 To see whether the code in WS_ENTRY_BB blocks the combined
834 parallel+workshare call, we collect all the variables used in the
835 GIMPLE_OMP_FOR header check whether they appear on the LHS of any
836 statement in WS_ENTRY_BB. If so, then we cannot emit the combined
837 call.
838
839 FIXME. If we had the SSA form built at this point, we could merely
840 hoist the code in block 3 into block 2 and be done with it. But at
841 this point we don't have dataflow information and though we could
842 hack something up here, it is really not worth the aggravation. */
843
844 static bool
845 workshare_safe_to_combine_p (basic_block ws_entry_bb)
846 {
847 struct omp_for_data fd;
848 gimple *ws_stmt = last_stmt (ws_entry_bb);
849
850 if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
851 return true;
852
853 gcc_assert (gimple_code (ws_stmt) == GIMPLE_OMP_FOR);
854
855 extract_omp_for_data (as_a <gomp_for *> (ws_stmt), &fd, NULL);
856
857 if (fd.collapse > 1 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
858 return false;
859 if (fd.iter_type != long_integer_type_node)
860 return false;
861
862 /* FIXME. We give up too easily here. If any of these arguments
863 are not constants, they will likely involve variables that have
864 been mapped into fields of .omp_data_s for sharing with the child
865 function. With appropriate data flow, it would be possible to
866 see through this. */
867 if (!is_gimple_min_invariant (fd.loop.n1)
868 || !is_gimple_min_invariant (fd.loop.n2)
869 || !is_gimple_min_invariant (fd.loop.step)
870 || (fd.chunk_size && !is_gimple_min_invariant (fd.chunk_size)))
871 return false;
872
873 return true;
874 }
875
876
877 static int omp_max_vf (void);
878
879 /* Adjust CHUNK_SIZE from SCHEDULE clause, depending on simd modifier
880 presence (SIMD_SCHEDULE). */
881
882 static tree
883 omp_adjust_chunk_size (tree chunk_size, bool simd_schedule)
884 {
885 if (!simd_schedule)
886 return chunk_size;
887
888 int vf = omp_max_vf ();
889 if (vf == 1)
890 return chunk_size;
891
892 tree type = TREE_TYPE (chunk_size);
893 chunk_size = fold_build2 (PLUS_EXPR, type, chunk_size,
894 build_int_cst (type, vf - 1));
895 return fold_build2 (BIT_AND_EXPR, type, chunk_size,
896 build_int_cst (type, -vf));
897 }
898
899
900 /* Collect additional arguments needed to emit a combined
901 parallel+workshare call. WS_STMT is the workshare directive being
902 expanded. */
903
904 static vec<tree, va_gc> *
905 get_ws_args_for (gimple *par_stmt, gimple *ws_stmt)
906 {
907 tree t;
908 location_t loc = gimple_location (ws_stmt);
909 vec<tree, va_gc> *ws_args;
910
911 if (gomp_for *for_stmt = dyn_cast <gomp_for *> (ws_stmt))
912 {
913 struct omp_for_data fd;
914 tree n1, n2;
915
916 extract_omp_for_data (for_stmt, &fd, NULL);
917 n1 = fd.loop.n1;
918 n2 = fd.loop.n2;
919
920 if (gimple_omp_for_combined_into_p (for_stmt))
921 {
922 tree innerc
923 = find_omp_clause (gimple_omp_parallel_clauses (par_stmt),
924 OMP_CLAUSE__LOOPTEMP_);
925 gcc_assert (innerc);
926 n1 = OMP_CLAUSE_DECL (innerc);
927 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
928 OMP_CLAUSE__LOOPTEMP_);
929 gcc_assert (innerc);
930 n2 = OMP_CLAUSE_DECL (innerc);
931 }
932
933 vec_alloc (ws_args, 3 + (fd.chunk_size != 0));
934
935 t = fold_convert_loc (loc, long_integer_type_node, n1);
936 ws_args->quick_push (t);
937
938 t = fold_convert_loc (loc, long_integer_type_node, n2);
939 ws_args->quick_push (t);
940
941 t = fold_convert_loc (loc, long_integer_type_node, fd.loop.step);
942 ws_args->quick_push (t);
943
944 if (fd.chunk_size)
945 {
946 t = fold_convert_loc (loc, long_integer_type_node, fd.chunk_size);
947 t = omp_adjust_chunk_size (t, fd.simd_schedule);
948 ws_args->quick_push (t);
949 }
950
951 return ws_args;
952 }
953 else if (gimple_code (ws_stmt) == GIMPLE_OMP_SECTIONS)
954 {
955 /* Number of sections is equal to the number of edges from the
956 GIMPLE_OMP_SECTIONS_SWITCH statement, except for the one to
957 the exit of the sections region. */
958 basic_block bb = single_succ (gimple_bb (ws_stmt));
959 t = build_int_cst (unsigned_type_node, EDGE_COUNT (bb->succs) - 1);
960 vec_alloc (ws_args, 1);
961 ws_args->quick_push (t);
962 return ws_args;
963 }
964
965 gcc_unreachable ();
966 }
967
968
969 /* Discover whether REGION is a combined parallel+workshare region. */
970
971 static void
972 determine_parallel_type (struct omp_region *region)
973 {
974 basic_block par_entry_bb, par_exit_bb;
975 basic_block ws_entry_bb, ws_exit_bb;
976
977 if (region == NULL || region->inner == NULL
978 || region->exit == NULL || region->inner->exit == NULL
979 || region->inner->cont == NULL)
980 return;
981
982 /* We only support parallel+for and parallel+sections. */
983 if (region->type != GIMPLE_OMP_PARALLEL
984 || (region->inner->type != GIMPLE_OMP_FOR
985 && region->inner->type != GIMPLE_OMP_SECTIONS))
986 return;
987
988 /* Check for perfect nesting PAR_ENTRY_BB -> WS_ENTRY_BB and
989 WS_EXIT_BB -> PAR_EXIT_BB. */
990 par_entry_bb = region->entry;
991 par_exit_bb = region->exit;
992 ws_entry_bb = region->inner->entry;
993 ws_exit_bb = region->inner->exit;
994
995 if (single_succ (par_entry_bb) == ws_entry_bb
996 && single_succ (ws_exit_bb) == par_exit_bb
997 && workshare_safe_to_combine_p (ws_entry_bb)
998 && (gimple_omp_parallel_combined_p (last_stmt (par_entry_bb))
999 || (last_and_only_stmt (ws_entry_bb)
1000 && last_and_only_stmt (par_exit_bb))))
1001 {
1002 gimple *par_stmt = last_stmt (par_entry_bb);
1003 gimple *ws_stmt = last_stmt (ws_entry_bb);
1004
1005 if (region->inner->type == GIMPLE_OMP_FOR)
1006 {
1007 /* If this is a combined parallel loop, we need to determine
1008 whether or not to use the combined library calls. There
1009 are two cases where we do not apply the transformation:
1010 static loops and any kind of ordered loop. In the first
1011 case, we already open code the loop so there is no need
1012 to do anything else. In the latter case, the combined
1013 parallel loop call would still need extra synchronization
1014 to implement ordered semantics, so there would not be any
1015 gain in using the combined call. */
1016 tree clauses = gimple_omp_for_clauses (ws_stmt);
1017 tree c = find_omp_clause (clauses, OMP_CLAUSE_SCHEDULE);
1018 if (c == NULL
1019 || ((OMP_CLAUSE_SCHEDULE_KIND (c) & OMP_CLAUSE_SCHEDULE_MASK)
1020 == OMP_CLAUSE_SCHEDULE_STATIC)
1021 || find_omp_clause (clauses, OMP_CLAUSE_ORDERED))
1022 {
1023 region->is_combined_parallel = false;
1024 region->inner->is_combined_parallel = false;
1025 return;
1026 }
1027 }
1028
1029 region->is_combined_parallel = true;
1030 region->inner->is_combined_parallel = true;
1031 region->ws_args = get_ws_args_for (par_stmt, ws_stmt);
1032 }
1033 }
1034
1035
1036 /* Return true if EXPR is variable sized. */
1037
1038 static inline bool
1039 is_variable_sized (const_tree expr)
1040 {
1041 return !TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
1042 }
1043
1044 /* Return true if DECL is a reference type. */
1045
1046 static inline bool
1047 is_reference (tree decl)
1048 {
1049 return lang_hooks.decls.omp_privatize_by_reference (decl);
1050 }
1051
1052 /* Return the type of a decl. If the decl is reference type,
1053 return its base type. */
1054 static inline tree
1055 get_base_type (tree decl)
1056 {
1057 tree type = TREE_TYPE (decl);
1058 if (is_reference (decl))
1059 type = TREE_TYPE (type);
1060 return type;
1061 }
1062
1063 /* Lookup variables. The "maybe" form
1064 allows for the variable form to not have been entered, otherwise we
1065 assert that the variable must have been entered. */
1066
1067 static inline tree
1068 lookup_decl (tree var, omp_context *ctx)
1069 {
1070 tree *n = ctx->cb.decl_map->get (var);
1071 return *n;
1072 }
1073
1074 static inline tree
1075 maybe_lookup_decl (const_tree var, omp_context *ctx)
1076 {
1077 tree *n = ctx->cb.decl_map->get (const_cast<tree> (var));
1078 return n ? *n : NULL_TREE;
1079 }
1080
1081 static inline tree
1082 lookup_field (tree var, omp_context *ctx)
1083 {
1084 splay_tree_node n;
1085 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) var);
1086 return (tree) n->value;
1087 }
1088
1089 static inline tree
1090 lookup_sfield (splay_tree_key key, omp_context *ctx)
1091 {
1092 splay_tree_node n;
1093 n = splay_tree_lookup (ctx->sfield_map
1094 ? ctx->sfield_map : ctx->field_map, key);
1095 return (tree) n->value;
1096 }
1097
1098 static inline tree
1099 lookup_sfield (tree var, omp_context *ctx)
1100 {
1101 return lookup_sfield ((splay_tree_key) var, ctx);
1102 }
1103
1104 static inline tree
1105 maybe_lookup_field (splay_tree_key key, omp_context *ctx)
1106 {
1107 splay_tree_node n;
1108 n = splay_tree_lookup (ctx->field_map, key);
1109 return n ? (tree) n->value : NULL_TREE;
1110 }
1111
1112 static inline tree
1113 maybe_lookup_field (tree var, omp_context *ctx)
1114 {
1115 return maybe_lookup_field ((splay_tree_key) var, ctx);
1116 }
1117
1118 /* Return true if DECL should be copied by pointer. SHARED_CTX is
1119 the parallel context if DECL is to be shared. */
1120
1121 static bool
1122 use_pointer_for_field (tree decl, omp_context *shared_ctx)
1123 {
1124 if (AGGREGATE_TYPE_P (TREE_TYPE (decl))
1125 || TYPE_ATOMIC (TREE_TYPE (decl)))
1126 return true;
1127
1128 /* We can only use copy-in/copy-out semantics for shared variables
1129 when we know the value is not accessible from an outer scope. */
1130 if (shared_ctx)
1131 {
1132 gcc_assert (!is_gimple_omp_oacc (shared_ctx->stmt));
1133
1134 /* ??? Trivially accessible from anywhere. But why would we even
1135 be passing an address in this case? Should we simply assert
1136 this to be false, or should we have a cleanup pass that removes
1137 these from the list of mappings? */
1138 if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1139 return true;
1140
1141 /* For variables with DECL_HAS_VALUE_EXPR_P set, we cannot tell
1142 without analyzing the expression whether or not its location
1143 is accessible to anyone else. In the case of nested parallel
1144 regions it certainly may be. */
1145 if (TREE_CODE (decl) != RESULT_DECL && DECL_HAS_VALUE_EXPR_P (decl))
1146 return true;
1147
1148 /* Do not use copy-in/copy-out for variables that have their
1149 address taken. */
1150 if (TREE_ADDRESSABLE (decl))
1151 return true;
1152
1153 /* lower_send_shared_vars only uses copy-in, but not copy-out
1154 for these. */
1155 if (TREE_READONLY (decl)
1156 || ((TREE_CODE (decl) == RESULT_DECL
1157 || TREE_CODE (decl) == PARM_DECL)
1158 && DECL_BY_REFERENCE (decl)))
1159 return false;
1160
1161 /* Disallow copy-in/out in nested parallel if
1162 decl is shared in outer parallel, otherwise
1163 each thread could store the shared variable
1164 in its own copy-in location, making the
1165 variable no longer really shared. */
1166 if (shared_ctx->is_nested)
1167 {
1168 omp_context *up;
1169
1170 for (up = shared_ctx->outer; up; up = up->outer)
1171 if (is_taskreg_ctx (up) && maybe_lookup_decl (decl, up))
1172 break;
1173
1174 if (up)
1175 {
1176 tree c;
1177
1178 for (c = gimple_omp_taskreg_clauses (up->stmt);
1179 c; c = OMP_CLAUSE_CHAIN (c))
1180 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1181 && OMP_CLAUSE_DECL (c) == decl)
1182 break;
1183
1184 if (c)
1185 goto maybe_mark_addressable_and_ret;
1186 }
1187 }
1188
1189 /* For tasks avoid using copy-in/out. As tasks can be
1190 deferred or executed in different thread, when GOMP_task
1191 returns, the task hasn't necessarily terminated. */
1192 if (is_task_ctx (shared_ctx))
1193 {
1194 tree outer;
1195 maybe_mark_addressable_and_ret:
1196 outer = maybe_lookup_decl_in_outer_ctx (decl, shared_ctx);
1197 if (is_gimple_reg (outer) && !omp_member_access_dummy_var (outer))
1198 {
1199 /* Taking address of OUTER in lower_send_shared_vars
1200 might need regimplification of everything that uses the
1201 variable. */
1202 if (!task_shared_vars)
1203 task_shared_vars = BITMAP_ALLOC (NULL);
1204 bitmap_set_bit (task_shared_vars, DECL_UID (outer));
1205 TREE_ADDRESSABLE (outer) = 1;
1206 }
1207 return true;
1208 }
1209 }
1210
1211 return false;
1212 }
1213
1214 /* Construct a new automatic decl similar to VAR. */
1215
1216 static tree
1217 omp_copy_decl_2 (tree var, tree name, tree type, omp_context *ctx)
1218 {
1219 tree copy = copy_var_decl (var, name, type);
1220
1221 DECL_CONTEXT (copy) = current_function_decl;
1222 DECL_CHAIN (copy) = ctx->block_vars;
1223 /* If VAR is listed in task_shared_vars, it means it wasn't
1224 originally addressable and is just because task needs to take
1225 it's address. But we don't need to take address of privatizations
1226 from that var. */
1227 if (TREE_ADDRESSABLE (var)
1228 && task_shared_vars
1229 && bitmap_bit_p (task_shared_vars, DECL_UID (var)))
1230 TREE_ADDRESSABLE (copy) = 0;
1231 ctx->block_vars = copy;
1232
1233 return copy;
1234 }
1235
1236 static tree
1237 omp_copy_decl_1 (tree var, omp_context *ctx)
1238 {
1239 return omp_copy_decl_2 (var, DECL_NAME (var), TREE_TYPE (var), ctx);
1240 }
1241
1242 /* Build COMPONENT_REF and set TREE_THIS_VOLATILE and TREE_READONLY on it
1243 as appropriate. */
1244 static tree
1245 omp_build_component_ref (tree obj, tree field)
1246 {
1247 tree ret = build3 (COMPONENT_REF, TREE_TYPE (field), obj, field, NULL);
1248 if (TREE_THIS_VOLATILE (field))
1249 TREE_THIS_VOLATILE (ret) |= 1;
1250 if (TREE_READONLY (field))
1251 TREE_READONLY (ret) |= 1;
1252 return ret;
1253 }
1254
1255 /* Build tree nodes to access the field for VAR on the receiver side. */
1256
1257 static tree
1258 build_receiver_ref (tree var, bool by_ref, omp_context *ctx)
1259 {
1260 tree x, field = lookup_field (var, ctx);
1261
1262 /* If the receiver record type was remapped in the child function,
1263 remap the field into the new record type. */
1264 x = maybe_lookup_field (field, ctx);
1265 if (x != NULL)
1266 field = x;
1267
1268 x = build_simple_mem_ref (ctx->receiver_decl);
1269 TREE_THIS_NOTRAP (x) = 1;
1270 x = omp_build_component_ref (x, field);
1271 if (by_ref)
1272 {
1273 x = build_simple_mem_ref (x);
1274 TREE_THIS_NOTRAP (x) = 1;
1275 }
1276
1277 return x;
1278 }
1279
1280 /* Build tree nodes to access VAR in the scope outer to CTX. In the case
1281 of a parallel, this is a component reference; for workshare constructs
1282 this is some variable. */
1283
1284 static tree
1285 build_outer_var_ref (tree var, omp_context *ctx, bool lastprivate = false)
1286 {
1287 tree x;
1288
1289 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx)))
1290 x = var;
1291 else if (is_variable_sized (var))
1292 {
1293 x = TREE_OPERAND (DECL_VALUE_EXPR (var), 0);
1294 x = build_outer_var_ref (x, ctx, lastprivate);
1295 x = build_simple_mem_ref (x);
1296 }
1297 else if (is_taskreg_ctx (ctx))
1298 {
1299 bool by_ref = use_pointer_for_field (var, NULL);
1300 x = build_receiver_ref (var, by_ref, ctx);
1301 }
1302 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
1303 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
1304 {
1305 /* #pragma omp simd isn't a worksharing construct, and can reference even
1306 private vars in its linear etc. clauses. */
1307 x = NULL_TREE;
1308 if (ctx->outer && is_taskreg_ctx (ctx))
1309 x = lookup_decl (var, ctx->outer);
1310 else if (ctx->outer)
1311 x = maybe_lookup_decl_in_outer_ctx (var, ctx);
1312 if (x == NULL_TREE)
1313 x = var;
1314 }
1315 else if (lastprivate && is_taskloop_ctx (ctx))
1316 {
1317 gcc_assert (ctx->outer);
1318 splay_tree_node n
1319 = splay_tree_lookup (ctx->outer->field_map,
1320 (splay_tree_key) &DECL_UID (var));
1321 if (n == NULL)
1322 {
1323 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx->outer)))
1324 x = var;
1325 else
1326 x = lookup_decl (var, ctx->outer);
1327 }
1328 else
1329 {
1330 tree field = (tree) n->value;
1331 /* If the receiver record type was remapped in the child function,
1332 remap the field into the new record type. */
1333 x = maybe_lookup_field (field, ctx->outer);
1334 if (x != NULL)
1335 field = x;
1336
1337 x = build_simple_mem_ref (ctx->outer->receiver_decl);
1338 x = omp_build_component_ref (x, field);
1339 if (use_pointer_for_field (var, ctx->outer))
1340 x = build_simple_mem_ref (x);
1341 }
1342 }
1343 else if (ctx->outer)
1344 {
1345 omp_context *outer = ctx->outer;
1346 if (gimple_code (outer->stmt) == GIMPLE_OMP_GRID_BODY)
1347 {
1348 outer = outer->outer;
1349 gcc_assert (outer
1350 && gimple_code (outer->stmt) != GIMPLE_OMP_GRID_BODY);
1351 }
1352 x = lookup_decl (var, outer);
1353 }
1354 else if (is_reference (var))
1355 /* This can happen with orphaned constructs. If var is reference, it is
1356 possible it is shared and as such valid. */
1357 x = var;
1358 else if (omp_member_access_dummy_var (var))
1359 x = var;
1360 else
1361 gcc_unreachable ();
1362
1363 if (x == var)
1364 {
1365 tree t = omp_member_access_dummy_var (var);
1366 if (t)
1367 {
1368 x = DECL_VALUE_EXPR (var);
1369 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
1370 if (o != t)
1371 x = unshare_and_remap (x, t, o);
1372 else
1373 x = unshare_expr (x);
1374 }
1375 }
1376
1377 if (is_reference (var))
1378 x = build_simple_mem_ref (x);
1379
1380 return x;
1381 }
1382
1383 /* Build tree nodes to access the field for VAR on the sender side. */
1384
1385 static tree
1386 build_sender_ref (splay_tree_key key, omp_context *ctx)
1387 {
1388 tree field = lookup_sfield (key, ctx);
1389 return omp_build_component_ref (ctx->sender_decl, field);
1390 }
1391
1392 static tree
1393 build_sender_ref (tree var, omp_context *ctx)
1394 {
1395 return build_sender_ref ((splay_tree_key) var, ctx);
1396 }
1397
1398 /* Add a new field for VAR inside the structure CTX->SENDER_DECL. If
1399 BASE_POINTERS_RESTRICT, declare the field with restrict. */
1400
1401 static void
1402 install_var_field (tree var, bool by_ref, int mask, omp_context *ctx,
1403 bool base_pointers_restrict = false)
1404 {
1405 tree field, type, sfield = NULL_TREE;
1406 splay_tree_key key = (splay_tree_key) var;
1407
1408 if ((mask & 8) != 0)
1409 {
1410 key = (splay_tree_key) &DECL_UID (var);
1411 gcc_checking_assert (key != (splay_tree_key) var);
1412 }
1413 gcc_assert ((mask & 1) == 0
1414 || !splay_tree_lookup (ctx->field_map, key));
1415 gcc_assert ((mask & 2) == 0 || !ctx->sfield_map
1416 || !splay_tree_lookup (ctx->sfield_map, key));
1417 gcc_assert ((mask & 3) == 3
1418 || !is_gimple_omp_oacc (ctx->stmt));
1419
1420 type = TREE_TYPE (var);
1421 /* Prevent redeclaring the var in the split-off function with a restrict
1422 pointer type. Note that we only clear type itself, restrict qualifiers in
1423 the pointed-to type will be ignored by points-to analysis. */
1424 if (POINTER_TYPE_P (type)
1425 && TYPE_RESTRICT (type))
1426 type = build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_RESTRICT);
1427
1428 if (mask & 4)
1429 {
1430 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
1431 type = build_pointer_type (build_pointer_type (type));
1432 }
1433 else if (by_ref)
1434 {
1435 type = build_pointer_type (type);
1436 if (base_pointers_restrict)
1437 type = build_qualified_type (type, TYPE_QUAL_RESTRICT);
1438 }
1439 else if ((mask & 3) == 1 && is_reference (var))
1440 type = TREE_TYPE (type);
1441
1442 field = build_decl (DECL_SOURCE_LOCATION (var),
1443 FIELD_DECL, DECL_NAME (var), type);
1444
1445 /* Remember what variable this field was created for. This does have a
1446 side effect of making dwarf2out ignore this member, so for helpful
1447 debugging we clear it later in delete_omp_context. */
1448 DECL_ABSTRACT_ORIGIN (field) = var;
1449 if (type == TREE_TYPE (var))
1450 {
1451 SET_DECL_ALIGN (field, DECL_ALIGN (var));
1452 DECL_USER_ALIGN (field) = DECL_USER_ALIGN (var);
1453 TREE_THIS_VOLATILE (field) = TREE_THIS_VOLATILE (var);
1454 }
1455 else
1456 SET_DECL_ALIGN (field, TYPE_ALIGN (type));
1457
1458 if ((mask & 3) == 3)
1459 {
1460 insert_field_into_struct (ctx->record_type, field);
1461 if (ctx->srecord_type)
1462 {
1463 sfield = build_decl (DECL_SOURCE_LOCATION (var),
1464 FIELD_DECL, DECL_NAME (var), type);
1465 DECL_ABSTRACT_ORIGIN (sfield) = var;
1466 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
1467 DECL_USER_ALIGN (sfield) = DECL_USER_ALIGN (field);
1468 TREE_THIS_VOLATILE (sfield) = TREE_THIS_VOLATILE (field);
1469 insert_field_into_struct (ctx->srecord_type, sfield);
1470 }
1471 }
1472 else
1473 {
1474 if (ctx->srecord_type == NULL_TREE)
1475 {
1476 tree t;
1477
1478 ctx->srecord_type = lang_hooks.types.make_type (RECORD_TYPE);
1479 ctx->sfield_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
1480 for (t = TYPE_FIELDS (ctx->record_type); t ; t = TREE_CHAIN (t))
1481 {
1482 sfield = build_decl (DECL_SOURCE_LOCATION (t),
1483 FIELD_DECL, DECL_NAME (t), TREE_TYPE (t));
1484 DECL_ABSTRACT_ORIGIN (sfield) = DECL_ABSTRACT_ORIGIN (t);
1485 insert_field_into_struct (ctx->srecord_type, sfield);
1486 splay_tree_insert (ctx->sfield_map,
1487 (splay_tree_key) DECL_ABSTRACT_ORIGIN (t),
1488 (splay_tree_value) sfield);
1489 }
1490 }
1491 sfield = field;
1492 insert_field_into_struct ((mask & 1) ? ctx->record_type
1493 : ctx->srecord_type, field);
1494 }
1495
1496 if (mask & 1)
1497 splay_tree_insert (ctx->field_map, key, (splay_tree_value) field);
1498 if ((mask & 2) && ctx->sfield_map)
1499 splay_tree_insert (ctx->sfield_map, key, (splay_tree_value) sfield);
1500 }
1501
1502 static tree
1503 install_var_local (tree var, omp_context *ctx)
1504 {
1505 tree new_var = omp_copy_decl_1 (var, ctx);
1506 insert_decl_map (&ctx->cb, var, new_var);
1507 return new_var;
1508 }
1509
1510 /* Adjust the replacement for DECL in CTX for the new context. This means
1511 copying the DECL_VALUE_EXPR, and fixing up the type. */
1512
1513 static void
1514 fixup_remapped_decl (tree decl, omp_context *ctx, bool private_debug)
1515 {
1516 tree new_decl, size;
1517
1518 new_decl = lookup_decl (decl, ctx);
1519
1520 TREE_TYPE (new_decl) = remap_type (TREE_TYPE (decl), &ctx->cb);
1521
1522 if ((!TREE_CONSTANT (DECL_SIZE (new_decl)) || private_debug)
1523 && DECL_HAS_VALUE_EXPR_P (decl))
1524 {
1525 tree ve = DECL_VALUE_EXPR (decl);
1526 walk_tree (&ve, copy_tree_body_r, &ctx->cb, NULL);
1527 SET_DECL_VALUE_EXPR (new_decl, ve);
1528 DECL_HAS_VALUE_EXPR_P (new_decl) = 1;
1529 }
1530
1531 if (!TREE_CONSTANT (DECL_SIZE (new_decl)))
1532 {
1533 size = remap_decl (DECL_SIZE (decl), &ctx->cb);
1534 if (size == error_mark_node)
1535 size = TYPE_SIZE (TREE_TYPE (new_decl));
1536 DECL_SIZE (new_decl) = size;
1537
1538 size = remap_decl (DECL_SIZE_UNIT (decl), &ctx->cb);
1539 if (size == error_mark_node)
1540 size = TYPE_SIZE_UNIT (TREE_TYPE (new_decl));
1541 DECL_SIZE_UNIT (new_decl) = size;
1542 }
1543 }
1544
1545 /* The callback for remap_decl. Search all containing contexts for a
1546 mapping of the variable; this avoids having to duplicate the splay
1547 tree ahead of time. We know a mapping doesn't already exist in the
1548 given context. Create new mappings to implement default semantics. */
1549
1550 static tree
1551 omp_copy_decl (tree var, copy_body_data *cb)
1552 {
1553 omp_context *ctx = (omp_context *) cb;
1554 tree new_var;
1555
1556 if (TREE_CODE (var) == LABEL_DECL)
1557 {
1558 new_var = create_artificial_label (DECL_SOURCE_LOCATION (var));
1559 DECL_CONTEXT (new_var) = current_function_decl;
1560 insert_decl_map (&ctx->cb, var, new_var);
1561 return new_var;
1562 }
1563
1564 while (!is_taskreg_ctx (ctx))
1565 {
1566 ctx = ctx->outer;
1567 if (ctx == NULL)
1568 return var;
1569 new_var = maybe_lookup_decl (var, ctx);
1570 if (new_var)
1571 return new_var;
1572 }
1573
1574 if (is_global_var (var) || decl_function_context (var) != ctx->cb.src_fn)
1575 return var;
1576
1577 return error_mark_node;
1578 }
1579
1580
1581 /* Debugging dumps for parallel regions. */
1582 void dump_omp_region (FILE *, struct omp_region *, int);
1583 void debug_omp_region (struct omp_region *);
1584 void debug_all_omp_regions (void);
1585
1586 /* Dump the parallel region tree rooted at REGION. */
1587
1588 void
1589 dump_omp_region (FILE *file, struct omp_region *region, int indent)
1590 {
1591 fprintf (file, "%*sbb %d: %s\n", indent, "", region->entry->index,
1592 gimple_code_name[region->type]);
1593
1594 if (region->inner)
1595 dump_omp_region (file, region->inner, indent + 4);
1596
1597 if (region->cont)
1598 {
1599 fprintf (file, "%*sbb %d: GIMPLE_OMP_CONTINUE\n", indent, "",
1600 region->cont->index);
1601 }
1602
1603 if (region->exit)
1604 fprintf (file, "%*sbb %d: GIMPLE_OMP_RETURN\n", indent, "",
1605 region->exit->index);
1606 else
1607 fprintf (file, "%*s[no exit marker]\n", indent, "");
1608
1609 if (region->next)
1610 dump_omp_region (file, region->next, indent);
1611 }
1612
1613 DEBUG_FUNCTION void
1614 debug_omp_region (struct omp_region *region)
1615 {
1616 dump_omp_region (stderr, region, 0);
1617 }
1618
1619 DEBUG_FUNCTION void
1620 debug_all_omp_regions (void)
1621 {
1622 dump_omp_region (stderr, root_omp_region, 0);
1623 }
1624
1625
1626 /* Create a new parallel region starting at STMT inside region PARENT. */
1627
1628 static struct omp_region *
1629 new_omp_region (basic_block bb, enum gimple_code type,
1630 struct omp_region *parent)
1631 {
1632 struct omp_region *region = XCNEW (struct omp_region);
1633
1634 region->outer = parent;
1635 region->entry = bb;
1636 region->type = type;
1637
1638 if (parent)
1639 {
1640 /* This is a nested region. Add it to the list of inner
1641 regions in PARENT. */
1642 region->next = parent->inner;
1643 parent->inner = region;
1644 }
1645 else
1646 {
1647 /* This is a toplevel region. Add it to the list of toplevel
1648 regions in ROOT_OMP_REGION. */
1649 region->next = root_omp_region;
1650 root_omp_region = region;
1651 }
1652
1653 return region;
1654 }
1655
1656 /* Release the memory associated with the region tree rooted at REGION. */
1657
1658 static void
1659 free_omp_region_1 (struct omp_region *region)
1660 {
1661 struct omp_region *i, *n;
1662
1663 for (i = region->inner; i ; i = n)
1664 {
1665 n = i->next;
1666 free_omp_region_1 (i);
1667 }
1668
1669 free (region);
1670 }
1671
1672 /* Release the memory for the entire omp region tree. */
1673
1674 void
1675 free_omp_regions (void)
1676 {
1677 struct omp_region *r, *n;
1678 for (r = root_omp_region; r ; r = n)
1679 {
1680 n = r->next;
1681 free_omp_region_1 (r);
1682 }
1683 root_omp_region = NULL;
1684 }
1685
1686
1687 /* Create a new context, with OUTER_CTX being the surrounding context. */
1688
1689 static omp_context *
1690 new_omp_context (gimple *stmt, omp_context *outer_ctx)
1691 {
1692 omp_context *ctx = XCNEW (omp_context);
1693
1694 splay_tree_insert (all_contexts, (splay_tree_key) stmt,
1695 (splay_tree_value) ctx);
1696 ctx->stmt = stmt;
1697
1698 if (outer_ctx)
1699 {
1700 ctx->outer = outer_ctx;
1701 ctx->cb = outer_ctx->cb;
1702 ctx->cb.block = NULL;
1703 ctx->depth = outer_ctx->depth + 1;
1704 }
1705 else
1706 {
1707 ctx->cb.src_fn = current_function_decl;
1708 ctx->cb.dst_fn = current_function_decl;
1709 ctx->cb.src_node = cgraph_node::get (current_function_decl);
1710 gcc_checking_assert (ctx->cb.src_node);
1711 ctx->cb.dst_node = ctx->cb.src_node;
1712 ctx->cb.src_cfun = cfun;
1713 ctx->cb.copy_decl = omp_copy_decl;
1714 ctx->cb.eh_lp_nr = 0;
1715 ctx->cb.transform_call_graph_edges = CB_CGE_MOVE;
1716 ctx->depth = 1;
1717 }
1718
1719 ctx->cb.decl_map = new hash_map<tree, tree>;
1720
1721 return ctx;
1722 }
1723
1724 static gimple_seq maybe_catch_exception (gimple_seq);
1725
1726 /* Finalize task copyfn. */
1727
1728 static void
1729 finalize_task_copyfn (gomp_task *task_stmt)
1730 {
1731 struct function *child_cfun;
1732 tree child_fn;
1733 gimple_seq seq = NULL, new_seq;
1734 gbind *bind;
1735
1736 child_fn = gimple_omp_task_copy_fn (task_stmt);
1737 if (child_fn == NULL_TREE)
1738 return;
1739
1740 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
1741 DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties;
1742
1743 push_cfun (child_cfun);
1744 bind = gimplify_body (child_fn, false);
1745 gimple_seq_add_stmt (&seq, bind);
1746 new_seq = maybe_catch_exception (seq);
1747 if (new_seq != seq)
1748 {
1749 bind = gimple_build_bind (NULL, new_seq, NULL);
1750 seq = NULL;
1751 gimple_seq_add_stmt (&seq, bind);
1752 }
1753 gimple_set_body (child_fn, seq);
1754 pop_cfun ();
1755
1756 /* Inform the callgraph about the new function. */
1757 cgraph_node *node = cgraph_node::get_create (child_fn);
1758 node->parallelized_function = 1;
1759 cgraph_node::add_new_function (child_fn, false);
1760 }
1761
1762 /* Destroy a omp_context data structures. Called through the splay tree
1763 value delete callback. */
1764
1765 static void
1766 delete_omp_context (splay_tree_value value)
1767 {
1768 omp_context *ctx = (omp_context *) value;
1769
1770 delete ctx->cb.decl_map;
1771
1772 if (ctx->field_map)
1773 splay_tree_delete (ctx->field_map);
1774 if (ctx->sfield_map)
1775 splay_tree_delete (ctx->sfield_map);
1776
1777 /* We hijacked DECL_ABSTRACT_ORIGIN earlier. We need to clear it before
1778 it produces corrupt debug information. */
1779 if (ctx->record_type)
1780 {
1781 tree t;
1782 for (t = TYPE_FIELDS (ctx->record_type); t ; t = DECL_CHAIN (t))
1783 DECL_ABSTRACT_ORIGIN (t) = NULL;
1784 }
1785 if (ctx->srecord_type)
1786 {
1787 tree t;
1788 for (t = TYPE_FIELDS (ctx->srecord_type); t ; t = DECL_CHAIN (t))
1789 DECL_ABSTRACT_ORIGIN (t) = NULL;
1790 }
1791
1792 if (is_task_ctx (ctx))
1793 finalize_task_copyfn (as_a <gomp_task *> (ctx->stmt));
1794
1795 XDELETE (ctx);
1796 }
1797
1798 /* Fix up RECEIVER_DECL with a type that has been remapped to the child
1799 context. */
1800
1801 static void
1802 fixup_child_record_type (omp_context *ctx)
1803 {
1804 tree f, type = ctx->record_type;
1805
1806 if (!ctx->receiver_decl)
1807 return;
1808 /* ??? It isn't sufficient to just call remap_type here, because
1809 variably_modified_type_p doesn't work the way we expect for
1810 record types. Testing each field for whether it needs remapping
1811 and creating a new record by hand works, however. */
1812 for (f = TYPE_FIELDS (type); f ; f = DECL_CHAIN (f))
1813 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
1814 break;
1815 if (f)
1816 {
1817 tree name, new_fields = NULL;
1818
1819 type = lang_hooks.types.make_type (RECORD_TYPE);
1820 name = DECL_NAME (TYPE_NAME (ctx->record_type));
1821 name = build_decl (DECL_SOURCE_LOCATION (ctx->receiver_decl),
1822 TYPE_DECL, name, type);
1823 TYPE_NAME (type) = name;
1824
1825 for (f = TYPE_FIELDS (ctx->record_type); f ; f = DECL_CHAIN (f))
1826 {
1827 tree new_f = copy_node (f);
1828 DECL_CONTEXT (new_f) = type;
1829 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &ctx->cb);
1830 DECL_CHAIN (new_f) = new_fields;
1831 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &ctx->cb, NULL);
1832 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r,
1833 &ctx->cb, NULL);
1834 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
1835 &ctx->cb, NULL);
1836 new_fields = new_f;
1837
1838 /* Arrange to be able to look up the receiver field
1839 given the sender field. */
1840 splay_tree_insert (ctx->field_map, (splay_tree_key) f,
1841 (splay_tree_value) new_f);
1842 }
1843 TYPE_FIELDS (type) = nreverse (new_fields);
1844 layout_type (type);
1845 }
1846
1847 /* In a target region we never modify any of the pointers in *.omp_data_i,
1848 so attempt to help the optimizers. */
1849 if (is_gimple_omp_offloaded (ctx->stmt))
1850 type = build_qualified_type (type, TYPE_QUAL_CONST);
1851
1852 TREE_TYPE (ctx->receiver_decl)
1853 = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT);
1854 }
1855
1856 /* Instantiate decls as necessary in CTX to satisfy the data sharing
1857 specified by CLAUSES. If BASE_POINTERS_RESTRICT, install var field with
1858 restrict. */
1859
1860 static void
1861 scan_sharing_clauses (tree clauses, omp_context *ctx,
1862 bool base_pointers_restrict = false)
1863 {
1864 tree c, decl;
1865 bool scan_array_reductions = false;
1866
1867 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
1868 {
1869 bool by_ref;
1870
1871 switch (OMP_CLAUSE_CODE (c))
1872 {
1873 case OMP_CLAUSE_PRIVATE:
1874 decl = OMP_CLAUSE_DECL (c);
1875 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
1876 goto do_private;
1877 else if (!is_variable_sized (decl))
1878 install_var_local (decl, ctx);
1879 break;
1880
1881 case OMP_CLAUSE_SHARED:
1882 decl = OMP_CLAUSE_DECL (c);
1883 /* Ignore shared directives in teams construct. */
1884 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
1885 {
1886 /* Global variables don't need to be copied,
1887 the receiver side will use them directly. */
1888 tree odecl = maybe_lookup_decl_in_outer_ctx (decl, ctx);
1889 if (is_global_var (odecl))
1890 break;
1891 insert_decl_map (&ctx->cb, decl, odecl);
1892 break;
1893 }
1894 gcc_assert (is_taskreg_ctx (ctx));
1895 gcc_assert (!COMPLETE_TYPE_P (TREE_TYPE (decl))
1896 || !is_variable_sized (decl));
1897 /* Global variables don't need to be copied,
1898 the receiver side will use them directly. */
1899 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
1900 break;
1901 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
1902 {
1903 use_pointer_for_field (decl, ctx);
1904 break;
1905 }
1906 by_ref = use_pointer_for_field (decl, NULL);
1907 if ((! TREE_READONLY (decl) && !OMP_CLAUSE_SHARED_READONLY (c))
1908 || TREE_ADDRESSABLE (decl)
1909 || by_ref
1910 || is_reference (decl))
1911 {
1912 by_ref = use_pointer_for_field (decl, ctx);
1913 install_var_field (decl, by_ref, 3, ctx);
1914 install_var_local (decl, ctx);
1915 break;
1916 }
1917 /* We don't need to copy const scalar vars back. */
1918 OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_FIRSTPRIVATE);
1919 goto do_private;
1920
1921 case OMP_CLAUSE_REDUCTION:
1922 decl = OMP_CLAUSE_DECL (c);
1923 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
1924 && TREE_CODE (decl) == MEM_REF)
1925 {
1926 tree t = TREE_OPERAND (decl, 0);
1927 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
1928 t = TREE_OPERAND (t, 0);
1929 if (TREE_CODE (t) == INDIRECT_REF
1930 || TREE_CODE (t) == ADDR_EXPR)
1931 t = TREE_OPERAND (t, 0);
1932 install_var_local (t, ctx);
1933 if (is_taskreg_ctx (ctx)
1934 && !is_global_var (maybe_lookup_decl_in_outer_ctx (t, ctx))
1935 && !is_variable_sized (t))
1936 {
1937 by_ref = use_pointer_for_field (t, ctx);
1938 install_var_field (t, by_ref, 3, ctx);
1939 }
1940 break;
1941 }
1942 goto do_private;
1943
1944 case OMP_CLAUSE_LASTPRIVATE:
1945 /* Let the corresponding firstprivate clause create
1946 the variable. */
1947 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
1948 break;
1949 /* FALLTHRU */
1950
1951 case OMP_CLAUSE_FIRSTPRIVATE:
1952 case OMP_CLAUSE_LINEAR:
1953 decl = OMP_CLAUSE_DECL (c);
1954 do_private:
1955 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
1956 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
1957 && is_gimple_omp_offloaded (ctx->stmt))
1958 {
1959 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
1960 install_var_field (decl, !is_reference (decl), 3, ctx);
1961 else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1962 install_var_field (decl, true, 3, ctx);
1963 else
1964 install_var_field (decl, false, 3, ctx);
1965 }
1966 if (is_variable_sized (decl))
1967 {
1968 if (is_task_ctx (ctx))
1969 install_var_field (decl, false, 1, ctx);
1970 break;
1971 }
1972 else if (is_taskreg_ctx (ctx))
1973 {
1974 bool global
1975 = is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx));
1976 by_ref = use_pointer_for_field (decl, NULL);
1977
1978 if (is_task_ctx (ctx)
1979 && (global || by_ref || is_reference (decl)))
1980 {
1981 install_var_field (decl, false, 1, ctx);
1982 if (!global)
1983 install_var_field (decl, by_ref, 2, ctx);
1984 }
1985 else if (!global)
1986 install_var_field (decl, by_ref, 3, ctx);
1987 }
1988 install_var_local (decl, ctx);
1989 break;
1990
1991 case OMP_CLAUSE_USE_DEVICE_PTR:
1992 decl = OMP_CLAUSE_DECL (c);
1993 if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
1994 install_var_field (decl, true, 3, ctx);
1995 else
1996 install_var_field (decl, false, 3, ctx);
1997 if (DECL_SIZE (decl)
1998 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
1999 {
2000 tree decl2 = DECL_VALUE_EXPR (decl);
2001 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2002 decl2 = TREE_OPERAND (decl2, 0);
2003 gcc_assert (DECL_P (decl2));
2004 install_var_local (decl2, ctx);
2005 }
2006 install_var_local (decl, ctx);
2007 break;
2008
2009 case OMP_CLAUSE_IS_DEVICE_PTR:
2010 decl = OMP_CLAUSE_DECL (c);
2011 goto do_private;
2012
2013 case OMP_CLAUSE__LOOPTEMP_:
2014 gcc_assert (is_taskreg_ctx (ctx));
2015 decl = OMP_CLAUSE_DECL (c);
2016 install_var_field (decl, false, 3, ctx);
2017 install_var_local (decl, ctx);
2018 break;
2019
2020 case OMP_CLAUSE_COPYPRIVATE:
2021 case OMP_CLAUSE_COPYIN:
2022 decl = OMP_CLAUSE_DECL (c);
2023 by_ref = use_pointer_for_field (decl, NULL);
2024 install_var_field (decl, by_ref, 3, ctx);
2025 break;
2026
2027 case OMP_CLAUSE_DEFAULT:
2028 ctx->default_kind = OMP_CLAUSE_DEFAULT_KIND (c);
2029 break;
2030
2031 case OMP_CLAUSE_FINAL:
2032 case OMP_CLAUSE_IF:
2033 case OMP_CLAUSE_NUM_THREADS:
2034 case OMP_CLAUSE_NUM_TEAMS:
2035 case OMP_CLAUSE_THREAD_LIMIT:
2036 case OMP_CLAUSE_DEVICE:
2037 case OMP_CLAUSE_SCHEDULE:
2038 case OMP_CLAUSE_DIST_SCHEDULE:
2039 case OMP_CLAUSE_DEPEND:
2040 case OMP_CLAUSE_PRIORITY:
2041 case OMP_CLAUSE_GRAINSIZE:
2042 case OMP_CLAUSE_NUM_TASKS:
2043 case OMP_CLAUSE__CILK_FOR_COUNT_:
2044 case OMP_CLAUSE_NUM_GANGS:
2045 case OMP_CLAUSE_NUM_WORKERS:
2046 case OMP_CLAUSE_VECTOR_LENGTH:
2047 if (ctx->outer)
2048 scan_omp_op (&OMP_CLAUSE_OPERAND (c, 0), ctx->outer);
2049 break;
2050
2051 case OMP_CLAUSE_TO:
2052 case OMP_CLAUSE_FROM:
2053 case OMP_CLAUSE_MAP:
2054 if (ctx->outer)
2055 scan_omp_op (&OMP_CLAUSE_SIZE (c), ctx->outer);
2056 decl = OMP_CLAUSE_DECL (c);
2057 /* Global variables with "omp declare target" attribute
2058 don't need to be copied, the receiver side will use them
2059 directly. However, global variables with "omp declare target link"
2060 attribute need to be copied. */
2061 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2062 && DECL_P (decl)
2063 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2064 && (OMP_CLAUSE_MAP_KIND (c)
2065 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2066 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2067 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2068 && varpool_node::get_create (decl)->offloadable
2069 && !lookup_attribute ("omp declare target link",
2070 DECL_ATTRIBUTES (decl)))
2071 break;
2072 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2073 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER)
2074 {
2075 /* Ignore GOMP_MAP_POINTER kind for arrays in regions that are
2076 not offloaded; there is nothing to map for those. */
2077 if (!is_gimple_omp_offloaded (ctx->stmt)
2078 && !POINTER_TYPE_P (TREE_TYPE (decl))
2079 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
2080 break;
2081 }
2082 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2083 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
2084 || (OMP_CLAUSE_MAP_KIND (c)
2085 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
2086 {
2087 if (TREE_CODE (decl) == COMPONENT_REF
2088 || (TREE_CODE (decl) == INDIRECT_REF
2089 && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF
2090 && (TREE_CODE (TREE_TYPE (TREE_OPERAND (decl, 0)))
2091 == REFERENCE_TYPE)))
2092 break;
2093 if (DECL_SIZE (decl)
2094 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2095 {
2096 tree decl2 = DECL_VALUE_EXPR (decl);
2097 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2098 decl2 = TREE_OPERAND (decl2, 0);
2099 gcc_assert (DECL_P (decl2));
2100 install_var_local (decl2, ctx);
2101 }
2102 install_var_local (decl, ctx);
2103 break;
2104 }
2105 if (DECL_P (decl))
2106 {
2107 if (DECL_SIZE (decl)
2108 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2109 {
2110 tree decl2 = DECL_VALUE_EXPR (decl);
2111 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2112 decl2 = TREE_OPERAND (decl2, 0);
2113 gcc_assert (DECL_P (decl2));
2114 install_var_field (decl2, true, 3, ctx);
2115 install_var_local (decl2, ctx);
2116 install_var_local (decl, ctx);
2117 }
2118 else
2119 {
2120 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
2121 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2122 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
2123 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2124 install_var_field (decl, true, 7, ctx);
2125 else
2126 install_var_field (decl, true, 3, ctx,
2127 base_pointers_restrict);
2128 if (is_gimple_omp_offloaded (ctx->stmt)
2129 && !OMP_CLAUSE_MAP_IN_REDUCTION (c))
2130 install_var_local (decl, ctx);
2131 }
2132 }
2133 else
2134 {
2135 tree base = get_base_address (decl);
2136 tree nc = OMP_CLAUSE_CHAIN (c);
2137 if (DECL_P (base)
2138 && nc != NULL_TREE
2139 && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP
2140 && OMP_CLAUSE_DECL (nc) == base
2141 && OMP_CLAUSE_MAP_KIND (nc) == GOMP_MAP_POINTER
2142 && integer_zerop (OMP_CLAUSE_SIZE (nc)))
2143 {
2144 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c) = 1;
2145 OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (nc) = 1;
2146 }
2147 else
2148 {
2149 if (ctx->outer)
2150 {
2151 scan_omp_op (&OMP_CLAUSE_DECL (c), ctx->outer);
2152 decl = OMP_CLAUSE_DECL (c);
2153 }
2154 gcc_assert (!splay_tree_lookup (ctx->field_map,
2155 (splay_tree_key) decl));
2156 tree field
2157 = build_decl (OMP_CLAUSE_LOCATION (c),
2158 FIELD_DECL, NULL_TREE, ptr_type_node);
2159 SET_DECL_ALIGN (field, TYPE_ALIGN (ptr_type_node));
2160 insert_field_into_struct (ctx->record_type, field);
2161 splay_tree_insert (ctx->field_map, (splay_tree_key) decl,
2162 (splay_tree_value) field);
2163 }
2164 }
2165 break;
2166
2167 case OMP_CLAUSE__GRIDDIM_:
2168 if (ctx->outer)
2169 {
2170 scan_omp_op (&OMP_CLAUSE__GRIDDIM__SIZE (c), ctx->outer);
2171 scan_omp_op (&OMP_CLAUSE__GRIDDIM__GROUP (c), ctx->outer);
2172 }
2173 break;
2174
2175 case OMP_CLAUSE_NOWAIT:
2176 case OMP_CLAUSE_ORDERED:
2177 case OMP_CLAUSE_COLLAPSE:
2178 case OMP_CLAUSE_UNTIED:
2179 case OMP_CLAUSE_MERGEABLE:
2180 case OMP_CLAUSE_PROC_BIND:
2181 case OMP_CLAUSE_SAFELEN:
2182 case OMP_CLAUSE_SIMDLEN:
2183 case OMP_CLAUSE_THREADS:
2184 case OMP_CLAUSE_SIMD:
2185 case OMP_CLAUSE_NOGROUP:
2186 case OMP_CLAUSE_DEFAULTMAP:
2187 case OMP_CLAUSE_ASYNC:
2188 case OMP_CLAUSE_WAIT:
2189 case OMP_CLAUSE_GANG:
2190 case OMP_CLAUSE_WORKER:
2191 case OMP_CLAUSE_VECTOR:
2192 case OMP_CLAUSE_INDEPENDENT:
2193 case OMP_CLAUSE_AUTO:
2194 case OMP_CLAUSE_SEQ:
2195 break;
2196
2197 case OMP_CLAUSE_ALIGNED:
2198 decl = OMP_CLAUSE_DECL (c);
2199 if (is_global_var (decl)
2200 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2201 install_var_local (decl, ctx);
2202 break;
2203
2204 case OMP_CLAUSE_TILE:
2205 case OMP_CLAUSE__CACHE_:
2206 default:
2207 gcc_unreachable ();
2208 }
2209 }
2210
2211 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2212 {
2213 switch (OMP_CLAUSE_CODE (c))
2214 {
2215 case OMP_CLAUSE_LASTPRIVATE:
2216 /* Let the corresponding firstprivate clause create
2217 the variable. */
2218 if (OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2219 scan_array_reductions = true;
2220 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
2221 break;
2222 /* FALLTHRU */
2223
2224 case OMP_CLAUSE_FIRSTPRIVATE:
2225 case OMP_CLAUSE_PRIVATE:
2226 case OMP_CLAUSE_LINEAR:
2227 case OMP_CLAUSE_IS_DEVICE_PTR:
2228 decl = OMP_CLAUSE_DECL (c);
2229 if (is_variable_sized (decl))
2230 {
2231 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
2232 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IS_DEVICE_PTR)
2233 && is_gimple_omp_offloaded (ctx->stmt))
2234 {
2235 tree decl2 = DECL_VALUE_EXPR (decl);
2236 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2237 decl2 = TREE_OPERAND (decl2, 0);
2238 gcc_assert (DECL_P (decl2));
2239 install_var_local (decl2, ctx);
2240 fixup_remapped_decl (decl2, ctx, false);
2241 }
2242 install_var_local (decl, ctx);
2243 }
2244 fixup_remapped_decl (decl, ctx,
2245 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2246 && OMP_CLAUSE_PRIVATE_DEBUG (c));
2247 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2248 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2249 scan_array_reductions = true;
2250 break;
2251
2252 case OMP_CLAUSE_REDUCTION:
2253 decl = OMP_CLAUSE_DECL (c);
2254 if (TREE_CODE (decl) != MEM_REF)
2255 {
2256 if (is_variable_sized (decl))
2257 install_var_local (decl, ctx);
2258 fixup_remapped_decl (decl, ctx, false);
2259 }
2260 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2261 scan_array_reductions = true;
2262 break;
2263
2264 case OMP_CLAUSE_SHARED:
2265 /* Ignore shared directives in teams construct. */
2266 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
2267 break;
2268 decl = OMP_CLAUSE_DECL (c);
2269 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2270 break;
2271 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2272 {
2273 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl,
2274 ctx->outer)))
2275 break;
2276 bool by_ref = use_pointer_for_field (decl, ctx);
2277 install_var_field (decl, by_ref, 11, ctx);
2278 break;
2279 }
2280 fixup_remapped_decl (decl, ctx, false);
2281 break;
2282
2283 case OMP_CLAUSE_MAP:
2284 if (!is_gimple_omp_offloaded (ctx->stmt))
2285 break;
2286 decl = OMP_CLAUSE_DECL (c);
2287 if (DECL_P (decl)
2288 && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER
2289 && (OMP_CLAUSE_MAP_KIND (c)
2290 != GOMP_MAP_FIRSTPRIVATE_REFERENCE))
2291 || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
2292 && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))
2293 && varpool_node::get_create (decl)->offloadable)
2294 break;
2295 if (DECL_P (decl))
2296 {
2297 if ((OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
2298 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER)
2299 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2300 && !COMPLETE_TYPE_P (TREE_TYPE (decl)))
2301 {
2302 tree new_decl = lookup_decl (decl, ctx);
2303 TREE_TYPE (new_decl)
2304 = remap_type (TREE_TYPE (decl), &ctx->cb);
2305 }
2306 else if (DECL_SIZE (decl)
2307 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
2308 {
2309 tree decl2 = DECL_VALUE_EXPR (decl);
2310 gcc_assert (TREE_CODE (decl2) == INDIRECT_REF);
2311 decl2 = TREE_OPERAND (decl2, 0);
2312 gcc_assert (DECL_P (decl2));
2313 fixup_remapped_decl (decl2, ctx, false);
2314 fixup_remapped_decl (decl, ctx, true);
2315 }
2316 else
2317 fixup_remapped_decl (decl, ctx, false);
2318 }
2319 break;
2320
2321 case OMP_CLAUSE_COPYPRIVATE:
2322 case OMP_CLAUSE_COPYIN:
2323 case OMP_CLAUSE_DEFAULT:
2324 case OMP_CLAUSE_IF:
2325 case OMP_CLAUSE_NUM_THREADS:
2326 case OMP_CLAUSE_NUM_TEAMS:
2327 case OMP_CLAUSE_THREAD_LIMIT:
2328 case OMP_CLAUSE_DEVICE:
2329 case OMP_CLAUSE_SCHEDULE:
2330 case OMP_CLAUSE_DIST_SCHEDULE:
2331 case OMP_CLAUSE_NOWAIT:
2332 case OMP_CLAUSE_ORDERED:
2333 case OMP_CLAUSE_COLLAPSE:
2334 case OMP_CLAUSE_UNTIED:
2335 case OMP_CLAUSE_FINAL:
2336 case OMP_CLAUSE_MERGEABLE:
2337 case OMP_CLAUSE_PROC_BIND:
2338 case OMP_CLAUSE_SAFELEN:
2339 case OMP_CLAUSE_SIMDLEN:
2340 case OMP_CLAUSE_ALIGNED:
2341 case OMP_CLAUSE_DEPEND:
2342 case OMP_CLAUSE__LOOPTEMP_:
2343 case OMP_CLAUSE_TO:
2344 case OMP_CLAUSE_FROM:
2345 case OMP_CLAUSE_PRIORITY:
2346 case OMP_CLAUSE_GRAINSIZE:
2347 case OMP_CLAUSE_NUM_TASKS:
2348 case OMP_CLAUSE_THREADS:
2349 case OMP_CLAUSE_SIMD:
2350 case OMP_CLAUSE_NOGROUP:
2351 case OMP_CLAUSE_DEFAULTMAP:
2352 case OMP_CLAUSE_USE_DEVICE_PTR:
2353 case OMP_CLAUSE__CILK_FOR_COUNT_:
2354 case OMP_CLAUSE_ASYNC:
2355 case OMP_CLAUSE_WAIT:
2356 case OMP_CLAUSE_NUM_GANGS:
2357 case OMP_CLAUSE_NUM_WORKERS:
2358 case OMP_CLAUSE_VECTOR_LENGTH:
2359 case OMP_CLAUSE_GANG:
2360 case OMP_CLAUSE_WORKER:
2361 case OMP_CLAUSE_VECTOR:
2362 case OMP_CLAUSE_INDEPENDENT:
2363 case OMP_CLAUSE_AUTO:
2364 case OMP_CLAUSE_SEQ:
2365 case OMP_CLAUSE__GRIDDIM_:
2366 break;
2367
2368 case OMP_CLAUSE_TILE:
2369 case OMP_CLAUSE__CACHE_:
2370 default:
2371 gcc_unreachable ();
2372 }
2373 }
2374
2375 gcc_checking_assert (!scan_array_reductions
2376 || !is_gimple_omp_oacc (ctx->stmt));
2377 if (scan_array_reductions)
2378 {
2379 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2380 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
2381 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
2382 {
2383 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c), ctx);
2384 scan_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
2385 }
2386 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
2387 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
2388 scan_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
2389 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
2390 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
2391 scan_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
2392 }
2393 }
2394
2395 /* Create a new name for omp child function. Returns an identifier. If
2396 IS_CILK_FOR is true then the suffix for the child function is
2397 "_cilk_for_fn." */
2398
2399 static tree
2400 create_omp_child_function_name (bool task_copy, bool is_cilk_for)
2401 {
2402 if (is_cilk_for)
2403 return clone_function_name (current_function_decl, "_cilk_for_fn");
2404 return clone_function_name (current_function_decl,
2405 task_copy ? "_omp_cpyfn" : "_omp_fn");
2406 }
2407
2408 /* Returns the type of the induction variable for the child function for
2409 _Cilk_for and the types for _high and _low variables based on TYPE. */
2410
2411 static tree
2412 cilk_for_check_loop_diff_type (tree type)
2413 {
2414 if (TYPE_PRECISION (type) <= TYPE_PRECISION (uint32_type_node))
2415 {
2416 if (TYPE_UNSIGNED (type))
2417 return uint32_type_node;
2418 else
2419 return integer_type_node;
2420 }
2421 else
2422 {
2423 if (TYPE_UNSIGNED (type))
2424 return uint64_type_node;
2425 else
2426 return long_long_integer_type_node;
2427 }
2428 }
2429
2430 /* Build a decl for the omp child function. It'll not contain a body
2431 yet, just the bare decl. */
2432
2433 static void
2434 create_omp_child_function (omp_context *ctx, bool task_copy)
2435 {
2436 tree decl, type, name, t;
2437
2438 tree cilk_for_count
2439 = (flag_cilkplus && gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2440 ? find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
2441 OMP_CLAUSE__CILK_FOR_COUNT_) : NULL_TREE;
2442 tree cilk_var_type = NULL_TREE;
2443
2444 name = create_omp_child_function_name (task_copy,
2445 cilk_for_count != NULL_TREE);
2446 if (task_copy)
2447 type = build_function_type_list (void_type_node, ptr_type_node,
2448 ptr_type_node, NULL_TREE);
2449 else if (cilk_for_count)
2450 {
2451 type = TREE_TYPE (OMP_CLAUSE_OPERAND (cilk_for_count, 0));
2452 cilk_var_type = cilk_for_check_loop_diff_type (type);
2453 type = build_function_type_list (void_type_node, ptr_type_node,
2454 cilk_var_type, cilk_var_type, NULL_TREE);
2455 }
2456 else
2457 type = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
2458
2459 decl = build_decl (gimple_location (ctx->stmt), FUNCTION_DECL, name, type);
2460
2461 gcc_checking_assert (!is_gimple_omp_oacc (ctx->stmt)
2462 || !task_copy);
2463 if (!task_copy)
2464 ctx->cb.dst_fn = decl;
2465 else
2466 gimple_omp_task_set_copy_fn (ctx->stmt, decl);
2467
2468 TREE_STATIC (decl) = 1;
2469 TREE_USED (decl) = 1;
2470 DECL_ARTIFICIAL (decl) = 1;
2471 DECL_IGNORED_P (decl) = 0;
2472 TREE_PUBLIC (decl) = 0;
2473 DECL_UNINLINABLE (decl) = 1;
2474 DECL_EXTERNAL (decl) = 0;
2475 DECL_CONTEXT (decl) = NULL_TREE;
2476 DECL_INITIAL (decl) = make_node (BLOCK);
2477 BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl;
2478 if (cgraph_node::get (current_function_decl)->offloadable)
2479 cgraph_node::get_create (decl)->offloadable = 1;
2480 else
2481 {
2482 omp_context *octx;
2483 for (octx = ctx; octx; octx = octx->outer)
2484 if (is_gimple_omp_offloaded (octx->stmt))
2485 {
2486 cgraph_node::get_create (decl)->offloadable = 1;
2487 if (ENABLE_OFFLOADING)
2488 g->have_offload = true;
2489
2490 break;
2491 }
2492 }
2493
2494 if (cgraph_node::get_create (decl)->offloadable
2495 && !lookup_attribute ("omp declare target",
2496 DECL_ATTRIBUTES (current_function_decl)))
2497 DECL_ATTRIBUTES (decl)
2498 = tree_cons (get_identifier ("omp target entrypoint"),
2499 NULL_TREE, DECL_ATTRIBUTES (decl));
2500
2501 t = build_decl (DECL_SOURCE_LOCATION (decl),
2502 RESULT_DECL, NULL_TREE, void_type_node);
2503 DECL_ARTIFICIAL (t) = 1;
2504 DECL_IGNORED_P (t) = 1;
2505 DECL_CONTEXT (t) = decl;
2506 DECL_RESULT (decl) = t;
2507
2508 /* _Cilk_for's child function requires two extra parameters called
2509 __low and __high that are set the by Cilk runtime when it calls this
2510 function. */
2511 if (cilk_for_count)
2512 {
2513 t = build_decl (DECL_SOURCE_LOCATION (decl),
2514 PARM_DECL, get_identifier ("__high"), cilk_var_type);
2515 DECL_ARTIFICIAL (t) = 1;
2516 DECL_NAMELESS (t) = 1;
2517 DECL_ARG_TYPE (t) = ptr_type_node;
2518 DECL_CONTEXT (t) = current_function_decl;
2519 TREE_USED (t) = 1;
2520 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2521 DECL_ARGUMENTS (decl) = t;
2522
2523 t = build_decl (DECL_SOURCE_LOCATION (decl),
2524 PARM_DECL, get_identifier ("__low"), cilk_var_type);
2525 DECL_ARTIFICIAL (t) = 1;
2526 DECL_NAMELESS (t) = 1;
2527 DECL_ARG_TYPE (t) = ptr_type_node;
2528 DECL_CONTEXT (t) = current_function_decl;
2529 TREE_USED (t) = 1;
2530 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2531 DECL_ARGUMENTS (decl) = t;
2532 }
2533
2534 tree data_name = get_identifier (".omp_data_i");
2535 t = build_decl (DECL_SOURCE_LOCATION (decl), PARM_DECL, data_name,
2536 ptr_type_node);
2537 DECL_ARTIFICIAL (t) = 1;
2538 DECL_NAMELESS (t) = 1;
2539 DECL_ARG_TYPE (t) = ptr_type_node;
2540 DECL_CONTEXT (t) = current_function_decl;
2541 TREE_USED (t) = 1;
2542 TREE_READONLY (t) = 1;
2543 if (cilk_for_count)
2544 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2545 DECL_ARGUMENTS (decl) = t;
2546 if (!task_copy)
2547 ctx->receiver_decl = t;
2548 else
2549 {
2550 t = build_decl (DECL_SOURCE_LOCATION (decl),
2551 PARM_DECL, get_identifier (".omp_data_o"),
2552 ptr_type_node);
2553 DECL_ARTIFICIAL (t) = 1;
2554 DECL_NAMELESS (t) = 1;
2555 DECL_ARG_TYPE (t) = ptr_type_node;
2556 DECL_CONTEXT (t) = current_function_decl;
2557 TREE_USED (t) = 1;
2558 TREE_ADDRESSABLE (t) = 1;
2559 DECL_CHAIN (t) = DECL_ARGUMENTS (decl);
2560 DECL_ARGUMENTS (decl) = t;
2561 }
2562
2563 /* Allocate memory for the function structure. The call to
2564 allocate_struct_function clobbers CFUN, so we need to restore
2565 it afterward. */
2566 push_struct_function (decl);
2567 cfun->function_end_locus = gimple_location (ctx->stmt);
2568 init_tree_ssa (cfun);
2569 pop_cfun ();
2570 }
2571
2572 /* Callback for walk_gimple_seq. Check if combined parallel
2573 contains gimple_omp_for_combined_into_p OMP_FOR. */
2574
2575 static tree
2576 find_combined_for (gimple_stmt_iterator *gsi_p,
2577 bool *handled_ops_p,
2578 struct walk_stmt_info *wi)
2579 {
2580 gimple *stmt = gsi_stmt (*gsi_p);
2581
2582 *handled_ops_p = true;
2583 switch (gimple_code (stmt))
2584 {
2585 WALK_SUBSTMTS;
2586
2587 case GIMPLE_OMP_FOR:
2588 if (gimple_omp_for_combined_into_p (stmt)
2589 && gimple_omp_for_kind (stmt)
2590 == *(const enum gf_mask *) (wi->info))
2591 {
2592 wi->info = stmt;
2593 return integer_zero_node;
2594 }
2595 break;
2596 default:
2597 break;
2598 }
2599 return NULL;
2600 }
2601
2602 /* Add _LOOPTEMP_ clauses on OpenMP parallel or task. */
2603
2604 static void
2605 add_taskreg_looptemp_clauses (enum gf_mask msk, gimple *stmt,
2606 omp_context *outer_ctx)
2607 {
2608 struct walk_stmt_info wi;
2609
2610 memset (&wi, 0, sizeof (wi));
2611 wi.val_only = true;
2612 wi.info = (void *) &msk;
2613 walk_gimple_seq (gimple_omp_body (stmt), find_combined_for, NULL, &wi);
2614 if (wi.info != (void *) &msk)
2615 {
2616 gomp_for *for_stmt = as_a <gomp_for *> ((gimple *) wi.info);
2617 struct omp_for_data fd;
2618 extract_omp_for_data (for_stmt, &fd, NULL);
2619 /* We need two temporaries with fd.loop.v type (istart/iend)
2620 and then (fd.collapse - 1) temporaries with the same
2621 type for count2 ... countN-1 vars if not constant. */
2622 size_t count = 2, i;
2623 tree type = fd.iter_type;
2624 if (fd.collapse > 1
2625 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
2626 {
2627 count += fd.collapse - 1;
2628 /* If there are lastprivate clauses on the inner
2629 GIMPLE_OMP_FOR, add one more temporaries for the total number
2630 of iterations (product of count1 ... countN-1). */
2631 if (find_omp_clause (gimple_omp_for_clauses (for_stmt),
2632 OMP_CLAUSE_LASTPRIVATE))
2633 count++;
2634 else if (msk == GF_OMP_FOR_KIND_FOR
2635 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2636 OMP_CLAUSE_LASTPRIVATE))
2637 count++;
2638 }
2639 for (i = 0; i < count; i++)
2640 {
2641 tree temp = create_tmp_var (type);
2642 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
2643 insert_decl_map (&outer_ctx->cb, temp, temp);
2644 OMP_CLAUSE_DECL (c) = temp;
2645 OMP_CLAUSE_CHAIN (c) = gimple_omp_taskreg_clauses (stmt);
2646 gimple_omp_taskreg_set_clauses (stmt, c);
2647 }
2648 }
2649 }
2650
2651 /* Scan an OpenMP parallel directive. */
2652
2653 static void
2654 scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2655 {
2656 omp_context *ctx;
2657 tree name;
2658 gomp_parallel *stmt = as_a <gomp_parallel *> (gsi_stmt (*gsi));
2659
2660 /* Ignore parallel directives with empty bodies, unless there
2661 are copyin clauses. */
2662 if (optimize > 0
2663 && empty_body_p (gimple_omp_body (stmt))
2664 && find_omp_clause (gimple_omp_parallel_clauses (stmt),
2665 OMP_CLAUSE_COPYIN) == NULL)
2666 {
2667 gsi_replace (gsi, gimple_build_nop (), false);
2668 return;
2669 }
2670
2671 if (gimple_omp_parallel_combined_p (stmt))
2672 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_FOR, stmt, outer_ctx);
2673
2674 ctx = new_omp_context (stmt, outer_ctx);
2675 taskreg_contexts.safe_push (ctx);
2676 if (taskreg_nesting_level > 1)
2677 ctx->is_nested = true;
2678 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2679 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2680 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2681 name = create_tmp_var_name (".omp_data_s");
2682 name = build_decl (gimple_location (stmt),
2683 TYPE_DECL, name, ctx->record_type);
2684 DECL_ARTIFICIAL (name) = 1;
2685 DECL_NAMELESS (name) = 1;
2686 TYPE_NAME (ctx->record_type) = name;
2687 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2688 if (!gimple_omp_parallel_grid_phony (stmt))
2689 {
2690 create_omp_child_function (ctx, false);
2691 gimple_omp_parallel_set_child_fn (stmt, ctx->cb.dst_fn);
2692 }
2693
2694 scan_sharing_clauses (gimple_omp_parallel_clauses (stmt), ctx);
2695 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2696
2697 if (TYPE_FIELDS (ctx->record_type) == NULL)
2698 ctx->record_type = ctx->receiver_decl = NULL;
2699 }
2700
2701 /* Scan an OpenMP task directive. */
2702
2703 static void
2704 scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx)
2705 {
2706 omp_context *ctx;
2707 tree name, t;
2708 gomp_task *stmt = as_a <gomp_task *> (gsi_stmt (*gsi));
2709
2710 /* Ignore task directives with empty bodies. */
2711 if (optimize > 0
2712 && empty_body_p (gimple_omp_body (stmt)))
2713 {
2714 gsi_replace (gsi, gimple_build_nop (), false);
2715 return;
2716 }
2717
2718 if (gimple_omp_task_taskloop_p (stmt))
2719 add_taskreg_looptemp_clauses (GF_OMP_FOR_KIND_TASKLOOP, stmt, outer_ctx);
2720
2721 ctx = new_omp_context (stmt, outer_ctx);
2722 taskreg_contexts.safe_push (ctx);
2723 if (taskreg_nesting_level > 1)
2724 ctx->is_nested = true;
2725 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
2726 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
2727 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
2728 name = create_tmp_var_name (".omp_data_s");
2729 name = build_decl (gimple_location (stmt),
2730 TYPE_DECL, name, ctx->record_type);
2731 DECL_ARTIFICIAL (name) = 1;
2732 DECL_NAMELESS (name) = 1;
2733 TYPE_NAME (ctx->record_type) = name;
2734 TYPE_ARTIFICIAL (ctx->record_type) = 1;
2735 create_omp_child_function (ctx, false);
2736 gimple_omp_task_set_child_fn (stmt, ctx->cb.dst_fn);
2737
2738 scan_sharing_clauses (gimple_omp_task_clauses (stmt), ctx);
2739
2740 if (ctx->srecord_type)
2741 {
2742 name = create_tmp_var_name (".omp_data_a");
2743 name = build_decl (gimple_location (stmt),
2744 TYPE_DECL, name, ctx->srecord_type);
2745 DECL_ARTIFICIAL (name) = 1;
2746 DECL_NAMELESS (name) = 1;
2747 TYPE_NAME (ctx->srecord_type) = name;
2748 TYPE_ARTIFICIAL (ctx->srecord_type) = 1;
2749 create_omp_child_function (ctx, true);
2750 }
2751
2752 scan_omp (gimple_omp_body_ptr (stmt), ctx);
2753
2754 if (TYPE_FIELDS (ctx->record_type) == NULL)
2755 {
2756 ctx->record_type = ctx->receiver_decl = NULL;
2757 t = build_int_cst (long_integer_type_node, 0);
2758 gimple_omp_task_set_arg_size (stmt, t);
2759 t = build_int_cst (long_integer_type_node, 1);
2760 gimple_omp_task_set_arg_align (stmt, t);
2761 }
2762 }
2763
2764
2765 /* If any decls have been made addressable during scan_omp,
2766 adjust their fields if needed, and layout record types
2767 of parallel/task constructs. */
2768
2769 static void
2770 finish_taskreg_scan (omp_context *ctx)
2771 {
2772 if (ctx->record_type == NULL_TREE)
2773 return;
2774
2775 /* If any task_shared_vars were needed, verify all
2776 OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK}
2777 statements if use_pointer_for_field hasn't changed
2778 because of that. If it did, update field types now. */
2779 if (task_shared_vars)
2780 {
2781 tree c;
2782
2783 for (c = gimple_omp_taskreg_clauses (ctx->stmt);
2784 c; c = OMP_CLAUSE_CHAIN (c))
2785 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
2786 && !OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
2787 {
2788 tree decl = OMP_CLAUSE_DECL (c);
2789
2790 /* Global variables don't need to be copied,
2791 the receiver side will use them directly. */
2792 if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)))
2793 continue;
2794 if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl))
2795 || !use_pointer_for_field (decl, ctx))
2796 continue;
2797 tree field = lookup_field (decl, ctx);
2798 if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
2799 && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl))
2800 continue;
2801 TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl));
2802 TREE_THIS_VOLATILE (field) = 0;
2803 DECL_USER_ALIGN (field) = 0;
2804 SET_DECL_ALIGN (field, TYPE_ALIGN (TREE_TYPE (field)));
2805 if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field))
2806 SET_TYPE_ALIGN (ctx->record_type, DECL_ALIGN (field));
2807 if (ctx->srecord_type)
2808 {
2809 tree sfield = lookup_sfield (decl, ctx);
2810 TREE_TYPE (sfield) = TREE_TYPE (field);
2811 TREE_THIS_VOLATILE (sfield) = 0;
2812 DECL_USER_ALIGN (sfield) = 0;
2813 SET_DECL_ALIGN (sfield, DECL_ALIGN (field));
2814 if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield))
2815 SET_TYPE_ALIGN (ctx->srecord_type, DECL_ALIGN (sfield));
2816 }
2817 }
2818 }
2819
2820 if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL)
2821 {
2822 layout_type (ctx->record_type);
2823 fixup_child_record_type (ctx);
2824 }
2825 else
2826 {
2827 location_t loc = gimple_location (ctx->stmt);
2828 tree *p, vla_fields = NULL_TREE, *q = &vla_fields;
2829 /* Move VLA fields to the end. */
2830 p = &TYPE_FIELDS (ctx->record_type);
2831 while (*p)
2832 if (!TYPE_SIZE_UNIT (TREE_TYPE (*p))
2833 || ! TREE_CONSTANT (TYPE_SIZE_UNIT (TREE_TYPE (*p))))
2834 {
2835 *q = *p;
2836 *p = TREE_CHAIN (*p);
2837 TREE_CHAIN (*q) = NULL_TREE;
2838 q = &TREE_CHAIN (*q);
2839 }
2840 else
2841 p = &DECL_CHAIN (*p);
2842 *p = vla_fields;
2843 if (gimple_omp_task_taskloop_p (ctx->stmt))
2844 {
2845 /* Move fields corresponding to first and second _looptemp_
2846 clause first. There are filled by GOMP_taskloop
2847 and thus need to be in specific positions. */
2848 tree c1 = gimple_omp_task_clauses (ctx->stmt);
2849 c1 = find_omp_clause (c1, OMP_CLAUSE__LOOPTEMP_);
2850 tree c2 = find_omp_clause (OMP_CLAUSE_CHAIN (c1),
2851 OMP_CLAUSE__LOOPTEMP_);
2852 tree f1 = lookup_field (OMP_CLAUSE_DECL (c1), ctx);
2853 tree f2 = lookup_field (OMP_CLAUSE_DECL (c2), ctx);
2854 p = &TYPE_FIELDS (ctx->record_type);
2855 while (*p)
2856 if (*p == f1 || *p == f2)
2857 *p = DECL_CHAIN (*p);
2858 else
2859 p = &DECL_CHAIN (*p);
2860 DECL_CHAIN (f1) = f2;
2861 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->record_type);
2862 TYPE_FIELDS (ctx->record_type) = f1;
2863 if (ctx->srecord_type)
2864 {
2865 f1 = lookup_sfield (OMP_CLAUSE_DECL (c1), ctx);
2866 f2 = lookup_sfield (OMP_CLAUSE_DECL (c2), ctx);
2867 p = &TYPE_FIELDS (ctx->srecord_type);
2868 while (*p)
2869 if (*p == f1 || *p == f2)
2870 *p = DECL_CHAIN (*p);
2871 else
2872 p = &DECL_CHAIN (*p);
2873 DECL_CHAIN (f1) = f2;
2874 DECL_CHAIN (f2) = TYPE_FIELDS (ctx->srecord_type);
2875 TYPE_FIELDS (ctx->srecord_type) = f1;
2876 }
2877 }
2878 layout_type (ctx->record_type);
2879 fixup_child_record_type (ctx);
2880 if (ctx->srecord_type)
2881 layout_type (ctx->srecord_type);
2882 tree t = fold_convert_loc (loc, long_integer_type_node,
2883 TYPE_SIZE_UNIT (ctx->record_type));
2884 gimple_omp_task_set_arg_size (ctx->stmt, t);
2885 t = build_int_cst (long_integer_type_node,
2886 TYPE_ALIGN_UNIT (ctx->record_type));
2887 gimple_omp_task_set_arg_align (ctx->stmt, t);
2888 }
2889 }
2890
2891 /* Find the enclosing offload context. */
2892
2893 static omp_context *
2894 enclosing_target_ctx (omp_context *ctx)
2895 {
2896 for (; ctx; ctx = ctx->outer)
2897 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TARGET)
2898 break;
2899
2900 return ctx;
2901 }
2902
2903 /* Return true if ctx is part of an oacc kernels region. */
2904
2905 static bool
2906 ctx_in_oacc_kernels_region (omp_context *ctx)
2907 {
2908 for (;ctx != NULL; ctx = ctx->outer)
2909 {
2910 gimple *stmt = ctx->stmt;
2911 if (gimple_code (stmt) == GIMPLE_OMP_TARGET
2912 && gimple_omp_target_kind (stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
2913 return true;
2914 }
2915
2916 return false;
2917 }
2918
2919 /* Check the parallelism clauses inside a kernels regions.
2920 Until kernels handling moves to use the same loop indirection
2921 scheme as parallel, we need to do this checking early. */
2922
2923 static unsigned
2924 check_oacc_kernel_gwv (gomp_for *stmt, omp_context *ctx)
2925 {
2926 bool checking = true;
2927 unsigned outer_mask = 0;
2928 unsigned this_mask = 0;
2929 bool has_seq = false, has_auto = false;
2930
2931 if (ctx->outer)
2932 outer_mask = check_oacc_kernel_gwv (NULL, ctx->outer);
2933 if (!stmt)
2934 {
2935 checking = false;
2936 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR)
2937 return outer_mask;
2938 stmt = as_a <gomp_for *> (ctx->stmt);
2939 }
2940
2941 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
2942 {
2943 switch (OMP_CLAUSE_CODE (c))
2944 {
2945 case OMP_CLAUSE_GANG:
2946 this_mask |= GOMP_DIM_MASK (GOMP_DIM_GANG);
2947 break;
2948 case OMP_CLAUSE_WORKER:
2949 this_mask |= GOMP_DIM_MASK (GOMP_DIM_WORKER);
2950 break;
2951 case OMP_CLAUSE_VECTOR:
2952 this_mask |= GOMP_DIM_MASK (GOMP_DIM_VECTOR);
2953 break;
2954 case OMP_CLAUSE_SEQ:
2955 has_seq = true;
2956 break;
2957 case OMP_CLAUSE_AUTO:
2958 has_auto = true;
2959 break;
2960 default:
2961 break;
2962 }
2963 }
2964
2965 if (checking)
2966 {
2967 if (has_seq && (this_mask || has_auto))
2968 error_at (gimple_location (stmt), "%<seq%> overrides other"
2969 " OpenACC loop specifiers");
2970 else if (has_auto && this_mask)
2971 error_at (gimple_location (stmt), "%<auto%> conflicts with other"
2972 " OpenACC loop specifiers");
2973
2974 if (this_mask & outer_mask)
2975 error_at (gimple_location (stmt), "inner loop uses same"
2976 " OpenACC parallelism as containing loop");
2977 }
2978
2979 return outer_mask | this_mask;
2980 }
2981
2982 /* Scan a GIMPLE_OMP_FOR. */
2983
2984 static void
2985 scan_omp_for (gomp_for *stmt, omp_context *outer_ctx)
2986 {
2987 omp_context *ctx;
2988 size_t i;
2989 tree clauses = gimple_omp_for_clauses (stmt);
2990
2991 ctx = new_omp_context (stmt, outer_ctx);
2992
2993 if (is_gimple_omp_oacc (stmt))
2994 {
2995 omp_context *tgt = enclosing_target_ctx (outer_ctx);
2996
2997 if (!tgt || is_oacc_parallel (tgt))
2998 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
2999 {
3000 char const *check = NULL;
3001
3002 switch (OMP_CLAUSE_CODE (c))
3003 {
3004 case OMP_CLAUSE_GANG:
3005 check = "gang";
3006 break;
3007
3008 case OMP_CLAUSE_WORKER:
3009 check = "worker";
3010 break;
3011
3012 case OMP_CLAUSE_VECTOR:
3013 check = "vector";
3014 break;
3015
3016 default:
3017 break;
3018 }
3019
3020 if (check && OMP_CLAUSE_OPERAND (c, 0))
3021 error_at (gimple_location (stmt),
3022 "argument not permitted on %qs clause in"
3023 " OpenACC %<parallel%>", check);
3024 }
3025
3026 if (tgt && is_oacc_kernels (tgt))
3027 {
3028 /* Strip out reductions, as they are not handled yet. */
3029 tree *prev_ptr = &clauses;
3030
3031 while (tree probe = *prev_ptr)
3032 {
3033 tree *next_ptr = &OMP_CLAUSE_CHAIN (probe);
3034
3035 if (OMP_CLAUSE_CODE (probe) == OMP_CLAUSE_REDUCTION)
3036 *prev_ptr = *next_ptr;
3037 else
3038 prev_ptr = next_ptr;
3039 }
3040
3041 gimple_omp_for_set_clauses (stmt, clauses);
3042 check_oacc_kernel_gwv (stmt, ctx);
3043 }
3044 }
3045
3046 scan_sharing_clauses (clauses, ctx);
3047
3048 scan_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
3049 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
3050 {
3051 scan_omp_op (gimple_omp_for_index_ptr (stmt, i), ctx);
3052 scan_omp_op (gimple_omp_for_initial_ptr (stmt, i), ctx);
3053 scan_omp_op (gimple_omp_for_final_ptr (stmt, i), ctx);
3054 scan_omp_op (gimple_omp_for_incr_ptr (stmt, i), ctx);
3055 }
3056 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3057 }
3058
3059 /* Scan an OpenMP sections directive. */
3060
3061 static void
3062 scan_omp_sections (gomp_sections *stmt, omp_context *outer_ctx)
3063 {
3064 omp_context *ctx;
3065
3066 ctx = new_omp_context (stmt, outer_ctx);
3067 scan_sharing_clauses (gimple_omp_sections_clauses (stmt), ctx);
3068 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3069 }
3070
3071 /* Scan an OpenMP single directive. */
3072
3073 static void
3074 scan_omp_single (gomp_single *stmt, omp_context *outer_ctx)
3075 {
3076 omp_context *ctx;
3077 tree name;
3078
3079 ctx = new_omp_context (stmt, outer_ctx);
3080 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3081 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3082 name = create_tmp_var_name (".omp_copy_s");
3083 name = build_decl (gimple_location (stmt),
3084 TYPE_DECL, name, ctx->record_type);
3085 TYPE_NAME (ctx->record_type) = name;
3086
3087 scan_sharing_clauses (gimple_omp_single_clauses (stmt), ctx);
3088 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3089
3090 if (TYPE_FIELDS (ctx->record_type) == NULL)
3091 ctx->record_type = NULL;
3092 else
3093 layout_type (ctx->record_type);
3094 }
3095
3096 /* Return true if the CLAUSES of an omp target guarantee that the base pointers
3097 used in the corresponding offloaded function are restrict. */
3098
3099 static bool
3100 omp_target_base_pointers_restrict_p (tree clauses)
3101 {
3102 /* The analysis relies on the GOMP_MAP_FORCE_* mapping kinds, which are only
3103 used by OpenACC. */
3104 if (flag_openacc == 0)
3105 return false;
3106
3107 /* I. Basic example:
3108
3109 void foo (void)
3110 {
3111 unsigned int a[2], b[2];
3112
3113 #pragma acc kernels \
3114 copyout (a) \
3115 copyout (b)
3116 {
3117 a[0] = 0;
3118 b[0] = 1;
3119 }
3120 }
3121
3122 After gimplification, we have:
3123
3124 #pragma omp target oacc_kernels \
3125 map(force_from:a [len: 8]) \
3126 map(force_from:b [len: 8])
3127 {
3128 a[0] = 0;
3129 b[0] = 1;
3130 }
3131
3132 Because both mappings have the force prefix, we know that they will be
3133 allocated when calling the corresponding offloaded function, which means we
3134 can mark the base pointers for a and b in the offloaded function as
3135 restrict. */
3136
3137 tree c;
3138 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
3139 {
3140 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
3141 return false;
3142
3143 switch (OMP_CLAUSE_MAP_KIND (c))
3144 {
3145 case GOMP_MAP_FORCE_ALLOC:
3146 case GOMP_MAP_FORCE_TO:
3147 case GOMP_MAP_FORCE_FROM:
3148 case GOMP_MAP_FORCE_TOFROM:
3149 break;
3150 default:
3151 return false;
3152 }
3153 }
3154
3155 return true;
3156 }
3157
3158 /* Scan a GIMPLE_OMP_TARGET. */
3159
3160 static void
3161 scan_omp_target (gomp_target *stmt, omp_context *outer_ctx)
3162 {
3163 omp_context *ctx;
3164 tree name;
3165 bool offloaded = is_gimple_omp_offloaded (stmt);
3166 tree clauses = gimple_omp_target_clauses (stmt);
3167
3168 ctx = new_omp_context (stmt, outer_ctx);
3169 ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0);
3170 ctx->default_kind = OMP_CLAUSE_DEFAULT_SHARED;
3171 ctx->record_type = lang_hooks.types.make_type (RECORD_TYPE);
3172 name = create_tmp_var_name (".omp_data_t");
3173 name = build_decl (gimple_location (stmt),
3174 TYPE_DECL, name, ctx->record_type);
3175 DECL_ARTIFICIAL (name) = 1;
3176 DECL_NAMELESS (name) = 1;
3177 TYPE_NAME (ctx->record_type) = name;
3178 TYPE_ARTIFICIAL (ctx->record_type) = 1;
3179
3180 bool base_pointers_restrict = false;
3181 if (offloaded)
3182 {
3183 create_omp_child_function (ctx, false);
3184 gimple_omp_target_set_child_fn (stmt, ctx->cb.dst_fn);
3185
3186 base_pointers_restrict = omp_target_base_pointers_restrict_p (clauses);
3187 if (base_pointers_restrict
3188 && dump_file && (dump_flags & TDF_DETAILS))
3189 fprintf (dump_file,
3190 "Base pointers in offloaded function are restrict\n");
3191 }
3192
3193 scan_sharing_clauses (clauses, ctx, base_pointers_restrict);
3194 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3195
3196 if (TYPE_FIELDS (ctx->record_type) == NULL)
3197 ctx->record_type = ctx->receiver_decl = NULL;
3198 else
3199 {
3200 TYPE_FIELDS (ctx->record_type)
3201 = nreverse (TYPE_FIELDS (ctx->record_type));
3202 if (flag_checking)
3203 {
3204 unsigned int align = DECL_ALIGN (TYPE_FIELDS (ctx->record_type));
3205 for (tree field = TYPE_FIELDS (ctx->record_type);
3206 field;
3207 field = DECL_CHAIN (field))
3208 gcc_assert (DECL_ALIGN (field) == align);
3209 }
3210 layout_type (ctx->record_type);
3211 if (offloaded)
3212 fixup_child_record_type (ctx);
3213 }
3214 }
3215
3216 /* Scan an OpenMP teams directive. */
3217
3218 static void
3219 scan_omp_teams (gomp_teams *stmt, omp_context *outer_ctx)
3220 {
3221 omp_context *ctx = new_omp_context (stmt, outer_ctx);
3222 scan_sharing_clauses (gimple_omp_teams_clauses (stmt), ctx);
3223 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3224 }
3225
3226 /* Check nesting restrictions. */
3227 static bool
3228 check_omp_nesting_restrictions (gimple *stmt, omp_context *ctx)
3229 {
3230 tree c;
3231
3232 if (ctx && gimple_code (ctx->stmt) == GIMPLE_OMP_GRID_BODY)
3233 /* GRID_BODY is an artificial construct, nesting rules will be checked in
3234 the original copy of its contents. */
3235 return true;
3236
3237 /* No nesting of non-OpenACC STMT (that is, an OpenMP one, or a GOMP builtin)
3238 inside an OpenACC CTX. */
3239 if (!(is_gimple_omp (stmt)
3240 && is_gimple_omp_oacc (stmt))
3241 /* Except for atomic codes that we share with OpenMP. */
3242 && !(gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD
3243 || gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE))
3244 {
3245 if (get_oacc_fn_attrib (cfun->decl) != NULL)
3246 {
3247 error_at (gimple_location (stmt),
3248 "non-OpenACC construct inside of OpenACC routine");
3249 return false;
3250 }
3251 else
3252 for (omp_context *octx = ctx; octx != NULL; octx = octx->outer)
3253 if (is_gimple_omp (octx->stmt)
3254 && is_gimple_omp_oacc (octx->stmt))
3255 {
3256 error_at (gimple_location (stmt),
3257 "non-OpenACC construct inside of OpenACC region");
3258 return false;
3259 }
3260 }
3261
3262 if (ctx != NULL)
3263 {
3264 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3265 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3266 {
3267 c = NULL_TREE;
3268 if (gimple_code (stmt) == GIMPLE_OMP_ORDERED)
3269 {
3270 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3271 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3272 {
3273 if (find_omp_clause (c, OMP_CLAUSE_THREADS)
3274 && (ctx->outer == NULL
3275 || !gimple_omp_for_combined_into_p (ctx->stmt)
3276 || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR
3277 || (gimple_omp_for_kind (ctx->outer->stmt)
3278 != GF_OMP_FOR_KIND_FOR)
3279 || !gimple_omp_for_combined_p (ctx->outer->stmt)))
3280 {
3281 error_at (gimple_location (stmt),
3282 "%<ordered simd threads%> must be closely "
3283 "nested inside of %<for simd%> region");
3284 return false;
3285 }
3286 return true;
3287 }
3288 }
3289 error_at (gimple_location (stmt),
3290 "OpenMP constructs other than %<#pragma omp ordered simd%>"
3291 " may not be nested inside %<simd%> region");
3292 return false;
3293 }
3294 else if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
3295 {
3296 if ((gimple_code (stmt) != GIMPLE_OMP_FOR
3297 || (gimple_omp_for_kind (stmt)
3298 != GF_OMP_FOR_KIND_DISTRIBUTE))
3299 && gimple_code (stmt) != GIMPLE_OMP_PARALLEL)
3300 {
3301 error_at (gimple_location (stmt),
3302 "only %<distribute%> or %<parallel%> regions are "
3303 "allowed to be strictly nested inside %<teams%> "
3304 "region");
3305 return false;
3306 }
3307 }
3308 }
3309 switch (gimple_code (stmt))
3310 {
3311 case GIMPLE_OMP_FOR:
3312 if (gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
3313 return true;
3314 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
3315 {
3316 if (ctx != NULL && gimple_code (ctx->stmt) != GIMPLE_OMP_TEAMS)
3317 {
3318 error_at (gimple_location (stmt),
3319 "%<distribute%> region must be strictly nested "
3320 "inside %<teams%> construct");
3321 return false;
3322 }
3323 return true;
3324 }
3325 /* We split taskloop into task and nested taskloop in it. */
3326 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3327 return true;
3328 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
3329 {
3330 bool ok = false;
3331
3332 if (ctx)
3333 switch (gimple_code (ctx->stmt))
3334 {
3335 case GIMPLE_OMP_FOR:
3336 ok = (gimple_omp_for_kind (ctx->stmt)
3337 == GF_OMP_FOR_KIND_OACC_LOOP);
3338 break;
3339
3340 case GIMPLE_OMP_TARGET:
3341 switch (gimple_omp_target_kind (ctx->stmt))
3342 {
3343 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3344 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3345 ok = true;
3346 break;
3347
3348 default:
3349 break;
3350 }
3351
3352 default:
3353 break;
3354 }
3355 else if (get_oacc_fn_attrib (current_function_decl))
3356 ok = true;
3357 if (!ok)
3358 {
3359 error_at (gimple_location (stmt),
3360 "OpenACC loop directive must be associated with"
3361 " an OpenACC compute region");
3362 return false;
3363 }
3364 }
3365 /* FALLTHRU */
3366 case GIMPLE_CALL:
3367 if (is_gimple_call (stmt)
3368 && (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3369 == BUILT_IN_GOMP_CANCEL
3370 || DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3371 == BUILT_IN_GOMP_CANCELLATION_POINT))
3372 {
3373 const char *bad = NULL;
3374 const char *kind = NULL;
3375 const char *construct
3376 = (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3377 == BUILT_IN_GOMP_CANCEL)
3378 ? "#pragma omp cancel"
3379 : "#pragma omp cancellation point";
3380 if (ctx == NULL)
3381 {
3382 error_at (gimple_location (stmt), "orphaned %qs construct",
3383 construct);
3384 return false;
3385 }
3386 switch (tree_fits_shwi_p (gimple_call_arg (stmt, 0))
3387 ? tree_to_shwi (gimple_call_arg (stmt, 0))
3388 : 0)
3389 {
3390 case 1:
3391 if (gimple_code (ctx->stmt) != GIMPLE_OMP_PARALLEL)
3392 bad = "#pragma omp parallel";
3393 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3394 == BUILT_IN_GOMP_CANCEL
3395 && !integer_zerop (gimple_call_arg (stmt, 1)))
3396 ctx->cancellable = true;
3397 kind = "parallel";
3398 break;
3399 case 2:
3400 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3401 || gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR)
3402 bad = "#pragma omp for";
3403 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3404 == BUILT_IN_GOMP_CANCEL
3405 && !integer_zerop (gimple_call_arg (stmt, 1)))
3406 {
3407 ctx->cancellable = true;
3408 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3409 OMP_CLAUSE_NOWAIT))
3410 warning_at (gimple_location (stmt), 0,
3411 "%<#pragma omp cancel for%> inside "
3412 "%<nowait%> for construct");
3413 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3414 OMP_CLAUSE_ORDERED))
3415 warning_at (gimple_location (stmt), 0,
3416 "%<#pragma omp cancel for%> inside "
3417 "%<ordered%> for construct");
3418 }
3419 kind = "for";
3420 break;
3421 case 4:
3422 if (gimple_code (ctx->stmt) != GIMPLE_OMP_SECTIONS
3423 && gimple_code (ctx->stmt) != GIMPLE_OMP_SECTION)
3424 bad = "#pragma omp sections";
3425 else if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3426 == BUILT_IN_GOMP_CANCEL
3427 && !integer_zerop (gimple_call_arg (stmt, 1)))
3428 {
3429 if (gimple_code (ctx->stmt) == GIMPLE_OMP_SECTIONS)
3430 {
3431 ctx->cancellable = true;
3432 if (find_omp_clause (gimple_omp_sections_clauses
3433 (ctx->stmt),
3434 OMP_CLAUSE_NOWAIT))
3435 warning_at (gimple_location (stmt), 0,
3436 "%<#pragma omp cancel sections%> inside "
3437 "%<nowait%> sections construct");
3438 }
3439 else
3440 {
3441 gcc_assert (ctx->outer
3442 && gimple_code (ctx->outer->stmt)
3443 == GIMPLE_OMP_SECTIONS);
3444 ctx->outer->cancellable = true;
3445 if (find_omp_clause (gimple_omp_sections_clauses
3446 (ctx->outer->stmt),
3447 OMP_CLAUSE_NOWAIT))
3448 warning_at (gimple_location (stmt), 0,
3449 "%<#pragma omp cancel sections%> inside "
3450 "%<nowait%> sections construct");
3451 }
3452 }
3453 kind = "sections";
3454 break;
3455 case 8:
3456 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TASK)
3457 bad = "#pragma omp task";
3458 else
3459 {
3460 for (omp_context *octx = ctx->outer;
3461 octx; octx = octx->outer)
3462 {
3463 switch (gimple_code (octx->stmt))
3464 {
3465 case GIMPLE_OMP_TASKGROUP:
3466 break;
3467 case GIMPLE_OMP_TARGET:
3468 if (gimple_omp_target_kind (octx->stmt)
3469 != GF_OMP_TARGET_KIND_REGION)
3470 continue;
3471 /* FALLTHRU */
3472 case GIMPLE_OMP_PARALLEL:
3473 case GIMPLE_OMP_TEAMS:
3474 error_at (gimple_location (stmt),
3475 "%<%s taskgroup%> construct not closely "
3476 "nested inside of %<taskgroup%> region",
3477 construct);
3478 return false;
3479 default:
3480 continue;
3481 }
3482 break;
3483 }
3484 ctx->cancellable = true;
3485 }
3486 kind = "taskgroup";
3487 break;
3488 default:
3489 error_at (gimple_location (stmt), "invalid arguments");
3490 return false;
3491 }
3492 if (bad)
3493 {
3494 error_at (gimple_location (stmt),
3495 "%<%s %s%> construct not closely nested inside of %qs",
3496 construct, kind, bad);
3497 return false;
3498 }
3499 }
3500 /* FALLTHRU */
3501 case GIMPLE_OMP_SECTIONS:
3502 case GIMPLE_OMP_SINGLE:
3503 for (; ctx != NULL; ctx = ctx->outer)
3504 switch (gimple_code (ctx->stmt))
3505 {
3506 case GIMPLE_OMP_FOR:
3507 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3508 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3509 break;
3510 /* FALLTHRU */
3511 case GIMPLE_OMP_SECTIONS:
3512 case GIMPLE_OMP_SINGLE:
3513 case GIMPLE_OMP_ORDERED:
3514 case GIMPLE_OMP_MASTER:
3515 case GIMPLE_OMP_TASK:
3516 case GIMPLE_OMP_CRITICAL:
3517 if (is_gimple_call (stmt))
3518 {
3519 if (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt))
3520 != BUILT_IN_GOMP_BARRIER)
3521 return true;
3522 error_at (gimple_location (stmt),
3523 "barrier region may not be closely nested inside "
3524 "of work-sharing, %<critical%>, %<ordered%>, "
3525 "%<master%>, explicit %<task%> or %<taskloop%> "
3526 "region");
3527 return false;
3528 }
3529 error_at (gimple_location (stmt),
3530 "work-sharing region may not be closely nested inside "
3531 "of work-sharing, %<critical%>, %<ordered%>, "
3532 "%<master%>, explicit %<task%> or %<taskloop%> region");
3533 return false;
3534 case GIMPLE_OMP_PARALLEL:
3535 case GIMPLE_OMP_TEAMS:
3536 return true;
3537 case GIMPLE_OMP_TARGET:
3538 if (gimple_omp_target_kind (ctx->stmt)
3539 == GF_OMP_TARGET_KIND_REGION)
3540 return true;
3541 break;
3542 default:
3543 break;
3544 }
3545 break;
3546 case GIMPLE_OMP_MASTER:
3547 for (; ctx != NULL; ctx = ctx->outer)
3548 switch (gimple_code (ctx->stmt))
3549 {
3550 case GIMPLE_OMP_FOR:
3551 if (gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_FOR
3552 && gimple_omp_for_kind (ctx->stmt) != GF_OMP_FOR_KIND_TASKLOOP)
3553 break;
3554 /* FALLTHRU */
3555 case GIMPLE_OMP_SECTIONS:
3556 case GIMPLE_OMP_SINGLE:
3557 case GIMPLE_OMP_TASK:
3558 error_at (gimple_location (stmt),
3559 "%<master%> region may not be closely nested inside "
3560 "of work-sharing, explicit %<task%> or %<taskloop%> "
3561 "region");
3562 return false;
3563 case GIMPLE_OMP_PARALLEL:
3564 case GIMPLE_OMP_TEAMS:
3565 return true;
3566 case GIMPLE_OMP_TARGET:
3567 if (gimple_omp_target_kind (ctx->stmt)
3568 == GF_OMP_TARGET_KIND_REGION)
3569 return true;
3570 break;
3571 default:
3572 break;
3573 }
3574 break;
3575 case GIMPLE_OMP_TASK:
3576 for (c = gimple_omp_task_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3577 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3578 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3579 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3580 {
3581 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3582 error_at (OMP_CLAUSE_LOCATION (c),
3583 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3584 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3585 return false;
3586 }
3587 break;
3588 case GIMPLE_OMP_ORDERED:
3589 for (c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3590 c; c = OMP_CLAUSE_CHAIN (c))
3591 {
3592 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
3593 {
3594 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREADS
3595 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SIMD);
3596 continue;
3597 }
3598 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3599 if (kind == OMP_CLAUSE_DEPEND_SOURCE
3600 || kind == OMP_CLAUSE_DEPEND_SINK)
3601 {
3602 tree oclause;
3603 /* Look for containing ordered(N) loop. */
3604 if (ctx == NULL
3605 || gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
3606 || (oclause
3607 = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3608 OMP_CLAUSE_ORDERED)) == NULL_TREE)
3609 {
3610 error_at (OMP_CLAUSE_LOCATION (c),
3611 "%<ordered%> construct with %<depend%> clause "
3612 "must be closely nested inside an %<ordered%> "
3613 "loop");
3614 return false;
3615 }
3616 else if (OMP_CLAUSE_ORDERED_EXPR (oclause) == NULL_TREE)
3617 {
3618 error_at (OMP_CLAUSE_LOCATION (c),
3619 "%<ordered%> construct with %<depend%> clause "
3620 "must be closely nested inside a loop with "
3621 "%<ordered%> clause with a parameter");
3622 return false;
3623 }
3624 }
3625 else
3626 {
3627 error_at (OMP_CLAUSE_LOCATION (c),
3628 "invalid depend kind in omp %<ordered%> %<depend%>");
3629 return false;
3630 }
3631 }
3632 c = gimple_omp_ordered_clauses (as_a <gomp_ordered *> (stmt));
3633 if (find_omp_clause (c, OMP_CLAUSE_SIMD))
3634 {
3635 /* ordered simd must be closely nested inside of simd region,
3636 and simd region must not encounter constructs other than
3637 ordered simd, therefore ordered simd may be either orphaned,
3638 or ctx->stmt must be simd. The latter case is handled already
3639 earlier. */
3640 if (ctx != NULL)
3641 {
3642 error_at (gimple_location (stmt),
3643 "%<ordered%> %<simd%> must be closely nested inside "
3644 "%<simd%> region");
3645 return false;
3646 }
3647 }
3648 for (; ctx != NULL; ctx = ctx->outer)
3649 switch (gimple_code (ctx->stmt))
3650 {
3651 case GIMPLE_OMP_CRITICAL:
3652 case GIMPLE_OMP_TASK:
3653 case GIMPLE_OMP_ORDERED:
3654 ordered_in_taskloop:
3655 error_at (gimple_location (stmt),
3656 "%<ordered%> region may not be closely nested inside "
3657 "of %<critical%>, %<ordered%>, explicit %<task%> or "
3658 "%<taskloop%> region");
3659 return false;
3660 case GIMPLE_OMP_FOR:
3661 if (gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_TASKLOOP)
3662 goto ordered_in_taskloop;
3663 if (find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
3664 OMP_CLAUSE_ORDERED) == NULL)
3665 {
3666 error_at (gimple_location (stmt),
3667 "%<ordered%> region must be closely nested inside "
3668 "a loop region with an %<ordered%> clause");
3669 return false;
3670 }
3671 return true;
3672 case GIMPLE_OMP_TARGET:
3673 if (gimple_omp_target_kind (ctx->stmt)
3674 != GF_OMP_TARGET_KIND_REGION)
3675 break;
3676 /* FALLTHRU */
3677 case GIMPLE_OMP_PARALLEL:
3678 case GIMPLE_OMP_TEAMS:
3679 error_at (gimple_location (stmt),
3680 "%<ordered%> region must be closely nested inside "
3681 "a loop region with an %<ordered%> clause");
3682 return false;
3683 default:
3684 break;
3685 }
3686 break;
3687 case GIMPLE_OMP_CRITICAL:
3688 {
3689 tree this_stmt_name
3690 = gimple_omp_critical_name (as_a <gomp_critical *> (stmt));
3691 for (; ctx != NULL; ctx = ctx->outer)
3692 if (gomp_critical *other_crit
3693 = dyn_cast <gomp_critical *> (ctx->stmt))
3694 if (this_stmt_name == gimple_omp_critical_name (other_crit))
3695 {
3696 error_at (gimple_location (stmt),
3697 "%<critical%> region may not be nested inside "
3698 "a %<critical%> region with the same name");
3699 return false;
3700 }
3701 }
3702 break;
3703 case GIMPLE_OMP_TEAMS:
3704 if (ctx == NULL
3705 || gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET
3706 || gimple_omp_target_kind (ctx->stmt) != GF_OMP_TARGET_KIND_REGION)
3707 {
3708 error_at (gimple_location (stmt),
3709 "%<teams%> construct not closely nested inside of "
3710 "%<target%> construct");
3711 return false;
3712 }
3713 break;
3714 case GIMPLE_OMP_TARGET:
3715 for (c = gimple_omp_target_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
3716 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
3717 && (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE
3718 || OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK))
3719 {
3720 enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_KIND (c);
3721 error_at (OMP_CLAUSE_LOCATION (c),
3722 "%<depend(%s)%> is only allowed in %<omp ordered%>",
3723 kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
3724 return false;
3725 }
3726 if (is_gimple_omp_offloaded (stmt)
3727 && get_oacc_fn_attrib (cfun->decl) != NULL)
3728 {
3729 error_at (gimple_location (stmt),
3730 "OpenACC region inside of OpenACC routine, nested "
3731 "parallelism not supported yet");
3732 return false;
3733 }
3734 for (; ctx != NULL; ctx = ctx->outer)
3735 {
3736 if (gimple_code (ctx->stmt) != GIMPLE_OMP_TARGET)
3737 {
3738 if (is_gimple_omp (stmt)
3739 && is_gimple_omp_oacc (stmt)
3740 && is_gimple_omp (ctx->stmt))
3741 {
3742 error_at (gimple_location (stmt),
3743 "OpenACC construct inside of non-OpenACC region");
3744 return false;
3745 }
3746 continue;
3747 }
3748
3749 const char *stmt_name, *ctx_stmt_name;
3750 switch (gimple_omp_target_kind (stmt))
3751 {
3752 case GF_OMP_TARGET_KIND_REGION: stmt_name = "target"; break;
3753 case GF_OMP_TARGET_KIND_DATA: stmt_name = "target data"; break;
3754 case GF_OMP_TARGET_KIND_UPDATE: stmt_name = "target update"; break;
3755 case GF_OMP_TARGET_KIND_ENTER_DATA:
3756 stmt_name = "target enter data"; break;
3757 case GF_OMP_TARGET_KIND_EXIT_DATA:
3758 stmt_name = "target exit data"; break;
3759 case GF_OMP_TARGET_KIND_OACC_PARALLEL: stmt_name = "parallel"; break;
3760 case GF_OMP_TARGET_KIND_OACC_KERNELS: stmt_name = "kernels"; break;
3761 case GF_OMP_TARGET_KIND_OACC_DATA: stmt_name = "data"; break;
3762 case GF_OMP_TARGET_KIND_OACC_UPDATE: stmt_name = "update"; break;
3763 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
3764 stmt_name = "enter/exit data"; break;
3765 case GF_OMP_TARGET_KIND_OACC_HOST_DATA: stmt_name = "host_data";
3766 break;
3767 default: gcc_unreachable ();
3768 }
3769 switch (gimple_omp_target_kind (ctx->stmt))
3770 {
3771 case GF_OMP_TARGET_KIND_REGION: ctx_stmt_name = "target"; break;
3772 case GF_OMP_TARGET_KIND_DATA: ctx_stmt_name = "target data"; break;
3773 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
3774 ctx_stmt_name = "parallel"; break;
3775 case GF_OMP_TARGET_KIND_OACC_KERNELS:
3776 ctx_stmt_name = "kernels"; break;
3777 case GF_OMP_TARGET_KIND_OACC_DATA: ctx_stmt_name = "data"; break;
3778 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
3779 ctx_stmt_name = "host_data"; break;
3780 default: gcc_unreachable ();
3781 }
3782
3783 /* OpenACC/OpenMP mismatch? */
3784 if (is_gimple_omp_oacc (stmt)
3785 != is_gimple_omp_oacc (ctx->stmt))
3786 {
3787 error_at (gimple_location (stmt),
3788 "%s %qs construct inside of %s %qs region",
3789 (is_gimple_omp_oacc (stmt)
3790 ? "OpenACC" : "OpenMP"), stmt_name,
3791 (is_gimple_omp_oacc (ctx->stmt)
3792 ? "OpenACC" : "OpenMP"), ctx_stmt_name);
3793 return false;
3794 }
3795 if (is_gimple_omp_offloaded (ctx->stmt))
3796 {
3797 /* No GIMPLE_OMP_TARGET inside offloaded OpenACC CTX. */
3798 if (is_gimple_omp_oacc (ctx->stmt))
3799 {
3800 error_at (gimple_location (stmt),
3801 "%qs construct inside of %qs region",
3802 stmt_name, ctx_stmt_name);
3803 return false;
3804 }
3805 else
3806 {
3807 warning_at (gimple_location (stmt), 0,
3808 "%qs construct inside of %qs region",
3809 stmt_name, ctx_stmt_name);
3810 }
3811 }
3812 }
3813 break;
3814 default:
3815 break;
3816 }
3817 return true;
3818 }
3819
3820
3821 /* Helper function scan_omp.
3822
3823 Callback for walk_tree or operators in walk_gimple_stmt used to
3824 scan for OMP directives in TP. */
3825
3826 static tree
3827 scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
3828 {
3829 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
3830 omp_context *ctx = (omp_context *) wi->info;
3831 tree t = *tp;
3832
3833 switch (TREE_CODE (t))
3834 {
3835 case VAR_DECL:
3836 case PARM_DECL:
3837 case LABEL_DECL:
3838 case RESULT_DECL:
3839 if (ctx)
3840 {
3841 tree repl = remap_decl (t, &ctx->cb);
3842 gcc_checking_assert (TREE_CODE (repl) != ERROR_MARK);
3843 *tp = repl;
3844 }
3845 break;
3846
3847 default:
3848 if (ctx && TYPE_P (t))
3849 *tp = remap_type (t, &ctx->cb);
3850 else if (!DECL_P (t))
3851 {
3852 *walk_subtrees = 1;
3853 if (ctx)
3854 {
3855 tree tem = remap_type (TREE_TYPE (t), &ctx->cb);
3856 if (tem != TREE_TYPE (t))
3857 {
3858 if (TREE_CODE (t) == INTEGER_CST)
3859 *tp = wide_int_to_tree (tem, t);
3860 else
3861 TREE_TYPE (t) = tem;
3862 }
3863 }
3864 }
3865 break;
3866 }
3867
3868 return NULL_TREE;
3869 }
3870
3871 /* Return true if FNDECL is a setjmp or a longjmp. */
3872
3873 static bool
3874 setjmp_or_longjmp_p (const_tree fndecl)
3875 {
3876 if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
3877 && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_SETJMP
3878 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_LONGJMP))
3879 return true;
3880
3881 tree declname = DECL_NAME (fndecl);
3882 if (!declname)
3883 return false;
3884 const char *name = IDENTIFIER_POINTER (declname);
3885 return !strcmp (name, "setjmp") || !strcmp (name, "longjmp");
3886 }
3887
3888
3889 /* Helper function for scan_omp.
3890
3891 Callback for walk_gimple_stmt used to scan for OMP directives in
3892 the current statement in GSI. */
3893
3894 static tree
3895 scan_omp_1_stmt (gimple_stmt_iterator *gsi, bool *handled_ops_p,
3896 struct walk_stmt_info *wi)
3897 {
3898 gimple *stmt = gsi_stmt (*gsi);
3899 omp_context *ctx = (omp_context *) wi->info;
3900
3901 if (gimple_has_location (stmt))
3902 input_location = gimple_location (stmt);
3903
3904 /* Check the nesting restrictions. */
3905 bool remove = false;
3906 if (is_gimple_omp (stmt))
3907 remove = !check_omp_nesting_restrictions (stmt, ctx);
3908 else if (is_gimple_call (stmt))
3909 {
3910 tree fndecl = gimple_call_fndecl (stmt);
3911 if (fndecl)
3912 {
3913 if (setjmp_or_longjmp_p (fndecl)
3914 && ctx
3915 && gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
3916 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
3917 {
3918 remove = true;
3919 error_at (gimple_location (stmt),
3920 "setjmp/longjmp inside simd construct");
3921 }
3922 else if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
3923 switch (DECL_FUNCTION_CODE (fndecl))
3924 {
3925 case BUILT_IN_GOMP_BARRIER:
3926 case BUILT_IN_GOMP_CANCEL:
3927 case BUILT_IN_GOMP_CANCELLATION_POINT:
3928 case BUILT_IN_GOMP_TASKYIELD:
3929 case BUILT_IN_GOMP_TASKWAIT:
3930 case BUILT_IN_GOMP_TASKGROUP_START:
3931 case BUILT_IN_GOMP_TASKGROUP_END:
3932 remove = !check_omp_nesting_restrictions (stmt, ctx);
3933 break;
3934 default:
3935 break;
3936 }
3937 }
3938 }
3939 if (remove)
3940 {
3941 stmt = gimple_build_nop ();
3942 gsi_replace (gsi, stmt, false);
3943 }
3944
3945 *handled_ops_p = true;
3946
3947 switch (gimple_code (stmt))
3948 {
3949 case GIMPLE_OMP_PARALLEL:
3950 taskreg_nesting_level++;
3951 scan_omp_parallel (gsi, ctx);
3952 taskreg_nesting_level--;
3953 break;
3954
3955 case GIMPLE_OMP_TASK:
3956 taskreg_nesting_level++;
3957 scan_omp_task (gsi, ctx);
3958 taskreg_nesting_level--;
3959 break;
3960
3961 case GIMPLE_OMP_FOR:
3962 scan_omp_for (as_a <gomp_for *> (stmt), ctx);
3963 break;
3964
3965 case GIMPLE_OMP_SECTIONS:
3966 scan_omp_sections (as_a <gomp_sections *> (stmt), ctx);
3967 break;
3968
3969 case GIMPLE_OMP_SINGLE:
3970 scan_omp_single (as_a <gomp_single *> (stmt), ctx);
3971 break;
3972
3973 case GIMPLE_OMP_SECTION:
3974 case GIMPLE_OMP_MASTER:
3975 case GIMPLE_OMP_TASKGROUP:
3976 case GIMPLE_OMP_ORDERED:
3977 case GIMPLE_OMP_CRITICAL:
3978 case GIMPLE_OMP_GRID_BODY:
3979 ctx = new_omp_context (stmt, ctx);
3980 scan_omp (gimple_omp_body_ptr (stmt), ctx);
3981 break;
3982
3983 case GIMPLE_OMP_TARGET:
3984 scan_omp_target (as_a <gomp_target *> (stmt), ctx);
3985 break;
3986
3987 case GIMPLE_OMP_TEAMS:
3988 scan_omp_teams (as_a <gomp_teams *> (stmt), ctx);
3989 break;
3990
3991 case GIMPLE_BIND:
3992 {
3993 tree var;
3994
3995 *handled_ops_p = false;
3996 if (ctx)
3997 for (var = gimple_bind_vars (as_a <gbind *> (stmt));
3998 var ;
3999 var = DECL_CHAIN (var))
4000 insert_decl_map (&ctx->cb, var, var);
4001 }
4002 break;
4003 default:
4004 *handled_ops_p = false;
4005 break;
4006 }
4007
4008 return NULL_TREE;
4009 }
4010
4011
4012 /* Scan all the statements starting at the current statement. CTX
4013 contains context information about the OMP directives and
4014 clauses found during the scan. */
4015
4016 static void
4017 scan_omp (gimple_seq *body_p, omp_context *ctx)
4018 {
4019 location_t saved_location;
4020 struct walk_stmt_info wi;
4021
4022 memset (&wi, 0, sizeof (wi));
4023 wi.info = ctx;
4024 wi.want_locations = true;
4025
4026 saved_location = input_location;
4027 walk_gimple_seq_mod (body_p, scan_omp_1_stmt, scan_omp_1_op, &wi);
4028 input_location = saved_location;
4029 }
4030 \f
4031 /* Re-gimplification and code generation routines. */
4032
4033 /* Build a call to GOMP_barrier. */
4034
4035 static gimple *
4036 build_omp_barrier (tree lhs)
4037 {
4038 tree fndecl = builtin_decl_explicit (lhs ? BUILT_IN_GOMP_BARRIER_CANCEL
4039 : BUILT_IN_GOMP_BARRIER);
4040 gcall *g = gimple_build_call (fndecl, 0);
4041 if (lhs)
4042 gimple_call_set_lhs (g, lhs);
4043 return g;
4044 }
4045
4046 /* If a context was created for STMT when it was scanned, return it. */
4047
4048 static omp_context *
4049 maybe_lookup_ctx (gimple *stmt)
4050 {
4051 splay_tree_node n;
4052 n = splay_tree_lookup (all_contexts, (splay_tree_key) stmt);
4053 return n ? (omp_context *) n->value : NULL;
4054 }
4055
4056
4057 /* Find the mapping for DECL in CTX or the immediately enclosing
4058 context that has a mapping for DECL.
4059
4060 If CTX is a nested parallel directive, we may have to use the decl
4061 mappings created in CTX's parent context. Suppose that we have the
4062 following parallel nesting (variable UIDs showed for clarity):
4063
4064 iD.1562 = 0;
4065 #omp parallel shared(iD.1562) -> outer parallel
4066 iD.1562 = iD.1562 + 1;
4067
4068 #omp parallel shared (iD.1562) -> inner parallel
4069 iD.1562 = iD.1562 - 1;
4070
4071 Each parallel structure will create a distinct .omp_data_s structure
4072 for copying iD.1562 in/out of the directive:
4073
4074 outer parallel .omp_data_s.1.i -> iD.1562
4075 inner parallel .omp_data_s.2.i -> iD.1562
4076
4077 A shared variable mapping will produce a copy-out operation before
4078 the parallel directive and a copy-in operation after it. So, in
4079 this case we would have:
4080
4081 iD.1562 = 0;
4082 .omp_data_o.1.i = iD.1562;
4083 #omp parallel shared(iD.1562) -> outer parallel
4084 .omp_data_i.1 = &.omp_data_o.1
4085 .omp_data_i.1->i = .omp_data_i.1->i + 1;
4086
4087 .omp_data_o.2.i = iD.1562; -> **
4088 #omp parallel shared(iD.1562) -> inner parallel
4089 .omp_data_i.2 = &.omp_data_o.2
4090 .omp_data_i.2->i = .omp_data_i.2->i - 1;
4091
4092
4093 ** This is a problem. The symbol iD.1562 cannot be referenced
4094 inside the body of the outer parallel region. But since we are
4095 emitting this copy operation while expanding the inner parallel
4096 directive, we need to access the CTX structure of the outer
4097 parallel directive to get the correct mapping:
4098
4099 .omp_data_o.2.i = .omp_data_i.1->i
4100
4101 Since there may be other workshare or parallel directives enclosing
4102 the parallel directive, it may be necessary to walk up the context
4103 parent chain. This is not a problem in general because nested
4104 parallelism happens only rarely. */
4105
4106 static tree
4107 lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4108 {
4109 tree t;
4110 omp_context *up;
4111
4112 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4113 t = maybe_lookup_decl (decl, up);
4114
4115 gcc_assert (!ctx->is_nested || t || is_global_var (decl));
4116
4117 return t ? t : decl;
4118 }
4119
4120
4121 /* Similar to lookup_decl_in_outer_ctx, but return DECL if not found
4122 in outer contexts. */
4123
4124 static tree
4125 maybe_lookup_decl_in_outer_ctx (tree decl, omp_context *ctx)
4126 {
4127 tree t = NULL;
4128 omp_context *up;
4129
4130 for (up = ctx->outer, t = NULL; up && t == NULL; up = up->outer)
4131 t = maybe_lookup_decl (decl, up);
4132
4133 return t ? t : decl;
4134 }
4135
4136
4137 /* Construct the initialization value for reduction operation OP. */
4138
4139 tree
4140 omp_reduction_init_op (location_t loc, enum tree_code op, tree type)
4141 {
4142 switch (op)
4143 {
4144 case PLUS_EXPR:
4145 case MINUS_EXPR:
4146 case BIT_IOR_EXPR:
4147 case BIT_XOR_EXPR:
4148 case TRUTH_OR_EXPR:
4149 case TRUTH_ORIF_EXPR:
4150 case TRUTH_XOR_EXPR:
4151 case NE_EXPR:
4152 return build_zero_cst (type);
4153
4154 case MULT_EXPR:
4155 case TRUTH_AND_EXPR:
4156 case TRUTH_ANDIF_EXPR:
4157 case EQ_EXPR:
4158 return fold_convert_loc (loc, type, integer_one_node);
4159
4160 case BIT_AND_EXPR:
4161 return fold_convert_loc (loc, type, integer_minus_one_node);
4162
4163 case MAX_EXPR:
4164 if (SCALAR_FLOAT_TYPE_P (type))
4165 {
4166 REAL_VALUE_TYPE max, min;
4167 if (HONOR_INFINITIES (type))
4168 {
4169 real_inf (&max);
4170 real_arithmetic (&min, NEGATE_EXPR, &max, NULL);
4171 }
4172 else
4173 real_maxval (&min, 1, TYPE_MODE (type));
4174 return build_real (type, min);
4175 }
4176 else if (POINTER_TYPE_P (type))
4177 {
4178 wide_int min
4179 = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4180 return wide_int_to_tree (type, min);
4181 }
4182 else
4183 {
4184 gcc_assert (INTEGRAL_TYPE_P (type));
4185 return TYPE_MIN_VALUE (type);
4186 }
4187
4188 case MIN_EXPR:
4189 if (SCALAR_FLOAT_TYPE_P (type))
4190 {
4191 REAL_VALUE_TYPE max;
4192 if (HONOR_INFINITIES (type))
4193 real_inf (&max);
4194 else
4195 real_maxval (&max, 0, TYPE_MODE (type));
4196 return build_real (type, max);
4197 }
4198 else if (POINTER_TYPE_P (type))
4199 {
4200 wide_int max
4201 = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
4202 return wide_int_to_tree (type, max);
4203 }
4204 else
4205 {
4206 gcc_assert (INTEGRAL_TYPE_P (type));
4207 return TYPE_MAX_VALUE (type);
4208 }
4209
4210 default:
4211 gcc_unreachable ();
4212 }
4213 }
4214
4215 /* Construct the initialization value for reduction CLAUSE. */
4216
4217 tree
4218 omp_reduction_init (tree clause, tree type)
4219 {
4220 return omp_reduction_init_op (OMP_CLAUSE_LOCATION (clause),
4221 OMP_CLAUSE_REDUCTION_CODE (clause), type);
4222 }
4223
4224 /* Return alignment to be assumed for var in CLAUSE, which should be
4225 OMP_CLAUSE_ALIGNED. */
4226
4227 static tree
4228 omp_clause_aligned_alignment (tree clause)
4229 {
4230 if (OMP_CLAUSE_ALIGNED_ALIGNMENT (clause))
4231 return OMP_CLAUSE_ALIGNED_ALIGNMENT (clause);
4232
4233 /* Otherwise return implementation defined alignment. */
4234 unsigned int al = 1;
4235 machine_mode mode, vmode;
4236 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4237 if (vs)
4238 vs = 1 << floor_log2 (vs);
4239 static enum mode_class classes[]
4240 = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
4241 for (int i = 0; i < 4; i += 2)
4242 for (mode = GET_CLASS_NARROWEST_MODE (classes[i]);
4243 mode != VOIDmode;
4244 mode = GET_MODE_WIDER_MODE (mode))
4245 {
4246 vmode = targetm.vectorize.preferred_simd_mode (mode);
4247 if (GET_MODE_CLASS (vmode) != classes[i + 1])
4248 continue;
4249 while (vs
4250 && GET_MODE_SIZE (vmode) < vs
4251 && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
4252 vmode = GET_MODE_2XWIDER_MODE (vmode);
4253
4254 tree type = lang_hooks.types.type_for_mode (mode, 1);
4255 if (type == NULL_TREE || TYPE_MODE (type) != mode)
4256 continue;
4257 type = build_vector_type (type, GET_MODE_SIZE (vmode)
4258 / GET_MODE_SIZE (mode));
4259 if (TYPE_MODE (type) != vmode)
4260 continue;
4261 if (TYPE_ALIGN_UNIT (type) > al)
4262 al = TYPE_ALIGN_UNIT (type);
4263 }
4264 return build_int_cst (integer_type_node, al);
4265 }
4266
4267 /* Return maximum possible vectorization factor for the target. */
4268
4269 static int
4270 omp_max_vf (void)
4271 {
4272 if (!optimize
4273 || optimize_debug
4274 || !flag_tree_loop_optimize
4275 || (!flag_tree_loop_vectorize
4276 && (global_options_set.x_flag_tree_loop_vectorize
4277 || global_options_set.x_flag_tree_vectorize)))
4278 return 1;
4279
4280 int vs = targetm.vectorize.autovectorize_vector_sizes ();
4281 if (vs)
4282 {
4283 vs = 1 << floor_log2 (vs);
4284 return vs;
4285 }
4286 machine_mode vqimode = targetm.vectorize.preferred_simd_mode (QImode);
4287 if (GET_MODE_CLASS (vqimode) == MODE_VECTOR_INT)
4288 return GET_MODE_NUNITS (vqimode);
4289 return 1;
4290 }
4291
4292 /* Helper function of lower_rec_input_clauses, used for #pragma omp simd
4293 privatization. */
4294
4295 static bool
4296 lower_rec_simd_input_clauses (tree new_var, omp_context *ctx, int &max_vf,
4297 tree &idx, tree &lane, tree &ivar, tree &lvar)
4298 {
4299 if (max_vf == 0)
4300 {
4301 max_vf = omp_max_vf ();
4302 if (max_vf > 1)
4303 {
4304 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
4305 OMP_CLAUSE_SAFELEN);
4306 if (c
4307 && (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) != INTEGER_CST
4308 || tree_int_cst_sgn (OMP_CLAUSE_SAFELEN_EXPR (c)) != 1))
4309 max_vf = 1;
4310 else if (c && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
4311 max_vf) == -1)
4312 max_vf = tree_to_shwi (OMP_CLAUSE_SAFELEN_EXPR (c));
4313 }
4314 if (max_vf > 1)
4315 {
4316 idx = create_tmp_var (unsigned_type_node);
4317 lane = create_tmp_var (unsigned_type_node);
4318 }
4319 }
4320 if (max_vf == 1)
4321 return false;
4322
4323 tree atype = build_array_type_nelts (TREE_TYPE (new_var), max_vf);
4324 tree avar = create_tmp_var_raw (atype);
4325 if (TREE_ADDRESSABLE (new_var))
4326 TREE_ADDRESSABLE (avar) = 1;
4327 DECL_ATTRIBUTES (avar)
4328 = tree_cons (get_identifier ("omp simd array"), NULL,
4329 DECL_ATTRIBUTES (avar));
4330 gimple_add_tmp_var (avar);
4331 ivar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, idx,
4332 NULL_TREE, NULL_TREE);
4333 lvar = build4 (ARRAY_REF, TREE_TYPE (new_var), avar, lane,
4334 NULL_TREE, NULL_TREE);
4335 if (DECL_P (new_var))
4336 {
4337 SET_DECL_VALUE_EXPR (new_var, lvar);
4338 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4339 }
4340 return true;
4341 }
4342
4343 /* Helper function of lower_rec_input_clauses. For a reference
4344 in simd reduction, add an underlying variable it will reference. */
4345
4346 static void
4347 handle_simd_reference (location_t loc, tree new_vard, gimple_seq *ilist)
4348 {
4349 tree z = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard)));
4350 if (TREE_CONSTANT (z))
4351 {
4352 z = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_vard)),
4353 get_name (new_vard));
4354 gimple_add_tmp_var (z);
4355 TREE_ADDRESSABLE (z) = 1;
4356 z = build_fold_addr_expr_loc (loc, z);
4357 gimplify_assign (new_vard, z, ilist);
4358 }
4359 }
4360
4361 /* Generate code to implement the input clauses, FIRSTPRIVATE and COPYIN,
4362 from the receiver (aka child) side and initializers for REFERENCE_TYPE
4363 private variables. Initialization statements go in ILIST, while calls
4364 to destructors go in DLIST. */
4365
4366 static void
4367 lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist,
4368 omp_context *ctx, struct omp_for_data *fd)
4369 {
4370 tree c, dtor, copyin_seq, x, ptr;
4371 bool copyin_by_ref = false;
4372 bool lastprivate_firstprivate = false;
4373 bool reduction_omp_orig_ref = false;
4374 int pass;
4375 bool is_simd = (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
4376 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD);
4377 int max_vf = 0;
4378 tree lane = NULL_TREE, idx = NULL_TREE;
4379 tree ivar = NULL_TREE, lvar = NULL_TREE;
4380 gimple_seq llist[2] = { NULL, NULL };
4381
4382 copyin_seq = NULL;
4383
4384 /* Set max_vf=1 (which will later enforce safelen=1) in simd loops
4385 with data sharing clauses referencing variable sized vars. That
4386 is unnecessarily hard to support and very unlikely to result in
4387 vectorized code anyway. */
4388 if (is_simd)
4389 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4390 switch (OMP_CLAUSE_CODE (c))
4391 {
4392 case OMP_CLAUSE_LINEAR:
4393 if (OMP_CLAUSE_LINEAR_ARRAY (c))
4394 max_vf = 1;
4395 /* FALLTHRU */
4396 case OMP_CLAUSE_PRIVATE:
4397 case OMP_CLAUSE_FIRSTPRIVATE:
4398 case OMP_CLAUSE_LASTPRIVATE:
4399 if (is_variable_sized (OMP_CLAUSE_DECL (c)))
4400 max_vf = 1;
4401 break;
4402 case OMP_CLAUSE_REDUCTION:
4403 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF
4404 || is_variable_sized (OMP_CLAUSE_DECL (c)))
4405 max_vf = 1;
4406 break;
4407 default:
4408 continue;
4409 }
4410
4411 /* Do all the fixed sized types in the first pass, and the variable sized
4412 types in the second pass. This makes sure that the scalar arguments to
4413 the variable sized types are processed before we use them in the
4414 variable sized operations. */
4415 for (pass = 0; pass < 2; ++pass)
4416 {
4417 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
4418 {
4419 enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
4420 tree var, new_var;
4421 bool by_ref;
4422 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
4423
4424 switch (c_kind)
4425 {
4426 case OMP_CLAUSE_PRIVATE:
4427 if (OMP_CLAUSE_PRIVATE_DEBUG (c))
4428 continue;
4429 break;
4430 case OMP_CLAUSE_SHARED:
4431 /* Ignore shared directives in teams construct. */
4432 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4433 continue;
4434 if (maybe_lookup_decl (OMP_CLAUSE_DECL (c), ctx) == NULL)
4435 {
4436 gcc_assert (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c)
4437 || is_global_var (OMP_CLAUSE_DECL (c)));
4438 continue;
4439 }
4440 case OMP_CLAUSE_FIRSTPRIVATE:
4441 case OMP_CLAUSE_COPYIN:
4442 break;
4443 case OMP_CLAUSE_LINEAR:
4444 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c)
4445 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
4446 lastprivate_firstprivate = true;
4447 break;
4448 case OMP_CLAUSE_REDUCTION:
4449 if (OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4450 reduction_omp_orig_ref = true;
4451 break;
4452 case OMP_CLAUSE__LOOPTEMP_:
4453 /* Handle _looptemp_ clauses only on parallel/task. */
4454 if (fd)
4455 continue;
4456 break;
4457 case OMP_CLAUSE_LASTPRIVATE:
4458 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4459 {
4460 lastprivate_firstprivate = true;
4461 if (pass != 0 || is_taskloop_ctx (ctx))
4462 continue;
4463 }
4464 /* Even without corresponding firstprivate, if
4465 decl is Fortran allocatable, it needs outer var
4466 reference. */
4467 else if (pass == 0
4468 && lang_hooks.decls.omp_private_outer_ref
4469 (OMP_CLAUSE_DECL (c)))
4470 lastprivate_firstprivate = true;
4471 break;
4472 case OMP_CLAUSE_ALIGNED:
4473 if (pass == 0)
4474 continue;
4475 var = OMP_CLAUSE_DECL (c);
4476 if (TREE_CODE (TREE_TYPE (var)) == POINTER_TYPE
4477 && !is_global_var (var))
4478 {
4479 new_var = maybe_lookup_decl (var, ctx);
4480 if (new_var == NULL_TREE)
4481 new_var = maybe_lookup_decl_in_outer_ctx (var, ctx);
4482 x = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4483 tree alarg = omp_clause_aligned_alignment (c);
4484 alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
4485 x = build_call_expr_loc (clause_loc, x, 2, new_var, alarg);
4486 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4487 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
4488 gimplify_and_add (x, ilist);
4489 }
4490 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
4491 && is_global_var (var))
4492 {
4493 tree ptype = build_pointer_type (TREE_TYPE (var)), t, t2;
4494 new_var = lookup_decl (var, ctx);
4495 t = maybe_lookup_decl_in_outer_ctx (var, ctx);
4496 t = build_fold_addr_expr_loc (clause_loc, t);
4497 t2 = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
4498 tree alarg = omp_clause_aligned_alignment (c);
4499 alarg = fold_convert_loc (clause_loc, size_type_node, alarg);
4500 t = build_call_expr_loc (clause_loc, t2, 2, t, alarg);
4501 t = fold_convert_loc (clause_loc, ptype, t);
4502 x = create_tmp_var (ptype);
4503 t = build2 (MODIFY_EXPR, ptype, x, t);
4504 gimplify_and_add (t, ilist);
4505 t = build_simple_mem_ref_loc (clause_loc, x);
4506 SET_DECL_VALUE_EXPR (new_var, t);
4507 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4508 }
4509 continue;
4510 default:
4511 continue;
4512 }
4513
4514 new_var = var = OMP_CLAUSE_DECL (c);
4515 if (c_kind == OMP_CLAUSE_REDUCTION && TREE_CODE (var) == MEM_REF)
4516 {
4517 var = TREE_OPERAND (var, 0);
4518 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
4519 var = TREE_OPERAND (var, 0);
4520 if (TREE_CODE (var) == INDIRECT_REF
4521 || TREE_CODE (var) == ADDR_EXPR)
4522 var = TREE_OPERAND (var, 0);
4523 if (is_variable_sized (var))
4524 {
4525 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
4526 var = DECL_VALUE_EXPR (var);
4527 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
4528 var = TREE_OPERAND (var, 0);
4529 gcc_assert (DECL_P (var));
4530 }
4531 new_var = var;
4532 }
4533 if (c_kind != OMP_CLAUSE_COPYIN)
4534 new_var = lookup_decl (var, ctx);
4535
4536 if (c_kind == OMP_CLAUSE_SHARED || c_kind == OMP_CLAUSE_COPYIN)
4537 {
4538 if (pass != 0)
4539 continue;
4540 }
4541 /* C/C++ array section reductions. */
4542 else if (c_kind == OMP_CLAUSE_REDUCTION
4543 && var != OMP_CLAUSE_DECL (c))
4544 {
4545 if (pass == 0)
4546 continue;
4547
4548 tree bias = TREE_OPERAND (OMP_CLAUSE_DECL (c), 1);
4549 tree orig_var = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
4550 if (TREE_CODE (orig_var) == POINTER_PLUS_EXPR)
4551 {
4552 tree b = TREE_OPERAND (orig_var, 1);
4553 b = maybe_lookup_decl (b, ctx);
4554 if (b == NULL)
4555 {
4556 b = TREE_OPERAND (orig_var, 1);
4557 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
4558 }
4559 if (integer_zerop (bias))
4560 bias = b;
4561 else
4562 {
4563 bias = fold_convert_loc (clause_loc,
4564 TREE_TYPE (b), bias);
4565 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
4566 TREE_TYPE (b), b, bias);
4567 }
4568 orig_var = TREE_OPERAND (orig_var, 0);
4569 }
4570 if (TREE_CODE (orig_var) == INDIRECT_REF
4571 || TREE_CODE (orig_var) == ADDR_EXPR)
4572 orig_var = TREE_OPERAND (orig_var, 0);
4573 tree d = OMP_CLAUSE_DECL (c);
4574 tree type = TREE_TYPE (d);
4575 gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
4576 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
4577 const char *name = get_name (orig_var);
4578 if (TREE_CONSTANT (v))
4579 {
4580 x = create_tmp_var_raw (type, name);
4581 gimple_add_tmp_var (x);
4582 TREE_ADDRESSABLE (x) = 1;
4583 x = build_fold_addr_expr_loc (clause_loc, x);
4584 }
4585 else
4586 {
4587 tree atmp
4588 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4589 tree t = maybe_lookup_decl (v, ctx);
4590 if (t)
4591 v = t;
4592 else
4593 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
4594 gimplify_expr (&v, ilist, NULL, is_gimple_val, fb_rvalue);
4595 t = fold_build2_loc (clause_loc, PLUS_EXPR,
4596 TREE_TYPE (v), v,
4597 build_int_cst (TREE_TYPE (v), 1));
4598 t = fold_build2_loc (clause_loc, MULT_EXPR,
4599 TREE_TYPE (v), t,
4600 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4601 tree al = size_int (TYPE_ALIGN (TREE_TYPE (type)));
4602 x = build_call_expr_loc (clause_loc, atmp, 2, t, al);
4603 }
4604
4605 tree ptype = build_pointer_type (TREE_TYPE (type));
4606 x = fold_convert_loc (clause_loc, ptype, x);
4607 tree y = create_tmp_var (ptype, name);
4608 gimplify_assign (y, x, ilist);
4609 x = y;
4610 tree yb = y;
4611
4612 if (!integer_zerop (bias))
4613 {
4614 bias = fold_convert_loc (clause_loc, pointer_sized_int_node,
4615 bias);
4616 yb = fold_convert_loc (clause_loc, pointer_sized_int_node,
4617 x);
4618 yb = fold_build2_loc (clause_loc, MINUS_EXPR,
4619 pointer_sized_int_node, yb, bias);
4620 x = fold_convert_loc (clause_loc, TREE_TYPE (x), yb);
4621 yb = create_tmp_var (ptype, name);
4622 gimplify_assign (yb, x, ilist);
4623 x = yb;
4624 }
4625
4626 d = TREE_OPERAND (d, 0);
4627 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
4628 d = TREE_OPERAND (d, 0);
4629 if (TREE_CODE (d) == ADDR_EXPR)
4630 {
4631 if (orig_var != var)
4632 {
4633 gcc_assert (is_variable_sized (orig_var));
4634 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var),
4635 x);
4636 gimplify_assign (new_var, x, ilist);
4637 tree new_orig_var = lookup_decl (orig_var, ctx);
4638 tree t = build_fold_indirect_ref (new_var);
4639 DECL_IGNORED_P (new_var) = 0;
4640 TREE_THIS_NOTRAP (t);
4641 SET_DECL_VALUE_EXPR (new_orig_var, t);
4642 DECL_HAS_VALUE_EXPR_P (new_orig_var) = 1;
4643 }
4644 else
4645 {
4646 x = build2 (MEM_REF, TREE_TYPE (new_var), x,
4647 build_int_cst (ptype, 0));
4648 SET_DECL_VALUE_EXPR (new_var, x);
4649 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4650 }
4651 }
4652 else
4653 {
4654 gcc_assert (orig_var == var);
4655 if (TREE_CODE (d) == INDIRECT_REF)
4656 {
4657 x = create_tmp_var (ptype, name);
4658 TREE_ADDRESSABLE (x) = 1;
4659 gimplify_assign (x, yb, ilist);
4660 x = build_fold_addr_expr_loc (clause_loc, x);
4661 }
4662 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4663 gimplify_assign (new_var, x, ilist);
4664 }
4665 tree y1 = create_tmp_var (ptype, NULL);
4666 gimplify_assign (y1, y, ilist);
4667 tree i2 = NULL_TREE, y2 = NULL_TREE;
4668 tree body2 = NULL_TREE, end2 = NULL_TREE;
4669 tree y3 = NULL_TREE, y4 = NULL_TREE;
4670 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) || is_simd)
4671 {
4672 y2 = create_tmp_var (ptype, NULL);
4673 gimplify_assign (y2, y, ilist);
4674 tree ref = build_outer_var_ref (var, ctx);
4675 /* For ref build_outer_var_ref already performs this. */
4676 if (TREE_CODE (d) == INDIRECT_REF)
4677 gcc_assert (is_reference (var));
4678 else if (TREE_CODE (d) == ADDR_EXPR)
4679 ref = build_fold_addr_expr (ref);
4680 else if (is_reference (var))
4681 ref = build_fold_addr_expr (ref);
4682 ref = fold_convert_loc (clause_loc, ptype, ref);
4683 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
4684 && OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c))
4685 {
4686 y3 = create_tmp_var (ptype, NULL);
4687 gimplify_assign (y3, unshare_expr (ref), ilist);
4688 }
4689 if (is_simd)
4690 {
4691 y4 = create_tmp_var (ptype, NULL);
4692 gimplify_assign (y4, ref, dlist);
4693 }
4694 }
4695 tree i = create_tmp_var (TREE_TYPE (v), NULL);
4696 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), ilist);
4697 tree body = create_artificial_label (UNKNOWN_LOCATION);
4698 tree end = create_artificial_label (UNKNOWN_LOCATION);
4699 gimple_seq_add_stmt (ilist, gimple_build_label (body));
4700 if (y2)
4701 {
4702 i2 = create_tmp_var (TREE_TYPE (v), NULL);
4703 gimplify_assign (i2, build_int_cst (TREE_TYPE (v), 0), dlist);
4704 body2 = create_artificial_label (UNKNOWN_LOCATION);
4705 end2 = create_artificial_label (UNKNOWN_LOCATION);
4706 gimple_seq_add_stmt (dlist, gimple_build_label (body2));
4707 }
4708 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4709 {
4710 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
4711 tree decl_placeholder
4712 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
4713 SET_DECL_VALUE_EXPR (decl_placeholder,
4714 build_simple_mem_ref (y1));
4715 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
4716 SET_DECL_VALUE_EXPR (placeholder,
4717 y3 ? build_simple_mem_ref (y3)
4718 : error_mark_node);
4719 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
4720 x = lang_hooks.decls.omp_clause_default_ctor
4721 (c, build_simple_mem_ref (y1),
4722 y3 ? build_simple_mem_ref (y3) : NULL_TREE);
4723 if (x)
4724 gimplify_and_add (x, ilist);
4725 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
4726 {
4727 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
4728 lower_omp (&tseq, ctx);
4729 gimple_seq_add_seq (ilist, tseq);
4730 }
4731 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
4732 if (is_simd)
4733 {
4734 SET_DECL_VALUE_EXPR (decl_placeholder,
4735 build_simple_mem_ref (y2));
4736 SET_DECL_VALUE_EXPR (placeholder,
4737 build_simple_mem_ref (y4));
4738 gimple_seq tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
4739 lower_omp (&tseq, ctx);
4740 gimple_seq_add_seq (dlist, tseq);
4741 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
4742 }
4743 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
4744 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 0;
4745 x = lang_hooks.decls.omp_clause_dtor
4746 (c, build_simple_mem_ref (y2));
4747 if (x)
4748 {
4749 gimple_seq tseq = NULL;
4750 dtor = x;
4751 gimplify_stmt (&dtor, &tseq);
4752 gimple_seq_add_seq (dlist, tseq);
4753 }
4754 }
4755 else
4756 {
4757 x = omp_reduction_init (c, TREE_TYPE (type));
4758 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
4759
4760 /* reduction(-:var) sums up the partial results, so it
4761 acts identically to reduction(+:var). */
4762 if (code == MINUS_EXPR)
4763 code = PLUS_EXPR;
4764
4765 gimplify_assign (build_simple_mem_ref (y1), x, ilist);
4766 if (is_simd)
4767 {
4768 x = build2 (code, TREE_TYPE (type),
4769 build_simple_mem_ref (y4),
4770 build_simple_mem_ref (y2));
4771 gimplify_assign (build_simple_mem_ref (y4), x, dlist);
4772 }
4773 }
4774 gimple *g
4775 = gimple_build_assign (y1, POINTER_PLUS_EXPR, y1,
4776 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4777 gimple_seq_add_stmt (ilist, g);
4778 if (y3)
4779 {
4780 g = gimple_build_assign (y3, POINTER_PLUS_EXPR, y3,
4781 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4782 gimple_seq_add_stmt (ilist, g);
4783 }
4784 g = gimple_build_assign (i, PLUS_EXPR, i,
4785 build_int_cst (TREE_TYPE (i), 1));
4786 gimple_seq_add_stmt (ilist, g);
4787 g = gimple_build_cond (LE_EXPR, i, v, body, end);
4788 gimple_seq_add_stmt (ilist, g);
4789 gimple_seq_add_stmt (ilist, gimple_build_label (end));
4790 if (y2)
4791 {
4792 g = gimple_build_assign (y2, POINTER_PLUS_EXPR, y2,
4793 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4794 gimple_seq_add_stmt (dlist, g);
4795 if (y4)
4796 {
4797 g = gimple_build_assign
4798 (y4, POINTER_PLUS_EXPR, y4,
4799 TYPE_SIZE_UNIT (TREE_TYPE (type)));
4800 gimple_seq_add_stmt (dlist, g);
4801 }
4802 g = gimple_build_assign (i2, PLUS_EXPR, i2,
4803 build_int_cst (TREE_TYPE (i2), 1));
4804 gimple_seq_add_stmt (dlist, g);
4805 g = gimple_build_cond (LE_EXPR, i2, v, body2, end2);
4806 gimple_seq_add_stmt (dlist, g);
4807 gimple_seq_add_stmt (dlist, gimple_build_label (end2));
4808 }
4809 continue;
4810 }
4811 else if (is_variable_sized (var))
4812 {
4813 /* For variable sized types, we need to allocate the
4814 actual storage here. Call alloca and store the
4815 result in the pointer decl that we created elsewhere. */
4816 if (pass == 0)
4817 continue;
4818
4819 if (c_kind != OMP_CLAUSE_FIRSTPRIVATE || !is_task_ctx (ctx))
4820 {
4821 gcall *stmt;
4822 tree tmp, atmp;
4823
4824 ptr = DECL_VALUE_EXPR (new_var);
4825 gcc_assert (TREE_CODE (ptr) == INDIRECT_REF);
4826 ptr = TREE_OPERAND (ptr, 0);
4827 gcc_assert (DECL_P (ptr));
4828 x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
4829
4830 /* void *tmp = __builtin_alloca */
4831 atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4832 stmt = gimple_build_call (atmp, 2, x,
4833 size_int (DECL_ALIGN (var)));
4834 tmp = create_tmp_var_raw (ptr_type_node);
4835 gimple_add_tmp_var (tmp);
4836 gimple_call_set_lhs (stmt, tmp);
4837
4838 gimple_seq_add_stmt (ilist, stmt);
4839
4840 x = fold_convert_loc (clause_loc, TREE_TYPE (ptr), tmp);
4841 gimplify_assign (ptr, x, ilist);
4842 }
4843 }
4844 else if (is_reference (var))
4845 {
4846 /* For references that are being privatized for Fortran,
4847 allocate new backing storage for the new pointer
4848 variable. This allows us to avoid changing all the
4849 code that expects a pointer to something that expects
4850 a direct variable. */
4851 if (pass == 0)
4852 continue;
4853
4854 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
4855 if (c_kind == OMP_CLAUSE_FIRSTPRIVATE && is_task_ctx (ctx))
4856 {
4857 x = build_receiver_ref (var, false, ctx);
4858 x = build_fold_addr_expr_loc (clause_loc, x);
4859 }
4860 else if (TREE_CONSTANT (x))
4861 {
4862 /* For reduction in SIMD loop, defer adding the
4863 initialization of the reference, because if we decide
4864 to use SIMD array for it, the initilization could cause
4865 expansion ICE. */
4866 if (c_kind == OMP_CLAUSE_REDUCTION && is_simd)
4867 x = NULL_TREE;
4868 else
4869 {
4870 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
4871 get_name (var));
4872 gimple_add_tmp_var (x);
4873 TREE_ADDRESSABLE (x) = 1;
4874 x = build_fold_addr_expr_loc (clause_loc, x);
4875 }
4876 }
4877 else
4878 {
4879 tree atmp
4880 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
4881 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
4882 tree al = size_int (TYPE_ALIGN (rtype));
4883 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
4884 }
4885
4886 if (x)
4887 {
4888 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
4889 gimplify_assign (new_var, x, ilist);
4890 }
4891
4892 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
4893 }
4894 else if (c_kind == OMP_CLAUSE_REDUCTION
4895 && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
4896 {
4897 if (pass == 0)
4898 continue;
4899 }
4900 else if (pass != 0)
4901 continue;
4902
4903 switch (OMP_CLAUSE_CODE (c))
4904 {
4905 case OMP_CLAUSE_SHARED:
4906 /* Ignore shared directives in teams construct. */
4907 if (gimple_code (ctx->stmt) == GIMPLE_OMP_TEAMS)
4908 continue;
4909 /* Shared global vars are just accessed directly. */
4910 if (is_global_var (new_var))
4911 break;
4912 /* For taskloop firstprivate/lastprivate, represented
4913 as firstprivate and shared clause on the task, new_var
4914 is the firstprivate var. */
4915 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
4916 break;
4917 /* Set up the DECL_VALUE_EXPR for shared variables now. This
4918 needs to be delayed until after fixup_child_record_type so
4919 that we get the correct type during the dereference. */
4920 by_ref = use_pointer_for_field (var, ctx);
4921 x = build_receiver_ref (var, by_ref, ctx);
4922 SET_DECL_VALUE_EXPR (new_var, x);
4923 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
4924
4925 /* ??? If VAR is not passed by reference, and the variable
4926 hasn't been initialized yet, then we'll get a warning for
4927 the store into the omp_data_s structure. Ideally, we'd be
4928 able to notice this and not store anything at all, but
4929 we're generating code too early. Suppress the warning. */
4930 if (!by_ref)
4931 TREE_NO_WARNING (var) = 1;
4932 break;
4933
4934 case OMP_CLAUSE_LASTPRIVATE:
4935 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
4936 break;
4937 /* FALLTHRU */
4938
4939 case OMP_CLAUSE_PRIVATE:
4940 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE)
4941 x = build_outer_var_ref (var, ctx);
4942 else if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
4943 {
4944 if (is_task_ctx (ctx))
4945 x = build_receiver_ref (var, false, ctx);
4946 else
4947 x = build_outer_var_ref (var, ctx);
4948 }
4949 else
4950 x = NULL;
4951 do_private:
4952 tree nx;
4953 nx = lang_hooks.decls.omp_clause_default_ctor
4954 (c, unshare_expr (new_var), x);
4955 if (is_simd)
4956 {
4957 tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
4958 if ((TREE_ADDRESSABLE (new_var) || nx || y
4959 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
4960 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
4961 idx, lane, ivar, lvar))
4962 {
4963 if (nx)
4964 x = lang_hooks.decls.omp_clause_default_ctor
4965 (c, unshare_expr (ivar), x);
4966 if (nx && x)
4967 gimplify_and_add (x, &llist[0]);
4968 if (y)
4969 {
4970 y = lang_hooks.decls.omp_clause_dtor (c, ivar);
4971 if (y)
4972 {
4973 gimple_seq tseq = NULL;
4974
4975 dtor = y;
4976 gimplify_stmt (&dtor, &tseq);
4977 gimple_seq_add_seq (&llist[1], tseq);
4978 }
4979 }
4980 break;
4981 }
4982 }
4983 if (nx)
4984 gimplify_and_add (nx, ilist);
4985 /* FALLTHRU */
4986
4987 do_dtor:
4988 x = lang_hooks.decls.omp_clause_dtor (c, new_var);
4989 if (x)
4990 {
4991 gimple_seq tseq = NULL;
4992
4993 dtor = x;
4994 gimplify_stmt (&dtor, &tseq);
4995 gimple_seq_add_seq (dlist, tseq);
4996 }
4997 break;
4998
4999 case OMP_CLAUSE_LINEAR:
5000 if (!OMP_CLAUSE_LINEAR_NO_COPYIN (c))
5001 goto do_firstprivate;
5002 if (OMP_CLAUSE_LINEAR_NO_COPYOUT (c))
5003 x = NULL;
5004 else
5005 x = build_outer_var_ref (var, ctx);
5006 goto do_private;
5007
5008 case OMP_CLAUSE_FIRSTPRIVATE:
5009 if (is_task_ctx (ctx))
5010 {
5011 if (is_reference (var) || is_variable_sized (var))
5012 goto do_dtor;
5013 else if (is_global_var (maybe_lookup_decl_in_outer_ctx (var,
5014 ctx))
5015 || use_pointer_for_field (var, NULL))
5016 {
5017 x = build_receiver_ref (var, false, ctx);
5018 SET_DECL_VALUE_EXPR (new_var, x);
5019 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
5020 goto do_dtor;
5021 }
5022 }
5023 do_firstprivate:
5024 x = build_outer_var_ref (var, ctx);
5025 if (is_simd)
5026 {
5027 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5028 && gimple_omp_for_combined_into_p (ctx->stmt))
5029 {
5030 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5031 tree stept = TREE_TYPE (t);
5032 tree ct = find_omp_clause (clauses,
5033 OMP_CLAUSE__LOOPTEMP_);
5034 gcc_assert (ct);
5035 tree l = OMP_CLAUSE_DECL (ct);
5036 tree n1 = fd->loop.n1;
5037 tree step = fd->loop.step;
5038 tree itype = TREE_TYPE (l);
5039 if (POINTER_TYPE_P (itype))
5040 itype = signed_type_for (itype);
5041 l = fold_build2 (MINUS_EXPR, itype, l, n1);
5042 if (TYPE_UNSIGNED (itype)
5043 && fd->loop.cond_code == GT_EXPR)
5044 l = fold_build2 (TRUNC_DIV_EXPR, itype,
5045 fold_build1 (NEGATE_EXPR, itype, l),
5046 fold_build1 (NEGATE_EXPR,
5047 itype, step));
5048 else
5049 l = fold_build2 (TRUNC_DIV_EXPR, itype, l, step);
5050 t = fold_build2 (MULT_EXPR, stept,
5051 fold_convert (stept, l), t);
5052
5053 if (OMP_CLAUSE_LINEAR_ARRAY (c))
5054 {
5055 x = lang_hooks.decls.omp_clause_linear_ctor
5056 (c, new_var, x, t);
5057 gimplify_and_add (x, ilist);
5058 goto do_dtor;
5059 }
5060
5061 if (POINTER_TYPE_P (TREE_TYPE (x)))
5062 x = fold_build2 (POINTER_PLUS_EXPR,
5063 TREE_TYPE (x), x, t);
5064 else
5065 x = fold_build2 (PLUS_EXPR, TREE_TYPE (x), x, t);
5066 }
5067
5068 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR
5069 || TREE_ADDRESSABLE (new_var))
5070 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5071 idx, lane, ivar, lvar))
5072 {
5073 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR)
5074 {
5075 tree iv = create_tmp_var (TREE_TYPE (new_var));
5076 x = lang_hooks.decls.omp_clause_copy_ctor (c, iv, x);
5077 gimplify_and_add (x, ilist);
5078 gimple_stmt_iterator gsi
5079 = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5080 gassign *g
5081 = gimple_build_assign (unshare_expr (lvar), iv);
5082 gsi_insert_before_without_update (&gsi, g,
5083 GSI_SAME_STMT);
5084 tree t = OMP_CLAUSE_LINEAR_STEP (c);
5085 enum tree_code code = PLUS_EXPR;
5086 if (POINTER_TYPE_P (TREE_TYPE (new_var)))
5087 code = POINTER_PLUS_EXPR;
5088 g = gimple_build_assign (iv, code, iv, t);
5089 gsi_insert_before_without_update (&gsi, g,
5090 GSI_SAME_STMT);
5091 break;
5092 }
5093 x = lang_hooks.decls.omp_clause_copy_ctor
5094 (c, unshare_expr (ivar), x);
5095 gimplify_and_add (x, &llist[0]);
5096 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5097 if (x)
5098 {
5099 gimple_seq tseq = NULL;
5100
5101 dtor = x;
5102 gimplify_stmt (&dtor, &tseq);
5103 gimple_seq_add_seq (&llist[1], tseq);
5104 }
5105 break;
5106 }
5107 }
5108 x = lang_hooks.decls.omp_clause_copy_ctor
5109 (c, unshare_expr (new_var), x);
5110 gimplify_and_add (x, ilist);
5111 goto do_dtor;
5112
5113 case OMP_CLAUSE__LOOPTEMP_:
5114 gcc_assert (is_taskreg_ctx (ctx));
5115 x = build_outer_var_ref (var, ctx);
5116 x = build2 (MODIFY_EXPR, TREE_TYPE (new_var), new_var, x);
5117 gimplify_and_add (x, ilist);
5118 break;
5119
5120 case OMP_CLAUSE_COPYIN:
5121 by_ref = use_pointer_for_field (var, NULL);
5122 x = build_receiver_ref (var, by_ref, ctx);
5123 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, x);
5124 append_to_statement_list (x, &copyin_seq);
5125 copyin_by_ref |= by_ref;
5126 break;
5127
5128 case OMP_CLAUSE_REDUCTION:
5129 /* OpenACC reductions are initialized using the
5130 GOACC_REDUCTION internal function. */
5131 if (is_gimple_omp_oacc (ctx->stmt))
5132 break;
5133 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5134 {
5135 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5136 gimple *tseq;
5137 x = build_outer_var_ref (var, ctx);
5138
5139 if (is_reference (var)
5140 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5141 TREE_TYPE (x)))
5142 x = build_fold_addr_expr_loc (clause_loc, x);
5143 SET_DECL_VALUE_EXPR (placeholder, x);
5144 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5145 tree new_vard = new_var;
5146 if (is_reference (var))
5147 {
5148 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5149 new_vard = TREE_OPERAND (new_var, 0);
5150 gcc_assert (DECL_P (new_vard));
5151 }
5152 if (is_simd
5153 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5154 idx, lane, ivar, lvar))
5155 {
5156 if (new_vard == new_var)
5157 {
5158 gcc_assert (DECL_VALUE_EXPR (new_var) == lvar);
5159 SET_DECL_VALUE_EXPR (new_var, ivar);
5160 }
5161 else
5162 {
5163 SET_DECL_VALUE_EXPR (new_vard,
5164 build_fold_addr_expr (ivar));
5165 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5166 }
5167 x = lang_hooks.decls.omp_clause_default_ctor
5168 (c, unshare_expr (ivar),
5169 build_outer_var_ref (var, ctx));
5170 if (x)
5171 gimplify_and_add (x, &llist[0]);
5172 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5173 {
5174 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5175 lower_omp (&tseq, ctx);
5176 gimple_seq_add_seq (&llist[0], tseq);
5177 }
5178 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5179 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5180 lower_omp (&tseq, ctx);
5181 gimple_seq_add_seq (&llist[1], tseq);
5182 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5183 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5184 if (new_vard == new_var)
5185 SET_DECL_VALUE_EXPR (new_var, lvar);
5186 else
5187 SET_DECL_VALUE_EXPR (new_vard,
5188 build_fold_addr_expr (lvar));
5189 x = lang_hooks.decls.omp_clause_dtor (c, ivar);
5190 if (x)
5191 {
5192 tseq = NULL;
5193 dtor = x;
5194 gimplify_stmt (&dtor, &tseq);
5195 gimple_seq_add_seq (&llist[1], tseq);
5196 }
5197 break;
5198 }
5199 /* If this is a reference to constant size reduction var
5200 with placeholder, we haven't emitted the initializer
5201 for it because it is undesirable if SIMD arrays are used.
5202 But if they aren't used, we need to emit the deferred
5203 initialization now. */
5204 else if (is_reference (var) && is_simd)
5205 handle_simd_reference (clause_loc, new_vard, ilist);
5206 x = lang_hooks.decls.omp_clause_default_ctor
5207 (c, unshare_expr (new_var),
5208 build_outer_var_ref (var, ctx));
5209 if (x)
5210 gimplify_and_add (x, ilist);
5211 if (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c))
5212 {
5213 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c);
5214 lower_omp (&tseq, ctx);
5215 gimple_seq_add_seq (ilist, tseq);
5216 }
5217 OMP_CLAUSE_REDUCTION_GIMPLE_INIT (c) = NULL;
5218 if (is_simd)
5219 {
5220 tseq = OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c);
5221 lower_omp (&tseq, ctx);
5222 gimple_seq_add_seq (dlist, tseq);
5223 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5224 }
5225 DECL_HAS_VALUE_EXPR_P (placeholder) = 0;
5226 goto do_dtor;
5227 }
5228 else
5229 {
5230 x = omp_reduction_init (c, TREE_TYPE (new_var));
5231 gcc_assert (TREE_CODE (TREE_TYPE (new_var)) != ARRAY_TYPE);
5232 enum tree_code code = OMP_CLAUSE_REDUCTION_CODE (c);
5233
5234 /* reduction(-:var) sums up the partial results, so it
5235 acts identically to reduction(+:var). */
5236 if (code == MINUS_EXPR)
5237 code = PLUS_EXPR;
5238
5239 tree new_vard = new_var;
5240 if (is_simd && is_reference (var))
5241 {
5242 gcc_assert (TREE_CODE (new_var) == MEM_REF);
5243 new_vard = TREE_OPERAND (new_var, 0);
5244 gcc_assert (DECL_P (new_vard));
5245 }
5246 if (is_simd
5247 && lower_rec_simd_input_clauses (new_var, ctx, max_vf,
5248 idx, lane, ivar, lvar))
5249 {
5250 tree ref = build_outer_var_ref (var, ctx);
5251
5252 gimplify_assign (unshare_expr (ivar), x, &llist[0]);
5253
5254 x = build2 (code, TREE_TYPE (ref), ref, ivar);
5255 ref = build_outer_var_ref (var, ctx);
5256 gimplify_assign (ref, x, &llist[1]);
5257
5258 if (new_vard != new_var)
5259 {
5260 SET_DECL_VALUE_EXPR (new_vard,
5261 build_fold_addr_expr (lvar));
5262 DECL_HAS_VALUE_EXPR_P (new_vard) = 1;
5263 }
5264 }
5265 else
5266 {
5267 if (is_reference (var) && is_simd)
5268 handle_simd_reference (clause_loc, new_vard, ilist);
5269 gimplify_assign (new_var, x, ilist);
5270 if (is_simd)
5271 {
5272 tree ref = build_outer_var_ref (var, ctx);
5273
5274 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5275 ref = build_outer_var_ref (var, ctx);
5276 gimplify_assign (ref, x, dlist);
5277 }
5278 }
5279 }
5280 break;
5281
5282 default:
5283 gcc_unreachable ();
5284 }
5285 }
5286 }
5287
5288 if (lane)
5289 {
5290 tree uid = create_tmp_var (ptr_type_node, "simduid");
5291 /* Don't want uninit warnings on simduid, it is always uninitialized,
5292 but we use it not for the value, but for the DECL_UID only. */
5293 TREE_NO_WARNING (uid) = 1;
5294 gimple *g
5295 = gimple_build_call_internal (IFN_GOMP_SIMD_LANE, 1, uid);
5296 gimple_call_set_lhs (g, lane);
5297 gimple_stmt_iterator gsi = gsi_start_1 (gimple_omp_body_ptr (ctx->stmt));
5298 gsi_insert_before_without_update (&gsi, g, GSI_SAME_STMT);
5299 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__SIMDUID_);
5300 OMP_CLAUSE__SIMDUID__DECL (c) = uid;
5301 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5302 gimple_omp_for_set_clauses (ctx->stmt, c);
5303 g = gimple_build_assign (lane, INTEGER_CST,
5304 build_int_cst (unsigned_type_node, 0));
5305 gimple_seq_add_stmt (ilist, g);
5306 for (int i = 0; i < 2; i++)
5307 if (llist[i])
5308 {
5309 tree vf = create_tmp_var (unsigned_type_node);
5310 g = gimple_build_call_internal (IFN_GOMP_SIMD_VF, 1, uid);
5311 gimple_call_set_lhs (g, vf);
5312 gimple_seq *seq = i == 0 ? ilist : dlist;
5313 gimple_seq_add_stmt (seq, g);
5314 tree t = build_int_cst (unsigned_type_node, 0);
5315 g = gimple_build_assign (idx, INTEGER_CST, t);
5316 gimple_seq_add_stmt (seq, g);
5317 tree body = create_artificial_label (UNKNOWN_LOCATION);
5318 tree header = create_artificial_label (UNKNOWN_LOCATION);
5319 tree end = create_artificial_label (UNKNOWN_LOCATION);
5320 gimple_seq_add_stmt (seq, gimple_build_goto (header));
5321 gimple_seq_add_stmt (seq, gimple_build_label (body));
5322 gimple_seq_add_seq (seq, llist[i]);
5323 t = build_int_cst (unsigned_type_node, 1);
5324 g = gimple_build_assign (idx, PLUS_EXPR, idx, t);
5325 gimple_seq_add_stmt (seq, g);
5326 gimple_seq_add_stmt (seq, gimple_build_label (header));
5327 g = gimple_build_cond (LT_EXPR, idx, vf, body, end);
5328 gimple_seq_add_stmt (seq, g);
5329 gimple_seq_add_stmt (seq, gimple_build_label (end));
5330 }
5331 }
5332
5333 /* The copyin sequence is not to be executed by the main thread, since
5334 that would result in self-copies. Perhaps not visible to scalars,
5335 but it certainly is to C++ operator=. */
5336 if (copyin_seq)
5337 {
5338 x = build_call_expr (builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM),
5339 0);
5340 x = build2 (NE_EXPR, boolean_type_node, x,
5341 build_int_cst (TREE_TYPE (x), 0));
5342 x = build3 (COND_EXPR, void_type_node, x, copyin_seq, NULL);
5343 gimplify_and_add (x, ilist);
5344 }
5345
5346 /* If any copyin variable is passed by reference, we must ensure the
5347 master thread doesn't modify it before it is copied over in all
5348 threads. Similarly for variables in both firstprivate and
5349 lastprivate clauses we need to ensure the lastprivate copying
5350 happens after firstprivate copying in all threads. And similarly
5351 for UDRs if initializer expression refers to omp_orig. */
5352 if (copyin_by_ref || lastprivate_firstprivate || reduction_omp_orig_ref)
5353 {
5354 /* Don't add any barrier for #pragma omp simd or
5355 #pragma omp distribute. */
5356 if (gimple_code (ctx->stmt) != GIMPLE_OMP_FOR
5357 || gimple_omp_for_kind (ctx->stmt) == GF_OMP_FOR_KIND_FOR)
5358 gimple_seq_add_stmt (ilist, build_omp_barrier (NULL_TREE));
5359 }
5360
5361 /* If max_vf is non-zero, then we can use only a vectorization factor
5362 up to the max_vf we chose. So stick it into the safelen clause. */
5363 if (max_vf)
5364 {
5365 tree c = find_omp_clause (gimple_omp_for_clauses (ctx->stmt),
5366 OMP_CLAUSE_SAFELEN);
5367 if (c == NULL_TREE
5368 || (TREE_CODE (OMP_CLAUSE_SAFELEN_EXPR (c)) == INTEGER_CST
5369 && compare_tree_int (OMP_CLAUSE_SAFELEN_EXPR (c),
5370 max_vf) == 1))
5371 {
5372 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_SAFELEN);
5373 OMP_CLAUSE_SAFELEN_EXPR (c) = build_int_cst (integer_type_node,
5374 max_vf);
5375 OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt);
5376 gimple_omp_for_set_clauses (ctx->stmt, c);
5377 }
5378 }
5379 }
5380
5381
5382 /* Generate code to implement the LASTPRIVATE clauses. This is used for
5383 both parallel and workshare constructs. PREDICATE may be NULL if it's
5384 always true. */
5385
5386 static void
5387 lower_lastprivate_clauses (tree clauses, tree predicate, gimple_seq *stmt_list,
5388 omp_context *ctx)
5389 {
5390 tree x, c, label = NULL, orig_clauses = clauses;
5391 bool par_clauses = false;
5392 tree simduid = NULL, lastlane = NULL;
5393
5394 /* Early exit if there are no lastprivate or linear clauses. */
5395 for (; clauses ; clauses = OMP_CLAUSE_CHAIN (clauses))
5396 if (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LASTPRIVATE
5397 || (OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_LINEAR
5398 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (clauses)))
5399 break;
5400 if (clauses == NULL)
5401 {
5402 /* If this was a workshare clause, see if it had been combined
5403 with its parallel. In that case, look for the clauses on the
5404 parallel statement itself. */
5405 if (is_parallel_ctx (ctx))
5406 return;
5407
5408 ctx = ctx->outer;
5409 if (ctx == NULL || !is_parallel_ctx (ctx))
5410 return;
5411
5412 clauses = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5413 OMP_CLAUSE_LASTPRIVATE);
5414 if (clauses == NULL)
5415 return;
5416 par_clauses = true;
5417 }
5418
5419 if (predicate)
5420 {
5421 gcond *stmt;
5422 tree label_true, arm1, arm2;
5423
5424 label = create_artificial_label (UNKNOWN_LOCATION);
5425 label_true = create_artificial_label (UNKNOWN_LOCATION);
5426 arm1 = TREE_OPERAND (predicate, 0);
5427 arm2 = TREE_OPERAND (predicate, 1);
5428 gimplify_expr (&arm1, stmt_list, NULL, is_gimple_val, fb_rvalue);
5429 gimplify_expr (&arm2, stmt_list, NULL, is_gimple_val, fb_rvalue);
5430 stmt = gimple_build_cond (TREE_CODE (predicate), arm1, arm2,
5431 label_true, label);
5432 gimple_seq_add_stmt (stmt_list, stmt);
5433 gimple_seq_add_stmt (stmt_list, gimple_build_label (label_true));
5434 }
5435
5436 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5437 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5438 {
5439 simduid = find_omp_clause (orig_clauses, OMP_CLAUSE__SIMDUID_);
5440 if (simduid)
5441 simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
5442 }
5443
5444 for (c = clauses; c ;)
5445 {
5446 tree var, new_var;
5447 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5448
5449 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5450 || (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5451 && !OMP_CLAUSE_LINEAR_NO_COPYOUT (c)))
5452 {
5453 var = OMP_CLAUSE_DECL (c);
5454 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5455 && OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c)
5456 && is_taskloop_ctx (ctx))
5457 {
5458 gcc_checking_assert (ctx->outer && is_task_ctx (ctx->outer));
5459 new_var = lookup_decl (var, ctx->outer);
5460 }
5461 else
5462 {
5463 new_var = lookup_decl (var, ctx);
5464 /* Avoid uninitialized warnings for lastprivate and
5465 for linear iterators. */
5466 if (predicate
5467 && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5468 || OMP_CLAUSE_LINEAR_NO_COPYIN (c)))
5469 TREE_NO_WARNING (new_var) = 1;
5470 }
5471
5472 if (simduid && DECL_HAS_VALUE_EXPR_P (new_var))
5473 {
5474 tree val = DECL_VALUE_EXPR (new_var);
5475 if (TREE_CODE (val) == ARRAY_REF
5476 && VAR_P (TREE_OPERAND (val, 0))
5477 && lookup_attribute ("omp simd array",
5478 DECL_ATTRIBUTES (TREE_OPERAND (val,
5479 0))))
5480 {
5481 if (lastlane == NULL)
5482 {
5483 lastlane = create_tmp_var (unsigned_type_node);
5484 gcall *g
5485 = gimple_build_call_internal (IFN_GOMP_SIMD_LAST_LANE,
5486 2, simduid,
5487 TREE_OPERAND (val, 1));
5488 gimple_call_set_lhs (g, lastlane);
5489 gimple_seq_add_stmt (stmt_list, g);
5490 }
5491 new_var = build4 (ARRAY_REF, TREE_TYPE (val),
5492 TREE_OPERAND (val, 0), lastlane,
5493 NULL_TREE, NULL_TREE);
5494 }
5495 }
5496
5497 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5498 && OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c))
5499 {
5500 lower_omp (&OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c), ctx);
5501 gimple_seq_add_seq (stmt_list,
5502 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c));
5503 OMP_CLAUSE_LASTPRIVATE_GIMPLE_SEQ (c) = NULL;
5504 }
5505 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
5506 && OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c))
5507 {
5508 lower_omp (&OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c), ctx);
5509 gimple_seq_add_seq (stmt_list,
5510 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c));
5511 OMP_CLAUSE_LINEAR_GIMPLE_SEQ (c) = NULL;
5512 }
5513
5514 x = NULL_TREE;
5515 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
5516 && OMP_CLAUSE_LASTPRIVATE_TASKLOOP_IV (c))
5517 {
5518 gcc_checking_assert (is_taskloop_ctx (ctx));
5519 tree ovar = maybe_lookup_decl_in_outer_ctx (var,
5520 ctx->outer->outer);
5521 if (is_global_var (ovar))
5522 x = ovar;
5523 }
5524 if (!x)
5525 x = build_outer_var_ref (var, ctx, true);
5526 if (is_reference (var))
5527 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5528 x = lang_hooks.decls.omp_clause_assign_op (c, x, new_var);
5529 gimplify_and_add (x, stmt_list);
5530 }
5531 c = OMP_CLAUSE_CHAIN (c);
5532 if (c == NULL && !par_clauses)
5533 {
5534 /* If this was a workshare clause, see if it had been combined
5535 with its parallel. In that case, continue looking for the
5536 clauses also on the parallel statement itself. */
5537 if (is_parallel_ctx (ctx))
5538 break;
5539
5540 ctx = ctx->outer;
5541 if (ctx == NULL || !is_parallel_ctx (ctx))
5542 break;
5543
5544 c = find_omp_clause (gimple_omp_parallel_clauses (ctx->stmt),
5545 OMP_CLAUSE_LASTPRIVATE);
5546 par_clauses = true;
5547 }
5548 }
5549
5550 if (label)
5551 gimple_seq_add_stmt (stmt_list, gimple_build_label (label));
5552 }
5553
5554 /* Lower the OpenACC reductions of CLAUSES for compute axis LEVEL
5555 (which might be a placeholder). INNER is true if this is an inner
5556 axis of a multi-axis loop. FORK and JOIN are (optional) fork and
5557 join markers. Generate the before-loop forking sequence in
5558 FORK_SEQ and the after-loop joining sequence to JOIN_SEQ. The
5559 general form of these sequences is
5560
5561 GOACC_REDUCTION_SETUP
5562 GOACC_FORK
5563 GOACC_REDUCTION_INIT
5564 ...
5565 GOACC_REDUCTION_FINI
5566 GOACC_JOIN
5567 GOACC_REDUCTION_TEARDOWN. */
5568
5569 static void
5570 lower_oacc_reductions (location_t loc, tree clauses, tree level, bool inner,
5571 gcall *fork, gcall *join, gimple_seq *fork_seq,
5572 gimple_seq *join_seq, omp_context *ctx)
5573 {
5574 gimple_seq before_fork = NULL;
5575 gimple_seq after_fork = NULL;
5576 gimple_seq before_join = NULL;
5577 gimple_seq after_join = NULL;
5578 tree init_code = NULL_TREE, fini_code = NULL_TREE,
5579 setup_code = NULL_TREE, teardown_code = NULL_TREE;
5580 unsigned offset = 0;
5581
5582 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
5583 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5584 {
5585 tree orig = OMP_CLAUSE_DECL (c);
5586 tree var = maybe_lookup_decl (orig, ctx);
5587 tree ref_to_res = NULL_TREE;
5588 tree incoming, outgoing, v1, v2, v3;
5589 bool is_private = false;
5590
5591 enum tree_code rcode = OMP_CLAUSE_REDUCTION_CODE (c);
5592 if (rcode == MINUS_EXPR)
5593 rcode = PLUS_EXPR;
5594 else if (rcode == TRUTH_ANDIF_EXPR)
5595 rcode = BIT_AND_EXPR;
5596 else if (rcode == TRUTH_ORIF_EXPR)
5597 rcode = BIT_IOR_EXPR;
5598 tree op = build_int_cst (unsigned_type_node, rcode);
5599
5600 if (!var)
5601 var = orig;
5602
5603 incoming = outgoing = var;
5604
5605 if (!inner)
5606 {
5607 /* See if an outer construct also reduces this variable. */
5608 omp_context *outer = ctx;
5609
5610 while (omp_context *probe = outer->outer)
5611 {
5612 enum gimple_code type = gimple_code (probe->stmt);
5613 tree cls;
5614
5615 switch (type)
5616 {
5617 case GIMPLE_OMP_FOR:
5618 cls = gimple_omp_for_clauses (probe->stmt);
5619 break;
5620
5621 case GIMPLE_OMP_TARGET:
5622 if (gimple_omp_target_kind (probe->stmt)
5623 != GF_OMP_TARGET_KIND_OACC_PARALLEL)
5624 goto do_lookup;
5625
5626 cls = gimple_omp_target_clauses (probe->stmt);
5627 break;
5628
5629 default:
5630 goto do_lookup;
5631 }
5632
5633 outer = probe;
5634 for (; cls; cls = OMP_CLAUSE_CHAIN (cls))
5635 if (OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_REDUCTION
5636 && orig == OMP_CLAUSE_DECL (cls))
5637 {
5638 incoming = outgoing = lookup_decl (orig, probe);
5639 goto has_outer_reduction;
5640 }
5641 else if ((OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_FIRSTPRIVATE
5642 || OMP_CLAUSE_CODE (cls) == OMP_CLAUSE_PRIVATE)
5643 && orig == OMP_CLAUSE_DECL (cls))
5644 {
5645 is_private = true;
5646 goto do_lookup;
5647 }
5648 }
5649
5650 do_lookup:
5651 /* This is the outermost construct with this reduction,
5652 see if there's a mapping for it. */
5653 if (gimple_code (outer->stmt) == GIMPLE_OMP_TARGET
5654 && maybe_lookup_field (orig, outer) && !is_private)
5655 {
5656 ref_to_res = build_receiver_ref (orig, false, outer);
5657 if (is_reference (orig))
5658 ref_to_res = build_simple_mem_ref (ref_to_res);
5659
5660 tree type = TREE_TYPE (var);
5661 if (POINTER_TYPE_P (type))
5662 type = TREE_TYPE (type);
5663
5664 outgoing = var;
5665 incoming = omp_reduction_init_op (loc, rcode, type);
5666 }
5667 else
5668 {
5669 /* Try to look at enclosing contexts for reduction var,
5670 use original if no mapping found. */
5671 tree t = NULL_TREE;
5672 omp_context *c = ctx->outer;
5673 while (c && !t)
5674 {
5675 t = maybe_lookup_decl (orig, c);
5676 c = c->outer;
5677 }
5678 incoming = outgoing = (t ? t : orig);
5679 }
5680
5681 has_outer_reduction:;
5682 }
5683
5684 if (!ref_to_res)
5685 ref_to_res = integer_zero_node;
5686
5687 if (is_reference (orig))
5688 {
5689 tree type = TREE_TYPE (var);
5690 const char *id = IDENTIFIER_POINTER (DECL_NAME (var));
5691
5692 if (!inner)
5693 {
5694 tree x = create_tmp_var (TREE_TYPE (type), id);
5695 gimplify_assign (var, build_fold_addr_expr (x), fork_seq);
5696 }
5697
5698 v1 = create_tmp_var (type, id);
5699 v2 = create_tmp_var (type, id);
5700 v3 = create_tmp_var (type, id);
5701
5702 gimplify_assign (v1, var, fork_seq);
5703 gimplify_assign (v2, var, fork_seq);
5704 gimplify_assign (v3, var, fork_seq);
5705
5706 var = build_simple_mem_ref (var);
5707 v1 = build_simple_mem_ref (v1);
5708 v2 = build_simple_mem_ref (v2);
5709 v3 = build_simple_mem_ref (v3);
5710 outgoing = build_simple_mem_ref (outgoing);
5711
5712 if (!TREE_CONSTANT (incoming))
5713 incoming = build_simple_mem_ref (incoming);
5714 }
5715 else
5716 v1 = v2 = v3 = var;
5717
5718 /* Determine position in reduction buffer, which may be used
5719 by target. */
5720 enum machine_mode mode = TYPE_MODE (TREE_TYPE (var));
5721 unsigned align = GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT;
5722 offset = (offset + align - 1) & ~(align - 1);
5723 tree off = build_int_cst (sizetype, offset);
5724 offset += GET_MODE_SIZE (mode);
5725
5726 if (!init_code)
5727 {
5728 init_code = build_int_cst (integer_type_node,
5729 IFN_GOACC_REDUCTION_INIT);
5730 fini_code = build_int_cst (integer_type_node,
5731 IFN_GOACC_REDUCTION_FINI);
5732 setup_code = build_int_cst (integer_type_node,
5733 IFN_GOACC_REDUCTION_SETUP);
5734 teardown_code = build_int_cst (integer_type_node,
5735 IFN_GOACC_REDUCTION_TEARDOWN);
5736 }
5737
5738 tree setup_call
5739 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5740 TREE_TYPE (var), 6, setup_code,
5741 unshare_expr (ref_to_res),
5742 incoming, level, op, off);
5743 tree init_call
5744 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5745 TREE_TYPE (var), 6, init_code,
5746 unshare_expr (ref_to_res),
5747 v1, level, op, off);
5748 tree fini_call
5749 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5750 TREE_TYPE (var), 6, fini_code,
5751 unshare_expr (ref_to_res),
5752 v2, level, op, off);
5753 tree teardown_call
5754 = build_call_expr_internal_loc (loc, IFN_GOACC_REDUCTION,
5755 TREE_TYPE (var), 6, teardown_code,
5756 ref_to_res, v3, level, op, off);
5757
5758 gimplify_assign (v1, setup_call, &before_fork);
5759 gimplify_assign (v2, init_call, &after_fork);
5760 gimplify_assign (v3, fini_call, &before_join);
5761 gimplify_assign (outgoing, teardown_call, &after_join);
5762 }
5763
5764 /* Now stitch things together. */
5765 gimple_seq_add_seq (fork_seq, before_fork);
5766 if (fork)
5767 gimple_seq_add_stmt (fork_seq, fork);
5768 gimple_seq_add_seq (fork_seq, after_fork);
5769
5770 gimple_seq_add_seq (join_seq, before_join);
5771 if (join)
5772 gimple_seq_add_stmt (join_seq, join);
5773 gimple_seq_add_seq (join_seq, after_join);
5774 }
5775
5776 /* Generate code to implement the REDUCTION clauses. */
5777
5778 static void
5779 lower_reduction_clauses (tree clauses, gimple_seq *stmt_seqp, omp_context *ctx)
5780 {
5781 gimple_seq sub_seq = NULL;
5782 gimple *stmt;
5783 tree x, c;
5784 int count = 0;
5785
5786 /* OpenACC loop reductions are handled elsewhere. */
5787 if (is_gimple_omp_oacc (ctx->stmt))
5788 return;
5789
5790 /* SIMD reductions are handled in lower_rec_input_clauses. */
5791 if (gimple_code (ctx->stmt) == GIMPLE_OMP_FOR
5792 && gimple_omp_for_kind (ctx->stmt) & GF_OMP_FOR_SIMD)
5793 return;
5794
5795 /* First see if there is exactly one reduction clause. Use OMP_ATOMIC
5796 update in that case, otherwise use a lock. */
5797 for (c = clauses; c && count < 2; c = OMP_CLAUSE_CHAIN (c))
5798 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
5799 {
5800 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
5801 || TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5802 {
5803 /* Never use OMP_ATOMIC for array reductions or UDRs. */
5804 count = -1;
5805 break;
5806 }
5807 count++;
5808 }
5809
5810 if (count == 0)
5811 return;
5812
5813 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
5814 {
5815 tree var, ref, new_var, orig_var;
5816 enum tree_code code;
5817 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
5818
5819 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION)
5820 continue;
5821
5822 orig_var = var = OMP_CLAUSE_DECL (c);
5823 if (TREE_CODE (var) == MEM_REF)
5824 {
5825 var = TREE_OPERAND (var, 0);
5826 if (TREE_CODE (var) == POINTER_PLUS_EXPR)
5827 var = TREE_OPERAND (var, 0);
5828 if (TREE_CODE (var) == INDIRECT_REF
5829 || TREE_CODE (var) == ADDR_EXPR)
5830 var = TREE_OPERAND (var, 0);
5831 orig_var = var;
5832 if (is_variable_sized (var))
5833 {
5834 gcc_assert (DECL_HAS_VALUE_EXPR_P (var));
5835 var = DECL_VALUE_EXPR (var);
5836 gcc_assert (TREE_CODE (var) == INDIRECT_REF);
5837 var = TREE_OPERAND (var, 0);
5838 gcc_assert (DECL_P (var));
5839 }
5840 }
5841 new_var = lookup_decl (var, ctx);
5842 if (var == OMP_CLAUSE_DECL (c) && is_reference (var))
5843 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5844 ref = build_outer_var_ref (var, ctx);
5845 code = OMP_CLAUSE_REDUCTION_CODE (c);
5846
5847 /* reduction(-:var) sums up the partial results, so it acts
5848 identically to reduction(+:var). */
5849 if (code == MINUS_EXPR)
5850 code = PLUS_EXPR;
5851
5852 if (count == 1)
5853 {
5854 tree addr = build_fold_addr_expr_loc (clause_loc, ref);
5855
5856 addr = save_expr (addr);
5857 ref = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (addr)), addr);
5858 x = fold_build2_loc (clause_loc, code, TREE_TYPE (ref), ref, new_var);
5859 x = build2 (OMP_ATOMIC, void_type_node, addr, x);
5860 gimplify_and_add (x, stmt_seqp);
5861 return;
5862 }
5863 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
5864 {
5865 tree d = OMP_CLAUSE_DECL (c);
5866 tree type = TREE_TYPE (d);
5867 tree v = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5868 tree i = create_tmp_var (TREE_TYPE (v), NULL);
5869 tree ptype = build_pointer_type (TREE_TYPE (type));
5870 tree bias = TREE_OPERAND (d, 1);
5871 d = TREE_OPERAND (d, 0);
5872 if (TREE_CODE (d) == POINTER_PLUS_EXPR)
5873 {
5874 tree b = TREE_OPERAND (d, 1);
5875 b = maybe_lookup_decl (b, ctx);
5876 if (b == NULL)
5877 {
5878 b = TREE_OPERAND (d, 1);
5879 b = maybe_lookup_decl_in_outer_ctx (b, ctx);
5880 }
5881 if (integer_zerop (bias))
5882 bias = b;
5883 else
5884 {
5885 bias = fold_convert_loc (clause_loc, TREE_TYPE (b), bias);
5886 bias = fold_build2_loc (clause_loc, PLUS_EXPR,
5887 TREE_TYPE (b), b, bias);
5888 }
5889 d = TREE_OPERAND (d, 0);
5890 }
5891 /* For ref build_outer_var_ref already performs this, so
5892 only new_var needs a dereference. */
5893 if (TREE_CODE (d) == INDIRECT_REF)
5894 {
5895 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
5896 gcc_assert (is_reference (var) && var == orig_var);
5897 }
5898 else if (TREE_CODE (d) == ADDR_EXPR)
5899 {
5900 if (orig_var == var)
5901 {
5902 new_var = build_fold_addr_expr (new_var);
5903 ref = build_fold_addr_expr (ref);
5904 }
5905 }
5906 else
5907 {
5908 gcc_assert (orig_var == var);
5909 if (is_reference (var))
5910 ref = build_fold_addr_expr (ref);
5911 }
5912 if (DECL_P (v))
5913 {
5914 tree t = maybe_lookup_decl (v, ctx);
5915 if (t)
5916 v = t;
5917 else
5918 v = maybe_lookup_decl_in_outer_ctx (v, ctx);
5919 gimplify_expr (&v, stmt_seqp, NULL, is_gimple_val, fb_rvalue);
5920 }
5921 if (!integer_zerop (bias))
5922 {
5923 bias = fold_convert_loc (clause_loc, sizetype, bias);
5924 new_var = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5925 TREE_TYPE (new_var), new_var,
5926 unshare_expr (bias));
5927 ref = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
5928 TREE_TYPE (ref), ref, bias);
5929 }
5930 new_var = fold_convert_loc (clause_loc, ptype, new_var);
5931 ref = fold_convert_loc (clause_loc, ptype, ref);
5932 tree m = create_tmp_var (ptype, NULL);
5933 gimplify_assign (m, new_var, stmt_seqp);
5934 new_var = m;
5935 m = create_tmp_var (ptype, NULL);
5936 gimplify_assign (m, ref, stmt_seqp);
5937 ref = m;
5938 gimplify_assign (i, build_int_cst (TREE_TYPE (v), 0), stmt_seqp);
5939 tree body = create_artificial_label (UNKNOWN_LOCATION);
5940 tree end = create_artificial_label (UNKNOWN_LOCATION);
5941 gimple_seq_add_stmt (&sub_seq, gimple_build_label (body));
5942 tree priv = build_simple_mem_ref_loc (clause_loc, new_var);
5943 tree out = build_simple_mem_ref_loc (clause_loc, ref);
5944 if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5945 {
5946 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5947 tree decl_placeholder
5948 = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c);
5949 SET_DECL_VALUE_EXPR (placeholder, out);
5950 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5951 SET_DECL_VALUE_EXPR (decl_placeholder, priv);
5952 DECL_HAS_VALUE_EXPR_P (decl_placeholder) = 1;
5953 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5954 gimple_seq_add_seq (&sub_seq,
5955 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5956 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5957 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5958 OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = NULL;
5959 }
5960 else
5961 {
5962 x = build2 (code, TREE_TYPE (out), out, priv);
5963 out = unshare_expr (out);
5964 gimplify_assign (out, x, &sub_seq);
5965 }
5966 gimple *g = gimple_build_assign (new_var, POINTER_PLUS_EXPR, new_var,
5967 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5968 gimple_seq_add_stmt (&sub_seq, g);
5969 g = gimple_build_assign (ref, POINTER_PLUS_EXPR, ref,
5970 TYPE_SIZE_UNIT (TREE_TYPE (type)));
5971 gimple_seq_add_stmt (&sub_seq, g);
5972 g = gimple_build_assign (i, PLUS_EXPR, i,
5973 build_int_cst (TREE_TYPE (i), 1));
5974 gimple_seq_add_stmt (&sub_seq, g);
5975 g = gimple_build_cond (LE_EXPR, i, v, body, end);
5976 gimple_seq_add_stmt (&sub_seq, g);
5977 gimple_seq_add_stmt (&sub_seq, gimple_build_label (end));
5978 }
5979 else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c))
5980 {
5981 tree placeholder = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c);
5982
5983 if (is_reference (var)
5984 && !useless_type_conversion_p (TREE_TYPE (placeholder),
5985 TREE_TYPE (ref)))
5986 ref = build_fold_addr_expr_loc (clause_loc, ref);
5987 SET_DECL_VALUE_EXPR (placeholder, ref);
5988 DECL_HAS_VALUE_EXPR_P (placeholder) = 1;
5989 lower_omp (&OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c), ctx);
5990 gimple_seq_add_seq (&sub_seq, OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c));
5991 OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (c) = NULL;
5992 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL;
5993 }
5994 else
5995 {
5996 x = build2 (code, TREE_TYPE (ref), ref, new_var);
5997 ref = build_outer_var_ref (var, ctx);
5998 gimplify_assign (ref, x, &sub_seq);
5999 }
6000 }
6001
6002 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START),
6003 0);
6004 gimple_seq_add_stmt (stmt_seqp, stmt);
6005
6006 gimple_seq_add_seq (stmt_seqp, sub_seq);
6007
6008 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END),
6009 0);
6010 gimple_seq_add_stmt (stmt_seqp, stmt);
6011 }
6012
6013
6014 /* Generate code to implement the COPYPRIVATE clauses. */
6015
6016 static void
6017 lower_copyprivate_clauses (tree clauses, gimple_seq *slist, gimple_seq *rlist,
6018 omp_context *ctx)
6019 {
6020 tree c;
6021
6022 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6023 {
6024 tree var, new_var, ref, x;
6025 bool by_ref;
6026 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6027
6028 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYPRIVATE)
6029 continue;
6030
6031 var = OMP_CLAUSE_DECL (c);
6032 by_ref = use_pointer_for_field (var, NULL);
6033
6034 ref = build_sender_ref (var, ctx);
6035 x = new_var = lookup_decl_in_outer_ctx (var, ctx);
6036 if (by_ref)
6037 {
6038 x = build_fold_addr_expr_loc (clause_loc, new_var);
6039 x = fold_convert_loc (clause_loc, TREE_TYPE (ref), x);
6040 }
6041 gimplify_assign (ref, x, slist);
6042
6043 ref = build_receiver_ref (var, false, ctx);
6044 if (by_ref)
6045 {
6046 ref = fold_convert_loc (clause_loc,
6047 build_pointer_type (TREE_TYPE (new_var)),
6048 ref);
6049 ref = build_fold_indirect_ref_loc (clause_loc, ref);
6050 }
6051 if (is_reference (var))
6052 {
6053 ref = fold_convert_loc (clause_loc, TREE_TYPE (new_var), ref);
6054 ref = build_simple_mem_ref_loc (clause_loc, ref);
6055 new_var = build_simple_mem_ref_loc (clause_loc, new_var);
6056 }
6057 x = lang_hooks.decls.omp_clause_assign_op (c, new_var, ref);
6058 gimplify_and_add (x, rlist);
6059 }
6060 }
6061
6062
6063 /* Generate code to implement the clauses, FIRSTPRIVATE, COPYIN, LASTPRIVATE,
6064 and REDUCTION from the sender (aka parent) side. */
6065
6066 static void
6067 lower_send_clauses (tree clauses, gimple_seq *ilist, gimple_seq *olist,
6068 omp_context *ctx)
6069 {
6070 tree c, t;
6071 int ignored_looptemp = 0;
6072 bool is_taskloop = false;
6073
6074 /* For taskloop, ignore first two _looptemp_ clauses, those are initialized
6075 by GOMP_taskloop. */
6076 if (is_task_ctx (ctx) && gimple_omp_task_taskloop_p (ctx->stmt))
6077 {
6078 ignored_looptemp = 2;
6079 is_taskloop = true;
6080 }
6081
6082 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
6083 {
6084 tree val, ref, x, var;
6085 bool by_ref, do_in = false, do_out = false;
6086 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
6087
6088 switch (OMP_CLAUSE_CODE (c))
6089 {
6090 case OMP_CLAUSE_PRIVATE:
6091 if (OMP_CLAUSE_PRIVATE_OUTER_REF (c))
6092 break;
6093 continue;
6094 case OMP_CLAUSE_FIRSTPRIVATE:
6095 case OMP_CLAUSE_COPYIN:
6096 case OMP_CLAUSE_LASTPRIVATE:
6097 case OMP_CLAUSE_REDUCTION:
6098 break;
6099 case OMP_CLAUSE_SHARED:
6100 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6101 break;
6102 continue;
6103 case OMP_CLAUSE__LOOPTEMP_:
6104 if (ignored_looptemp)
6105 {
6106 ignored_looptemp--;
6107 continue;
6108 }
6109 break;
6110 default:
6111 continue;
6112 }
6113
6114 val = OMP_CLAUSE_DECL (c);
6115 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
6116 && TREE_CODE (val) == MEM_REF)
6117 {
6118 val = TREE_OPERAND (val, 0);
6119 if (TREE_CODE (val) == POINTER_PLUS_EXPR)
6120 val = TREE_OPERAND (val, 0);
6121 if (TREE_CODE (val) == INDIRECT_REF
6122 || TREE_CODE (val) == ADDR_EXPR)
6123 val = TREE_OPERAND (val, 0);
6124 if (is_variable_sized (val))
6125 continue;
6126 }
6127
6128 /* For OMP_CLAUSE_SHARED_FIRSTPRIVATE, look beyond the
6129 outer taskloop region. */
6130 omp_context *ctx_for_o = ctx;
6131 if (is_taskloop
6132 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
6133 && OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
6134 ctx_for_o = ctx->outer;
6135
6136 var = lookup_decl_in_outer_ctx (val, ctx_for_o);
6137
6138 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_COPYIN
6139 && is_global_var (var))
6140 continue;
6141
6142 t = omp_member_access_dummy_var (var);
6143 if (t)
6144 {
6145 var = DECL_VALUE_EXPR (var);
6146 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx_for_o);
6147 if (o != t)
6148 var = unshare_and_remap (var, t, o);
6149 else
6150 var = unshare_expr (var);
6151 }
6152
6153 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED)
6154 {
6155 /* Handle taskloop firstprivate/lastprivate, where the
6156 lastprivate on GIMPLE_OMP_TASK is represented as
6157 OMP_CLAUSE_SHARED_FIRSTPRIVATE. */
6158 tree f = lookup_sfield ((splay_tree_key) &DECL_UID (val), ctx);
6159 x = omp_build_component_ref (ctx->sender_decl, f);
6160 if (use_pointer_for_field (val, ctx))
6161 var = build_fold_addr_expr (var);
6162 gimplify_assign (x, var, ilist);
6163 DECL_ABSTRACT_ORIGIN (f) = NULL;
6164 continue;
6165 }
6166
6167 if ((OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION
6168 || val == OMP_CLAUSE_DECL (c))
6169 && is_variable_sized (val))
6170 continue;
6171 by_ref = use_pointer_for_field (val, NULL);
6172
6173 switch (OMP_CLAUSE_CODE (c))
6174 {
6175 case OMP_CLAUSE_FIRSTPRIVATE:
6176 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c)
6177 && !by_ref
6178 && is_task_ctx (ctx))
6179 TREE_NO_WARNING (var) = 1;
6180 do_in = true;
6181 break;
6182
6183 case OMP_CLAUSE_PRIVATE:
6184 case OMP_CLAUSE_COPYIN:
6185 case OMP_CLAUSE__LOOPTEMP_:
6186 do_in = true;
6187 break;
6188
6189 case OMP_CLAUSE_LASTPRIVATE:
6190 if (by_ref || is_reference (val))
6191 {
6192 if (OMP_CLAUSE_LASTPRIVATE_FIRSTPRIVATE (c))
6193 continue;
6194 do_in = true;
6195 }
6196 else
6197 {
6198 do_out = true;
6199 if (lang_hooks.decls.omp_private_outer_ref (val))
6200 do_in = true;
6201 }
6202 break;
6203
6204 case OMP_CLAUSE_REDUCTION:
6205 do_in = true;
6206 if (val == OMP_CLAUSE_DECL (c))
6207 do_out = !(by_ref || is_reference (val));
6208 else
6209 by_ref = TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE;
6210 break;
6211
6212 default:
6213 gcc_unreachable ();
6214 }
6215
6216 if (do_in)
6217 {
6218 ref = build_sender_ref (val, ctx);
6219 x = by_ref ? build_fold_addr_expr_loc (clause_loc, var) : var;
6220 gimplify_assign (ref, x, ilist);
6221 if (is_task_ctx (ctx))
6222 DECL_ABSTRACT_ORIGIN (TREE_OPERAND (ref, 1)) = NULL;
6223 }
6224
6225 if (do_out)
6226 {
6227 ref = build_sender_ref (val, ctx);
6228 gimplify_assign (var, ref, olist);
6229 }
6230 }
6231 }
6232
6233 /* Generate code to implement SHARED from the sender (aka parent)
6234 side. This is trickier, since GIMPLE_OMP_PARALLEL_CLAUSES doesn't
6235 list things that got automatically shared. */
6236
6237 static void
6238 lower_send_shared_vars (gimple_seq *ilist, gimple_seq *olist, omp_context *ctx)
6239 {
6240 tree var, ovar, nvar, t, f, x, record_type;
6241
6242 if (ctx->record_type == NULL)
6243 return;
6244
6245 record_type = ctx->srecord_type ? ctx->srecord_type : ctx->record_type;
6246 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
6247 {
6248 ovar = DECL_ABSTRACT_ORIGIN (f);
6249 if (!ovar || TREE_CODE (ovar) == FIELD_DECL)
6250 continue;
6251
6252 nvar = maybe_lookup_decl (ovar, ctx);
6253 if (!nvar || !DECL_HAS_VALUE_EXPR_P (nvar))
6254 continue;
6255
6256 /* If CTX is a nested parallel directive. Find the immediately
6257 enclosing parallel or workshare construct that contains a
6258 mapping for OVAR. */
6259 var = lookup_decl_in_outer_ctx (ovar, ctx);
6260
6261 t = omp_member_access_dummy_var (var);
6262 if (t)
6263 {
6264 var = DECL_VALUE_EXPR (var);
6265 tree o = maybe_lookup_decl_in_outer_ctx (t, ctx);
6266 if (o != t)
6267 var = unshare_and_remap (var, t, o);
6268 else
6269 var = unshare_expr (var);
6270 }
6271
6272 if (use_pointer_for_field (ovar, ctx))
6273 {
6274 x = build_sender_ref (ovar, ctx);
6275 var = build_fold_addr_expr (var);
6276 gimplify_assign (x, var, ilist);
6277 }
6278 else
6279 {
6280 x = build_sender_ref (ovar, ctx);
6281 gimplify_assign (x, var, ilist);
6282
6283 if (!TREE_READONLY (var)
6284 /* We don't need to receive a new reference to a result
6285 or parm decl. In fact we may not store to it as we will
6286 invalidate any pending RSO and generate wrong gimple
6287 during inlining. */
6288 && !((TREE_CODE (var) == RESULT_DECL
6289 || TREE_CODE (var) == PARM_DECL)
6290 && DECL_BY_REFERENCE (var)))
6291 {
6292 x = build_sender_ref (ovar, ctx);
6293 gimplify_assign (var, x, olist);
6294 }
6295 }
6296 }
6297 }
6298
6299 /* Emit an OpenACC head marker call, encapulating the partitioning and
6300 other information that must be processed by the target compiler.
6301 Return the maximum number of dimensions the associated loop might
6302 be partitioned over. */
6303
6304 static unsigned
6305 lower_oacc_head_mark (location_t loc, tree ddvar, tree clauses,
6306 gimple_seq *seq, omp_context *ctx)
6307 {
6308 unsigned levels = 0;
6309 unsigned tag = 0;
6310 tree gang_static = NULL_TREE;
6311 auto_vec<tree, 5> args;
6312
6313 args.quick_push (build_int_cst
6314 (integer_type_node, IFN_UNIQUE_OACC_HEAD_MARK));
6315 args.quick_push (ddvar);
6316 for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
6317 {
6318 switch (OMP_CLAUSE_CODE (c))
6319 {
6320 case OMP_CLAUSE_GANG:
6321 tag |= OLF_DIM_GANG;
6322 gang_static = OMP_CLAUSE_GANG_STATIC_EXPR (c);
6323 /* static:* is represented by -1, and we can ignore it, as
6324 scheduling is always static. */
6325 if (gang_static && integer_minus_onep (gang_static))
6326 gang_static = NULL_TREE;
6327 levels++;
6328 break;
6329
6330 case OMP_CLAUSE_WORKER:
6331 tag |= OLF_DIM_WORKER;
6332 levels++;
6333 break;
6334
6335 case OMP_CLAUSE_VECTOR:
6336 tag |= OLF_DIM_VECTOR;
6337 levels++;
6338 break;
6339
6340 case OMP_CLAUSE_SEQ:
6341 tag |= OLF_SEQ;
6342 break;
6343
6344 case OMP_CLAUSE_AUTO:
6345 tag |= OLF_AUTO;
6346 break;
6347
6348 case OMP_CLAUSE_INDEPENDENT:
6349 tag |= OLF_INDEPENDENT;
6350 break;
6351
6352 default:
6353 continue;
6354 }
6355 }
6356
6357 if (gang_static)
6358 {
6359 if (DECL_P (gang_static))
6360 gang_static = build_outer_var_ref (gang_static, ctx);
6361 tag |= OLF_GANG_STATIC;
6362 }
6363
6364 /* In a parallel region, loops are implicitly INDEPENDENT. */
6365 omp_context *tgt = enclosing_target_ctx (ctx);
6366 if (!tgt || is_oacc_parallel (tgt))
6367 tag |= OLF_INDEPENDENT;
6368
6369 /* A loop lacking SEQ, GANG, WORKER and/or VECTOR is implicitly AUTO. */
6370 if (!(tag & (((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE)
6371 | OLF_SEQ)))
6372 tag |= OLF_AUTO;
6373
6374 /* Ensure at least one level. */
6375 if (!levels)
6376 levels++;
6377
6378 args.quick_push (build_int_cst (integer_type_node, levels));
6379 args.quick_push (build_int_cst (integer_type_node, tag));
6380 if (gang_static)
6381 args.quick_push (gang_static);
6382
6383 gcall *call = gimple_build_call_internal_vec (IFN_UNIQUE, args);
6384 gimple_set_location (call, loc);
6385 gimple_set_lhs (call, ddvar);
6386 gimple_seq_add_stmt (seq, call);
6387
6388 return levels;
6389 }
6390
6391 /* Emit an OpenACC lopp head or tail marker to SEQ. LEVEL is the
6392 partitioning level of the enclosed region. */
6393
6394 static void
6395 lower_oacc_loop_marker (location_t loc, tree ddvar, bool head,
6396 tree tofollow, gimple_seq *seq)
6397 {
6398 int marker_kind = (head ? IFN_UNIQUE_OACC_HEAD_MARK
6399 : IFN_UNIQUE_OACC_TAIL_MARK);
6400 tree marker = build_int_cst (integer_type_node, marker_kind);
6401 int nargs = 2 + (tofollow != NULL_TREE);
6402 gcall *call = gimple_build_call_internal (IFN_UNIQUE, nargs,
6403 marker, ddvar, tofollow);
6404 gimple_set_location (call, loc);
6405 gimple_set_lhs (call, ddvar);
6406 gimple_seq_add_stmt (seq, call);
6407 }
6408
6409 /* Generate the before and after OpenACC loop sequences. CLAUSES are
6410 the loop clauses, from which we extract reductions. Initialize
6411 HEAD and TAIL. */
6412
6413 static void
6414 lower_oacc_head_tail (location_t loc, tree clauses,
6415 gimple_seq *head, gimple_seq *tail, omp_context *ctx)
6416 {
6417 bool inner = false;
6418 tree ddvar = create_tmp_var (integer_type_node, ".data_dep");
6419 gimple_seq_add_stmt (head, gimple_build_assign (ddvar, integer_zero_node));
6420
6421 unsigned count = lower_oacc_head_mark (loc, ddvar, clauses, head, ctx);
6422 tree fork_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_FORK);
6423 tree join_kind = build_int_cst (unsigned_type_node, IFN_UNIQUE_OACC_JOIN);
6424
6425 gcc_assert (count);
6426 for (unsigned done = 1; count; count--, done++)
6427 {
6428 gimple_seq fork_seq = NULL;
6429 gimple_seq join_seq = NULL;
6430
6431 tree place = build_int_cst (integer_type_node, -1);
6432 gcall *fork = gimple_build_call_internal (IFN_UNIQUE, 3,
6433 fork_kind, ddvar, place);
6434 gimple_set_location (fork, loc);
6435 gimple_set_lhs (fork, ddvar);
6436
6437 gcall *join = gimple_build_call_internal (IFN_UNIQUE, 3,
6438 join_kind, ddvar, place);
6439 gimple_set_location (join, loc);
6440 gimple_set_lhs (join, ddvar);
6441
6442 /* Mark the beginning of this level sequence. */
6443 if (inner)
6444 lower_oacc_loop_marker (loc, ddvar, true,
6445 build_int_cst (integer_type_node, count),
6446 &fork_seq);
6447 lower_oacc_loop_marker (loc, ddvar, false,
6448 build_int_cst (integer_type_node, done),
6449 &join_seq);
6450
6451 lower_oacc_reductions (loc, clauses, place, inner,
6452 fork, join, &fork_seq, &join_seq, ctx);
6453
6454 /* Append this level to head. */
6455 gimple_seq_add_seq (head, fork_seq);
6456 /* Prepend it to tail. */
6457 gimple_seq_add_seq (&join_seq, *tail);
6458 *tail = join_seq;
6459
6460 inner = true;
6461 }
6462
6463 /* Mark the end of the sequence. */
6464 lower_oacc_loop_marker (loc, ddvar, true, NULL_TREE, head);
6465 lower_oacc_loop_marker (loc, ddvar, false, NULL_TREE, tail);
6466 }
6467
6468 /* A convenience function to build an empty GIMPLE_COND with just the
6469 condition. */
6470
6471 static gcond *
6472 gimple_build_cond_empty (tree cond)
6473 {
6474 enum tree_code pred_code;
6475 tree lhs, rhs;
6476
6477 gimple_cond_get_ops_from_tree (cond, &pred_code, &lhs, &rhs);
6478 return gimple_build_cond (pred_code, lhs, rhs, NULL_TREE, NULL_TREE);
6479 }
6480
6481 /* Return true if a parallel REGION is within a declare target function or
6482 within a target region and is not a part of a gridified target. */
6483
6484 static bool
6485 parallel_needs_hsa_kernel_p (struct omp_region *region)
6486 {
6487 bool indirect = false;
6488 for (region = region->outer; region; region = region->outer)
6489 {
6490 if (region->type == GIMPLE_OMP_PARALLEL)
6491 indirect = true;
6492 else if (region->type == GIMPLE_OMP_TARGET)
6493 {
6494 gomp_target *tgt_stmt
6495 = as_a <gomp_target *> (last_stmt (region->entry));
6496
6497 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
6498 OMP_CLAUSE__GRIDDIM_))
6499 return indirect;
6500 else
6501 return true;
6502 }
6503 }
6504
6505 if (lookup_attribute ("omp declare target",
6506 DECL_ATTRIBUTES (current_function_decl)))
6507 return true;
6508
6509 return false;
6510 }
6511
6512 static void expand_omp_build_assign (gimple_stmt_iterator *, tree, tree,
6513 bool = false);
6514
6515 /* Build the function calls to GOMP_parallel_start etc to actually
6516 generate the parallel operation. REGION is the parallel region
6517 being expanded. BB is the block where to insert the code. WS_ARGS
6518 will be set if this is a call to a combined parallel+workshare
6519 construct, it contains the list of additional arguments needed by
6520 the workshare construct. */
6521
6522 static void
6523 expand_parallel_call (struct omp_region *region, basic_block bb,
6524 gomp_parallel *entry_stmt,
6525 vec<tree, va_gc> *ws_args)
6526 {
6527 tree t, t1, t2, val, cond, c, clauses, flags;
6528 gimple_stmt_iterator gsi;
6529 gimple *stmt;
6530 enum built_in_function start_ix;
6531 int start_ix2;
6532 location_t clause_loc;
6533 vec<tree, va_gc> *args;
6534
6535 clauses = gimple_omp_parallel_clauses (entry_stmt);
6536
6537 /* Determine what flavor of GOMP_parallel we will be
6538 emitting. */
6539 start_ix = BUILT_IN_GOMP_PARALLEL;
6540 if (is_combined_parallel (region))
6541 {
6542 switch (region->inner->type)
6543 {
6544 case GIMPLE_OMP_FOR:
6545 gcc_assert (region->inner->sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
6546 switch (region->inner->sched_kind)
6547 {
6548 case OMP_CLAUSE_SCHEDULE_RUNTIME:
6549 start_ix2 = 3;
6550 break;
6551 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
6552 case OMP_CLAUSE_SCHEDULE_GUIDED:
6553 if (region->inner->sched_modifiers
6554 & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
6555 {
6556 start_ix2 = 3 + region->inner->sched_kind;
6557 break;
6558 }
6559 /* FALLTHRU */
6560 default:
6561 start_ix2 = region->inner->sched_kind;
6562 break;
6563 }
6564 start_ix2 += (int) BUILT_IN_GOMP_PARALLEL_LOOP_STATIC;
6565 start_ix = (enum built_in_function) start_ix2;
6566 break;
6567 case GIMPLE_OMP_SECTIONS:
6568 start_ix = BUILT_IN_GOMP_PARALLEL_SECTIONS;
6569 break;
6570 default:
6571 gcc_unreachable ();
6572 }
6573 }
6574
6575 /* By default, the value of NUM_THREADS is zero (selected at run time)
6576 and there is no conditional. */
6577 cond = NULL_TREE;
6578 val = build_int_cst (unsigned_type_node, 0);
6579 flags = build_int_cst (unsigned_type_node, 0);
6580
6581 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
6582 if (c)
6583 cond = OMP_CLAUSE_IF_EXPR (c);
6584
6585 c = find_omp_clause (clauses, OMP_CLAUSE_NUM_THREADS);
6586 if (c)
6587 {
6588 val = OMP_CLAUSE_NUM_THREADS_EXPR (c);
6589 clause_loc = OMP_CLAUSE_LOCATION (c);
6590 }
6591 else
6592 clause_loc = gimple_location (entry_stmt);
6593
6594 c = find_omp_clause (clauses, OMP_CLAUSE_PROC_BIND);
6595 if (c)
6596 flags = build_int_cst (unsigned_type_node, OMP_CLAUSE_PROC_BIND_KIND (c));
6597
6598 /* Ensure 'val' is of the correct type. */
6599 val = fold_convert_loc (clause_loc, unsigned_type_node, val);
6600
6601 /* If we found the clause 'if (cond)', build either
6602 (cond != 0) or (cond ? val : 1u). */
6603 if (cond)
6604 {
6605 cond = gimple_boolify (cond);
6606
6607 if (integer_zerop (val))
6608 val = fold_build2_loc (clause_loc,
6609 EQ_EXPR, unsigned_type_node, cond,
6610 build_int_cst (TREE_TYPE (cond), 0));
6611 else
6612 {
6613 basic_block cond_bb, then_bb, else_bb;
6614 edge e, e_then, e_else;
6615 tree tmp_then, tmp_else, tmp_join, tmp_var;
6616
6617 tmp_var = create_tmp_var (TREE_TYPE (val));
6618 if (gimple_in_ssa_p (cfun))
6619 {
6620 tmp_then = make_ssa_name (tmp_var);
6621 tmp_else = make_ssa_name (tmp_var);
6622 tmp_join = make_ssa_name (tmp_var);
6623 }
6624 else
6625 {
6626 tmp_then = tmp_var;
6627 tmp_else = tmp_var;
6628 tmp_join = tmp_var;
6629 }
6630
6631 e = split_block_after_labels (bb);
6632 cond_bb = e->src;
6633 bb = e->dest;
6634 remove_edge (e);
6635
6636 then_bb = create_empty_bb (cond_bb);
6637 else_bb = create_empty_bb (then_bb);
6638 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
6639 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
6640
6641 stmt = gimple_build_cond_empty (cond);
6642 gsi = gsi_start_bb (cond_bb);
6643 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
6644
6645 gsi = gsi_start_bb (then_bb);
6646 expand_omp_build_assign (&gsi, tmp_then, val, true);
6647
6648 gsi = gsi_start_bb (else_bb);
6649 expand_omp_build_assign (&gsi, tmp_else,
6650 build_int_cst (unsigned_type_node, 1),
6651 true);
6652
6653 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
6654 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
6655 add_bb_to_loop (then_bb, cond_bb->loop_father);
6656 add_bb_to_loop (else_bb, cond_bb->loop_father);
6657 e_then = make_edge (then_bb, bb, EDGE_FALLTHRU);
6658 e_else = make_edge (else_bb, bb, EDGE_FALLTHRU);
6659
6660 if (gimple_in_ssa_p (cfun))
6661 {
6662 gphi *phi = create_phi_node (tmp_join, bb);
6663 add_phi_arg (phi, tmp_then, e_then, UNKNOWN_LOCATION);
6664 add_phi_arg (phi, tmp_else, e_else, UNKNOWN_LOCATION);
6665 }
6666
6667 val = tmp_join;
6668 }
6669
6670 gsi = gsi_start_bb (bb);
6671 val = force_gimple_operand_gsi (&gsi, val, true, NULL_TREE,
6672 false, GSI_CONTINUE_LINKING);
6673 }
6674
6675 gsi = gsi_last_bb (bb);
6676 t = gimple_omp_parallel_data_arg (entry_stmt);
6677 if (t == NULL)
6678 t1 = null_pointer_node;
6679 else
6680 t1 = build_fold_addr_expr (t);
6681 tree child_fndecl = gimple_omp_parallel_child_fn (entry_stmt);
6682 t2 = build_fold_addr_expr (child_fndecl);
6683
6684 vec_alloc (args, 4 + vec_safe_length (ws_args));
6685 args->quick_push (t2);
6686 args->quick_push (t1);
6687 args->quick_push (val);
6688 if (ws_args)
6689 args->splice (*ws_args);
6690 args->quick_push (flags);
6691
6692 t = build_call_expr_loc_vec (UNKNOWN_LOCATION,
6693 builtin_decl_explicit (start_ix), args);
6694
6695 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6696 false, GSI_CONTINUE_LINKING);
6697
6698 if (hsa_gen_requested_p ()
6699 && parallel_needs_hsa_kernel_p (region))
6700 {
6701 cgraph_node *child_cnode = cgraph_node::get (child_fndecl);
6702 hsa_register_kernel (child_cnode);
6703 }
6704 }
6705
6706 /* Insert a function call whose name is FUNC_NAME with the information from
6707 ENTRY_STMT into the basic_block BB. */
6708
6709 static void
6710 expand_cilk_for_call (basic_block bb, gomp_parallel *entry_stmt,
6711 vec <tree, va_gc> *ws_args)
6712 {
6713 tree t, t1, t2;
6714 gimple_stmt_iterator gsi;
6715 vec <tree, va_gc> *args;
6716
6717 gcc_assert (vec_safe_length (ws_args) == 2);
6718 tree func_name = (*ws_args)[0];
6719 tree grain = (*ws_args)[1];
6720
6721 tree clauses = gimple_omp_parallel_clauses (entry_stmt);
6722 tree count = find_omp_clause (clauses, OMP_CLAUSE__CILK_FOR_COUNT_);
6723 gcc_assert (count != NULL_TREE);
6724 count = OMP_CLAUSE_OPERAND (count, 0);
6725
6726 gsi = gsi_last_bb (bb);
6727 t = gimple_omp_parallel_data_arg (entry_stmt);
6728 if (t == NULL)
6729 t1 = null_pointer_node;
6730 else
6731 t1 = build_fold_addr_expr (t);
6732 t2 = build_fold_addr_expr (gimple_omp_parallel_child_fn (entry_stmt));
6733
6734 vec_alloc (args, 4);
6735 args->quick_push (t2);
6736 args->quick_push (t1);
6737 args->quick_push (count);
6738 args->quick_push (grain);
6739 t = build_call_expr_loc_vec (UNKNOWN_LOCATION, func_name, args);
6740
6741 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, false,
6742 GSI_CONTINUE_LINKING);
6743 }
6744
6745 /* Build the function call to GOMP_task to actually
6746 generate the task operation. BB is the block where to insert the code. */
6747
6748 static void
6749 expand_task_call (struct omp_region *region, basic_block bb,
6750 gomp_task *entry_stmt)
6751 {
6752 tree t1, t2, t3;
6753 gimple_stmt_iterator gsi;
6754 location_t loc = gimple_location (entry_stmt);
6755
6756 tree clauses = gimple_omp_task_clauses (entry_stmt);
6757
6758 tree ifc = find_omp_clause (clauses, OMP_CLAUSE_IF);
6759 tree untied = find_omp_clause (clauses, OMP_CLAUSE_UNTIED);
6760 tree mergeable = find_omp_clause (clauses, OMP_CLAUSE_MERGEABLE);
6761 tree depend = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
6762 tree finalc = find_omp_clause (clauses, OMP_CLAUSE_FINAL);
6763 tree priority = find_omp_clause (clauses, OMP_CLAUSE_PRIORITY);
6764
6765 unsigned int iflags
6766 = (untied ? GOMP_TASK_FLAG_UNTIED : 0)
6767 | (mergeable ? GOMP_TASK_FLAG_MERGEABLE : 0)
6768 | (depend ? GOMP_TASK_FLAG_DEPEND : 0);
6769
6770 bool taskloop_p = gimple_omp_task_taskloop_p (entry_stmt);
6771 tree startvar = NULL_TREE, endvar = NULL_TREE, step = NULL_TREE;
6772 tree num_tasks = NULL_TREE;
6773 bool ull = false;
6774 if (taskloop_p)
6775 {
6776 gimple *g = last_stmt (region->outer->entry);
6777 gcc_assert (gimple_code (g) == GIMPLE_OMP_FOR
6778 && gimple_omp_for_kind (g) == GF_OMP_FOR_KIND_TASKLOOP);
6779 struct omp_for_data fd;
6780 extract_omp_for_data (as_a <gomp_for *> (g), &fd, NULL);
6781 startvar = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
6782 endvar = find_omp_clause (OMP_CLAUSE_CHAIN (startvar),
6783 OMP_CLAUSE__LOOPTEMP_);
6784 startvar = OMP_CLAUSE_DECL (startvar);
6785 endvar = OMP_CLAUSE_DECL (endvar);
6786 step = fold_convert_loc (loc, fd.iter_type, fd.loop.step);
6787 if (fd.loop.cond_code == LT_EXPR)
6788 iflags |= GOMP_TASK_FLAG_UP;
6789 tree tclauses = gimple_omp_for_clauses (g);
6790 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_NUM_TASKS);
6791 if (num_tasks)
6792 num_tasks = OMP_CLAUSE_NUM_TASKS_EXPR (num_tasks);
6793 else
6794 {
6795 num_tasks = find_omp_clause (tclauses, OMP_CLAUSE_GRAINSIZE);
6796 if (num_tasks)
6797 {
6798 iflags |= GOMP_TASK_FLAG_GRAINSIZE;
6799 num_tasks = OMP_CLAUSE_GRAINSIZE_EXPR (num_tasks);
6800 }
6801 else
6802 num_tasks = integer_zero_node;
6803 }
6804 num_tasks = fold_convert_loc (loc, long_integer_type_node, num_tasks);
6805 if (ifc == NULL_TREE)
6806 iflags |= GOMP_TASK_FLAG_IF;
6807 if (find_omp_clause (tclauses, OMP_CLAUSE_NOGROUP))
6808 iflags |= GOMP_TASK_FLAG_NOGROUP;
6809 ull = fd.iter_type == long_long_unsigned_type_node;
6810 }
6811 else if (priority)
6812 iflags |= GOMP_TASK_FLAG_PRIORITY;
6813
6814 tree flags = build_int_cst (unsigned_type_node, iflags);
6815
6816 tree cond = boolean_true_node;
6817 if (ifc)
6818 {
6819 if (taskloop_p)
6820 {
6821 tree t = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6822 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6823 build_int_cst (unsigned_type_node,
6824 GOMP_TASK_FLAG_IF),
6825 build_int_cst (unsigned_type_node, 0));
6826 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node,
6827 flags, t);
6828 }
6829 else
6830 cond = gimple_boolify (OMP_CLAUSE_IF_EXPR (ifc));
6831 }
6832
6833 if (finalc)
6834 {
6835 tree t = gimple_boolify (OMP_CLAUSE_FINAL_EXPR (finalc));
6836 t = fold_build3_loc (loc, COND_EXPR, unsigned_type_node, t,
6837 build_int_cst (unsigned_type_node,
6838 GOMP_TASK_FLAG_FINAL),
6839 build_int_cst (unsigned_type_node, 0));
6840 flags = fold_build2_loc (loc, PLUS_EXPR, unsigned_type_node, flags, t);
6841 }
6842 if (depend)
6843 depend = OMP_CLAUSE_DECL (depend);
6844 else
6845 depend = build_int_cst (ptr_type_node, 0);
6846 if (priority)
6847 priority = fold_convert (integer_type_node,
6848 OMP_CLAUSE_PRIORITY_EXPR (priority));
6849 else
6850 priority = integer_zero_node;
6851
6852 gsi = gsi_last_bb (bb);
6853 tree t = gimple_omp_task_data_arg (entry_stmt);
6854 if (t == NULL)
6855 t2 = null_pointer_node;
6856 else
6857 t2 = build_fold_addr_expr_loc (loc, t);
6858 t1 = build_fold_addr_expr_loc (loc, gimple_omp_task_child_fn (entry_stmt));
6859 t = gimple_omp_task_copy_fn (entry_stmt);
6860 if (t == NULL)
6861 t3 = null_pointer_node;
6862 else
6863 t3 = build_fold_addr_expr_loc (loc, t);
6864
6865 if (taskloop_p)
6866 t = build_call_expr (ull
6867 ? builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP_ULL)
6868 : builtin_decl_explicit (BUILT_IN_GOMP_TASKLOOP),
6869 11, t1, t2, t3,
6870 gimple_omp_task_arg_size (entry_stmt),
6871 gimple_omp_task_arg_align (entry_stmt), flags,
6872 num_tasks, priority, startvar, endvar, step);
6873 else
6874 t = build_call_expr (builtin_decl_explicit (BUILT_IN_GOMP_TASK),
6875 9, t1, t2, t3,
6876 gimple_omp_task_arg_size (entry_stmt),
6877 gimple_omp_task_arg_align (entry_stmt), cond, flags,
6878 depend, priority);
6879
6880 force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
6881 false, GSI_CONTINUE_LINKING);
6882 }
6883
6884
6885 /* If exceptions are enabled, wrap the statements in BODY in a MUST_NOT_THROW
6886 catch handler and return it. This prevents programs from violating the
6887 structured block semantics with throws. */
6888
6889 static gimple_seq
6890 maybe_catch_exception (gimple_seq body)
6891 {
6892 gimple *g;
6893 tree decl;
6894
6895 if (!flag_exceptions)
6896 return body;
6897
6898 if (lang_hooks.eh_protect_cleanup_actions != NULL)
6899 decl = lang_hooks.eh_protect_cleanup_actions ();
6900 else
6901 decl = builtin_decl_explicit (BUILT_IN_TRAP);
6902
6903 g = gimple_build_eh_must_not_throw (decl);
6904 g = gimple_build_try (body, gimple_seq_alloc_with_stmt (g),
6905 GIMPLE_TRY_CATCH);
6906
6907 return gimple_seq_alloc_with_stmt (g);
6908 }
6909
6910 /* Chain all the DECLs in LIST by their TREE_CHAIN fields. */
6911
6912 static tree
6913 vec2chain (vec<tree, va_gc> *v)
6914 {
6915 tree chain = NULL_TREE, t;
6916 unsigned ix;
6917
6918 FOR_EACH_VEC_SAFE_ELT_REVERSE (v, ix, t)
6919 {
6920 DECL_CHAIN (t) = chain;
6921 chain = t;
6922 }
6923
6924 return chain;
6925 }
6926
6927
6928 /* Remove barriers in REGION->EXIT's block. Note that this is only
6929 valid for GIMPLE_OMP_PARALLEL regions. Since the end of a parallel region
6930 is an implicit barrier, any workshare inside the GIMPLE_OMP_PARALLEL that
6931 left a barrier at the end of the GIMPLE_OMP_PARALLEL region can now be
6932 removed. */
6933
6934 static void
6935 remove_exit_barrier (struct omp_region *region)
6936 {
6937 gimple_stmt_iterator gsi;
6938 basic_block exit_bb;
6939 edge_iterator ei;
6940 edge e;
6941 gimple *stmt;
6942 int any_addressable_vars = -1;
6943
6944 exit_bb = region->exit;
6945
6946 /* If the parallel region doesn't return, we don't have REGION->EXIT
6947 block at all. */
6948 if (! exit_bb)
6949 return;
6950
6951 /* The last insn in the block will be the parallel's GIMPLE_OMP_RETURN. The
6952 workshare's GIMPLE_OMP_RETURN will be in a preceding block. The kinds of
6953 statements that can appear in between are extremely limited -- no
6954 memory operations at all. Here, we allow nothing at all, so the
6955 only thing we allow to precede this GIMPLE_OMP_RETURN is a label. */
6956 gsi = gsi_last_bb (exit_bb);
6957 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
6958 gsi_prev (&gsi);
6959 if (!gsi_end_p (gsi) && gimple_code (gsi_stmt (gsi)) != GIMPLE_LABEL)
6960 return;
6961
6962 FOR_EACH_EDGE (e, ei, exit_bb->preds)
6963 {
6964 gsi = gsi_last_bb (e->src);
6965 if (gsi_end_p (gsi))
6966 continue;
6967 stmt = gsi_stmt (gsi);
6968 if (gimple_code (stmt) == GIMPLE_OMP_RETURN
6969 && !gimple_omp_return_nowait_p (stmt))
6970 {
6971 /* OpenMP 3.0 tasks unfortunately prevent this optimization
6972 in many cases. If there could be tasks queued, the barrier
6973 might be needed to let the tasks run before some local
6974 variable of the parallel that the task uses as shared
6975 runs out of scope. The task can be spawned either
6976 from within current function (this would be easy to check)
6977 or from some function it calls and gets passed an address
6978 of such a variable. */
6979 if (any_addressable_vars < 0)
6980 {
6981 gomp_parallel *parallel_stmt
6982 = as_a <gomp_parallel *> (last_stmt (region->entry));
6983 tree child_fun = gimple_omp_parallel_child_fn (parallel_stmt);
6984 tree local_decls, block, decl;
6985 unsigned ix;
6986
6987 any_addressable_vars = 0;
6988 FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (child_fun), ix, decl)
6989 if (TREE_ADDRESSABLE (decl))
6990 {
6991 any_addressable_vars = 1;
6992 break;
6993 }
6994 for (block = gimple_block (stmt);
6995 !any_addressable_vars
6996 && block
6997 && TREE_CODE (block) == BLOCK;
6998 block = BLOCK_SUPERCONTEXT (block))
6999 {
7000 for (local_decls = BLOCK_VARS (block);
7001 local_decls;
7002 local_decls = DECL_CHAIN (local_decls))
7003 if (TREE_ADDRESSABLE (local_decls))
7004 {
7005 any_addressable_vars = 1;
7006 break;
7007 }
7008 if (block == gimple_block (parallel_stmt))
7009 break;
7010 }
7011 }
7012 if (!any_addressable_vars)
7013 gimple_omp_return_set_nowait (stmt);
7014 }
7015 }
7016 }
7017
7018 static void
7019 remove_exit_barriers (struct omp_region *region)
7020 {
7021 if (region->type == GIMPLE_OMP_PARALLEL)
7022 remove_exit_barrier (region);
7023
7024 if (region->inner)
7025 {
7026 region = region->inner;
7027 remove_exit_barriers (region);
7028 while (region->next)
7029 {
7030 region = region->next;
7031 remove_exit_barriers (region);
7032 }
7033 }
7034 }
7035
7036 /* Optimize omp_get_thread_num () and omp_get_num_threads ()
7037 calls. These can't be declared as const functions, but
7038 within one parallel body they are constant, so they can be
7039 transformed there into __builtin_omp_get_{thread_num,num_threads} ()
7040 which are declared const. Similarly for task body, except
7041 that in untied task omp_get_thread_num () can change at any task
7042 scheduling point. */
7043
7044 static void
7045 optimize_omp_library_calls (gimple *entry_stmt)
7046 {
7047 basic_block bb;
7048 gimple_stmt_iterator gsi;
7049 tree thr_num_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7050 tree thr_num_id = DECL_ASSEMBLER_NAME (thr_num_tree);
7051 tree num_thr_tree = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7052 tree num_thr_id = DECL_ASSEMBLER_NAME (num_thr_tree);
7053 bool untied_task = (gimple_code (entry_stmt) == GIMPLE_OMP_TASK
7054 && find_omp_clause (gimple_omp_task_clauses (entry_stmt),
7055 OMP_CLAUSE_UNTIED) != NULL);
7056
7057 FOR_EACH_BB_FN (bb, cfun)
7058 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
7059 {
7060 gimple *call = gsi_stmt (gsi);
7061 tree decl;
7062
7063 if (is_gimple_call (call)
7064 && (decl = gimple_call_fndecl (call))
7065 && DECL_EXTERNAL (decl)
7066 && TREE_PUBLIC (decl)
7067 && DECL_INITIAL (decl) == NULL)
7068 {
7069 tree built_in;
7070
7071 if (DECL_NAME (decl) == thr_num_id)
7072 {
7073 /* In #pragma omp task untied omp_get_thread_num () can change
7074 during the execution of the task region. */
7075 if (untied_task)
7076 continue;
7077 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
7078 }
7079 else if (DECL_NAME (decl) == num_thr_id)
7080 built_in = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
7081 else
7082 continue;
7083
7084 if (DECL_ASSEMBLER_NAME (decl) != DECL_ASSEMBLER_NAME (built_in)
7085 || gimple_call_num_args (call) != 0)
7086 continue;
7087
7088 if (flag_exceptions && !TREE_NOTHROW (decl))
7089 continue;
7090
7091 if (TREE_CODE (TREE_TYPE (decl)) != FUNCTION_TYPE
7092 || !types_compatible_p (TREE_TYPE (TREE_TYPE (decl)),
7093 TREE_TYPE (TREE_TYPE (built_in))))
7094 continue;
7095
7096 gimple_call_set_fndecl (call, built_in);
7097 }
7098 }
7099 }
7100
7101 /* Callback for expand_omp_build_assign. Return non-NULL if *tp needs to be
7102 regimplified. */
7103
7104 static tree
7105 expand_omp_regimplify_p (tree *tp, int *walk_subtrees, void *)
7106 {
7107 tree t = *tp;
7108
7109 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
7110 if (VAR_P (t) && DECL_HAS_VALUE_EXPR_P (t))
7111 return t;
7112
7113 if (TREE_CODE (t) == ADDR_EXPR)
7114 recompute_tree_invariant_for_addr_expr (t);
7115
7116 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
7117 return NULL_TREE;
7118 }
7119
7120 /* Prepend or append TO = FROM assignment before or after *GSI_P. */
7121
7122 static void
7123 expand_omp_build_assign (gimple_stmt_iterator *gsi_p, tree to, tree from,
7124 bool after)
7125 {
7126 bool simple_p = DECL_P (to) && TREE_ADDRESSABLE (to);
7127 from = force_gimple_operand_gsi (gsi_p, from, simple_p, NULL_TREE,
7128 !after, after ? GSI_CONTINUE_LINKING
7129 : GSI_SAME_STMT);
7130 gimple *stmt = gimple_build_assign (to, from);
7131 if (after)
7132 gsi_insert_after (gsi_p, stmt, GSI_CONTINUE_LINKING);
7133 else
7134 gsi_insert_before (gsi_p, stmt, GSI_SAME_STMT);
7135 if (walk_tree (&from, expand_omp_regimplify_p, NULL, NULL)
7136 || walk_tree (&to, expand_omp_regimplify_p, NULL, NULL))
7137 {
7138 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
7139 gimple_regimplify_operands (stmt, &gsi);
7140 }
7141 }
7142
7143 /* Expand the OpenMP parallel or task directive starting at REGION. */
7144
7145 static void
7146 expand_omp_taskreg (struct omp_region *region)
7147 {
7148 basic_block entry_bb, exit_bb, new_bb;
7149 struct function *child_cfun;
7150 tree child_fn, block, t;
7151 gimple_stmt_iterator gsi;
7152 gimple *entry_stmt, *stmt;
7153 edge e;
7154 vec<tree, va_gc> *ws_args;
7155
7156 entry_stmt = last_stmt (region->entry);
7157 child_fn = gimple_omp_taskreg_child_fn (entry_stmt);
7158 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
7159
7160 entry_bb = region->entry;
7161 if (gimple_code (entry_stmt) == GIMPLE_OMP_TASK)
7162 exit_bb = region->cont;
7163 else
7164 exit_bb = region->exit;
7165
7166 bool is_cilk_for
7167 = (flag_cilkplus
7168 && gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL
7169 && find_omp_clause (gimple_omp_parallel_clauses (entry_stmt),
7170 OMP_CLAUSE__CILK_FOR_COUNT_) != NULL_TREE);
7171
7172 if (is_cilk_for)
7173 /* If it is a _Cilk_for statement, it is modelled *like* a parallel for,
7174 and the inner statement contains the name of the built-in function
7175 and grain. */
7176 ws_args = region->inner->ws_args;
7177 else if (is_combined_parallel (region))
7178 ws_args = region->ws_args;
7179 else
7180 ws_args = NULL;
7181
7182 if (child_cfun->cfg)
7183 {
7184 /* Due to inlining, it may happen that we have already outlined
7185 the region, in which case all we need to do is make the
7186 sub-graph unreachable and emit the parallel call. */
7187 edge entry_succ_e, exit_succ_e;
7188
7189 entry_succ_e = single_succ_edge (entry_bb);
7190
7191 gsi = gsi_last_bb (entry_bb);
7192 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_PARALLEL
7193 || gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_TASK);
7194 gsi_remove (&gsi, true);
7195
7196 new_bb = entry_bb;
7197 if (exit_bb)
7198 {
7199 exit_succ_e = single_succ_edge (exit_bb);
7200 make_edge (new_bb, exit_succ_e->dest, EDGE_FALLTHRU);
7201 }
7202 remove_edge_and_dominated_blocks (entry_succ_e);
7203 }
7204 else
7205 {
7206 unsigned srcidx, dstidx, num;
7207
7208 /* If the parallel region needs data sent from the parent
7209 function, then the very first statement (except possible
7210 tree profile counter updates) of the parallel body
7211 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
7212 &.OMP_DATA_O is passed as an argument to the child function,
7213 we need to replace it with the argument as seen by the child
7214 function.
7215
7216 In most cases, this will end up being the identity assignment
7217 .OMP_DATA_I = .OMP_DATA_I. However, if the parallel body had
7218 a function call that has been inlined, the original PARM_DECL
7219 .OMP_DATA_I may have been converted into a different local
7220 variable. In which case, we need to keep the assignment. */
7221 if (gimple_omp_taskreg_data_arg (entry_stmt))
7222 {
7223 basic_block entry_succ_bb
7224 = single_succ_p (entry_bb) ? single_succ (entry_bb)
7225 : FALLTHRU_EDGE (entry_bb)->dest;
7226 tree arg;
7227 gimple *parcopy_stmt = NULL;
7228
7229 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
7230 {
7231 gimple *stmt;
7232
7233 gcc_assert (!gsi_end_p (gsi));
7234 stmt = gsi_stmt (gsi);
7235 if (gimple_code (stmt) != GIMPLE_ASSIGN)
7236 continue;
7237
7238 if (gimple_num_ops (stmt) == 2)
7239 {
7240 tree arg = gimple_assign_rhs1 (stmt);
7241
7242 /* We're ignore the subcode because we're
7243 effectively doing a STRIP_NOPS. */
7244
7245 if (TREE_CODE (arg) == ADDR_EXPR
7246 && TREE_OPERAND (arg, 0)
7247 == gimple_omp_taskreg_data_arg (entry_stmt))
7248 {
7249 parcopy_stmt = stmt;
7250 break;
7251 }
7252 }
7253 }
7254
7255 gcc_assert (parcopy_stmt != NULL);
7256 arg = DECL_ARGUMENTS (child_fn);
7257
7258 if (!gimple_in_ssa_p (cfun))
7259 {
7260 if (gimple_assign_lhs (parcopy_stmt) == arg)
7261 gsi_remove (&gsi, true);
7262 else
7263 {
7264 /* ?? Is setting the subcode really necessary ?? */
7265 gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (arg));
7266 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7267 }
7268 }
7269 else
7270 {
7271 tree lhs = gimple_assign_lhs (parcopy_stmt);
7272 gcc_assert (SSA_NAME_VAR (lhs) == arg);
7273 /* We'd like to set the rhs to the default def in the child_fn,
7274 but it's too early to create ssa names in the child_fn.
7275 Instead, we set the rhs to the parm. In
7276 move_sese_region_to_fn, we introduce a default def for the
7277 parm, map the parm to it's default def, and once we encounter
7278 this stmt, replace the parm with the default def. */
7279 gimple_assign_set_rhs1 (parcopy_stmt, arg);
7280 update_stmt (parcopy_stmt);
7281 }
7282 }
7283
7284 /* Declare local variables needed in CHILD_CFUN. */
7285 block = DECL_INITIAL (child_fn);
7286 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
7287 /* The gimplifier could record temporaries in parallel/task block
7288 rather than in containing function's local_decls chain,
7289 which would mean cgraph missed finalizing them. Do it now. */
7290 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
7291 if (VAR_P (t) && TREE_STATIC (t) && !DECL_EXTERNAL (t))
7292 varpool_node::finalize_decl (t);
7293 DECL_SAVED_TREE (child_fn) = NULL;
7294 /* We'll create a CFG for child_fn, so no gimple body is needed. */
7295 gimple_set_body (child_fn, NULL);
7296 TREE_USED (block) = 1;
7297
7298 /* Reset DECL_CONTEXT on function arguments. */
7299 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
7300 DECL_CONTEXT (t) = child_fn;
7301
7302 /* Split ENTRY_BB at GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK,
7303 so that it can be moved to the child function. */
7304 gsi = gsi_last_bb (entry_bb);
7305 stmt = gsi_stmt (gsi);
7306 gcc_assert (stmt && (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
7307 || gimple_code (stmt) == GIMPLE_OMP_TASK));
7308 e = split_block (entry_bb, stmt);
7309 gsi_remove (&gsi, true);
7310 entry_bb = e->dest;
7311 edge e2 = NULL;
7312 if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7313 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
7314 else
7315 {
7316 e2 = make_edge (e->src, BRANCH_EDGE (entry_bb)->dest, EDGE_ABNORMAL);
7317 gcc_assert (e2->dest == region->exit);
7318 remove_edge (BRANCH_EDGE (entry_bb));
7319 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e->src);
7320 gsi = gsi_last_bb (region->exit);
7321 gcc_assert (!gsi_end_p (gsi)
7322 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
7323 gsi_remove (&gsi, true);
7324 }
7325
7326 /* Convert GIMPLE_OMP_{RETURN,CONTINUE} into a RETURN_EXPR. */
7327 if (exit_bb)
7328 {
7329 gsi = gsi_last_bb (exit_bb);
7330 gcc_assert (!gsi_end_p (gsi)
7331 && (gimple_code (gsi_stmt (gsi))
7332 == (e2 ? GIMPLE_OMP_CONTINUE : GIMPLE_OMP_RETURN)));
7333 stmt = gimple_build_return (NULL);
7334 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
7335 gsi_remove (&gsi, true);
7336 }
7337
7338 /* Move the parallel region into CHILD_CFUN. */
7339
7340 if (gimple_in_ssa_p (cfun))
7341 {
7342 init_tree_ssa (child_cfun);
7343 init_ssa_operands (child_cfun);
7344 child_cfun->gimple_df->in_ssa_p = true;
7345 block = NULL_TREE;
7346 }
7347 else
7348 block = gimple_block (entry_stmt);
7349
7350 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
7351 if (exit_bb)
7352 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
7353 if (e2)
7354 {
7355 basic_block dest_bb = e2->dest;
7356 if (!exit_bb)
7357 make_edge (new_bb, dest_bb, EDGE_FALLTHRU);
7358 remove_edge (e2);
7359 set_immediate_dominator (CDI_DOMINATORS, dest_bb, new_bb);
7360 }
7361 /* When the OMP expansion process cannot guarantee an up-to-date
7362 loop tree arrange for the child function to fixup loops. */
7363 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7364 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
7365
7366 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
7367 num = vec_safe_length (child_cfun->local_decls);
7368 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
7369 {
7370 t = (*child_cfun->local_decls)[srcidx];
7371 if (DECL_CONTEXT (t) == cfun->decl)
7372 continue;
7373 if (srcidx != dstidx)
7374 (*child_cfun->local_decls)[dstidx] = t;
7375 dstidx++;
7376 }
7377 if (dstidx != num)
7378 vec_safe_truncate (child_cfun->local_decls, dstidx);
7379
7380 /* Inform the callgraph about the new function. */
7381 child_cfun->curr_properties = cfun->curr_properties;
7382 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
7383 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
7384 cgraph_node *node = cgraph_node::get_create (child_fn);
7385 node->parallelized_function = 1;
7386 cgraph_node::add_new_function (child_fn, true);
7387
7388 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
7389 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
7390
7391 /* Fix the callgraph edges for child_cfun. Those for cfun will be
7392 fixed in a following pass. */
7393 push_cfun (child_cfun);
7394 if (need_asm)
7395 assign_assembler_name_if_neeeded (child_fn);
7396
7397 if (optimize)
7398 optimize_omp_library_calls (entry_stmt);
7399 cgraph_edge::rebuild_edges ();
7400
7401 /* Some EH regions might become dead, see PR34608. If
7402 pass_cleanup_cfg isn't the first pass to happen with the
7403 new child, these dead EH edges might cause problems.
7404 Clean them up now. */
7405 if (flag_exceptions)
7406 {
7407 basic_block bb;
7408 bool changed = false;
7409
7410 FOR_EACH_BB_FN (bb, cfun)
7411 changed |= gimple_purge_dead_eh_edges (bb);
7412 if (changed)
7413 cleanup_tree_cfg ();
7414 }
7415 if (gimple_in_ssa_p (cfun))
7416 update_ssa (TODO_update_ssa);
7417 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
7418 verify_loop_structure ();
7419 pop_cfun ();
7420
7421 if (dump_file && !gimple_in_ssa_p (cfun))
7422 {
7423 omp_any_child_fn_dumped = true;
7424 dump_function_header (dump_file, child_fn, dump_flags);
7425 dump_function_to_file (child_fn, dump_file, dump_flags);
7426 }
7427 }
7428
7429 /* Emit a library call to launch the children threads. */
7430 if (is_cilk_for)
7431 expand_cilk_for_call (new_bb,
7432 as_a <gomp_parallel *> (entry_stmt), ws_args);
7433 else if (gimple_code (entry_stmt) == GIMPLE_OMP_PARALLEL)
7434 expand_parallel_call (region, new_bb,
7435 as_a <gomp_parallel *> (entry_stmt), ws_args);
7436 else
7437 expand_task_call (region, new_bb, as_a <gomp_task *> (entry_stmt));
7438 if (gimple_in_ssa_p (cfun))
7439 update_ssa (TODO_update_ssa_only_virtuals);
7440 }
7441
7442 /* Information about members of an OpenACC collapsed loop nest. */
7443
7444 struct oacc_collapse
7445 {
7446 tree base; /* Base value. */
7447 tree iters; /* Number of steps. */
7448 tree step; /* step size. */
7449 };
7450
7451 /* Helper for expand_oacc_for. Determine collapsed loop information.
7452 Fill in COUNTS array. Emit any initialization code before GSI.
7453 Return the calculated outer loop bound of BOUND_TYPE. */
7454
7455 static tree
7456 expand_oacc_collapse_init (const struct omp_for_data *fd,
7457 gimple_stmt_iterator *gsi,
7458 oacc_collapse *counts, tree bound_type)
7459 {
7460 tree total = build_int_cst (bound_type, 1);
7461 int ix;
7462
7463 gcc_assert (integer_onep (fd->loop.step));
7464 gcc_assert (integer_zerop (fd->loop.n1));
7465
7466 for (ix = 0; ix != fd->collapse; ix++)
7467 {
7468 const omp_for_data_loop *loop = &fd->loops[ix];
7469
7470 tree iter_type = TREE_TYPE (loop->v);
7471 tree diff_type = iter_type;
7472 tree plus_type = iter_type;
7473
7474 gcc_assert (loop->cond_code == fd->loop.cond_code);
7475
7476 if (POINTER_TYPE_P (iter_type))
7477 plus_type = sizetype;
7478 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
7479 diff_type = signed_type_for (diff_type);
7480
7481 tree b = loop->n1;
7482 tree e = loop->n2;
7483 tree s = loop->step;
7484 bool up = loop->cond_code == LT_EXPR;
7485 tree dir = build_int_cst (diff_type, up ? +1 : -1);
7486 bool negating;
7487 tree expr;
7488
7489 b = force_gimple_operand_gsi (gsi, b, true, NULL_TREE,
7490 true, GSI_SAME_STMT);
7491 e = force_gimple_operand_gsi (gsi, e, true, NULL_TREE,
7492 true, GSI_SAME_STMT);
7493
7494 /* Convert the step, avoiding possible unsigned->signed overflow. */
7495 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
7496 if (negating)
7497 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
7498 s = fold_convert (diff_type, s);
7499 if (negating)
7500 s = fold_build1 (NEGATE_EXPR, diff_type, s);
7501 s = force_gimple_operand_gsi (gsi, s, true, NULL_TREE,
7502 true, GSI_SAME_STMT);
7503
7504 /* Determine the range, avoiding possible unsigned->signed overflow. */
7505 negating = !up && TYPE_UNSIGNED (iter_type);
7506 expr = fold_build2 (MINUS_EXPR, plus_type,
7507 fold_convert (plus_type, negating ? b : e),
7508 fold_convert (plus_type, negating ? e : b));
7509 expr = fold_convert (diff_type, expr);
7510 if (negating)
7511 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
7512 tree range = force_gimple_operand_gsi
7513 (gsi, expr, true, NULL_TREE, true, GSI_SAME_STMT);
7514
7515 /* Determine number of iterations. */
7516 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
7517 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
7518 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
7519
7520 tree iters = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7521 true, GSI_SAME_STMT);
7522
7523 counts[ix].base = b;
7524 counts[ix].iters = iters;
7525 counts[ix].step = s;
7526
7527 total = fold_build2 (MULT_EXPR, bound_type, total,
7528 fold_convert (bound_type, iters));
7529 }
7530
7531 return total;
7532 }
7533
7534 /* Emit initializers for collapsed loop members. IVAR is the outer
7535 loop iteration variable, from which collapsed loop iteration values
7536 are calculated. COUNTS array has been initialized by
7537 expand_oacc_collapse_inits. */
7538
7539 static void
7540 expand_oacc_collapse_vars (const struct omp_for_data *fd,
7541 gimple_stmt_iterator *gsi,
7542 const oacc_collapse *counts, tree ivar)
7543 {
7544 tree ivar_type = TREE_TYPE (ivar);
7545
7546 /* The most rapidly changing iteration variable is the innermost
7547 one. */
7548 for (int ix = fd->collapse; ix--;)
7549 {
7550 const omp_for_data_loop *loop = &fd->loops[ix];
7551 const oacc_collapse *collapse = &counts[ix];
7552 tree iter_type = TREE_TYPE (loop->v);
7553 tree diff_type = TREE_TYPE (collapse->step);
7554 tree plus_type = iter_type;
7555 enum tree_code plus_code = PLUS_EXPR;
7556 tree expr;
7557
7558 if (POINTER_TYPE_P (iter_type))
7559 {
7560 plus_code = POINTER_PLUS_EXPR;
7561 plus_type = sizetype;
7562 }
7563
7564 expr = fold_build2 (TRUNC_MOD_EXPR, ivar_type, ivar,
7565 fold_convert (ivar_type, collapse->iters));
7566 expr = fold_build2 (MULT_EXPR, diff_type, fold_convert (diff_type, expr),
7567 collapse->step);
7568 expr = fold_build2 (plus_code, iter_type, collapse->base,
7569 fold_convert (plus_type, expr));
7570 expr = force_gimple_operand_gsi (gsi, expr, false, NULL_TREE,
7571 true, GSI_SAME_STMT);
7572 gassign *ass = gimple_build_assign (loop->v, expr);
7573 gsi_insert_before (gsi, ass, GSI_SAME_STMT);
7574
7575 if (ix)
7576 {
7577 expr = fold_build2 (TRUNC_DIV_EXPR, ivar_type, ivar,
7578 fold_convert (ivar_type, collapse->iters));
7579 ivar = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
7580 true, GSI_SAME_STMT);
7581 }
7582 }
7583 }
7584
7585
7586 /* Helper function for expand_omp_{for_*,simd}. If this is the outermost
7587 of the combined collapse > 1 loop constructs, generate code like:
7588 if (__builtin_expect (N32 cond3 N31, 0)) goto ZERO_ITER_BB;
7589 if (cond3 is <)
7590 adj = STEP3 - 1;
7591 else
7592 adj = STEP3 + 1;
7593 count3 = (adj + N32 - N31) / STEP3;
7594 if (__builtin_expect (N22 cond2 N21, 0)) goto ZERO_ITER_BB;
7595 if (cond2 is <)
7596 adj = STEP2 - 1;
7597 else
7598 adj = STEP2 + 1;
7599 count2 = (adj + N22 - N21) / STEP2;
7600 if (__builtin_expect (N12 cond1 N11, 0)) goto ZERO_ITER_BB;
7601 if (cond1 is <)
7602 adj = STEP1 - 1;
7603 else
7604 adj = STEP1 + 1;
7605 count1 = (adj + N12 - N11) / STEP1;
7606 count = count1 * count2 * count3;
7607 Furthermore, if ZERO_ITER_BB is NULL, create a BB which does:
7608 count = 0;
7609 and set ZERO_ITER_BB to that bb. If this isn't the outermost
7610 of the combined loop constructs, just initialize COUNTS array
7611 from the _looptemp_ clauses. */
7612
7613 /* NOTE: It *could* be better to moosh all of the BBs together,
7614 creating one larger BB with all the computation and the unexpected
7615 jump at the end. I.e.
7616
7617 bool zero3, zero2, zero1, zero;
7618
7619 zero3 = N32 c3 N31;
7620 count3 = (N32 - N31) /[cl] STEP3;
7621 zero2 = N22 c2 N21;
7622 count2 = (N22 - N21) /[cl] STEP2;
7623 zero1 = N12 c1 N11;
7624 count1 = (N12 - N11) /[cl] STEP1;
7625 zero = zero3 || zero2 || zero1;
7626 count = count1 * count2 * count3;
7627 if (__builtin_expect(zero, false)) goto zero_iter_bb;
7628
7629 After all, we expect the zero=false, and thus we expect to have to
7630 evaluate all of the comparison expressions, so short-circuiting
7631 oughtn't be a win. Since the condition isn't protecting a
7632 denominator, we're not concerned about divide-by-zero, so we can
7633 fully evaluate count even if a numerator turned out to be wrong.
7634
7635 It seems like putting this all together would create much better
7636 scheduling opportunities, and less pressure on the chip's branch
7637 predictor. */
7638
7639 static void
7640 expand_omp_for_init_counts (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7641 basic_block &entry_bb, tree *counts,
7642 basic_block &zero_iter1_bb, int &first_zero_iter1,
7643 basic_block &zero_iter2_bb, int &first_zero_iter2,
7644 basic_block &l2_dom_bb)
7645 {
7646 tree t, type = TREE_TYPE (fd->loop.v);
7647 edge e, ne;
7648 int i;
7649
7650 /* Collapsed loops need work for expansion into SSA form. */
7651 gcc_assert (!gimple_in_ssa_p (cfun));
7652
7653 if (gimple_omp_for_combined_into_p (fd->for_stmt)
7654 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
7655 {
7656 gcc_assert (fd->ordered == 0);
7657 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7658 isn't supposed to be handled, as the inner loop doesn't
7659 use it. */
7660 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
7661 OMP_CLAUSE__LOOPTEMP_);
7662 gcc_assert (innerc);
7663 for (i = 0; i < fd->collapse; i++)
7664 {
7665 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7666 OMP_CLAUSE__LOOPTEMP_);
7667 gcc_assert (innerc);
7668 if (i)
7669 counts[i] = OMP_CLAUSE_DECL (innerc);
7670 else
7671 counts[0] = NULL_TREE;
7672 }
7673 return;
7674 }
7675
7676 for (i = fd->collapse; i < fd->ordered; i++)
7677 {
7678 tree itype = TREE_TYPE (fd->loops[i].v);
7679 counts[i] = NULL_TREE;
7680 t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7681 fold_convert (itype, fd->loops[i].n1),
7682 fold_convert (itype, fd->loops[i].n2));
7683 if (t && integer_zerop (t))
7684 {
7685 for (i = fd->collapse; i < fd->ordered; i++)
7686 counts[i] = build_int_cst (type, 0);
7687 break;
7688 }
7689 }
7690 for (i = 0; i < (fd->ordered ? fd->ordered : fd->collapse); i++)
7691 {
7692 tree itype = TREE_TYPE (fd->loops[i].v);
7693
7694 if (i >= fd->collapse && counts[i])
7695 continue;
7696 if ((SSA_VAR_P (fd->loop.n2) || i >= fd->collapse)
7697 && ((t = fold_binary (fd->loops[i].cond_code, boolean_type_node,
7698 fold_convert (itype, fd->loops[i].n1),
7699 fold_convert (itype, fd->loops[i].n2)))
7700 == NULL_TREE || !integer_onep (t)))
7701 {
7702 gcond *cond_stmt;
7703 tree n1, n2;
7704 n1 = fold_convert (itype, unshare_expr (fd->loops[i].n1));
7705 n1 = force_gimple_operand_gsi (gsi, n1, true, NULL_TREE,
7706 true, GSI_SAME_STMT);
7707 n2 = fold_convert (itype, unshare_expr (fd->loops[i].n2));
7708 n2 = force_gimple_operand_gsi (gsi, n2, true, NULL_TREE,
7709 true, GSI_SAME_STMT);
7710 cond_stmt = gimple_build_cond (fd->loops[i].cond_code, n1, n2,
7711 NULL_TREE, NULL_TREE);
7712 gsi_insert_before (gsi, cond_stmt, GSI_SAME_STMT);
7713 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
7714 expand_omp_regimplify_p, NULL, NULL)
7715 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
7716 expand_omp_regimplify_p, NULL, NULL))
7717 {
7718 *gsi = gsi_for_stmt (cond_stmt);
7719 gimple_regimplify_operands (cond_stmt, gsi);
7720 }
7721 e = split_block (entry_bb, cond_stmt);
7722 basic_block &zero_iter_bb
7723 = i < fd->collapse ? zero_iter1_bb : zero_iter2_bb;
7724 int &first_zero_iter
7725 = i < fd->collapse ? first_zero_iter1 : first_zero_iter2;
7726 if (zero_iter_bb == NULL)
7727 {
7728 gassign *assign_stmt;
7729 first_zero_iter = i;
7730 zero_iter_bb = create_empty_bb (entry_bb);
7731 add_bb_to_loop (zero_iter_bb, entry_bb->loop_father);
7732 *gsi = gsi_after_labels (zero_iter_bb);
7733 if (i < fd->collapse)
7734 assign_stmt = gimple_build_assign (fd->loop.n2,
7735 build_zero_cst (type));
7736 else
7737 {
7738 counts[i] = create_tmp_reg (type, ".count");
7739 assign_stmt
7740 = gimple_build_assign (counts[i], build_zero_cst (type));
7741 }
7742 gsi_insert_before (gsi, assign_stmt, GSI_SAME_STMT);
7743 set_immediate_dominator (CDI_DOMINATORS, zero_iter_bb,
7744 entry_bb);
7745 }
7746 ne = make_edge (entry_bb, zero_iter_bb, EDGE_FALSE_VALUE);
7747 ne->probability = REG_BR_PROB_BASE / 2000 - 1;
7748 e->flags = EDGE_TRUE_VALUE;
7749 e->probability = REG_BR_PROB_BASE - ne->probability;
7750 if (l2_dom_bb == NULL)
7751 l2_dom_bb = entry_bb;
7752 entry_bb = e->dest;
7753 *gsi = gsi_last_bb (entry_bb);
7754 }
7755
7756 if (POINTER_TYPE_P (itype))
7757 itype = signed_type_for (itype);
7758 t = build_int_cst (itype, (fd->loops[i].cond_code == LT_EXPR
7759 ? -1 : 1));
7760 t = fold_build2 (PLUS_EXPR, itype,
7761 fold_convert (itype, fd->loops[i].step), t);
7762 t = fold_build2 (PLUS_EXPR, itype, t,
7763 fold_convert (itype, fd->loops[i].n2));
7764 t = fold_build2 (MINUS_EXPR, itype, t,
7765 fold_convert (itype, fd->loops[i].n1));
7766 /* ?? We could probably use CEIL_DIV_EXPR instead of
7767 TRUNC_DIV_EXPR and adjusting by hand. Unless we can't
7768 generate the same code in the end because generically we
7769 don't know that the values involved must be negative for
7770 GT?? */
7771 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
7772 t = fold_build2 (TRUNC_DIV_EXPR, itype,
7773 fold_build1 (NEGATE_EXPR, itype, t),
7774 fold_build1 (NEGATE_EXPR, itype,
7775 fold_convert (itype,
7776 fd->loops[i].step)));
7777 else
7778 t = fold_build2 (TRUNC_DIV_EXPR, itype, t,
7779 fold_convert (itype, fd->loops[i].step));
7780 t = fold_convert (type, t);
7781 if (TREE_CODE (t) == INTEGER_CST)
7782 counts[i] = t;
7783 else
7784 {
7785 if (i < fd->collapse || i != first_zero_iter2)
7786 counts[i] = create_tmp_reg (type, ".count");
7787 expand_omp_build_assign (gsi, counts[i], t);
7788 }
7789 if (SSA_VAR_P (fd->loop.n2) && i < fd->collapse)
7790 {
7791 if (i == 0)
7792 t = counts[0];
7793 else
7794 t = fold_build2 (MULT_EXPR, type, fd->loop.n2, counts[i]);
7795 expand_omp_build_assign (gsi, fd->loop.n2, t);
7796 }
7797 }
7798 }
7799
7800
7801 /* Helper function for expand_omp_{for_*,simd}. Generate code like:
7802 T = V;
7803 V3 = N31 + (T % count3) * STEP3;
7804 T = T / count3;
7805 V2 = N21 + (T % count2) * STEP2;
7806 T = T / count2;
7807 V1 = N11 + T * STEP1;
7808 if this loop doesn't have an inner loop construct combined with it.
7809 If it does have an inner loop construct combined with it and the
7810 iteration count isn't known constant, store values from counts array
7811 into its _looptemp_ temporaries instead. */
7812
7813 static void
7814 expand_omp_for_init_vars (struct omp_for_data *fd, gimple_stmt_iterator *gsi,
7815 tree *counts, gimple *inner_stmt, tree startvar)
7816 {
7817 int i;
7818 if (gimple_omp_for_combined_p (fd->for_stmt))
7819 {
7820 /* If fd->loop.n2 is constant, then no propagation of the counts
7821 is needed, they are constant. */
7822 if (TREE_CODE (fd->loop.n2) == INTEGER_CST)
7823 return;
7824
7825 tree clauses = gimple_code (inner_stmt) != GIMPLE_OMP_FOR
7826 ? gimple_omp_taskreg_clauses (inner_stmt)
7827 : gimple_omp_for_clauses (inner_stmt);
7828 /* First two _looptemp_ clauses are for istart/iend, counts[0]
7829 isn't supposed to be handled, as the inner loop doesn't
7830 use it. */
7831 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
7832 gcc_assert (innerc);
7833 for (i = 0; i < fd->collapse; i++)
7834 {
7835 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
7836 OMP_CLAUSE__LOOPTEMP_);
7837 gcc_assert (innerc);
7838 if (i)
7839 {
7840 tree tem = OMP_CLAUSE_DECL (innerc);
7841 tree t = fold_convert (TREE_TYPE (tem), counts[i]);
7842 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7843 false, GSI_CONTINUE_LINKING);
7844 gassign *stmt = gimple_build_assign (tem, t);
7845 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7846 }
7847 }
7848 return;
7849 }
7850
7851 tree type = TREE_TYPE (fd->loop.v);
7852 tree tem = create_tmp_reg (type, ".tem");
7853 gassign *stmt = gimple_build_assign (tem, startvar);
7854 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7855
7856 for (i = fd->collapse - 1; i >= 0; i--)
7857 {
7858 tree vtype = TREE_TYPE (fd->loops[i].v), itype, t;
7859 itype = vtype;
7860 if (POINTER_TYPE_P (vtype))
7861 itype = signed_type_for (vtype);
7862 if (i != 0)
7863 t = fold_build2 (TRUNC_MOD_EXPR, type, tem, counts[i]);
7864 else
7865 t = tem;
7866 t = fold_convert (itype, t);
7867 t = fold_build2 (MULT_EXPR, itype, t,
7868 fold_convert (itype, fd->loops[i].step));
7869 if (POINTER_TYPE_P (vtype))
7870 t = fold_build_pointer_plus (fd->loops[i].n1, t);
7871 else
7872 t = fold_build2 (PLUS_EXPR, itype, fd->loops[i].n1, t);
7873 t = force_gimple_operand_gsi (gsi, t,
7874 DECL_P (fd->loops[i].v)
7875 && TREE_ADDRESSABLE (fd->loops[i].v),
7876 NULL_TREE, false,
7877 GSI_CONTINUE_LINKING);
7878 stmt = gimple_build_assign (fd->loops[i].v, t);
7879 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7880 if (i != 0)
7881 {
7882 t = fold_build2 (TRUNC_DIV_EXPR, type, tem, counts[i]);
7883 t = force_gimple_operand_gsi (gsi, t, false, NULL_TREE,
7884 false, GSI_CONTINUE_LINKING);
7885 stmt = gimple_build_assign (tem, t);
7886 gsi_insert_after (gsi, stmt, GSI_CONTINUE_LINKING);
7887 }
7888 }
7889 }
7890
7891
7892 /* Helper function for expand_omp_for_*. Generate code like:
7893 L10:
7894 V3 += STEP3;
7895 if (V3 cond3 N32) goto BODY_BB; else goto L11;
7896 L11:
7897 V3 = N31;
7898 V2 += STEP2;
7899 if (V2 cond2 N22) goto BODY_BB; else goto L12;
7900 L12:
7901 V2 = N21;
7902 V1 += STEP1;
7903 goto BODY_BB; */
7904
7905 static basic_block
7906 extract_omp_for_update_vars (struct omp_for_data *fd, basic_block cont_bb,
7907 basic_block body_bb)
7908 {
7909 basic_block last_bb, bb, collapse_bb = NULL;
7910 int i;
7911 gimple_stmt_iterator gsi;
7912 edge e;
7913 tree t;
7914 gimple *stmt;
7915
7916 last_bb = cont_bb;
7917 for (i = fd->collapse - 1; i >= 0; i--)
7918 {
7919 tree vtype = TREE_TYPE (fd->loops[i].v);
7920
7921 bb = create_empty_bb (last_bb);
7922 add_bb_to_loop (bb, last_bb->loop_father);
7923 gsi = gsi_start_bb (bb);
7924
7925 if (i < fd->collapse - 1)
7926 {
7927 e = make_edge (last_bb, bb, EDGE_FALSE_VALUE);
7928 e->probability = REG_BR_PROB_BASE / 8;
7929
7930 t = fd->loops[i + 1].n1;
7931 t = force_gimple_operand_gsi (&gsi, t,
7932 DECL_P (fd->loops[i + 1].v)
7933 && TREE_ADDRESSABLE (fd->loops[i
7934 + 1].v),
7935 NULL_TREE, false,
7936 GSI_CONTINUE_LINKING);
7937 stmt = gimple_build_assign (fd->loops[i + 1].v, t);
7938 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7939 }
7940 else
7941 collapse_bb = bb;
7942
7943 set_immediate_dominator (CDI_DOMINATORS, bb, last_bb);
7944
7945 if (POINTER_TYPE_P (vtype))
7946 t = fold_build_pointer_plus (fd->loops[i].v, fd->loops[i].step);
7947 else
7948 t = fold_build2 (PLUS_EXPR, vtype, fd->loops[i].v, fd->loops[i].step);
7949 t = force_gimple_operand_gsi (&gsi, t,
7950 DECL_P (fd->loops[i].v)
7951 && TREE_ADDRESSABLE (fd->loops[i].v),
7952 NULL_TREE, false, GSI_CONTINUE_LINKING);
7953 stmt = gimple_build_assign (fd->loops[i].v, t);
7954 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7955
7956 if (i > 0)
7957 {
7958 t = fd->loops[i].n2;
7959 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
7960 false, GSI_CONTINUE_LINKING);
7961 tree v = fd->loops[i].v;
7962 if (DECL_P (v) && TREE_ADDRESSABLE (v))
7963 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
7964 false, GSI_CONTINUE_LINKING);
7965 t = fold_build2 (fd->loops[i].cond_code, boolean_type_node, v, t);
7966 stmt = gimple_build_cond_empty (t);
7967 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
7968 e = make_edge (bb, body_bb, EDGE_TRUE_VALUE);
7969 e->probability = REG_BR_PROB_BASE * 7 / 8;
7970 }
7971 else
7972 make_edge (bb, body_bb, EDGE_FALLTHRU);
7973 last_bb = bb;
7974 }
7975
7976 return collapse_bb;
7977 }
7978
7979
7980 /* Expand #pragma omp ordered depend(source). */
7981
7982 static void
7983 expand_omp_ordered_source (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
7984 tree *counts, location_t loc)
7985 {
7986 enum built_in_function source_ix
7987 = fd->iter_type == long_integer_type_node
7988 ? BUILT_IN_GOMP_DOACROSS_POST : BUILT_IN_GOMP_DOACROSS_ULL_POST;
7989 gimple *g
7990 = gimple_build_call (builtin_decl_explicit (source_ix), 1,
7991 build_fold_addr_expr (counts[fd->ordered]));
7992 gimple_set_location (g, loc);
7993 gsi_insert_before (gsi, g, GSI_SAME_STMT);
7994 }
7995
7996 /* Expand a single depend from #pragma omp ordered depend(sink:...). */
7997
7998 static void
7999 expand_omp_ordered_sink (gimple_stmt_iterator *gsi, struct omp_for_data *fd,
8000 tree *counts, tree c, location_t loc)
8001 {
8002 auto_vec<tree, 10> args;
8003 enum built_in_function sink_ix
8004 = fd->iter_type == long_integer_type_node
8005 ? BUILT_IN_GOMP_DOACROSS_WAIT : BUILT_IN_GOMP_DOACROSS_ULL_WAIT;
8006 tree t, off, coff = NULL_TREE, deps = OMP_CLAUSE_DECL (c), cond = NULL_TREE;
8007 int i;
8008 gimple_stmt_iterator gsi2 = *gsi;
8009 bool warned_step = false;
8010
8011 for (i = 0; i < fd->ordered; i++)
8012 {
8013 off = TREE_PURPOSE (deps);
8014 if (!integer_zerop (off))
8015 {
8016 gcc_assert (fd->loops[i].cond_code == LT_EXPR
8017 || fd->loops[i].cond_code == GT_EXPR);
8018 bool forward = fd->loops[i].cond_code == LT_EXPR;
8019 if (forward ^ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8020 warning_at (loc, 0, "%<depend(sink)%> clause waiting for "
8021 "lexically later iteration");
8022 break;
8023 }
8024 deps = TREE_CHAIN (deps);
8025 }
8026 /* If all offsets corresponding to the collapsed loops are zero,
8027 this depend clause can be ignored. FIXME: but there is still a
8028 flush needed. We need to emit one __sync_synchronize () for it
8029 though (perhaps conditionally)? Solve this together with the
8030 conservative dependence folding optimization.
8031 if (i >= fd->collapse)
8032 return; */
8033
8034 deps = OMP_CLAUSE_DECL (c);
8035 gsi_prev (&gsi2);
8036 edge e1 = split_block (gsi_bb (gsi2), gsi_stmt (gsi2));
8037 edge e2 = split_block_after_labels (e1->dest);
8038
8039 *gsi = gsi_after_labels (e1->dest);
8040 for (i = 0; i < fd->ordered; i++)
8041 {
8042 tree itype = TREE_TYPE (fd->loops[i].v);
8043 if (POINTER_TYPE_P (itype))
8044 itype = sizetype;
8045 if (i)
8046 deps = TREE_CHAIN (deps);
8047 off = TREE_PURPOSE (deps);
8048 tree s = fold_convert_loc (loc, itype, fd->loops[i].step);
8049
8050 if (integer_zerop (off))
8051 t = boolean_true_node;
8052 else
8053 {
8054 tree a;
8055 tree co = fold_convert_loc (loc, itype, off);
8056 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
8057 {
8058 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8059 co = fold_build1_loc (loc, NEGATE_EXPR, itype, co);
8060 a = fold_build2_loc (loc, POINTER_PLUS_EXPR,
8061 TREE_TYPE (fd->loops[i].v), fd->loops[i].v,
8062 co);
8063 }
8064 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8065 a = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8066 fd->loops[i].v, co);
8067 else
8068 a = fold_build2_loc (loc, PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
8069 fd->loops[i].v, co);
8070 if (fd->loops[i].cond_code == LT_EXPR)
8071 {
8072 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8073 t = fold_build2_loc (loc, GE_EXPR, boolean_type_node, a,
8074 fd->loops[i].n1);
8075 else
8076 t = fold_build2_loc (loc, LT_EXPR, boolean_type_node, a,
8077 fd->loops[i].n2);
8078 }
8079 else if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8080 t = fold_build2_loc (loc, GT_EXPR, boolean_type_node, a,
8081 fd->loops[i].n2);
8082 else
8083 t = fold_build2_loc (loc, LE_EXPR, boolean_type_node, a,
8084 fd->loops[i].n1);
8085 }
8086 if (cond)
8087 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node, cond, t);
8088 else
8089 cond = t;
8090
8091 off = fold_convert_loc (loc, itype, off);
8092
8093 if (fd->loops[i].cond_code == LT_EXPR
8094 ? !integer_onep (fd->loops[i].step)
8095 : !integer_minus_onep (fd->loops[i].step))
8096 {
8097 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8098 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off,
8099 fold_build1_loc (loc, NEGATE_EXPR, itype,
8100 s));
8101 else
8102 t = fold_build2_loc (loc, TRUNC_MOD_EXPR, itype, off, s);
8103 t = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, t,
8104 build_int_cst (itype, 0));
8105 if (integer_zerop (t) && !warned_step)
8106 {
8107 warning_at (loc, 0, "%<depend(sink)%> refers to iteration never "
8108 "in the iteration space");
8109 warned_step = true;
8110 }
8111 cond = fold_build2_loc (loc, BIT_AND_EXPR, boolean_type_node,
8112 cond, t);
8113 }
8114
8115 if (i <= fd->collapse - 1 && fd->collapse > 1)
8116 t = fd->loop.v;
8117 else if (counts[i])
8118 t = counts[i];
8119 else
8120 {
8121 t = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8122 fd->loops[i].v, fd->loops[i].n1);
8123 t = fold_convert_loc (loc, fd->iter_type, t);
8124 }
8125 if (TYPE_UNSIGNED (itype) && fd->loops[i].cond_code == GT_EXPR)
8126 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off,
8127 fold_build1_loc (loc, NEGATE_EXPR, itype,
8128 s));
8129 else
8130 off = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, off, s);
8131 if (OMP_CLAUSE_DEPEND_SINK_NEGATIVE (deps))
8132 off = fold_build1_loc (loc, NEGATE_EXPR, itype, off);
8133 off = fold_convert_loc (loc, fd->iter_type, off);
8134 if (i <= fd->collapse - 1 && fd->collapse > 1)
8135 {
8136 if (i)
8137 off = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, coff,
8138 off);
8139 if (i < fd->collapse - 1)
8140 {
8141 coff = fold_build2_loc (loc, MULT_EXPR, fd->iter_type, off,
8142 counts[i]);
8143 continue;
8144 }
8145 }
8146 off = unshare_expr (off);
8147 t = fold_build2_loc (loc, PLUS_EXPR, fd->iter_type, t, off);
8148 t = force_gimple_operand_gsi (gsi, t, true, NULL_TREE,
8149 true, GSI_SAME_STMT);
8150 args.safe_push (t);
8151 }
8152 gimple *g = gimple_build_call_vec (builtin_decl_explicit (sink_ix), args);
8153 gimple_set_location (g, loc);
8154 gsi_insert_before (gsi, g, GSI_SAME_STMT);
8155
8156 *gsi = gsi_last_bb (e1->src);
8157 cond = unshare_expr (cond);
8158 cond = force_gimple_operand_gsi (gsi, cond, true, NULL_TREE, false,
8159 GSI_CONTINUE_LINKING);
8160 gsi_insert_after (gsi, gimple_build_cond_empty (cond), GSI_NEW_STMT);
8161 edge e3 = make_edge (e1->src, e2->dest, EDGE_FALSE_VALUE);
8162 e3->probability = REG_BR_PROB_BASE / 8;
8163 e1->probability = REG_BR_PROB_BASE - e3->probability;
8164 e1->flags = EDGE_TRUE_VALUE;
8165 set_immediate_dominator (CDI_DOMINATORS, e2->dest, e1->src);
8166
8167 *gsi = gsi_after_labels (e2->dest);
8168 }
8169
8170 /* Expand all #pragma omp ordered depend(source) and
8171 #pragma omp ordered depend(sink:...) constructs in the current
8172 #pragma omp for ordered(n) region. */
8173
8174 static void
8175 expand_omp_ordered_source_sink (struct omp_region *region,
8176 struct omp_for_data *fd, tree *counts,
8177 basic_block cont_bb)
8178 {
8179 struct omp_region *inner;
8180 int i;
8181 for (i = fd->collapse - 1; i < fd->ordered; i++)
8182 if (i == fd->collapse - 1 && fd->collapse > 1)
8183 counts[i] = NULL_TREE;
8184 else if (i >= fd->collapse && !cont_bb)
8185 counts[i] = build_zero_cst (fd->iter_type);
8186 else if (!POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v))
8187 && integer_onep (fd->loops[i].step))
8188 counts[i] = NULL_TREE;
8189 else
8190 counts[i] = create_tmp_var (fd->iter_type, ".orditer");
8191 tree atype
8192 = build_array_type_nelts (fd->iter_type, fd->ordered - fd->collapse + 1);
8193 counts[fd->ordered] = create_tmp_var (atype, ".orditera");
8194 TREE_ADDRESSABLE (counts[fd->ordered]) = 1;
8195
8196 for (inner = region->inner; inner; inner = inner->next)
8197 if (inner->type == GIMPLE_OMP_ORDERED)
8198 {
8199 gomp_ordered *ord_stmt = inner->ord_stmt;
8200 gimple_stmt_iterator gsi = gsi_for_stmt (ord_stmt);
8201 location_t loc = gimple_location (ord_stmt);
8202 tree c;
8203 for (c = gimple_omp_ordered_clauses (ord_stmt);
8204 c; c = OMP_CLAUSE_CHAIN (c))
8205 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SOURCE)
8206 break;
8207 if (c)
8208 expand_omp_ordered_source (&gsi, fd, counts, loc);
8209 for (c = gimple_omp_ordered_clauses (ord_stmt);
8210 c; c = OMP_CLAUSE_CHAIN (c))
8211 if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
8212 expand_omp_ordered_sink (&gsi, fd, counts, c, loc);
8213 gsi_remove (&gsi, true);
8214 }
8215 }
8216
8217 /* Wrap the body into fd->ordered - fd->collapse loops that aren't
8218 collapsed. */
8219
8220 static basic_block
8221 expand_omp_for_ordered_loops (struct omp_for_data *fd, tree *counts,
8222 basic_block cont_bb, basic_block body_bb,
8223 bool ordered_lastprivate)
8224 {
8225 if (fd->ordered == fd->collapse)
8226 return cont_bb;
8227
8228 if (!cont_bb)
8229 {
8230 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8231 for (int i = fd->collapse; i < fd->ordered; i++)
8232 {
8233 tree type = TREE_TYPE (fd->loops[i].v);
8234 tree n1 = fold_convert (type, fd->loops[i].n1);
8235 expand_omp_build_assign (&gsi, fd->loops[i].v, n1);
8236 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8237 size_int (i - fd->collapse + 1),
8238 NULL_TREE, NULL_TREE);
8239 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8240 }
8241 return NULL;
8242 }
8243
8244 for (int i = fd->ordered - 1; i >= fd->collapse; i--)
8245 {
8246 tree t, type = TREE_TYPE (fd->loops[i].v);
8247 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8248 expand_omp_build_assign (&gsi, fd->loops[i].v,
8249 fold_convert (type, fd->loops[i].n1));
8250 if (counts[i])
8251 expand_omp_build_assign (&gsi, counts[i],
8252 build_zero_cst (fd->iter_type));
8253 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8254 size_int (i - fd->collapse + 1),
8255 NULL_TREE, NULL_TREE);
8256 expand_omp_build_assign (&gsi, aref, build_zero_cst (fd->iter_type));
8257 if (!gsi_end_p (gsi))
8258 gsi_prev (&gsi);
8259 else
8260 gsi = gsi_last_bb (body_bb);
8261 edge e1 = split_block (body_bb, gsi_stmt (gsi));
8262 basic_block new_body = e1->dest;
8263 if (body_bb == cont_bb)
8264 cont_bb = new_body;
8265 edge e2 = NULL;
8266 basic_block new_header;
8267 if (EDGE_COUNT (cont_bb->preds) > 0)
8268 {
8269 gsi = gsi_last_bb (cont_bb);
8270 if (POINTER_TYPE_P (type))
8271 t = fold_build_pointer_plus (fd->loops[i].v,
8272 fold_convert (sizetype,
8273 fd->loops[i].step));
8274 else
8275 t = fold_build2 (PLUS_EXPR, type, fd->loops[i].v,
8276 fold_convert (type, fd->loops[i].step));
8277 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
8278 if (counts[i])
8279 {
8280 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[i],
8281 build_int_cst (fd->iter_type, 1));
8282 expand_omp_build_assign (&gsi, counts[i], t);
8283 t = counts[i];
8284 }
8285 else
8286 {
8287 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[i].v),
8288 fd->loops[i].v, fd->loops[i].n1);
8289 t = fold_convert (fd->iter_type, t);
8290 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8291 true, GSI_SAME_STMT);
8292 }
8293 aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8294 size_int (i - fd->collapse + 1),
8295 NULL_TREE, NULL_TREE);
8296 expand_omp_build_assign (&gsi, aref, t);
8297 gsi_prev (&gsi);
8298 e2 = split_block (cont_bb, gsi_stmt (gsi));
8299 new_header = e2->dest;
8300 }
8301 else
8302 new_header = cont_bb;
8303 gsi = gsi_after_labels (new_header);
8304 tree v = force_gimple_operand_gsi (&gsi, fd->loops[i].v, true, NULL_TREE,
8305 true, GSI_SAME_STMT);
8306 tree n2
8307 = force_gimple_operand_gsi (&gsi, fold_convert (type, fd->loops[i].n2),
8308 true, NULL_TREE, true, GSI_SAME_STMT);
8309 t = build2 (fd->loops[i].cond_code, boolean_type_node, v, n2);
8310 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_NEW_STMT);
8311 edge e3 = split_block (new_header, gsi_stmt (gsi));
8312 cont_bb = e3->dest;
8313 remove_edge (e1);
8314 make_edge (body_bb, new_header, EDGE_FALLTHRU);
8315 e3->flags = EDGE_FALSE_VALUE;
8316 e3->probability = REG_BR_PROB_BASE / 8;
8317 e1 = make_edge (new_header, new_body, EDGE_TRUE_VALUE);
8318 e1->probability = REG_BR_PROB_BASE - e3->probability;
8319
8320 set_immediate_dominator (CDI_DOMINATORS, new_header, body_bb);
8321 set_immediate_dominator (CDI_DOMINATORS, new_body, new_header);
8322
8323 if (e2)
8324 {
8325 struct loop *loop = alloc_loop ();
8326 loop->header = new_header;
8327 loop->latch = e2->src;
8328 add_loop (loop, body_bb->loop_father);
8329 }
8330 }
8331
8332 /* If there are any lastprivate clauses and it is possible some loops
8333 might have zero iterations, ensure all the decls are initialized,
8334 otherwise we could crash evaluating C++ class iterators with lastprivate
8335 clauses. */
8336 bool need_inits = false;
8337 for (int i = fd->collapse; ordered_lastprivate && i < fd->ordered; i++)
8338 if (need_inits)
8339 {
8340 tree type = TREE_TYPE (fd->loops[i].v);
8341 gimple_stmt_iterator gsi = gsi_after_labels (body_bb);
8342 expand_omp_build_assign (&gsi, fd->loops[i].v,
8343 fold_convert (type, fd->loops[i].n1));
8344 }
8345 else
8346 {
8347 tree type = TREE_TYPE (fd->loops[i].v);
8348 tree this_cond = fold_build2 (fd->loops[i].cond_code,
8349 boolean_type_node,
8350 fold_convert (type, fd->loops[i].n1),
8351 fold_convert (type, fd->loops[i].n2));
8352 if (!integer_onep (this_cond))
8353 need_inits = true;
8354 }
8355
8356 return cont_bb;
8357 }
8358
8359
8360 /* A subroutine of expand_omp_for. Generate code for a parallel
8361 loop with any schedule. Given parameters:
8362
8363 for (V = N1; V cond N2; V += STEP) BODY;
8364
8365 where COND is "<" or ">", we generate pseudocode
8366
8367 more = GOMP_loop_foo_start (N1, N2, STEP, CHUNK, &istart0, &iend0);
8368 if (more) goto L0; else goto L3;
8369 L0:
8370 V = istart0;
8371 iend = iend0;
8372 L1:
8373 BODY;
8374 V += STEP;
8375 if (V cond iend) goto L1; else goto L2;
8376 L2:
8377 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8378 L3:
8379
8380 If this is a combined omp parallel loop, instead of the call to
8381 GOMP_loop_foo_start, we call GOMP_loop_foo_next.
8382 If this is gimple_omp_for_combined_p loop, then instead of assigning
8383 V and iend in L0 we assign the first two _looptemp_ clause decls of the
8384 inner GIMPLE_OMP_FOR and V += STEP; and
8385 if (V cond iend) goto L1; else goto L2; are removed.
8386
8387 For collapsed loops, given parameters:
8388 collapse(3)
8389 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
8390 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
8391 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
8392 BODY;
8393
8394 we generate pseudocode
8395
8396 if (__builtin_expect (N32 cond3 N31, 0)) goto Z0;
8397 if (cond3 is <)
8398 adj = STEP3 - 1;
8399 else
8400 adj = STEP3 + 1;
8401 count3 = (adj + N32 - N31) / STEP3;
8402 if (__builtin_expect (N22 cond2 N21, 0)) goto Z0;
8403 if (cond2 is <)
8404 adj = STEP2 - 1;
8405 else
8406 adj = STEP2 + 1;
8407 count2 = (adj + N22 - N21) / STEP2;
8408 if (__builtin_expect (N12 cond1 N11, 0)) goto Z0;
8409 if (cond1 is <)
8410 adj = STEP1 - 1;
8411 else
8412 adj = STEP1 + 1;
8413 count1 = (adj + N12 - N11) / STEP1;
8414 count = count1 * count2 * count3;
8415 goto Z1;
8416 Z0:
8417 count = 0;
8418 Z1:
8419 more = GOMP_loop_foo_start (0, count, 1, CHUNK, &istart0, &iend0);
8420 if (more) goto L0; else goto L3;
8421 L0:
8422 V = istart0;
8423 T = V;
8424 V3 = N31 + (T % count3) * STEP3;
8425 T = T / count3;
8426 V2 = N21 + (T % count2) * STEP2;
8427 T = T / count2;
8428 V1 = N11 + T * STEP1;
8429 iend = iend0;
8430 L1:
8431 BODY;
8432 V += 1;
8433 if (V < iend) goto L10; else goto L2;
8434 L10:
8435 V3 += STEP3;
8436 if (V3 cond3 N32) goto L1; else goto L11;
8437 L11:
8438 V3 = N31;
8439 V2 += STEP2;
8440 if (V2 cond2 N22) goto L1; else goto L12;
8441 L12:
8442 V2 = N21;
8443 V1 += STEP1;
8444 goto L1;
8445 L2:
8446 if (GOMP_loop_foo_next (&istart0, &iend0)) goto L0; else goto L3;
8447 L3:
8448
8449 */
8450
8451 static void
8452 expand_omp_for_generic (struct omp_region *region,
8453 struct omp_for_data *fd,
8454 enum built_in_function start_fn,
8455 enum built_in_function next_fn,
8456 gimple *inner_stmt)
8457 {
8458 tree type, istart0, iend0, iend;
8459 tree t, vmain, vback, bias = NULL_TREE;
8460 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, collapse_bb;
8461 basic_block l2_bb = NULL, l3_bb = NULL;
8462 gimple_stmt_iterator gsi;
8463 gassign *assign_stmt;
8464 bool in_combined_parallel = is_combined_parallel (region);
8465 bool broken_loop = region->cont == NULL;
8466 edge e, ne;
8467 tree *counts = NULL;
8468 int i;
8469 bool ordered_lastprivate = false;
8470
8471 gcc_assert (!broken_loop || !in_combined_parallel);
8472 gcc_assert (fd->iter_type == long_integer_type_node
8473 || !in_combined_parallel);
8474
8475 entry_bb = region->entry;
8476 cont_bb = region->cont;
8477 collapse_bb = NULL;
8478 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
8479 gcc_assert (broken_loop
8480 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
8481 l0_bb = split_edge (FALLTHRU_EDGE (entry_bb));
8482 l1_bb = single_succ (l0_bb);
8483 if (!broken_loop)
8484 {
8485 l2_bb = create_empty_bb (cont_bb);
8486 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l1_bb
8487 || (single_succ_edge (BRANCH_EDGE (cont_bb)->dest)->dest
8488 == l1_bb));
8489 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
8490 }
8491 else
8492 l2_bb = NULL;
8493 l3_bb = BRANCH_EDGE (entry_bb)->dest;
8494 exit_bb = region->exit;
8495
8496 gsi = gsi_last_bb (entry_bb);
8497
8498 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
8499 if (fd->ordered
8500 && find_omp_clause (gimple_omp_for_clauses (gsi_stmt (gsi)),
8501 OMP_CLAUSE_LASTPRIVATE))
8502 ordered_lastprivate = false;
8503 if (fd->collapse > 1 || fd->ordered)
8504 {
8505 int first_zero_iter1 = -1, first_zero_iter2 = -1;
8506 basic_block zero_iter1_bb = NULL, zero_iter2_bb = NULL, l2_dom_bb = NULL;
8507
8508 counts = XALLOCAVEC (tree, fd->ordered ? fd->ordered + 1 : fd->collapse);
8509 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
8510 zero_iter1_bb, first_zero_iter1,
8511 zero_iter2_bb, first_zero_iter2, l2_dom_bb);
8512
8513 if (zero_iter1_bb)
8514 {
8515 /* Some counts[i] vars might be uninitialized if
8516 some loop has zero iterations. But the body shouldn't
8517 be executed in that case, so just avoid uninit warnings. */
8518 for (i = first_zero_iter1;
8519 i < (fd->ordered ? fd->ordered : fd->collapse); i++)
8520 if (SSA_VAR_P (counts[i]))
8521 TREE_NO_WARNING (counts[i]) = 1;
8522 gsi_prev (&gsi);
8523 e = split_block (entry_bb, gsi_stmt (gsi));
8524 entry_bb = e->dest;
8525 make_edge (zero_iter1_bb, entry_bb, EDGE_FALLTHRU);
8526 gsi = gsi_last_bb (entry_bb);
8527 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8528 get_immediate_dominator (CDI_DOMINATORS,
8529 zero_iter1_bb));
8530 }
8531 if (zero_iter2_bb)
8532 {
8533 /* Some counts[i] vars might be uninitialized if
8534 some loop has zero iterations. But the body shouldn't
8535 be executed in that case, so just avoid uninit warnings. */
8536 for (i = first_zero_iter2; i < fd->ordered; i++)
8537 if (SSA_VAR_P (counts[i]))
8538 TREE_NO_WARNING (counts[i]) = 1;
8539 if (zero_iter1_bb)
8540 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8541 else
8542 {
8543 gsi_prev (&gsi);
8544 e = split_block (entry_bb, gsi_stmt (gsi));
8545 entry_bb = e->dest;
8546 make_edge (zero_iter2_bb, entry_bb, EDGE_FALLTHRU);
8547 gsi = gsi_last_bb (entry_bb);
8548 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
8549 get_immediate_dominator
8550 (CDI_DOMINATORS, zero_iter2_bb));
8551 }
8552 }
8553 if (fd->collapse == 1)
8554 {
8555 counts[0] = fd->loop.n2;
8556 fd->loop = fd->loops[0];
8557 }
8558 }
8559
8560 type = TREE_TYPE (fd->loop.v);
8561 istart0 = create_tmp_var (fd->iter_type, ".istart0");
8562 iend0 = create_tmp_var (fd->iter_type, ".iend0");
8563 TREE_ADDRESSABLE (istart0) = 1;
8564 TREE_ADDRESSABLE (iend0) = 1;
8565
8566 /* See if we need to bias by LLONG_MIN. */
8567 if (fd->iter_type == long_long_unsigned_type_node
8568 && TREE_CODE (type) == INTEGER_TYPE
8569 && !TYPE_UNSIGNED (type)
8570 && fd->ordered == 0)
8571 {
8572 tree n1, n2;
8573
8574 if (fd->loop.cond_code == LT_EXPR)
8575 {
8576 n1 = fd->loop.n1;
8577 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
8578 }
8579 else
8580 {
8581 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
8582 n2 = fd->loop.n1;
8583 }
8584 if (TREE_CODE (n1) != INTEGER_CST
8585 || TREE_CODE (n2) != INTEGER_CST
8586 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
8587 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
8588 }
8589
8590 gimple_stmt_iterator gsif = gsi;
8591 gsi_prev (&gsif);
8592
8593 tree arr = NULL_TREE;
8594 if (in_combined_parallel)
8595 {
8596 gcc_assert (fd->ordered == 0);
8597 /* In a combined parallel loop, emit a call to
8598 GOMP_loop_foo_next. */
8599 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
8600 build_fold_addr_expr (istart0),
8601 build_fold_addr_expr (iend0));
8602 }
8603 else
8604 {
8605 tree t0, t1, t2, t3, t4;
8606 /* If this is not a combined parallel loop, emit a call to
8607 GOMP_loop_foo_start in ENTRY_BB. */
8608 t4 = build_fold_addr_expr (iend0);
8609 t3 = build_fold_addr_expr (istart0);
8610 if (fd->ordered)
8611 {
8612 t0 = build_int_cst (unsigned_type_node,
8613 fd->ordered - fd->collapse + 1);
8614 arr = create_tmp_var (build_array_type_nelts (fd->iter_type,
8615 fd->ordered
8616 - fd->collapse + 1),
8617 ".omp_counts");
8618 DECL_NAMELESS (arr) = 1;
8619 TREE_ADDRESSABLE (arr) = 1;
8620 TREE_STATIC (arr) = 1;
8621 vec<constructor_elt, va_gc> *v;
8622 vec_alloc (v, fd->ordered - fd->collapse + 1);
8623 int idx;
8624
8625 for (idx = 0; idx < fd->ordered - fd->collapse + 1; idx++)
8626 {
8627 tree c;
8628 if (idx == 0 && fd->collapse > 1)
8629 c = fd->loop.n2;
8630 else
8631 c = counts[idx + fd->collapse - 1];
8632 tree purpose = size_int (idx);
8633 CONSTRUCTOR_APPEND_ELT (v, purpose, c);
8634 if (TREE_CODE (c) != INTEGER_CST)
8635 TREE_STATIC (arr) = 0;
8636 }
8637
8638 DECL_INITIAL (arr) = build_constructor (TREE_TYPE (arr), v);
8639 if (!TREE_STATIC (arr))
8640 force_gimple_operand_gsi (&gsi, build1 (DECL_EXPR,
8641 void_type_node, arr),
8642 true, NULL_TREE, true, GSI_SAME_STMT);
8643 t1 = build_fold_addr_expr (arr);
8644 t2 = NULL_TREE;
8645 }
8646 else
8647 {
8648 t2 = fold_convert (fd->iter_type, fd->loop.step);
8649 t1 = fd->loop.n2;
8650 t0 = fd->loop.n1;
8651 if (gimple_omp_for_combined_into_p (fd->for_stmt))
8652 {
8653 tree innerc
8654 = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
8655 OMP_CLAUSE__LOOPTEMP_);
8656 gcc_assert (innerc);
8657 t0 = OMP_CLAUSE_DECL (innerc);
8658 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8659 OMP_CLAUSE__LOOPTEMP_);
8660 gcc_assert (innerc);
8661 t1 = OMP_CLAUSE_DECL (innerc);
8662 }
8663 if (POINTER_TYPE_P (TREE_TYPE (t0))
8664 && TYPE_PRECISION (TREE_TYPE (t0))
8665 != TYPE_PRECISION (fd->iter_type))
8666 {
8667 /* Avoid casting pointers to integer of a different size. */
8668 tree itype = signed_type_for (type);
8669 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
8670 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
8671 }
8672 else
8673 {
8674 t1 = fold_convert (fd->iter_type, t1);
8675 t0 = fold_convert (fd->iter_type, t0);
8676 }
8677 if (bias)
8678 {
8679 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
8680 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
8681 }
8682 }
8683 if (fd->iter_type == long_integer_type_node || fd->ordered)
8684 {
8685 if (fd->chunk_size)
8686 {
8687 t = fold_convert (fd->iter_type, fd->chunk_size);
8688 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8689 if (fd->ordered)
8690 t = build_call_expr (builtin_decl_explicit (start_fn),
8691 5, t0, t1, t, t3, t4);
8692 else
8693 t = build_call_expr (builtin_decl_explicit (start_fn),
8694 6, t0, t1, t2, t, t3, t4);
8695 }
8696 else if (fd->ordered)
8697 t = build_call_expr (builtin_decl_explicit (start_fn),
8698 4, t0, t1, t3, t4);
8699 else
8700 t = build_call_expr (builtin_decl_explicit (start_fn),
8701 5, t0, t1, t2, t3, t4);
8702 }
8703 else
8704 {
8705 tree t5;
8706 tree c_bool_type;
8707 tree bfn_decl;
8708
8709 /* The GOMP_loop_ull_*start functions have additional boolean
8710 argument, true for < loops and false for > loops.
8711 In Fortran, the C bool type can be different from
8712 boolean_type_node. */
8713 bfn_decl = builtin_decl_explicit (start_fn);
8714 c_bool_type = TREE_TYPE (TREE_TYPE (bfn_decl));
8715 t5 = build_int_cst (c_bool_type,
8716 fd->loop.cond_code == LT_EXPR ? 1 : 0);
8717 if (fd->chunk_size)
8718 {
8719 tree bfn_decl = builtin_decl_explicit (start_fn);
8720 t = fold_convert (fd->iter_type, fd->chunk_size);
8721 t = omp_adjust_chunk_size (t, fd->simd_schedule);
8722 t = build_call_expr (bfn_decl, 7, t5, t0, t1, t2, t, t3, t4);
8723 }
8724 else
8725 t = build_call_expr (builtin_decl_explicit (start_fn),
8726 6, t5, t0, t1, t2, t3, t4);
8727 }
8728 }
8729 if (TREE_TYPE (t) != boolean_type_node)
8730 t = fold_build2 (NE_EXPR, boolean_type_node,
8731 t, build_int_cst (TREE_TYPE (t), 0));
8732 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8733 true, GSI_SAME_STMT);
8734 if (arr && !TREE_STATIC (arr))
8735 {
8736 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
8737 TREE_THIS_VOLATILE (clobber) = 1;
8738 gsi_insert_before (&gsi, gimple_build_assign (arr, clobber),
8739 GSI_SAME_STMT);
8740 }
8741 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
8742
8743 /* Remove the GIMPLE_OMP_FOR statement. */
8744 gsi_remove (&gsi, true);
8745
8746 if (gsi_end_p (gsif))
8747 gsif = gsi_after_labels (gsi_bb (gsif));
8748 gsi_next (&gsif);
8749
8750 /* Iteration setup for sequential loop goes in L0_BB. */
8751 tree startvar = fd->loop.v;
8752 tree endvar = NULL_TREE;
8753
8754 if (gimple_omp_for_combined_p (fd->for_stmt))
8755 {
8756 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_FOR
8757 && gimple_omp_for_kind (inner_stmt)
8758 == GF_OMP_FOR_KIND_SIMD);
8759 tree innerc = find_omp_clause (gimple_omp_for_clauses (inner_stmt),
8760 OMP_CLAUSE__LOOPTEMP_);
8761 gcc_assert (innerc);
8762 startvar = OMP_CLAUSE_DECL (innerc);
8763 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
8764 OMP_CLAUSE__LOOPTEMP_);
8765 gcc_assert (innerc);
8766 endvar = OMP_CLAUSE_DECL (innerc);
8767 }
8768
8769 gsi = gsi_start_bb (l0_bb);
8770 t = istart0;
8771 if (fd->ordered && fd->collapse == 1)
8772 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8773 fold_convert (fd->iter_type, fd->loop.step));
8774 else if (bias)
8775 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8776 if (fd->ordered && fd->collapse == 1)
8777 {
8778 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8779 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8780 fd->loop.n1, fold_convert (sizetype, t));
8781 else
8782 {
8783 t = fold_convert (TREE_TYPE (startvar), t);
8784 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8785 fd->loop.n1, t);
8786 }
8787 }
8788 else
8789 {
8790 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8791 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8792 t = fold_convert (TREE_TYPE (startvar), t);
8793 }
8794 t = force_gimple_operand_gsi (&gsi, t,
8795 DECL_P (startvar)
8796 && TREE_ADDRESSABLE (startvar),
8797 NULL_TREE, false, GSI_CONTINUE_LINKING);
8798 assign_stmt = gimple_build_assign (startvar, t);
8799 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8800
8801 t = iend0;
8802 if (fd->ordered && fd->collapse == 1)
8803 t = fold_build2 (MULT_EXPR, fd->iter_type, t,
8804 fold_convert (fd->iter_type, fd->loop.step));
8805 else if (bias)
8806 t = fold_build2 (MINUS_EXPR, fd->iter_type, t, bias);
8807 if (fd->ordered && fd->collapse == 1)
8808 {
8809 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8810 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (startvar),
8811 fd->loop.n1, fold_convert (sizetype, t));
8812 else
8813 {
8814 t = fold_convert (TREE_TYPE (startvar), t);
8815 t = fold_build2 (PLUS_EXPR, TREE_TYPE (startvar),
8816 fd->loop.n1, t);
8817 }
8818 }
8819 else
8820 {
8821 if (POINTER_TYPE_P (TREE_TYPE (startvar)))
8822 t = fold_convert (signed_type_for (TREE_TYPE (startvar)), t);
8823 t = fold_convert (TREE_TYPE (startvar), t);
8824 }
8825 iend = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8826 false, GSI_CONTINUE_LINKING);
8827 if (endvar)
8828 {
8829 assign_stmt = gimple_build_assign (endvar, iend);
8830 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8831 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend)))
8832 assign_stmt = gimple_build_assign (fd->loop.v, iend);
8833 else
8834 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, iend);
8835 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8836 }
8837 /* Handle linear clause adjustments. */
8838 tree itercnt = NULL_TREE;
8839 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
8840 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
8841 c; c = OMP_CLAUSE_CHAIN (c))
8842 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
8843 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
8844 {
8845 tree d = OMP_CLAUSE_DECL (c);
8846 bool is_ref = is_reference (d);
8847 tree t = d, a, dest;
8848 if (is_ref)
8849 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
8850 tree type = TREE_TYPE (t);
8851 if (POINTER_TYPE_P (type))
8852 type = sizetype;
8853 dest = unshare_expr (t);
8854 tree v = create_tmp_var (TREE_TYPE (t), NULL);
8855 expand_omp_build_assign (&gsif, v, t);
8856 if (itercnt == NULL_TREE)
8857 {
8858 itercnt = startvar;
8859 tree n1 = fd->loop.n1;
8860 if (POINTER_TYPE_P (TREE_TYPE (itercnt)))
8861 {
8862 itercnt
8863 = fold_convert (signed_type_for (TREE_TYPE (itercnt)),
8864 itercnt);
8865 n1 = fold_convert (TREE_TYPE (itercnt), n1);
8866 }
8867 itercnt = fold_build2 (MINUS_EXPR, TREE_TYPE (itercnt),
8868 itercnt, n1);
8869 itercnt = fold_build2 (EXACT_DIV_EXPR, TREE_TYPE (itercnt),
8870 itercnt, fd->loop.step);
8871 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
8872 NULL_TREE, false,
8873 GSI_CONTINUE_LINKING);
8874 }
8875 a = fold_build2 (MULT_EXPR, type,
8876 fold_convert (type, itercnt),
8877 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
8878 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
8879 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
8880 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8881 false, GSI_CONTINUE_LINKING);
8882 assign_stmt = gimple_build_assign (dest, t);
8883 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
8884 }
8885 if (fd->collapse > 1)
8886 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
8887
8888 if (fd->ordered)
8889 {
8890 /* Until now, counts array contained number of iterations or
8891 variable containing it for ith loop. From now on, we need
8892 those counts only for collapsed loops, and only for the 2nd
8893 till the last collapsed one. Move those one element earlier,
8894 we'll use counts[fd->collapse - 1] for the first source/sink
8895 iteration counter and so on and counts[fd->ordered]
8896 as the array holding the current counter values for
8897 depend(source). */
8898 if (fd->collapse > 1)
8899 memmove (counts, counts + 1, (fd->collapse - 1) * sizeof (counts[0]));
8900 if (broken_loop)
8901 {
8902 int i;
8903 for (i = fd->collapse; i < fd->ordered; i++)
8904 {
8905 tree type = TREE_TYPE (fd->loops[i].v);
8906 tree this_cond
8907 = fold_build2 (fd->loops[i].cond_code, boolean_type_node,
8908 fold_convert (type, fd->loops[i].n1),
8909 fold_convert (type, fd->loops[i].n2));
8910 if (!integer_onep (this_cond))
8911 break;
8912 }
8913 if (i < fd->ordered)
8914 {
8915 cont_bb
8916 = create_empty_bb (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb);
8917 add_bb_to_loop (cont_bb, l1_bb->loop_father);
8918 gimple_stmt_iterator gsi = gsi_after_labels (cont_bb);
8919 gimple *g = gimple_build_omp_continue (fd->loop.v, fd->loop.v);
8920 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
8921 make_edge (cont_bb, l3_bb, EDGE_FALLTHRU);
8922 make_edge (cont_bb, l1_bb, 0);
8923 l2_bb = create_empty_bb (cont_bb);
8924 broken_loop = false;
8925 }
8926 }
8927 expand_omp_ordered_source_sink (region, fd, counts, cont_bb);
8928 cont_bb = expand_omp_for_ordered_loops (fd, counts, cont_bb, l1_bb,
8929 ordered_lastprivate);
8930 if (counts[fd->collapse - 1])
8931 {
8932 gcc_assert (fd->collapse == 1);
8933 gsi = gsi_last_bb (l0_bb);
8934 expand_omp_build_assign (&gsi, counts[fd->collapse - 1],
8935 istart0, true);
8936 gsi = gsi_last_bb (cont_bb);
8937 t = fold_build2 (PLUS_EXPR, fd->iter_type, counts[fd->collapse - 1],
8938 build_int_cst (fd->iter_type, 1));
8939 expand_omp_build_assign (&gsi, counts[fd->collapse - 1], t);
8940 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8941 size_zero_node, NULL_TREE, NULL_TREE);
8942 expand_omp_build_assign (&gsi, aref, counts[fd->collapse - 1]);
8943 t = counts[fd->collapse - 1];
8944 }
8945 else if (fd->collapse > 1)
8946 t = fd->loop.v;
8947 else
8948 {
8949 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8950 fd->loops[0].v, fd->loops[0].n1);
8951 t = fold_convert (fd->iter_type, t);
8952 }
8953 gsi = gsi_last_bb (l0_bb);
8954 tree aref = build4 (ARRAY_REF, fd->iter_type, counts[fd->ordered],
8955 size_zero_node, NULL_TREE, NULL_TREE);
8956 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8957 false, GSI_CONTINUE_LINKING);
8958 expand_omp_build_assign (&gsi, aref, t, true);
8959 }
8960
8961 if (!broken_loop)
8962 {
8963 /* Code to control the increment and predicate for the sequential
8964 loop goes in the CONT_BB. */
8965 gsi = gsi_last_bb (cont_bb);
8966 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
8967 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
8968 vmain = gimple_omp_continue_control_use (cont_stmt);
8969 vback = gimple_omp_continue_control_def (cont_stmt);
8970
8971 if (!gimple_omp_for_combined_p (fd->for_stmt))
8972 {
8973 if (POINTER_TYPE_P (type))
8974 t = fold_build_pointer_plus (vmain, fd->loop.step);
8975 else
8976 t = fold_build2 (PLUS_EXPR, type, vmain, fd->loop.step);
8977 t = force_gimple_operand_gsi (&gsi, t,
8978 DECL_P (vback)
8979 && TREE_ADDRESSABLE (vback),
8980 NULL_TREE, true, GSI_SAME_STMT);
8981 assign_stmt = gimple_build_assign (vback, t);
8982 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
8983
8984 if (fd->ordered && counts[fd->collapse - 1] == NULL_TREE)
8985 {
8986 if (fd->collapse > 1)
8987 t = fd->loop.v;
8988 else
8989 {
8990 t = fold_build2 (MINUS_EXPR, TREE_TYPE (fd->loops[0].v),
8991 fd->loops[0].v, fd->loops[0].n1);
8992 t = fold_convert (fd->iter_type, t);
8993 }
8994 tree aref = build4 (ARRAY_REF, fd->iter_type,
8995 counts[fd->ordered], size_zero_node,
8996 NULL_TREE, NULL_TREE);
8997 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
8998 true, GSI_SAME_STMT);
8999 expand_omp_build_assign (&gsi, aref, t);
9000 }
9001
9002 t = build2 (fd->loop.cond_code, boolean_type_node,
9003 DECL_P (vback) && TREE_ADDRESSABLE (vback) ? t : vback,
9004 iend);
9005 gcond *cond_stmt = gimple_build_cond_empty (t);
9006 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9007 }
9008
9009 /* Remove GIMPLE_OMP_CONTINUE. */
9010 gsi_remove (&gsi, true);
9011
9012 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9013 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, l1_bb);
9014
9015 /* Emit code to get the next parallel iteration in L2_BB. */
9016 gsi = gsi_start_bb (l2_bb);
9017
9018 t = build_call_expr (builtin_decl_explicit (next_fn), 2,
9019 build_fold_addr_expr (istart0),
9020 build_fold_addr_expr (iend0));
9021 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9022 false, GSI_CONTINUE_LINKING);
9023 if (TREE_TYPE (t) != boolean_type_node)
9024 t = fold_build2 (NE_EXPR, boolean_type_node,
9025 t, build_int_cst (TREE_TYPE (t), 0));
9026 gcond *cond_stmt = gimple_build_cond_empty (t);
9027 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
9028 }
9029
9030 /* Add the loop cleanup function. */
9031 gsi = gsi_last_bb (exit_bb);
9032 if (gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9033 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_NOWAIT);
9034 else if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9035 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END_CANCEL);
9036 else
9037 t = builtin_decl_explicit (BUILT_IN_GOMP_LOOP_END);
9038 gcall *call_stmt = gimple_build_call (t, 0);
9039 if (gimple_omp_return_lhs (gsi_stmt (gsi)))
9040 gimple_call_set_lhs (call_stmt, gimple_omp_return_lhs (gsi_stmt (gsi)));
9041 gsi_insert_after (&gsi, call_stmt, GSI_SAME_STMT);
9042 if (fd->ordered)
9043 {
9044 tree arr = counts[fd->ordered];
9045 tree clobber = build_constructor (TREE_TYPE (arr), NULL);
9046 TREE_THIS_VOLATILE (clobber) = 1;
9047 gsi_insert_after (&gsi, gimple_build_assign (arr, clobber),
9048 GSI_SAME_STMT);
9049 }
9050 gsi_remove (&gsi, true);
9051
9052 /* Connect the new blocks. */
9053 find_edge (entry_bb, l0_bb)->flags = EDGE_TRUE_VALUE;
9054 find_edge (entry_bb, l3_bb)->flags = EDGE_FALSE_VALUE;
9055
9056 if (!broken_loop)
9057 {
9058 gimple_seq phis;
9059
9060 e = find_edge (cont_bb, l3_bb);
9061 ne = make_edge (l2_bb, l3_bb, EDGE_FALSE_VALUE);
9062
9063 phis = phi_nodes (l3_bb);
9064 for (gsi = gsi_start (phis); !gsi_end_p (gsi); gsi_next (&gsi))
9065 {
9066 gimple *phi = gsi_stmt (gsi);
9067 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, ne),
9068 PHI_ARG_DEF_FROM_EDGE (phi, e));
9069 }
9070 remove_edge (e);
9071
9072 make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE);
9073 e = find_edge (cont_bb, l1_bb);
9074 if (e == NULL)
9075 {
9076 e = BRANCH_EDGE (cont_bb);
9077 gcc_assert (single_succ (e->dest) == l1_bb);
9078 }
9079 if (gimple_omp_for_combined_p (fd->for_stmt))
9080 {
9081 remove_edge (e);
9082 e = NULL;
9083 }
9084 else if (fd->collapse > 1)
9085 {
9086 remove_edge (e);
9087 e = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9088 }
9089 else
9090 e->flags = EDGE_TRUE_VALUE;
9091 if (e)
9092 {
9093 e->probability = REG_BR_PROB_BASE * 7 / 8;
9094 find_edge (cont_bb, l2_bb)->probability = REG_BR_PROB_BASE / 8;
9095 }
9096 else
9097 {
9098 e = find_edge (cont_bb, l2_bb);
9099 e->flags = EDGE_FALLTHRU;
9100 }
9101 make_edge (l2_bb, l0_bb, EDGE_TRUE_VALUE);
9102
9103 if (gimple_in_ssa_p (cfun))
9104 {
9105 /* Add phis to the outer loop that connect to the phis in the inner,
9106 original loop, and move the loop entry value of the inner phi to
9107 the loop entry value of the outer phi. */
9108 gphi_iterator psi;
9109 for (psi = gsi_start_phis (l3_bb); !gsi_end_p (psi); gsi_next (&psi))
9110 {
9111 source_location locus;
9112 gphi *nphi;
9113 gphi *exit_phi = psi.phi ();
9114
9115 edge l2_to_l3 = find_edge (l2_bb, l3_bb);
9116 tree exit_res = PHI_ARG_DEF_FROM_EDGE (exit_phi, l2_to_l3);
9117
9118 basic_block latch = BRANCH_EDGE (cont_bb)->dest;
9119 edge latch_to_l1 = find_edge (latch, l1_bb);
9120 gphi *inner_phi
9121 = find_phi_with_arg_on_edge (exit_res, latch_to_l1);
9122
9123 tree t = gimple_phi_result (exit_phi);
9124 tree new_res = copy_ssa_name (t, NULL);
9125 nphi = create_phi_node (new_res, l0_bb);
9126
9127 edge l0_to_l1 = find_edge (l0_bb, l1_bb);
9128 t = PHI_ARG_DEF_FROM_EDGE (inner_phi, l0_to_l1);
9129 locus = gimple_phi_arg_location_from_edge (inner_phi, l0_to_l1);
9130 edge entry_to_l0 = find_edge (entry_bb, l0_bb);
9131 add_phi_arg (nphi, t, entry_to_l0, locus);
9132
9133 edge l2_to_l0 = find_edge (l2_bb, l0_bb);
9134 add_phi_arg (nphi, exit_res, l2_to_l0, UNKNOWN_LOCATION);
9135
9136 add_phi_arg (inner_phi, new_res, l0_to_l1, UNKNOWN_LOCATION);
9137 };
9138 }
9139
9140 set_immediate_dominator (CDI_DOMINATORS, l2_bb,
9141 recompute_dominator (CDI_DOMINATORS, l2_bb));
9142 set_immediate_dominator (CDI_DOMINATORS, l3_bb,
9143 recompute_dominator (CDI_DOMINATORS, l3_bb));
9144 set_immediate_dominator (CDI_DOMINATORS, l0_bb,
9145 recompute_dominator (CDI_DOMINATORS, l0_bb));
9146 set_immediate_dominator (CDI_DOMINATORS, l1_bb,
9147 recompute_dominator (CDI_DOMINATORS, l1_bb));
9148
9149 /* We enter expand_omp_for_generic with a loop. This original loop may
9150 have its own loop struct, or it may be part of an outer loop struct
9151 (which may be the fake loop). */
9152 struct loop *outer_loop = entry_bb->loop_father;
9153 bool orig_loop_has_loop_struct = l1_bb->loop_father != outer_loop;
9154
9155 add_bb_to_loop (l2_bb, outer_loop);
9156
9157 /* We've added a new loop around the original loop. Allocate the
9158 corresponding loop struct. */
9159 struct loop *new_loop = alloc_loop ();
9160 new_loop->header = l0_bb;
9161 new_loop->latch = l2_bb;
9162 add_loop (new_loop, outer_loop);
9163
9164 /* Allocate a loop structure for the original loop unless we already
9165 had one. */
9166 if (!orig_loop_has_loop_struct
9167 && !gimple_omp_for_combined_p (fd->for_stmt))
9168 {
9169 struct loop *orig_loop = alloc_loop ();
9170 orig_loop->header = l1_bb;
9171 /* The loop may have multiple latches. */
9172 add_loop (orig_loop, new_loop);
9173 }
9174 }
9175 }
9176
9177
9178 /* A subroutine of expand_omp_for. Generate code for a parallel
9179 loop with static schedule and no specified chunk size. Given
9180 parameters:
9181
9182 for (V = N1; V cond N2; V += STEP) BODY;
9183
9184 where COND is "<" or ">", we generate pseudocode
9185
9186 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9187 if (cond is <)
9188 adj = STEP - 1;
9189 else
9190 adj = STEP + 1;
9191 if ((__typeof (V)) -1 > 0 && cond is >)
9192 n = -(adj + N2 - N1) / -STEP;
9193 else
9194 n = (adj + N2 - N1) / STEP;
9195 q = n / nthreads;
9196 tt = n % nthreads;
9197 if (threadid < tt) goto L3; else goto L4;
9198 L3:
9199 tt = 0;
9200 q = q + 1;
9201 L4:
9202 s0 = q * threadid + tt;
9203 e0 = s0 + q;
9204 V = s0 * STEP + N1;
9205 if (s0 >= e0) goto L2; else goto L0;
9206 L0:
9207 e = e0 * STEP + N1;
9208 L1:
9209 BODY;
9210 V += STEP;
9211 if (V cond e) goto L1;
9212 L2:
9213 */
9214
9215 static void
9216 expand_omp_for_static_nochunk (struct omp_region *region,
9217 struct omp_for_data *fd,
9218 gimple *inner_stmt)
9219 {
9220 tree n, q, s0, e0, e, t, tt, nthreads, threadid;
9221 tree type, itype, vmain, vback;
9222 basic_block entry_bb, second_bb, third_bb, exit_bb, seq_start_bb;
9223 basic_block body_bb, cont_bb, collapse_bb = NULL;
9224 basic_block fin_bb;
9225 gimple_stmt_iterator gsi;
9226 edge ep;
9227 bool broken_loop = region->cont == NULL;
9228 tree *counts = NULL;
9229 tree n1, n2, step;
9230
9231 itype = type = TREE_TYPE (fd->loop.v);
9232 if (POINTER_TYPE_P (type))
9233 itype = signed_type_for (type);
9234
9235 entry_bb = region->entry;
9236 cont_bb = region->cont;
9237 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
9238 fin_bb = BRANCH_EDGE (entry_bb)->dest;
9239 gcc_assert (broken_loop
9240 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
9241 seq_start_bb = split_edge (FALLTHRU_EDGE (entry_bb));
9242 body_bb = single_succ (seq_start_bb);
9243 if (!broken_loop)
9244 {
9245 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9246 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9247 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9248 }
9249 exit_bb = region->exit;
9250
9251 /* Iteration space partitioning goes in ENTRY_BB. */
9252 gsi = gsi_last_bb (entry_bb);
9253 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9254
9255 if (fd->collapse > 1)
9256 {
9257 int first_zero_iter = -1, dummy = -1;
9258 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9259
9260 counts = XALLOCAVEC (tree, fd->collapse);
9261 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9262 fin_bb, first_zero_iter,
9263 dummy_bb, dummy, l2_dom_bb);
9264 t = NULL_TREE;
9265 }
9266 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9267 t = integer_one_node;
9268 else
9269 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9270 fold_convert (type, fd->loop.n1),
9271 fold_convert (type, fd->loop.n2));
9272 if (fd->collapse == 1
9273 && TYPE_UNSIGNED (type)
9274 && (t == NULL_TREE || !integer_onep (t)))
9275 {
9276 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9277 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9278 true, GSI_SAME_STMT);
9279 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9280 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9281 true, GSI_SAME_STMT);
9282 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9283 NULL_TREE, NULL_TREE);
9284 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9285 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9286 expand_omp_regimplify_p, NULL, NULL)
9287 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9288 expand_omp_regimplify_p, NULL, NULL))
9289 {
9290 gsi = gsi_for_stmt (cond_stmt);
9291 gimple_regimplify_operands (cond_stmt, &gsi);
9292 }
9293 ep = split_block (entry_bb, cond_stmt);
9294 ep->flags = EDGE_TRUE_VALUE;
9295 entry_bb = ep->dest;
9296 ep->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9297 ep = make_edge (ep->src, fin_bb, EDGE_FALSE_VALUE);
9298 ep->probability = REG_BR_PROB_BASE / 2000 - 1;
9299 if (gimple_in_ssa_p (cfun))
9300 {
9301 int dest_idx = find_edge (entry_bb, fin_bb)->dest_idx;
9302 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9303 !gsi_end_p (gpi); gsi_next (&gpi))
9304 {
9305 gphi *phi = gpi.phi ();
9306 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9307 ep, UNKNOWN_LOCATION);
9308 }
9309 }
9310 gsi = gsi_last_bb (entry_bb);
9311 }
9312
9313 switch (gimple_omp_for_kind (fd->for_stmt))
9314 {
9315 case GF_OMP_FOR_KIND_FOR:
9316 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9317 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9318 break;
9319 case GF_OMP_FOR_KIND_DISTRIBUTE:
9320 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9321 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9322 break;
9323 default:
9324 gcc_unreachable ();
9325 }
9326 nthreads = build_call_expr (nthreads, 0);
9327 nthreads = fold_convert (itype, nthreads);
9328 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9329 true, GSI_SAME_STMT);
9330 threadid = build_call_expr (threadid, 0);
9331 threadid = fold_convert (itype, threadid);
9332 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9333 true, GSI_SAME_STMT);
9334
9335 n1 = fd->loop.n1;
9336 n2 = fd->loop.n2;
9337 step = fd->loop.step;
9338 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9339 {
9340 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9341 OMP_CLAUSE__LOOPTEMP_);
9342 gcc_assert (innerc);
9343 n1 = OMP_CLAUSE_DECL (innerc);
9344 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9345 OMP_CLAUSE__LOOPTEMP_);
9346 gcc_assert (innerc);
9347 n2 = OMP_CLAUSE_DECL (innerc);
9348 }
9349 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9350 true, NULL_TREE, true, GSI_SAME_STMT);
9351 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9352 true, NULL_TREE, true, GSI_SAME_STMT);
9353 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9354 true, NULL_TREE, true, GSI_SAME_STMT);
9355
9356 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9357 t = fold_build2 (PLUS_EXPR, itype, step, t);
9358 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9359 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9360 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9361 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9362 fold_build1 (NEGATE_EXPR, itype, t),
9363 fold_build1 (NEGATE_EXPR, itype, step));
9364 else
9365 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9366 t = fold_convert (itype, t);
9367 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9368
9369 q = create_tmp_reg (itype, "q");
9370 t = fold_build2 (TRUNC_DIV_EXPR, itype, n, nthreads);
9371 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9372 gsi_insert_before (&gsi, gimple_build_assign (q, t), GSI_SAME_STMT);
9373
9374 tt = create_tmp_reg (itype, "tt");
9375 t = fold_build2 (TRUNC_MOD_EXPR, itype, n, nthreads);
9376 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, true, GSI_SAME_STMT);
9377 gsi_insert_before (&gsi, gimple_build_assign (tt, t), GSI_SAME_STMT);
9378
9379 t = build2 (LT_EXPR, boolean_type_node, threadid, tt);
9380 gcond *cond_stmt = gimple_build_cond_empty (t);
9381 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9382
9383 second_bb = split_block (entry_bb, cond_stmt)->dest;
9384 gsi = gsi_last_bb (second_bb);
9385 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9386
9387 gsi_insert_before (&gsi, gimple_build_assign (tt, build_int_cst (itype, 0)),
9388 GSI_SAME_STMT);
9389 gassign *assign_stmt
9390 = gimple_build_assign (q, PLUS_EXPR, q, build_int_cst (itype, 1));
9391 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9392
9393 third_bb = split_block (second_bb, assign_stmt)->dest;
9394 gsi = gsi_last_bb (third_bb);
9395 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9396
9397 t = build2 (MULT_EXPR, itype, q, threadid);
9398 t = build2 (PLUS_EXPR, itype, t, tt);
9399 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9400
9401 t = fold_build2 (PLUS_EXPR, itype, s0, q);
9402 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE, true, GSI_SAME_STMT);
9403
9404 t = build2 (GE_EXPR, boolean_type_node, s0, e0);
9405 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9406
9407 /* Remove the GIMPLE_OMP_FOR statement. */
9408 gsi_remove (&gsi, true);
9409
9410 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9411 gsi = gsi_start_bb (seq_start_bb);
9412
9413 tree startvar = fd->loop.v;
9414 tree endvar = NULL_TREE;
9415
9416 if (gimple_omp_for_combined_p (fd->for_stmt))
9417 {
9418 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9419 ? gimple_omp_parallel_clauses (inner_stmt)
9420 : gimple_omp_for_clauses (inner_stmt);
9421 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9422 gcc_assert (innerc);
9423 startvar = OMP_CLAUSE_DECL (innerc);
9424 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9425 OMP_CLAUSE__LOOPTEMP_);
9426 gcc_assert (innerc);
9427 endvar = OMP_CLAUSE_DECL (innerc);
9428 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9429 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9430 {
9431 int i;
9432 for (i = 1; i < fd->collapse; i++)
9433 {
9434 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9435 OMP_CLAUSE__LOOPTEMP_);
9436 gcc_assert (innerc);
9437 }
9438 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9439 OMP_CLAUSE__LOOPTEMP_);
9440 if (innerc)
9441 {
9442 /* If needed (distribute parallel for with lastprivate),
9443 propagate down the total number of iterations. */
9444 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9445 fd->loop.n2);
9446 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9447 GSI_CONTINUE_LINKING);
9448 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9449 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9450 }
9451 }
9452 }
9453 t = fold_convert (itype, s0);
9454 t = fold_build2 (MULT_EXPR, itype, t, step);
9455 if (POINTER_TYPE_P (type))
9456 t = fold_build_pointer_plus (n1, t);
9457 else
9458 t = fold_build2 (PLUS_EXPR, type, t, n1);
9459 t = fold_convert (TREE_TYPE (startvar), t);
9460 t = force_gimple_operand_gsi (&gsi, t,
9461 DECL_P (startvar)
9462 && TREE_ADDRESSABLE (startvar),
9463 NULL_TREE, false, GSI_CONTINUE_LINKING);
9464 assign_stmt = gimple_build_assign (startvar, t);
9465 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9466
9467 t = fold_convert (itype, e0);
9468 t = fold_build2 (MULT_EXPR, itype, t, step);
9469 if (POINTER_TYPE_P (type))
9470 t = fold_build_pointer_plus (n1, t);
9471 else
9472 t = fold_build2 (PLUS_EXPR, type, t, n1);
9473 t = fold_convert (TREE_TYPE (startvar), t);
9474 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9475 false, GSI_CONTINUE_LINKING);
9476 if (endvar)
9477 {
9478 assign_stmt = gimple_build_assign (endvar, e);
9479 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9480 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9481 assign_stmt = gimple_build_assign (fd->loop.v, e);
9482 else
9483 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9484 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9485 }
9486 /* Handle linear clause adjustments. */
9487 tree itercnt = NULL_TREE;
9488 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9489 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9490 c; c = OMP_CLAUSE_CHAIN (c))
9491 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9492 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9493 {
9494 tree d = OMP_CLAUSE_DECL (c);
9495 bool is_ref = is_reference (d);
9496 tree t = d, a, dest;
9497 if (is_ref)
9498 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9499 if (itercnt == NULL_TREE)
9500 {
9501 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9502 {
9503 itercnt = fold_build2 (MINUS_EXPR, itype,
9504 fold_convert (itype, n1),
9505 fold_convert (itype, fd->loop.n1));
9506 itercnt = fold_build2 (EXACT_DIV_EXPR, itype, itercnt, step);
9507 itercnt = fold_build2 (PLUS_EXPR, itype, itercnt, s0);
9508 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
9509 NULL_TREE, false,
9510 GSI_CONTINUE_LINKING);
9511 }
9512 else
9513 itercnt = s0;
9514 }
9515 tree type = TREE_TYPE (t);
9516 if (POINTER_TYPE_P (type))
9517 type = sizetype;
9518 a = fold_build2 (MULT_EXPR, type,
9519 fold_convert (type, itercnt),
9520 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
9521 dest = unshare_expr (t);
9522 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
9523 : POINTER_PLUS_EXPR, TREE_TYPE (t), t, a);
9524 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9525 false, GSI_CONTINUE_LINKING);
9526 assign_stmt = gimple_build_assign (dest, t);
9527 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9528 }
9529 if (fd->collapse > 1)
9530 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
9531
9532 if (!broken_loop)
9533 {
9534 /* The code controlling the sequential loop replaces the
9535 GIMPLE_OMP_CONTINUE. */
9536 gsi = gsi_last_bb (cont_bb);
9537 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
9538 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
9539 vmain = gimple_omp_continue_control_use (cont_stmt);
9540 vback = gimple_omp_continue_control_def (cont_stmt);
9541
9542 if (!gimple_omp_for_combined_p (fd->for_stmt))
9543 {
9544 if (POINTER_TYPE_P (type))
9545 t = fold_build_pointer_plus (vmain, step);
9546 else
9547 t = fold_build2 (PLUS_EXPR, type, vmain, step);
9548 t = force_gimple_operand_gsi (&gsi, t,
9549 DECL_P (vback)
9550 && TREE_ADDRESSABLE (vback),
9551 NULL_TREE, true, GSI_SAME_STMT);
9552 assign_stmt = gimple_build_assign (vback, t);
9553 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9554
9555 t = build2 (fd->loop.cond_code, boolean_type_node,
9556 DECL_P (vback) && TREE_ADDRESSABLE (vback)
9557 ? t : vback, e);
9558 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
9559 }
9560
9561 /* Remove the GIMPLE_OMP_CONTINUE statement. */
9562 gsi_remove (&gsi, true);
9563
9564 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
9565 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
9566 }
9567
9568 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
9569 gsi = gsi_last_bb (exit_bb);
9570 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
9571 {
9572 t = gimple_omp_return_lhs (gsi_stmt (gsi));
9573 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
9574 }
9575 gsi_remove (&gsi, true);
9576
9577 /* Connect all the blocks. */
9578 ep = make_edge (entry_bb, third_bb, EDGE_FALSE_VALUE);
9579 ep->probability = REG_BR_PROB_BASE / 4 * 3;
9580 ep = find_edge (entry_bb, second_bb);
9581 ep->flags = EDGE_TRUE_VALUE;
9582 ep->probability = REG_BR_PROB_BASE / 4;
9583 find_edge (third_bb, seq_start_bb)->flags = EDGE_FALSE_VALUE;
9584 find_edge (third_bb, fin_bb)->flags = EDGE_TRUE_VALUE;
9585
9586 if (!broken_loop)
9587 {
9588 ep = find_edge (cont_bb, body_bb);
9589 if (ep == NULL)
9590 {
9591 ep = BRANCH_EDGE (cont_bb);
9592 gcc_assert (single_succ (ep->dest) == body_bb);
9593 }
9594 if (gimple_omp_for_combined_p (fd->for_stmt))
9595 {
9596 remove_edge (ep);
9597 ep = NULL;
9598 }
9599 else if (fd->collapse > 1)
9600 {
9601 remove_edge (ep);
9602 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
9603 }
9604 else
9605 ep->flags = EDGE_TRUE_VALUE;
9606 find_edge (cont_bb, fin_bb)->flags
9607 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
9608 }
9609
9610 set_immediate_dominator (CDI_DOMINATORS, second_bb, entry_bb);
9611 set_immediate_dominator (CDI_DOMINATORS, third_bb, entry_bb);
9612 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb, third_bb);
9613
9614 set_immediate_dominator (CDI_DOMINATORS, body_bb,
9615 recompute_dominator (CDI_DOMINATORS, body_bb));
9616 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
9617 recompute_dominator (CDI_DOMINATORS, fin_bb));
9618
9619 struct loop *loop = body_bb->loop_father;
9620 if (loop != entry_bb->loop_father)
9621 {
9622 gcc_assert (loop->header == body_bb);
9623 gcc_assert (broken_loop
9624 || loop->latch == region->cont
9625 || single_pred (loop->latch) == region->cont);
9626 return;
9627 }
9628
9629 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
9630 {
9631 loop = alloc_loop ();
9632 loop->header = body_bb;
9633 if (collapse_bb == NULL)
9634 loop->latch = cont_bb;
9635 add_loop (loop, body_bb->loop_father);
9636 }
9637 }
9638
9639 /* Return phi in E->DEST with ARG on edge E. */
9640
9641 static gphi *
9642 find_phi_with_arg_on_edge (tree arg, edge e)
9643 {
9644 basic_block bb = e->dest;
9645
9646 for (gphi_iterator gpi = gsi_start_phis (bb);
9647 !gsi_end_p (gpi);
9648 gsi_next (&gpi))
9649 {
9650 gphi *phi = gpi.phi ();
9651 if (PHI_ARG_DEF_FROM_EDGE (phi, e) == arg)
9652 return phi;
9653 }
9654
9655 return NULL;
9656 }
9657
9658 /* A subroutine of expand_omp_for. Generate code for a parallel
9659 loop with static schedule and a specified chunk size. Given
9660 parameters:
9661
9662 for (V = N1; V cond N2; V += STEP) BODY;
9663
9664 where COND is "<" or ">", we generate pseudocode
9665
9666 if ((__typeof (V)) -1 > 0 && N2 cond N1) goto L2;
9667 if (cond is <)
9668 adj = STEP - 1;
9669 else
9670 adj = STEP + 1;
9671 if ((__typeof (V)) -1 > 0 && cond is >)
9672 n = -(adj + N2 - N1) / -STEP;
9673 else
9674 n = (adj + N2 - N1) / STEP;
9675 trip = 0;
9676 V = threadid * CHUNK * STEP + N1; -- this extra definition of V is
9677 here so that V is defined
9678 if the loop is not entered
9679 L0:
9680 s0 = (trip * nthreads + threadid) * CHUNK;
9681 e0 = min(s0 + CHUNK, n);
9682 if (s0 < n) goto L1; else goto L4;
9683 L1:
9684 V = s0 * STEP + N1;
9685 e = e0 * STEP + N1;
9686 L2:
9687 BODY;
9688 V += STEP;
9689 if (V cond e) goto L2; else goto L3;
9690 L3:
9691 trip += 1;
9692 goto L0;
9693 L4:
9694 */
9695
9696 static void
9697 expand_omp_for_static_chunk (struct omp_region *region,
9698 struct omp_for_data *fd, gimple *inner_stmt)
9699 {
9700 tree n, s0, e0, e, t;
9701 tree trip_var, trip_init, trip_main, trip_back, nthreads, threadid;
9702 tree type, itype, vmain, vback, vextra;
9703 basic_block entry_bb, exit_bb, body_bb, seq_start_bb, iter_part_bb;
9704 basic_block trip_update_bb = NULL, cont_bb, collapse_bb = NULL, fin_bb;
9705 gimple_stmt_iterator gsi;
9706 edge se;
9707 bool broken_loop = region->cont == NULL;
9708 tree *counts = NULL;
9709 tree n1, n2, step;
9710
9711 itype = type = TREE_TYPE (fd->loop.v);
9712 if (POINTER_TYPE_P (type))
9713 itype = signed_type_for (type);
9714
9715 entry_bb = region->entry;
9716 se = split_block (entry_bb, last_stmt (entry_bb));
9717 entry_bb = se->src;
9718 iter_part_bb = se->dest;
9719 cont_bb = region->cont;
9720 gcc_assert (EDGE_COUNT (iter_part_bb->succs) == 2);
9721 fin_bb = BRANCH_EDGE (iter_part_bb)->dest;
9722 gcc_assert (broken_loop
9723 || fin_bb == FALLTHRU_EDGE (cont_bb)->dest);
9724 seq_start_bb = split_edge (FALLTHRU_EDGE (iter_part_bb));
9725 body_bb = single_succ (seq_start_bb);
9726 if (!broken_loop)
9727 {
9728 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb
9729 || single_succ (BRANCH_EDGE (cont_bb)->dest) == body_bb);
9730 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
9731 trip_update_bb = split_edge (FALLTHRU_EDGE (cont_bb));
9732 }
9733 exit_bb = region->exit;
9734
9735 /* Trip and adjustment setup goes in ENTRY_BB. */
9736 gsi = gsi_last_bb (entry_bb);
9737 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
9738
9739 if (fd->collapse > 1)
9740 {
9741 int first_zero_iter = -1, dummy = -1;
9742 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
9743
9744 counts = XALLOCAVEC (tree, fd->collapse);
9745 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
9746 fin_bb, first_zero_iter,
9747 dummy_bb, dummy, l2_dom_bb);
9748 t = NULL_TREE;
9749 }
9750 else if (gimple_omp_for_combined_into_p (fd->for_stmt))
9751 t = integer_one_node;
9752 else
9753 t = fold_binary (fd->loop.cond_code, boolean_type_node,
9754 fold_convert (type, fd->loop.n1),
9755 fold_convert (type, fd->loop.n2));
9756 if (fd->collapse == 1
9757 && TYPE_UNSIGNED (type)
9758 && (t == NULL_TREE || !integer_onep (t)))
9759 {
9760 n1 = fold_convert (type, unshare_expr (fd->loop.n1));
9761 n1 = force_gimple_operand_gsi (&gsi, n1, true, NULL_TREE,
9762 true, GSI_SAME_STMT);
9763 n2 = fold_convert (type, unshare_expr (fd->loop.n2));
9764 n2 = force_gimple_operand_gsi (&gsi, n2, true, NULL_TREE,
9765 true, GSI_SAME_STMT);
9766 gcond *cond_stmt = gimple_build_cond (fd->loop.cond_code, n1, n2,
9767 NULL_TREE, NULL_TREE);
9768 gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
9769 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
9770 expand_omp_regimplify_p, NULL, NULL)
9771 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
9772 expand_omp_regimplify_p, NULL, NULL))
9773 {
9774 gsi = gsi_for_stmt (cond_stmt);
9775 gimple_regimplify_operands (cond_stmt, &gsi);
9776 }
9777 se = split_block (entry_bb, cond_stmt);
9778 se->flags = EDGE_TRUE_VALUE;
9779 entry_bb = se->dest;
9780 se->probability = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1);
9781 se = make_edge (se->src, fin_bb, EDGE_FALSE_VALUE);
9782 se->probability = REG_BR_PROB_BASE / 2000 - 1;
9783 if (gimple_in_ssa_p (cfun))
9784 {
9785 int dest_idx = find_edge (iter_part_bb, fin_bb)->dest_idx;
9786 for (gphi_iterator gpi = gsi_start_phis (fin_bb);
9787 !gsi_end_p (gpi); gsi_next (&gpi))
9788 {
9789 gphi *phi = gpi.phi ();
9790 add_phi_arg (phi, gimple_phi_arg_def (phi, dest_idx),
9791 se, UNKNOWN_LOCATION);
9792 }
9793 }
9794 gsi = gsi_last_bb (entry_bb);
9795 }
9796
9797 switch (gimple_omp_for_kind (fd->for_stmt))
9798 {
9799 case GF_OMP_FOR_KIND_FOR:
9800 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_THREADS);
9801 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
9802 break;
9803 case GF_OMP_FOR_KIND_DISTRIBUTE:
9804 nthreads = builtin_decl_explicit (BUILT_IN_OMP_GET_NUM_TEAMS);
9805 threadid = builtin_decl_explicit (BUILT_IN_OMP_GET_TEAM_NUM);
9806 break;
9807 default:
9808 gcc_unreachable ();
9809 }
9810 nthreads = build_call_expr (nthreads, 0);
9811 nthreads = fold_convert (itype, nthreads);
9812 nthreads = force_gimple_operand_gsi (&gsi, nthreads, true, NULL_TREE,
9813 true, GSI_SAME_STMT);
9814 threadid = build_call_expr (threadid, 0);
9815 threadid = fold_convert (itype, threadid);
9816 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
9817 true, GSI_SAME_STMT);
9818
9819 n1 = fd->loop.n1;
9820 n2 = fd->loop.n2;
9821 step = fd->loop.step;
9822 if (gimple_omp_for_combined_into_p (fd->for_stmt))
9823 {
9824 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
9825 OMP_CLAUSE__LOOPTEMP_);
9826 gcc_assert (innerc);
9827 n1 = OMP_CLAUSE_DECL (innerc);
9828 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9829 OMP_CLAUSE__LOOPTEMP_);
9830 gcc_assert (innerc);
9831 n2 = OMP_CLAUSE_DECL (innerc);
9832 }
9833 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
9834 true, NULL_TREE, true, GSI_SAME_STMT);
9835 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
9836 true, NULL_TREE, true, GSI_SAME_STMT);
9837 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
9838 true, NULL_TREE, true, GSI_SAME_STMT);
9839 tree chunk_size = fold_convert (itype, fd->chunk_size);
9840 chunk_size = omp_adjust_chunk_size (chunk_size, fd->simd_schedule);
9841 chunk_size
9842 = force_gimple_operand_gsi (&gsi, chunk_size, true, NULL_TREE, true,
9843 GSI_SAME_STMT);
9844
9845 t = build_int_cst (itype, (fd->loop.cond_code == LT_EXPR ? -1 : 1));
9846 t = fold_build2 (PLUS_EXPR, itype, step, t);
9847 t = fold_build2 (PLUS_EXPR, itype, t, n2);
9848 t = fold_build2 (MINUS_EXPR, itype, t, fold_convert (itype, n1));
9849 if (TYPE_UNSIGNED (itype) && fd->loop.cond_code == GT_EXPR)
9850 t = fold_build2 (TRUNC_DIV_EXPR, itype,
9851 fold_build1 (NEGATE_EXPR, itype, t),
9852 fold_build1 (NEGATE_EXPR, itype, step));
9853 else
9854 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
9855 t = fold_convert (itype, t);
9856 n = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9857 true, GSI_SAME_STMT);
9858
9859 trip_var = create_tmp_reg (itype, ".trip");
9860 if (gimple_in_ssa_p (cfun))
9861 {
9862 trip_init = make_ssa_name (trip_var);
9863 trip_main = make_ssa_name (trip_var);
9864 trip_back = make_ssa_name (trip_var);
9865 }
9866 else
9867 {
9868 trip_init = trip_var;
9869 trip_main = trip_var;
9870 trip_back = trip_var;
9871 }
9872
9873 gassign *assign_stmt
9874 = gimple_build_assign (trip_init, build_int_cst (itype, 0));
9875 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
9876
9877 t = fold_build2 (MULT_EXPR, itype, threadid, chunk_size);
9878 t = fold_build2 (MULT_EXPR, itype, t, step);
9879 if (POINTER_TYPE_P (type))
9880 t = fold_build_pointer_plus (n1, t);
9881 else
9882 t = fold_build2 (PLUS_EXPR, type, t, n1);
9883 vextra = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9884 true, GSI_SAME_STMT);
9885
9886 /* Remove the GIMPLE_OMP_FOR. */
9887 gsi_remove (&gsi, true);
9888
9889 gimple_stmt_iterator gsif = gsi;
9890
9891 /* Iteration space partitioning goes in ITER_PART_BB. */
9892 gsi = gsi_last_bb (iter_part_bb);
9893
9894 t = fold_build2 (MULT_EXPR, itype, trip_main, nthreads);
9895 t = fold_build2 (PLUS_EXPR, itype, t, threadid);
9896 t = fold_build2 (MULT_EXPR, itype, t, chunk_size);
9897 s0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9898 false, GSI_CONTINUE_LINKING);
9899
9900 t = fold_build2 (PLUS_EXPR, itype, s0, chunk_size);
9901 t = fold_build2 (MIN_EXPR, itype, t, n);
9902 e0 = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9903 false, GSI_CONTINUE_LINKING);
9904
9905 t = build2 (LT_EXPR, boolean_type_node, s0, n);
9906 gsi_insert_after (&gsi, gimple_build_cond_empty (t), GSI_CONTINUE_LINKING);
9907
9908 /* Setup code for sequential iteration goes in SEQ_START_BB. */
9909 gsi = gsi_start_bb (seq_start_bb);
9910
9911 tree startvar = fd->loop.v;
9912 tree endvar = NULL_TREE;
9913
9914 if (gimple_omp_for_combined_p (fd->for_stmt))
9915 {
9916 tree clauses = gimple_code (inner_stmt) == GIMPLE_OMP_PARALLEL
9917 ? gimple_omp_parallel_clauses (inner_stmt)
9918 : gimple_omp_for_clauses (inner_stmt);
9919 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
9920 gcc_assert (innerc);
9921 startvar = OMP_CLAUSE_DECL (innerc);
9922 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9923 OMP_CLAUSE__LOOPTEMP_);
9924 gcc_assert (innerc);
9925 endvar = OMP_CLAUSE_DECL (innerc);
9926 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST
9927 && gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_DISTRIBUTE)
9928 {
9929 int i;
9930 for (i = 1; i < fd->collapse; i++)
9931 {
9932 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9933 OMP_CLAUSE__LOOPTEMP_);
9934 gcc_assert (innerc);
9935 }
9936 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
9937 OMP_CLAUSE__LOOPTEMP_);
9938 if (innerc)
9939 {
9940 /* If needed (distribute parallel for with lastprivate),
9941 propagate down the total number of iterations. */
9942 tree t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (innerc)),
9943 fd->loop.n2);
9944 t = force_gimple_operand_gsi (&gsi, t, false, NULL_TREE, false,
9945 GSI_CONTINUE_LINKING);
9946 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
9947 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9948 }
9949 }
9950 }
9951
9952 t = fold_convert (itype, s0);
9953 t = fold_build2 (MULT_EXPR, itype, t, step);
9954 if (POINTER_TYPE_P (type))
9955 t = fold_build_pointer_plus (n1, t);
9956 else
9957 t = fold_build2 (PLUS_EXPR, type, t, n1);
9958 t = fold_convert (TREE_TYPE (startvar), t);
9959 t = force_gimple_operand_gsi (&gsi, t,
9960 DECL_P (startvar)
9961 && TREE_ADDRESSABLE (startvar),
9962 NULL_TREE, false, GSI_CONTINUE_LINKING);
9963 assign_stmt = gimple_build_assign (startvar, t);
9964 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9965
9966 t = fold_convert (itype, e0);
9967 t = fold_build2 (MULT_EXPR, itype, t, step);
9968 if (POINTER_TYPE_P (type))
9969 t = fold_build_pointer_plus (n1, t);
9970 else
9971 t = fold_build2 (PLUS_EXPR, type, t, n1);
9972 t = fold_convert (TREE_TYPE (startvar), t);
9973 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
9974 false, GSI_CONTINUE_LINKING);
9975 if (endvar)
9976 {
9977 assign_stmt = gimple_build_assign (endvar, e);
9978 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9979 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
9980 assign_stmt = gimple_build_assign (fd->loop.v, e);
9981 else
9982 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
9983 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
9984 }
9985 /* Handle linear clause adjustments. */
9986 tree itercnt = NULL_TREE, itercntbias = NULL_TREE;
9987 if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_FOR)
9988 for (tree c = gimple_omp_for_clauses (fd->for_stmt);
9989 c; c = OMP_CLAUSE_CHAIN (c))
9990 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
9991 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
9992 {
9993 tree d = OMP_CLAUSE_DECL (c);
9994 bool is_ref = is_reference (d);
9995 tree t = d, a, dest;
9996 if (is_ref)
9997 t = build_simple_mem_ref_loc (OMP_CLAUSE_LOCATION (c), t);
9998 tree type = TREE_TYPE (t);
9999 if (POINTER_TYPE_P (type))
10000 type = sizetype;
10001 dest = unshare_expr (t);
10002 tree v = create_tmp_var (TREE_TYPE (t), NULL);
10003 expand_omp_build_assign (&gsif, v, t);
10004 if (itercnt == NULL_TREE)
10005 {
10006 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10007 {
10008 itercntbias
10009 = fold_build2 (MINUS_EXPR, itype, fold_convert (itype, n1),
10010 fold_convert (itype, fd->loop.n1));
10011 itercntbias = fold_build2 (EXACT_DIV_EXPR, itype,
10012 itercntbias, step);
10013 itercntbias
10014 = force_gimple_operand_gsi (&gsif, itercntbias, true,
10015 NULL_TREE, true,
10016 GSI_SAME_STMT);
10017 itercnt = fold_build2 (PLUS_EXPR, itype, itercntbias, s0);
10018 itercnt = force_gimple_operand_gsi (&gsi, itercnt, true,
10019 NULL_TREE, false,
10020 GSI_CONTINUE_LINKING);
10021 }
10022 else
10023 itercnt = s0;
10024 }
10025 a = fold_build2 (MULT_EXPR, type,
10026 fold_convert (type, itercnt),
10027 fold_convert (type, OMP_CLAUSE_LINEAR_STEP (c)));
10028 t = fold_build2 (type == TREE_TYPE (t) ? PLUS_EXPR
10029 : POINTER_PLUS_EXPR, TREE_TYPE (t), v, a);
10030 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10031 false, GSI_CONTINUE_LINKING);
10032 assign_stmt = gimple_build_assign (dest, t);
10033 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10034 }
10035 if (fd->collapse > 1)
10036 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10037
10038 if (!broken_loop)
10039 {
10040 /* The code controlling the sequential loop goes in CONT_BB,
10041 replacing the GIMPLE_OMP_CONTINUE. */
10042 gsi = gsi_last_bb (cont_bb);
10043 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
10044 vmain = gimple_omp_continue_control_use (cont_stmt);
10045 vback = gimple_omp_continue_control_def (cont_stmt);
10046
10047 if (!gimple_omp_for_combined_p (fd->for_stmt))
10048 {
10049 if (POINTER_TYPE_P (type))
10050 t = fold_build_pointer_plus (vmain, step);
10051 else
10052 t = fold_build2 (PLUS_EXPR, type, vmain, step);
10053 if (DECL_P (vback) && TREE_ADDRESSABLE (vback))
10054 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10055 true, GSI_SAME_STMT);
10056 assign_stmt = gimple_build_assign (vback, t);
10057 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
10058
10059 if (tree_int_cst_equal (fd->chunk_size, integer_one_node))
10060 t = build2 (EQ_EXPR, boolean_type_node,
10061 build_int_cst (itype, 0),
10062 build_int_cst (itype, 1));
10063 else
10064 t = build2 (fd->loop.cond_code, boolean_type_node,
10065 DECL_P (vback) && TREE_ADDRESSABLE (vback)
10066 ? t : vback, e);
10067 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
10068 }
10069
10070 /* Remove GIMPLE_OMP_CONTINUE. */
10071 gsi_remove (&gsi, true);
10072
10073 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
10074 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
10075
10076 /* Trip update code goes into TRIP_UPDATE_BB. */
10077 gsi = gsi_start_bb (trip_update_bb);
10078
10079 t = build_int_cst (itype, 1);
10080 t = build2 (PLUS_EXPR, itype, trip_main, t);
10081 assign_stmt = gimple_build_assign (trip_back, t);
10082 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10083 }
10084
10085 /* Replace the GIMPLE_OMP_RETURN with a barrier, or nothing. */
10086 gsi = gsi_last_bb (exit_bb);
10087 if (!gimple_omp_return_nowait_p (gsi_stmt (gsi)))
10088 {
10089 t = gimple_omp_return_lhs (gsi_stmt (gsi));
10090 gsi_insert_after (&gsi, build_omp_barrier (t), GSI_SAME_STMT);
10091 }
10092 gsi_remove (&gsi, true);
10093
10094 /* Connect the new blocks. */
10095 find_edge (iter_part_bb, seq_start_bb)->flags = EDGE_TRUE_VALUE;
10096 find_edge (iter_part_bb, fin_bb)->flags = EDGE_FALSE_VALUE;
10097
10098 if (!broken_loop)
10099 {
10100 se = find_edge (cont_bb, body_bb);
10101 if (se == NULL)
10102 {
10103 se = BRANCH_EDGE (cont_bb);
10104 gcc_assert (single_succ (se->dest) == body_bb);
10105 }
10106 if (gimple_omp_for_combined_p (fd->for_stmt))
10107 {
10108 remove_edge (se);
10109 se = NULL;
10110 }
10111 else if (fd->collapse > 1)
10112 {
10113 remove_edge (se);
10114 se = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
10115 }
10116 else
10117 se->flags = EDGE_TRUE_VALUE;
10118 find_edge (cont_bb, trip_update_bb)->flags
10119 = se ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
10120
10121 redirect_edge_and_branch (single_succ_edge (trip_update_bb), iter_part_bb);
10122 }
10123
10124 if (gimple_in_ssa_p (cfun))
10125 {
10126 gphi_iterator psi;
10127 gphi *phi;
10128 edge re, ene;
10129 edge_var_map *vm;
10130 size_t i;
10131
10132 gcc_assert (fd->collapse == 1 && !broken_loop);
10133
10134 /* When we redirect the edge from trip_update_bb to iter_part_bb, we
10135 remove arguments of the phi nodes in fin_bb. We need to create
10136 appropriate phi nodes in iter_part_bb instead. */
10137 se = find_edge (iter_part_bb, fin_bb);
10138 re = single_succ_edge (trip_update_bb);
10139 vec<edge_var_map> *head = redirect_edge_var_map_vector (re);
10140 ene = single_succ_edge (entry_bb);
10141
10142 psi = gsi_start_phis (fin_bb);
10143 for (i = 0; !gsi_end_p (psi) && head->iterate (i, &vm);
10144 gsi_next (&psi), ++i)
10145 {
10146 gphi *nphi;
10147 source_location locus;
10148
10149 phi = psi.phi ();
10150 t = gimple_phi_result (phi);
10151 gcc_assert (t == redirect_edge_var_map_result (vm));
10152
10153 if (!single_pred_p (fin_bb))
10154 t = copy_ssa_name (t, phi);
10155
10156 nphi = create_phi_node (t, iter_part_bb);
10157
10158 t = PHI_ARG_DEF_FROM_EDGE (phi, se);
10159 locus = gimple_phi_arg_location_from_edge (phi, se);
10160
10161 /* A special case -- fd->loop.v is not yet computed in
10162 iter_part_bb, we need to use vextra instead. */
10163 if (t == fd->loop.v)
10164 t = vextra;
10165 add_phi_arg (nphi, t, ene, locus);
10166 locus = redirect_edge_var_map_location (vm);
10167 tree back_arg = redirect_edge_var_map_def (vm);
10168 add_phi_arg (nphi, back_arg, re, locus);
10169 edge ce = find_edge (cont_bb, body_bb);
10170 if (ce == NULL)
10171 {
10172 ce = BRANCH_EDGE (cont_bb);
10173 gcc_assert (single_succ (ce->dest) == body_bb);
10174 ce = single_succ_edge (ce->dest);
10175 }
10176 gphi *inner_loop_phi = find_phi_with_arg_on_edge (back_arg, ce);
10177 gcc_assert (inner_loop_phi != NULL);
10178 add_phi_arg (inner_loop_phi, gimple_phi_result (nphi),
10179 find_edge (seq_start_bb, body_bb), locus);
10180
10181 if (!single_pred_p (fin_bb))
10182 add_phi_arg (phi, gimple_phi_result (nphi), se, locus);
10183 }
10184 gcc_assert (gsi_end_p (psi) && (head == NULL || i == head->length ()));
10185 redirect_edge_var_map_clear (re);
10186 if (single_pred_p (fin_bb))
10187 while (1)
10188 {
10189 psi = gsi_start_phis (fin_bb);
10190 if (gsi_end_p (psi))
10191 break;
10192 remove_phi_node (&psi, false);
10193 }
10194
10195 /* Make phi node for trip. */
10196 phi = create_phi_node (trip_main, iter_part_bb);
10197 add_phi_arg (phi, trip_back, single_succ_edge (trip_update_bb),
10198 UNKNOWN_LOCATION);
10199 add_phi_arg (phi, trip_init, single_succ_edge (entry_bb),
10200 UNKNOWN_LOCATION);
10201 }
10202
10203 if (!broken_loop)
10204 set_immediate_dominator (CDI_DOMINATORS, trip_update_bb, cont_bb);
10205 set_immediate_dominator (CDI_DOMINATORS, iter_part_bb,
10206 recompute_dominator (CDI_DOMINATORS, iter_part_bb));
10207 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
10208 recompute_dominator (CDI_DOMINATORS, fin_bb));
10209 set_immediate_dominator (CDI_DOMINATORS, seq_start_bb,
10210 recompute_dominator (CDI_DOMINATORS, seq_start_bb));
10211 set_immediate_dominator (CDI_DOMINATORS, body_bb,
10212 recompute_dominator (CDI_DOMINATORS, body_bb));
10213
10214 if (!broken_loop)
10215 {
10216 struct loop *loop = body_bb->loop_father;
10217 struct loop *trip_loop = alloc_loop ();
10218 trip_loop->header = iter_part_bb;
10219 trip_loop->latch = trip_update_bb;
10220 add_loop (trip_loop, iter_part_bb->loop_father);
10221
10222 if (loop != entry_bb->loop_father)
10223 {
10224 gcc_assert (loop->header == body_bb);
10225 gcc_assert (loop->latch == region->cont
10226 || single_pred (loop->latch) == region->cont);
10227 trip_loop->inner = loop;
10228 return;
10229 }
10230
10231 if (!gimple_omp_for_combined_p (fd->for_stmt))
10232 {
10233 loop = alloc_loop ();
10234 loop->header = body_bb;
10235 if (collapse_bb == NULL)
10236 loop->latch = cont_bb;
10237 add_loop (loop, trip_loop);
10238 }
10239 }
10240 }
10241
10242 /* A subroutine of expand_omp_for. Generate code for _Cilk_for loop.
10243 Given parameters:
10244 for (V = N1; V cond N2; V += STEP) BODY;
10245
10246 where COND is "<" or ">" or "!=", we generate pseudocode
10247
10248 for (ind_var = low; ind_var < high; ind_var++)
10249 {
10250 V = n1 + (ind_var * STEP)
10251
10252 <BODY>
10253 }
10254
10255 In the above pseudocode, low and high are function parameters of the
10256 child function. In the function below, we are inserting a temp.
10257 variable that will be making a call to two OMP functions that will not be
10258 found in the body of _Cilk_for (since OMP_FOR cannot be mixed
10259 with _Cilk_for). These functions are replaced with low and high
10260 by the function that handles taskreg. */
10261
10262
10263 static void
10264 expand_cilk_for (struct omp_region *region, struct omp_for_data *fd)
10265 {
10266 bool broken_loop = region->cont == NULL;
10267 basic_block entry_bb = region->entry;
10268 basic_block cont_bb = region->cont;
10269
10270 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10271 gcc_assert (broken_loop
10272 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10273 basic_block l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10274 basic_block l1_bb, l2_bb;
10275
10276 if (!broken_loop)
10277 {
10278 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10279 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10280 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10281 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10282 }
10283 else
10284 {
10285 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10286 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10287 l2_bb = single_succ (l1_bb);
10288 }
10289 basic_block exit_bb = region->exit;
10290 basic_block l2_dom_bb = NULL;
10291
10292 gimple_stmt_iterator gsi = gsi_last_bb (entry_bb);
10293
10294 /* Below statements until the "tree high_val = ..." are pseudo statements
10295 used to pass information to be used by expand_omp_taskreg.
10296 low_val and high_val will be replaced by the __low and __high
10297 parameter from the child function.
10298
10299 The call_exprs part is a place-holder, it is mainly used
10300 to distinctly identify to the top-level part that this is
10301 where we should put low and high (reasoning given in header
10302 comment). */
10303
10304 tree child_fndecl
10305 = gimple_omp_parallel_child_fn (
10306 as_a <gomp_parallel *> (last_stmt (region->outer->entry)));
10307 tree t, low_val = NULL_TREE, high_val = NULL_TREE;
10308 for (t = DECL_ARGUMENTS (child_fndecl); t; t = TREE_CHAIN (t))
10309 {
10310 if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__high"))
10311 high_val = t;
10312 else if (!strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__low"))
10313 low_val = t;
10314 }
10315 gcc_assert (low_val && high_val);
10316
10317 tree type = TREE_TYPE (low_val);
10318 tree ind_var = create_tmp_reg (type, "__cilk_ind_var");
10319 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10320
10321 /* Not needed in SSA form right now. */
10322 gcc_assert (!gimple_in_ssa_p (cfun));
10323 if (l2_dom_bb == NULL)
10324 l2_dom_bb = l1_bb;
10325
10326 tree n1 = low_val;
10327 tree n2 = high_val;
10328
10329 gimple *stmt = gimple_build_assign (ind_var, n1);
10330
10331 /* Replace the GIMPLE_OMP_FOR statement. */
10332 gsi_replace (&gsi, stmt, true);
10333
10334 if (!broken_loop)
10335 {
10336 /* Code to control the increment goes in the CONT_BB. */
10337 gsi = gsi_last_bb (cont_bb);
10338 stmt = gsi_stmt (gsi);
10339 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10340 stmt = gimple_build_assign (ind_var, PLUS_EXPR, ind_var,
10341 build_one_cst (type));
10342
10343 /* Replace GIMPLE_OMP_CONTINUE. */
10344 gsi_replace (&gsi, stmt, true);
10345 }
10346
10347 /* Emit the condition in L1_BB. */
10348 gsi = gsi_after_labels (l1_bb);
10349 t = fold_build2 (MULT_EXPR, TREE_TYPE (fd->loop.step),
10350 fold_convert (TREE_TYPE (fd->loop.step), ind_var),
10351 fd->loop.step);
10352 if (POINTER_TYPE_P (TREE_TYPE (fd->loop.n1)))
10353 t = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10354 fd->loop.n1, fold_convert (sizetype, t));
10355 else
10356 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loop.n1),
10357 fd->loop.n1, fold_convert (TREE_TYPE (fd->loop.n1), t));
10358 t = fold_convert (TREE_TYPE (fd->loop.v), t);
10359 expand_omp_build_assign (&gsi, fd->loop.v, t);
10360
10361 /* The condition is always '<' since the runtime will fill in the low
10362 and high values. */
10363 stmt = gimple_build_cond (LT_EXPR, ind_var, n2, NULL_TREE, NULL_TREE);
10364 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
10365
10366 /* Remove GIMPLE_OMP_RETURN. */
10367 gsi = gsi_last_bb (exit_bb);
10368 gsi_remove (&gsi, true);
10369
10370 /* Connect the new blocks. */
10371 remove_edge (FALLTHRU_EDGE (entry_bb));
10372
10373 edge e, ne;
10374 if (!broken_loop)
10375 {
10376 remove_edge (BRANCH_EDGE (entry_bb));
10377 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10378
10379 e = BRANCH_EDGE (l1_bb);
10380 ne = FALLTHRU_EDGE (l1_bb);
10381 e->flags = EDGE_TRUE_VALUE;
10382 }
10383 else
10384 {
10385 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10386
10387 ne = single_succ_edge (l1_bb);
10388 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10389
10390 }
10391 ne->flags = EDGE_FALSE_VALUE;
10392 e->probability = REG_BR_PROB_BASE * 7 / 8;
10393 ne->probability = REG_BR_PROB_BASE / 8;
10394
10395 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10396 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10397 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10398
10399 if (!broken_loop)
10400 {
10401 struct loop *loop = alloc_loop ();
10402 loop->header = l1_bb;
10403 loop->latch = cont_bb;
10404 add_loop (loop, l1_bb->loop_father);
10405 loop->safelen = INT_MAX;
10406 }
10407
10408 /* Pick the correct library function based on the precision of the
10409 induction variable type. */
10410 tree lib_fun = NULL_TREE;
10411 if (TYPE_PRECISION (type) == 32)
10412 lib_fun = cilk_for_32_fndecl;
10413 else if (TYPE_PRECISION (type) == 64)
10414 lib_fun = cilk_for_64_fndecl;
10415 else
10416 gcc_unreachable ();
10417
10418 gcc_assert (fd->sched_kind == OMP_CLAUSE_SCHEDULE_CILKFOR);
10419
10420 /* WS_ARGS contains the library function flavor to call:
10421 __libcilkrts_cilk_for_64 or __libcilkrts_cilk_for_32), and the
10422 user-defined grain value. If the user does not define one, then zero
10423 is passed in by the parser. */
10424 vec_alloc (region->ws_args, 2);
10425 region->ws_args->quick_push (lib_fun);
10426 region->ws_args->quick_push (fd->chunk_size);
10427 }
10428
10429 /* A subroutine of expand_omp_for. Generate code for a simd non-worksharing
10430 loop. Given parameters:
10431
10432 for (V = N1; V cond N2; V += STEP) BODY;
10433
10434 where COND is "<" or ">", we generate pseudocode
10435
10436 V = N1;
10437 goto L1;
10438 L0:
10439 BODY;
10440 V += STEP;
10441 L1:
10442 if (V cond N2) goto L0; else goto L2;
10443 L2:
10444
10445 For collapsed loops, given parameters:
10446 collapse(3)
10447 for (V1 = N11; V1 cond1 N12; V1 += STEP1)
10448 for (V2 = N21; V2 cond2 N22; V2 += STEP2)
10449 for (V3 = N31; V3 cond3 N32; V3 += STEP3)
10450 BODY;
10451
10452 we generate pseudocode
10453
10454 if (cond3 is <)
10455 adj = STEP3 - 1;
10456 else
10457 adj = STEP3 + 1;
10458 count3 = (adj + N32 - N31) / STEP3;
10459 if (cond2 is <)
10460 adj = STEP2 - 1;
10461 else
10462 adj = STEP2 + 1;
10463 count2 = (adj + N22 - N21) / STEP2;
10464 if (cond1 is <)
10465 adj = STEP1 - 1;
10466 else
10467 adj = STEP1 + 1;
10468 count1 = (adj + N12 - N11) / STEP1;
10469 count = count1 * count2 * count3;
10470 V = 0;
10471 V1 = N11;
10472 V2 = N21;
10473 V3 = N31;
10474 goto L1;
10475 L0:
10476 BODY;
10477 V += 1;
10478 V3 += STEP3;
10479 V2 += (V3 cond3 N32) ? 0 : STEP2;
10480 V3 = (V3 cond3 N32) ? V3 : N31;
10481 V1 += (V2 cond2 N22) ? 0 : STEP1;
10482 V2 = (V2 cond2 N22) ? V2 : N21;
10483 L1:
10484 if (V < count) goto L0; else goto L2;
10485 L2:
10486
10487 */
10488
10489 static void
10490 expand_omp_simd (struct omp_region *region, struct omp_for_data *fd)
10491 {
10492 tree type, t;
10493 basic_block entry_bb, cont_bb, exit_bb, l0_bb, l1_bb, l2_bb, l2_dom_bb;
10494 gimple_stmt_iterator gsi;
10495 gimple *stmt;
10496 gcond *cond_stmt;
10497 bool broken_loop = region->cont == NULL;
10498 edge e, ne;
10499 tree *counts = NULL;
10500 int i;
10501 tree safelen = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10502 OMP_CLAUSE_SAFELEN);
10503 tree simduid = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10504 OMP_CLAUSE__SIMDUID_);
10505 tree n1, n2;
10506
10507 type = TREE_TYPE (fd->loop.v);
10508 entry_bb = region->entry;
10509 cont_bb = region->cont;
10510 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10511 gcc_assert (broken_loop
10512 || BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10513 l0_bb = FALLTHRU_EDGE (entry_bb)->dest;
10514 if (!broken_loop)
10515 {
10516 gcc_assert (BRANCH_EDGE (cont_bb)->dest == l0_bb);
10517 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10518 l1_bb = split_block (cont_bb, last_stmt (cont_bb))->dest;
10519 l2_bb = BRANCH_EDGE (entry_bb)->dest;
10520 }
10521 else
10522 {
10523 BRANCH_EDGE (entry_bb)->flags &= ~EDGE_ABNORMAL;
10524 l1_bb = split_edge (BRANCH_EDGE (entry_bb));
10525 l2_bb = single_succ (l1_bb);
10526 }
10527 exit_bb = region->exit;
10528 l2_dom_bb = NULL;
10529
10530 gsi = gsi_last_bb (entry_bb);
10531
10532 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10533 /* Not needed in SSA form right now. */
10534 gcc_assert (!gimple_in_ssa_p (cfun));
10535 if (fd->collapse > 1)
10536 {
10537 int first_zero_iter = -1, dummy = -1;
10538 basic_block zero_iter_bb = l2_bb, dummy_bb = NULL;
10539
10540 counts = XALLOCAVEC (tree, fd->collapse);
10541 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10542 zero_iter_bb, first_zero_iter,
10543 dummy_bb, dummy, l2_dom_bb);
10544 }
10545 if (l2_dom_bb == NULL)
10546 l2_dom_bb = l1_bb;
10547
10548 n1 = fd->loop.n1;
10549 n2 = fd->loop.n2;
10550 if (gimple_omp_for_combined_into_p (fd->for_stmt))
10551 {
10552 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10553 OMP_CLAUSE__LOOPTEMP_);
10554 gcc_assert (innerc);
10555 n1 = OMP_CLAUSE_DECL (innerc);
10556 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10557 OMP_CLAUSE__LOOPTEMP_);
10558 gcc_assert (innerc);
10559 n2 = OMP_CLAUSE_DECL (innerc);
10560 expand_omp_build_assign (&gsi, fd->loop.v,
10561 fold_convert (type, n1));
10562 if (fd->collapse > 1)
10563 {
10564 gsi_prev (&gsi);
10565 expand_omp_for_init_vars (fd, &gsi, counts, NULL, n1);
10566 gsi_next (&gsi);
10567 }
10568 }
10569 else
10570 {
10571 expand_omp_build_assign (&gsi, fd->loop.v,
10572 fold_convert (type, fd->loop.n1));
10573 if (fd->collapse > 1)
10574 for (i = 0; i < fd->collapse; i++)
10575 {
10576 tree itype = TREE_TYPE (fd->loops[i].v);
10577 if (POINTER_TYPE_P (itype))
10578 itype = signed_type_for (itype);
10579 t = fold_convert (TREE_TYPE (fd->loops[i].v), fd->loops[i].n1);
10580 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10581 }
10582 }
10583
10584 /* Remove the GIMPLE_OMP_FOR statement. */
10585 gsi_remove (&gsi, true);
10586
10587 if (!broken_loop)
10588 {
10589 /* Code to control the increment goes in the CONT_BB. */
10590 gsi = gsi_last_bb (cont_bb);
10591 stmt = gsi_stmt (gsi);
10592 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_CONTINUE);
10593
10594 if (POINTER_TYPE_P (type))
10595 t = fold_build_pointer_plus (fd->loop.v, fd->loop.step);
10596 else
10597 t = fold_build2 (PLUS_EXPR, type, fd->loop.v, fd->loop.step);
10598 expand_omp_build_assign (&gsi, fd->loop.v, t);
10599
10600 if (fd->collapse > 1)
10601 {
10602 i = fd->collapse - 1;
10603 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i].v)))
10604 {
10605 t = fold_convert (sizetype, fd->loops[i].step);
10606 t = fold_build_pointer_plus (fd->loops[i].v, t);
10607 }
10608 else
10609 {
10610 t = fold_convert (TREE_TYPE (fd->loops[i].v),
10611 fd->loops[i].step);
10612 t = fold_build2 (PLUS_EXPR, TREE_TYPE (fd->loops[i].v),
10613 fd->loops[i].v, t);
10614 }
10615 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10616
10617 for (i = fd->collapse - 1; i > 0; i--)
10618 {
10619 tree itype = TREE_TYPE (fd->loops[i].v);
10620 tree itype2 = TREE_TYPE (fd->loops[i - 1].v);
10621 if (POINTER_TYPE_P (itype2))
10622 itype2 = signed_type_for (itype2);
10623 t = build3 (COND_EXPR, itype2,
10624 build2 (fd->loops[i].cond_code, boolean_type_node,
10625 fd->loops[i].v,
10626 fold_convert (itype, fd->loops[i].n2)),
10627 build_int_cst (itype2, 0),
10628 fold_convert (itype2, fd->loops[i - 1].step));
10629 if (POINTER_TYPE_P (TREE_TYPE (fd->loops[i - 1].v)))
10630 t = fold_build_pointer_plus (fd->loops[i - 1].v, t);
10631 else
10632 t = fold_build2 (PLUS_EXPR, itype2, fd->loops[i - 1].v, t);
10633 expand_omp_build_assign (&gsi, fd->loops[i - 1].v, t);
10634
10635 t = build3 (COND_EXPR, itype,
10636 build2 (fd->loops[i].cond_code, boolean_type_node,
10637 fd->loops[i].v,
10638 fold_convert (itype, fd->loops[i].n2)),
10639 fd->loops[i].v,
10640 fold_convert (itype, fd->loops[i].n1));
10641 expand_omp_build_assign (&gsi, fd->loops[i].v, t);
10642 }
10643 }
10644
10645 /* Remove GIMPLE_OMP_CONTINUE. */
10646 gsi_remove (&gsi, true);
10647 }
10648
10649 /* Emit the condition in L1_BB. */
10650 gsi = gsi_start_bb (l1_bb);
10651
10652 t = fold_convert (type, n2);
10653 t = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
10654 false, GSI_CONTINUE_LINKING);
10655 tree v = fd->loop.v;
10656 if (DECL_P (v) && TREE_ADDRESSABLE (v))
10657 v = force_gimple_operand_gsi (&gsi, v, true, NULL_TREE,
10658 false, GSI_CONTINUE_LINKING);
10659 t = build2 (fd->loop.cond_code, boolean_type_node, v, t);
10660 cond_stmt = gimple_build_cond_empty (t);
10661 gsi_insert_after (&gsi, cond_stmt, GSI_CONTINUE_LINKING);
10662 if (walk_tree (gimple_cond_lhs_ptr (cond_stmt), expand_omp_regimplify_p,
10663 NULL, NULL)
10664 || walk_tree (gimple_cond_rhs_ptr (cond_stmt), expand_omp_regimplify_p,
10665 NULL, NULL))
10666 {
10667 gsi = gsi_for_stmt (cond_stmt);
10668 gimple_regimplify_operands (cond_stmt, &gsi);
10669 }
10670
10671 /* Remove GIMPLE_OMP_RETURN. */
10672 gsi = gsi_last_bb (exit_bb);
10673 gsi_remove (&gsi, true);
10674
10675 /* Connect the new blocks. */
10676 remove_edge (FALLTHRU_EDGE (entry_bb));
10677
10678 if (!broken_loop)
10679 {
10680 remove_edge (BRANCH_EDGE (entry_bb));
10681 make_edge (entry_bb, l1_bb, EDGE_FALLTHRU);
10682
10683 e = BRANCH_EDGE (l1_bb);
10684 ne = FALLTHRU_EDGE (l1_bb);
10685 e->flags = EDGE_TRUE_VALUE;
10686 }
10687 else
10688 {
10689 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
10690
10691 ne = single_succ_edge (l1_bb);
10692 e = make_edge (l1_bb, l0_bb, EDGE_TRUE_VALUE);
10693
10694 }
10695 ne->flags = EDGE_FALSE_VALUE;
10696 e->probability = REG_BR_PROB_BASE * 7 / 8;
10697 ne->probability = REG_BR_PROB_BASE / 8;
10698
10699 set_immediate_dominator (CDI_DOMINATORS, l1_bb, entry_bb);
10700 set_immediate_dominator (CDI_DOMINATORS, l2_bb, l2_dom_bb);
10701 set_immediate_dominator (CDI_DOMINATORS, l0_bb, l1_bb);
10702
10703 if (!broken_loop)
10704 {
10705 struct loop *loop = alloc_loop ();
10706 loop->header = l1_bb;
10707 loop->latch = cont_bb;
10708 add_loop (loop, l1_bb->loop_father);
10709 if (safelen == NULL_TREE)
10710 loop->safelen = INT_MAX;
10711 else
10712 {
10713 safelen = OMP_CLAUSE_SAFELEN_EXPR (safelen);
10714 if (TREE_CODE (safelen) != INTEGER_CST)
10715 loop->safelen = 0;
10716 else if (!tree_fits_uhwi_p (safelen)
10717 || tree_to_uhwi (safelen) > INT_MAX)
10718 loop->safelen = INT_MAX;
10719 else
10720 loop->safelen = tree_to_uhwi (safelen);
10721 if (loop->safelen == 1)
10722 loop->safelen = 0;
10723 }
10724 if (simduid)
10725 {
10726 loop->simduid = OMP_CLAUSE__SIMDUID__DECL (simduid);
10727 cfun->has_simduid_loops = true;
10728 }
10729 /* If not -fno-tree-loop-vectorize, hint that we want to vectorize
10730 the loop. */
10731 if ((flag_tree_loop_vectorize
10732 || (!global_options_set.x_flag_tree_loop_vectorize
10733 && !global_options_set.x_flag_tree_vectorize))
10734 && flag_tree_loop_optimize
10735 && loop->safelen > 1)
10736 {
10737 loop->force_vectorize = true;
10738 cfun->has_force_vectorize_loops = true;
10739 }
10740 }
10741 else if (simduid)
10742 cfun->has_simduid_loops = true;
10743 }
10744
10745 /* Taskloop construct is represented after gimplification with
10746 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10747 in between them. This routine expands the outer GIMPLE_OMP_FOR,
10748 which should just compute all the needed loop temporaries
10749 for GIMPLE_OMP_TASK. */
10750
10751 static void
10752 expand_omp_taskloop_for_outer (struct omp_region *region,
10753 struct omp_for_data *fd,
10754 gimple *inner_stmt)
10755 {
10756 tree type, bias = NULL_TREE;
10757 basic_block entry_bb, cont_bb, exit_bb;
10758 gimple_stmt_iterator gsi;
10759 gassign *assign_stmt;
10760 tree *counts = NULL;
10761 int i;
10762
10763 gcc_assert (inner_stmt);
10764 gcc_assert (region->cont);
10765 gcc_assert (gimple_code (inner_stmt) == GIMPLE_OMP_TASK
10766 && gimple_omp_task_taskloop_p (inner_stmt));
10767 type = TREE_TYPE (fd->loop.v);
10768
10769 /* See if we need to bias by LLONG_MIN. */
10770 if (fd->iter_type == long_long_unsigned_type_node
10771 && TREE_CODE (type) == INTEGER_TYPE
10772 && !TYPE_UNSIGNED (type))
10773 {
10774 tree n1, n2;
10775
10776 if (fd->loop.cond_code == LT_EXPR)
10777 {
10778 n1 = fd->loop.n1;
10779 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10780 }
10781 else
10782 {
10783 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10784 n2 = fd->loop.n1;
10785 }
10786 if (TREE_CODE (n1) != INTEGER_CST
10787 || TREE_CODE (n2) != INTEGER_CST
10788 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10789 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10790 }
10791
10792 entry_bb = region->entry;
10793 cont_bb = region->cont;
10794 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10795 gcc_assert (BRANCH_EDGE (entry_bb)->dest == FALLTHRU_EDGE (cont_bb)->dest);
10796 exit_bb = region->exit;
10797
10798 gsi = gsi_last_bb (entry_bb);
10799 gimple *for_stmt = gsi_stmt (gsi);
10800 gcc_assert (gimple_code (for_stmt) == GIMPLE_OMP_FOR);
10801 if (fd->collapse > 1)
10802 {
10803 int first_zero_iter = -1, dummy = -1;
10804 basic_block zero_iter_bb = NULL, dummy_bb = NULL, l2_dom_bb = NULL;
10805
10806 counts = XALLOCAVEC (tree, fd->collapse);
10807 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10808 zero_iter_bb, first_zero_iter,
10809 dummy_bb, dummy, l2_dom_bb);
10810
10811 if (zero_iter_bb)
10812 {
10813 /* Some counts[i] vars might be uninitialized if
10814 some loop has zero iterations. But the body shouldn't
10815 be executed in that case, so just avoid uninit warnings. */
10816 for (i = first_zero_iter; i < fd->collapse; i++)
10817 if (SSA_VAR_P (counts[i]))
10818 TREE_NO_WARNING (counts[i]) = 1;
10819 gsi_prev (&gsi);
10820 edge e = split_block (entry_bb, gsi_stmt (gsi));
10821 entry_bb = e->dest;
10822 make_edge (zero_iter_bb, entry_bb, EDGE_FALLTHRU);
10823 gsi = gsi_last_bb (entry_bb);
10824 set_immediate_dominator (CDI_DOMINATORS, entry_bb,
10825 get_immediate_dominator (CDI_DOMINATORS,
10826 zero_iter_bb));
10827 }
10828 }
10829
10830 tree t0, t1;
10831 t1 = fd->loop.n2;
10832 t0 = fd->loop.n1;
10833 if (POINTER_TYPE_P (TREE_TYPE (t0))
10834 && TYPE_PRECISION (TREE_TYPE (t0))
10835 != TYPE_PRECISION (fd->iter_type))
10836 {
10837 /* Avoid casting pointers to integer of a different size. */
10838 tree itype = signed_type_for (type);
10839 t1 = fold_convert (fd->iter_type, fold_convert (itype, t1));
10840 t0 = fold_convert (fd->iter_type, fold_convert (itype, t0));
10841 }
10842 else
10843 {
10844 t1 = fold_convert (fd->iter_type, t1);
10845 t0 = fold_convert (fd->iter_type, t0);
10846 }
10847 if (bias)
10848 {
10849 t1 = fold_build2 (PLUS_EXPR, fd->iter_type, t1, bias);
10850 t0 = fold_build2 (PLUS_EXPR, fd->iter_type, t0, bias);
10851 }
10852
10853 tree innerc = find_omp_clause (gimple_omp_task_clauses (inner_stmt),
10854 OMP_CLAUSE__LOOPTEMP_);
10855 gcc_assert (innerc);
10856 tree startvar = OMP_CLAUSE_DECL (innerc);
10857 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10858 gcc_assert (innerc);
10859 tree endvar = OMP_CLAUSE_DECL (innerc);
10860 if (fd->collapse > 1 && TREE_CODE (fd->loop.n2) != INTEGER_CST)
10861 {
10862 gcc_assert (innerc);
10863 for (i = 1; i < fd->collapse; i++)
10864 {
10865 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10866 OMP_CLAUSE__LOOPTEMP_);
10867 gcc_assert (innerc);
10868 }
10869 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
10870 OMP_CLAUSE__LOOPTEMP_);
10871 if (innerc)
10872 {
10873 /* If needed (inner taskloop has lastprivate clause), propagate
10874 down the total number of iterations. */
10875 tree t = force_gimple_operand_gsi (&gsi, fd->loop.n2, false,
10876 NULL_TREE, false,
10877 GSI_CONTINUE_LINKING);
10878 assign_stmt = gimple_build_assign (OMP_CLAUSE_DECL (innerc), t);
10879 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10880 }
10881 }
10882
10883 t0 = force_gimple_operand_gsi (&gsi, t0, false, NULL_TREE, false,
10884 GSI_CONTINUE_LINKING);
10885 assign_stmt = gimple_build_assign (startvar, t0);
10886 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10887
10888 t1 = force_gimple_operand_gsi (&gsi, t1, false, NULL_TREE, false,
10889 GSI_CONTINUE_LINKING);
10890 assign_stmt = gimple_build_assign (endvar, t1);
10891 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
10892 if (fd->collapse > 1)
10893 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
10894
10895 /* Remove the GIMPLE_OMP_FOR statement. */
10896 gsi = gsi_for_stmt (for_stmt);
10897 gsi_remove (&gsi, true);
10898
10899 gsi = gsi_last_bb (cont_bb);
10900 gsi_remove (&gsi, true);
10901
10902 gsi = gsi_last_bb (exit_bb);
10903 gsi_remove (&gsi, true);
10904
10905 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
10906 remove_edge (BRANCH_EDGE (entry_bb));
10907 FALLTHRU_EDGE (cont_bb)->probability = REG_BR_PROB_BASE;
10908 remove_edge (BRANCH_EDGE (cont_bb));
10909 set_immediate_dominator (CDI_DOMINATORS, exit_bb, cont_bb);
10910 set_immediate_dominator (CDI_DOMINATORS, region->entry,
10911 recompute_dominator (CDI_DOMINATORS, region->entry));
10912 }
10913
10914 /* Taskloop construct is represented after gimplification with
10915 two GIMPLE_OMP_FOR constructs with GIMPLE_OMP_TASK sandwiched
10916 in between them. This routine expands the inner GIMPLE_OMP_FOR.
10917 GOMP_taskloop{,_ull} function arranges for each task to be given just
10918 a single range of iterations. */
10919
10920 static void
10921 expand_omp_taskloop_for_inner (struct omp_region *region,
10922 struct omp_for_data *fd,
10923 gimple *inner_stmt)
10924 {
10925 tree e, t, type, itype, vmain, vback, bias = NULL_TREE;
10926 basic_block entry_bb, exit_bb, body_bb, cont_bb, collapse_bb = NULL;
10927 basic_block fin_bb;
10928 gimple_stmt_iterator gsi;
10929 edge ep;
10930 bool broken_loop = region->cont == NULL;
10931 tree *counts = NULL;
10932 tree n1, n2, step;
10933
10934 itype = type = TREE_TYPE (fd->loop.v);
10935 if (POINTER_TYPE_P (type))
10936 itype = signed_type_for (type);
10937
10938 /* See if we need to bias by LLONG_MIN. */
10939 if (fd->iter_type == long_long_unsigned_type_node
10940 && TREE_CODE (type) == INTEGER_TYPE
10941 && !TYPE_UNSIGNED (type))
10942 {
10943 tree n1, n2;
10944
10945 if (fd->loop.cond_code == LT_EXPR)
10946 {
10947 n1 = fd->loop.n1;
10948 n2 = fold_build2 (PLUS_EXPR, type, fd->loop.n2, fd->loop.step);
10949 }
10950 else
10951 {
10952 n1 = fold_build2 (MINUS_EXPR, type, fd->loop.n2, fd->loop.step);
10953 n2 = fd->loop.n1;
10954 }
10955 if (TREE_CODE (n1) != INTEGER_CST
10956 || TREE_CODE (n2) != INTEGER_CST
10957 || ((tree_int_cst_sgn (n1) < 0) ^ (tree_int_cst_sgn (n2) < 0)))
10958 bias = fold_convert (fd->iter_type, TYPE_MIN_VALUE (type));
10959 }
10960
10961 entry_bb = region->entry;
10962 cont_bb = region->cont;
10963 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2);
10964 fin_bb = BRANCH_EDGE (entry_bb)->dest;
10965 gcc_assert (broken_loop
10966 || (fin_bb == FALLTHRU_EDGE (cont_bb)->dest));
10967 body_bb = FALLTHRU_EDGE (entry_bb)->dest;
10968 if (!broken_loop)
10969 {
10970 gcc_assert (BRANCH_EDGE (cont_bb)->dest == body_bb);
10971 gcc_assert (EDGE_COUNT (cont_bb->succs) == 2);
10972 }
10973 exit_bb = region->exit;
10974
10975 /* Iteration space partitioning goes in ENTRY_BB. */
10976 gsi = gsi_last_bb (entry_bb);
10977 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_FOR);
10978
10979 if (fd->collapse > 1)
10980 {
10981 int first_zero_iter = -1, dummy = -1;
10982 basic_block l2_dom_bb = NULL, dummy_bb = NULL;
10983
10984 counts = XALLOCAVEC (tree, fd->collapse);
10985 expand_omp_for_init_counts (fd, &gsi, entry_bb, counts,
10986 fin_bb, first_zero_iter,
10987 dummy_bb, dummy, l2_dom_bb);
10988 t = NULL_TREE;
10989 }
10990 else
10991 t = integer_one_node;
10992
10993 step = fd->loop.step;
10994 tree innerc = find_omp_clause (gimple_omp_for_clauses (fd->for_stmt),
10995 OMP_CLAUSE__LOOPTEMP_);
10996 gcc_assert (innerc);
10997 n1 = OMP_CLAUSE_DECL (innerc);
10998 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc), OMP_CLAUSE__LOOPTEMP_);
10999 gcc_assert (innerc);
11000 n2 = OMP_CLAUSE_DECL (innerc);
11001 if (bias)
11002 {
11003 n1 = fold_build2 (PLUS_EXPR, fd->iter_type, n1, bias);
11004 n2 = fold_build2 (PLUS_EXPR, fd->iter_type, n2, bias);
11005 }
11006 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
11007 true, NULL_TREE, true, GSI_SAME_STMT);
11008 n2 = force_gimple_operand_gsi (&gsi, fold_convert (itype, n2),
11009 true, NULL_TREE, true, GSI_SAME_STMT);
11010 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
11011 true, NULL_TREE, true, GSI_SAME_STMT);
11012
11013 tree startvar = fd->loop.v;
11014 tree endvar = NULL_TREE;
11015
11016 if (gimple_omp_for_combined_p (fd->for_stmt))
11017 {
11018 tree clauses = gimple_omp_for_clauses (inner_stmt);
11019 tree innerc = find_omp_clause (clauses, OMP_CLAUSE__LOOPTEMP_);
11020 gcc_assert (innerc);
11021 startvar = OMP_CLAUSE_DECL (innerc);
11022 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
11023 OMP_CLAUSE__LOOPTEMP_);
11024 gcc_assert (innerc);
11025 endvar = OMP_CLAUSE_DECL (innerc);
11026 }
11027 t = fold_convert (TREE_TYPE (startvar), n1);
11028 t = force_gimple_operand_gsi (&gsi, t,
11029 DECL_P (startvar)
11030 && TREE_ADDRESSABLE (startvar),
11031 NULL_TREE, false, GSI_CONTINUE_LINKING);
11032 gimple *assign_stmt = gimple_build_assign (startvar, t);
11033 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11034
11035 t = fold_convert (TREE_TYPE (startvar), n2);
11036 e = force_gimple_operand_gsi (&gsi, t, true, NULL_TREE,
11037 false, GSI_CONTINUE_LINKING);
11038 if (endvar)
11039 {
11040 assign_stmt = gimple_build_assign (endvar, e);
11041 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11042 if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e)))
11043 assign_stmt = gimple_build_assign (fd->loop.v, e);
11044 else
11045 assign_stmt = gimple_build_assign (fd->loop.v, NOP_EXPR, e);
11046 gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING);
11047 }
11048 if (fd->collapse > 1)
11049 expand_omp_for_init_vars (fd, &gsi, counts, inner_stmt, startvar);
11050
11051 if (!broken_loop)
11052 {
11053 /* The code controlling the sequential loop replaces the
11054 GIMPLE_OMP_CONTINUE. */
11055 gsi = gsi_last_bb (cont_bb);
11056 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11057 gcc_assert (gimple_code (cont_stmt) == GIMPLE_OMP_CONTINUE);
11058 vmain = gimple_omp_continue_control_use (cont_stmt);
11059 vback = gimple_omp_continue_control_def (cont_stmt);
11060
11061 if (!gimple_omp_for_combined_p (fd->for_stmt))
11062 {
11063 if (POINTER_TYPE_P (type))
11064 t = fold_build_pointer_plus (vmain, step);
11065 else
11066 t = fold_build2 (PLUS_EXPR, type, vmain, step);
11067 t = force_gimple_operand_gsi (&gsi, t,
11068 DECL_P (vback)
11069 && TREE_ADDRESSABLE (vback),
11070 NULL_TREE, true, GSI_SAME_STMT);
11071 assign_stmt = gimple_build_assign (vback, t);
11072 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
11073
11074 t = build2 (fd->loop.cond_code, boolean_type_node,
11075 DECL_P (vback) && TREE_ADDRESSABLE (vback)
11076 ? t : vback, e);
11077 gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT);
11078 }
11079
11080 /* Remove the GIMPLE_OMP_CONTINUE statement. */
11081 gsi_remove (&gsi, true);
11082
11083 if (fd->collapse > 1 && !gimple_omp_for_combined_p (fd->for_stmt))
11084 collapse_bb = extract_omp_for_update_vars (fd, cont_bb, body_bb);
11085 }
11086
11087 /* Remove the GIMPLE_OMP_FOR statement. */
11088 gsi = gsi_for_stmt (fd->for_stmt);
11089 gsi_remove (&gsi, true);
11090
11091 /* Remove the GIMPLE_OMP_RETURN statement. */
11092 gsi = gsi_last_bb (exit_bb);
11093 gsi_remove (&gsi, true);
11094
11095 FALLTHRU_EDGE (entry_bb)->probability = REG_BR_PROB_BASE;
11096 if (!broken_loop)
11097 remove_edge (BRANCH_EDGE (entry_bb));
11098 else
11099 {
11100 remove_edge_and_dominated_blocks (BRANCH_EDGE (entry_bb));
11101 region->outer->cont = NULL;
11102 }
11103
11104 /* Connect all the blocks. */
11105 if (!broken_loop)
11106 {
11107 ep = find_edge (cont_bb, body_bb);
11108 if (gimple_omp_for_combined_p (fd->for_stmt))
11109 {
11110 remove_edge (ep);
11111 ep = NULL;
11112 }
11113 else if (fd->collapse > 1)
11114 {
11115 remove_edge (ep);
11116 ep = make_edge (cont_bb, collapse_bb, EDGE_TRUE_VALUE);
11117 }
11118 else
11119 ep->flags = EDGE_TRUE_VALUE;
11120 find_edge (cont_bb, fin_bb)->flags
11121 = ep ? EDGE_FALSE_VALUE : EDGE_FALLTHRU;
11122 }
11123
11124 set_immediate_dominator (CDI_DOMINATORS, body_bb,
11125 recompute_dominator (CDI_DOMINATORS, body_bb));
11126 if (!broken_loop)
11127 set_immediate_dominator (CDI_DOMINATORS, fin_bb,
11128 recompute_dominator (CDI_DOMINATORS, fin_bb));
11129
11130 if (!broken_loop && !gimple_omp_for_combined_p (fd->for_stmt))
11131 {
11132 struct loop *loop = alloc_loop ();
11133 loop->header = body_bb;
11134 if (collapse_bb == NULL)
11135 loop->latch = cont_bb;
11136 add_loop (loop, body_bb->loop_father);
11137 }
11138 }
11139
11140 /* A subroutine of expand_omp_for. Generate code for an OpenACC
11141 partitioned loop. The lowering here is abstracted, in that the
11142 loop parameters are passed through internal functions, which are
11143 further lowered by oacc_device_lower, once we get to the target
11144 compiler. The loop is of the form:
11145
11146 for (V = B; V LTGT E; V += S) {BODY}
11147
11148 where LTGT is < or >. We may have a specified chunking size, CHUNKING
11149 (constant 0 for no chunking) and we will have a GWV partitioning
11150 mask, specifying dimensions over which the loop is to be
11151 partitioned (see note below). We generate code that looks like:
11152
11153 <entry_bb> [incoming FALL->body, BRANCH->exit]
11154 typedef signedintify (typeof (V)) T; // underlying signed integral type
11155 T range = E - B;
11156 T chunk_no = 0;
11157 T DIR = LTGT == '<' ? +1 : -1;
11158 T chunk_max = GOACC_LOOP_CHUNK (dir, range, S, CHUNK_SIZE, GWV);
11159 T step = GOACC_LOOP_STEP (dir, range, S, CHUNK_SIZE, GWV);
11160
11161 <head_bb> [created by splitting end of entry_bb]
11162 T offset = GOACC_LOOP_OFFSET (dir, range, S, CHUNK_SIZE, GWV, chunk_no);
11163 T bound = GOACC_LOOP_BOUND (dir, range, S, CHUNK_SIZE, GWV, offset);
11164 if (!(offset LTGT bound)) goto bottom_bb;
11165
11166 <body_bb> [incoming]
11167 V = B + offset;
11168 {BODY}
11169
11170 <cont_bb> [incoming, may == body_bb FALL->exit_bb, BRANCH->body_bb]
11171 offset += step;
11172 if (offset LTGT bound) goto body_bb; [*]
11173
11174 <bottom_bb> [created by splitting start of exit_bb] insert BRANCH->head_bb
11175 chunk_no++;
11176 if (chunk < chunk_max) goto head_bb;
11177
11178 <exit_bb> [incoming]
11179 V = B + ((range -/+ 1) / S +/- 1) * S [*]
11180
11181 [*] Needed if V live at end of loop
11182
11183 Note: CHUNKING & GWV mask are specified explicitly here. This is a
11184 transition, and will be specified by a more general mechanism shortly.
11185 */
11186
11187 static void
11188 expand_oacc_for (struct omp_region *region, struct omp_for_data *fd)
11189 {
11190 tree v = fd->loop.v;
11191 enum tree_code cond_code = fd->loop.cond_code;
11192 enum tree_code plus_code = PLUS_EXPR;
11193
11194 tree chunk_size = integer_minus_one_node;
11195 tree gwv = integer_zero_node;
11196 tree iter_type = TREE_TYPE (v);
11197 tree diff_type = iter_type;
11198 tree plus_type = iter_type;
11199 struct oacc_collapse *counts = NULL;
11200
11201 gcc_checking_assert (gimple_omp_for_kind (fd->for_stmt)
11202 == GF_OMP_FOR_KIND_OACC_LOOP);
11203 gcc_assert (!gimple_omp_for_combined_into_p (fd->for_stmt));
11204 gcc_assert (cond_code == LT_EXPR || cond_code == GT_EXPR);
11205
11206 if (POINTER_TYPE_P (iter_type))
11207 {
11208 plus_code = POINTER_PLUS_EXPR;
11209 plus_type = sizetype;
11210 }
11211 if (POINTER_TYPE_P (diff_type) || TYPE_UNSIGNED (diff_type))
11212 diff_type = signed_type_for (diff_type);
11213
11214 basic_block entry_bb = region->entry; /* BB ending in OMP_FOR */
11215 basic_block exit_bb = region->exit; /* BB ending in OMP_RETURN */
11216 basic_block cont_bb = region->cont; /* BB ending in OMP_CONTINUE */
11217 basic_block bottom_bb = NULL;
11218
11219 /* entry_bb has two sucessors; the branch edge is to the exit
11220 block, fallthrough edge to body. */
11221 gcc_assert (EDGE_COUNT (entry_bb->succs) == 2
11222 && BRANCH_EDGE (entry_bb)->dest == exit_bb);
11223
11224 /* If cont_bb non-NULL, it has 2 successors. The branch successor is
11225 body_bb, or to a block whose only successor is the body_bb. Its
11226 fallthrough successor is the final block (same as the branch
11227 successor of the entry_bb). */
11228 if (cont_bb)
11229 {
11230 basic_block body_bb = FALLTHRU_EDGE (entry_bb)->dest;
11231 basic_block bed = BRANCH_EDGE (cont_bb)->dest;
11232
11233 gcc_assert (FALLTHRU_EDGE (cont_bb)->dest == exit_bb);
11234 gcc_assert (bed == body_bb || single_succ_edge (bed)->dest == body_bb);
11235 }
11236 else
11237 gcc_assert (!gimple_in_ssa_p (cfun));
11238
11239 /* The exit block only has entry_bb and cont_bb as predecessors. */
11240 gcc_assert (EDGE_COUNT (exit_bb->preds) == 1 + (cont_bb != NULL));
11241
11242 tree chunk_no;
11243 tree chunk_max = NULL_TREE;
11244 tree bound, offset;
11245 tree step = create_tmp_var (diff_type, ".step");
11246 bool up = cond_code == LT_EXPR;
11247 tree dir = build_int_cst (diff_type, up ? +1 : -1);
11248 bool chunking = !gimple_in_ssa_p (cfun);;
11249 bool negating;
11250
11251 /* SSA instances. */
11252 tree offset_incr = NULL_TREE;
11253 tree offset_init = NULL_TREE;
11254
11255 gimple_stmt_iterator gsi;
11256 gassign *ass;
11257 gcall *call;
11258 gimple *stmt;
11259 tree expr;
11260 location_t loc;
11261 edge split, be, fte;
11262
11263 /* Split the end of entry_bb to create head_bb. */
11264 split = split_block (entry_bb, last_stmt (entry_bb));
11265 basic_block head_bb = split->dest;
11266 entry_bb = split->src;
11267
11268 /* Chunk setup goes at end of entry_bb, replacing the omp_for. */
11269 gsi = gsi_last_bb (entry_bb);
11270 gomp_for *for_stmt = as_a <gomp_for *> (gsi_stmt (gsi));
11271 loc = gimple_location (for_stmt);
11272
11273 if (gimple_in_ssa_p (cfun))
11274 {
11275 offset_init = gimple_omp_for_index (for_stmt, 0);
11276 gcc_assert (integer_zerop (fd->loop.n1));
11277 /* The SSA parallelizer does gang parallelism. */
11278 gwv = build_int_cst (integer_type_node, GOMP_DIM_MASK (GOMP_DIM_GANG));
11279 }
11280
11281 if (fd->collapse > 1)
11282 {
11283 counts = XALLOCAVEC (struct oacc_collapse, fd->collapse);
11284 tree total = expand_oacc_collapse_init (fd, &gsi, counts,
11285 TREE_TYPE (fd->loop.n2));
11286
11287 if (SSA_VAR_P (fd->loop.n2))
11288 {
11289 total = force_gimple_operand_gsi (&gsi, total, false, NULL_TREE,
11290 true, GSI_SAME_STMT);
11291 ass = gimple_build_assign (fd->loop.n2, total);
11292 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11293 }
11294
11295 }
11296
11297 tree b = fd->loop.n1;
11298 tree e = fd->loop.n2;
11299 tree s = fd->loop.step;
11300
11301 b = force_gimple_operand_gsi (&gsi, b, true, NULL_TREE, true, GSI_SAME_STMT);
11302 e = force_gimple_operand_gsi (&gsi, e, true, NULL_TREE, true, GSI_SAME_STMT);
11303
11304 /* Convert the step, avoiding possible unsigned->signed overflow. */
11305 negating = !up && TYPE_UNSIGNED (TREE_TYPE (s));
11306 if (negating)
11307 s = fold_build1 (NEGATE_EXPR, TREE_TYPE (s), s);
11308 s = fold_convert (diff_type, s);
11309 if (negating)
11310 s = fold_build1 (NEGATE_EXPR, diff_type, s);
11311 s = force_gimple_operand_gsi (&gsi, s, true, NULL_TREE, true, GSI_SAME_STMT);
11312
11313 if (!chunking)
11314 chunk_size = integer_zero_node;
11315 expr = fold_convert (diff_type, chunk_size);
11316 chunk_size = force_gimple_operand_gsi (&gsi, expr, true,
11317 NULL_TREE, true, GSI_SAME_STMT);
11318 /* Determine the range, avoiding possible unsigned->signed overflow. */
11319 negating = !up && TYPE_UNSIGNED (iter_type);
11320 expr = fold_build2 (MINUS_EXPR, plus_type,
11321 fold_convert (plus_type, negating ? b : e),
11322 fold_convert (plus_type, negating ? e : b));
11323 expr = fold_convert (diff_type, expr);
11324 if (negating)
11325 expr = fold_build1 (NEGATE_EXPR, diff_type, expr);
11326 tree range = force_gimple_operand_gsi (&gsi, expr, true,
11327 NULL_TREE, true, GSI_SAME_STMT);
11328
11329 chunk_no = build_int_cst (diff_type, 0);
11330 if (chunking)
11331 {
11332 gcc_assert (!gimple_in_ssa_p (cfun));
11333
11334 expr = chunk_no;
11335 chunk_max = create_tmp_var (diff_type, ".chunk_max");
11336 chunk_no = create_tmp_var (diff_type, ".chunk_no");
11337
11338 ass = gimple_build_assign (chunk_no, expr);
11339 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11340
11341 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11342 build_int_cst (integer_type_node,
11343 IFN_GOACC_LOOP_CHUNKS),
11344 dir, range, s, chunk_size, gwv);
11345 gimple_call_set_lhs (call, chunk_max);
11346 gimple_set_location (call, loc);
11347 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11348 }
11349 else
11350 chunk_size = chunk_no;
11351
11352 call = gimple_build_call_internal (IFN_GOACC_LOOP, 6,
11353 build_int_cst (integer_type_node,
11354 IFN_GOACC_LOOP_STEP),
11355 dir, range, s, chunk_size, gwv);
11356 gimple_call_set_lhs (call, step);
11357 gimple_set_location (call, loc);
11358 gsi_insert_before (&gsi, call, GSI_SAME_STMT);
11359
11360 /* Remove the GIMPLE_OMP_FOR. */
11361 gsi_remove (&gsi, true);
11362
11363 /* Fixup edges from head_bb */
11364 be = BRANCH_EDGE (head_bb);
11365 fte = FALLTHRU_EDGE (head_bb);
11366 be->flags |= EDGE_FALSE_VALUE;
11367 fte->flags ^= EDGE_FALLTHRU | EDGE_TRUE_VALUE;
11368
11369 basic_block body_bb = fte->dest;
11370
11371 if (gimple_in_ssa_p (cfun))
11372 {
11373 gsi = gsi_last_bb (cont_bb);
11374 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11375
11376 offset = gimple_omp_continue_control_use (cont_stmt);
11377 offset_incr = gimple_omp_continue_control_def (cont_stmt);
11378 }
11379 else
11380 {
11381 offset = create_tmp_var (diff_type, ".offset");
11382 offset_init = offset_incr = offset;
11383 }
11384 bound = create_tmp_var (TREE_TYPE (offset), ".bound");
11385
11386 /* Loop offset & bound go into head_bb. */
11387 gsi = gsi_start_bb (head_bb);
11388
11389 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11390 build_int_cst (integer_type_node,
11391 IFN_GOACC_LOOP_OFFSET),
11392 dir, range, s,
11393 chunk_size, gwv, chunk_no);
11394 gimple_call_set_lhs (call, offset_init);
11395 gimple_set_location (call, loc);
11396 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11397
11398 call = gimple_build_call_internal (IFN_GOACC_LOOP, 7,
11399 build_int_cst (integer_type_node,
11400 IFN_GOACC_LOOP_BOUND),
11401 dir, range, s,
11402 chunk_size, gwv, offset_init);
11403 gimple_call_set_lhs (call, bound);
11404 gimple_set_location (call, loc);
11405 gsi_insert_after (&gsi, call, GSI_CONTINUE_LINKING);
11406
11407 expr = build2 (cond_code, boolean_type_node, offset_init, bound);
11408 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11409 GSI_CONTINUE_LINKING);
11410
11411 /* V assignment goes into body_bb. */
11412 if (!gimple_in_ssa_p (cfun))
11413 {
11414 gsi = gsi_start_bb (body_bb);
11415
11416 expr = build2 (plus_code, iter_type, b,
11417 fold_convert (plus_type, offset));
11418 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11419 true, GSI_SAME_STMT);
11420 ass = gimple_build_assign (v, expr);
11421 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11422 if (fd->collapse > 1)
11423 expand_oacc_collapse_vars (fd, &gsi, counts, v);
11424 }
11425
11426 /* Loop increment goes into cont_bb. If this is not a loop, we
11427 will have spawned threads as if it was, and each one will
11428 execute one iteration. The specification is not explicit about
11429 whether such constructs are ill-formed or not, and they can
11430 occur, especially when noreturn routines are involved. */
11431 if (cont_bb)
11432 {
11433 gsi = gsi_last_bb (cont_bb);
11434 gomp_continue *cont_stmt = as_a <gomp_continue *> (gsi_stmt (gsi));
11435 loc = gimple_location (cont_stmt);
11436
11437 /* Increment offset. */
11438 if (gimple_in_ssa_p (cfun))
11439 expr= build2 (plus_code, iter_type, offset,
11440 fold_convert (plus_type, step));
11441 else
11442 expr = build2 (PLUS_EXPR, diff_type, offset, step);
11443 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11444 true, GSI_SAME_STMT);
11445 ass = gimple_build_assign (offset_incr, expr);
11446 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11447 expr = build2 (cond_code, boolean_type_node, offset_incr, bound);
11448 gsi_insert_before (&gsi, gimple_build_cond_empty (expr), GSI_SAME_STMT);
11449
11450 /* Remove the GIMPLE_OMP_CONTINUE. */
11451 gsi_remove (&gsi, true);
11452
11453 /* Fixup edges from cont_bb */
11454 be = BRANCH_EDGE (cont_bb);
11455 fte = FALLTHRU_EDGE (cont_bb);
11456 be->flags |= EDGE_TRUE_VALUE;
11457 fte->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11458
11459 if (chunking)
11460 {
11461 /* Split the beginning of exit_bb to make bottom_bb. We
11462 need to insert a nop at the start, because splitting is
11463 after a stmt, not before. */
11464 gsi = gsi_start_bb (exit_bb);
11465 stmt = gimple_build_nop ();
11466 gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
11467 split = split_block (exit_bb, stmt);
11468 bottom_bb = split->src;
11469 exit_bb = split->dest;
11470 gsi = gsi_last_bb (bottom_bb);
11471
11472 /* Chunk increment and test goes into bottom_bb. */
11473 expr = build2 (PLUS_EXPR, diff_type, chunk_no,
11474 build_int_cst (diff_type, 1));
11475 ass = gimple_build_assign (chunk_no, expr);
11476 gsi_insert_after (&gsi, ass, GSI_CONTINUE_LINKING);
11477
11478 /* Chunk test at end of bottom_bb. */
11479 expr = build2 (LT_EXPR, boolean_type_node, chunk_no, chunk_max);
11480 gsi_insert_after (&gsi, gimple_build_cond_empty (expr),
11481 GSI_CONTINUE_LINKING);
11482
11483 /* Fixup edges from bottom_bb. */
11484 split->flags ^= EDGE_FALLTHRU | EDGE_FALSE_VALUE;
11485 make_edge (bottom_bb, head_bb, EDGE_TRUE_VALUE);
11486 }
11487 }
11488
11489 gsi = gsi_last_bb (exit_bb);
11490 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
11491 loc = gimple_location (gsi_stmt (gsi));
11492
11493 if (!gimple_in_ssa_p (cfun))
11494 {
11495 /* Insert the final value of V, in case it is live. This is the
11496 value for the only thread that survives past the join. */
11497 expr = fold_build2 (MINUS_EXPR, diff_type, range, dir);
11498 expr = fold_build2 (PLUS_EXPR, diff_type, expr, s);
11499 expr = fold_build2 (TRUNC_DIV_EXPR, diff_type, expr, s);
11500 expr = fold_build2 (MULT_EXPR, diff_type, expr, s);
11501 expr = build2 (plus_code, iter_type, b, fold_convert (plus_type, expr));
11502 expr = force_gimple_operand_gsi (&gsi, expr, false, NULL_TREE,
11503 true, GSI_SAME_STMT);
11504 ass = gimple_build_assign (v, expr);
11505 gsi_insert_before (&gsi, ass, GSI_SAME_STMT);
11506 }
11507
11508 /* Remove the OMP_RETURN. */
11509 gsi_remove (&gsi, true);
11510
11511 if (cont_bb)
11512 {
11513 /* We now have one or two nested loops. Update the loop
11514 structures. */
11515 struct loop *parent = entry_bb->loop_father;
11516 struct loop *body = body_bb->loop_father;
11517
11518 if (chunking)
11519 {
11520 struct loop *chunk_loop = alloc_loop ();
11521 chunk_loop->header = head_bb;
11522 chunk_loop->latch = bottom_bb;
11523 add_loop (chunk_loop, parent);
11524 parent = chunk_loop;
11525 }
11526 else if (parent != body)
11527 {
11528 gcc_assert (body->header == body_bb);
11529 gcc_assert (body->latch == cont_bb
11530 || single_pred (body->latch) == cont_bb);
11531 parent = NULL;
11532 }
11533
11534 if (parent)
11535 {
11536 struct loop *body_loop = alloc_loop ();
11537 body_loop->header = body_bb;
11538 body_loop->latch = cont_bb;
11539 add_loop (body_loop, parent);
11540 }
11541 }
11542 }
11543
11544 /* Expand the OMP loop defined by REGION. */
11545
11546 static void
11547 expand_omp_for (struct omp_region *region, gimple *inner_stmt)
11548 {
11549 struct omp_for_data fd;
11550 struct omp_for_data_loop *loops;
11551
11552 loops
11553 = (struct omp_for_data_loop *)
11554 alloca (gimple_omp_for_collapse (last_stmt (region->entry))
11555 * sizeof (struct omp_for_data_loop));
11556 extract_omp_for_data (as_a <gomp_for *> (last_stmt (region->entry)),
11557 &fd, loops);
11558 region->sched_kind = fd.sched_kind;
11559 region->sched_modifiers = fd.sched_modifiers;
11560
11561 gcc_assert (EDGE_COUNT (region->entry->succs) == 2);
11562 BRANCH_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11563 FALLTHRU_EDGE (region->entry)->flags &= ~EDGE_ABNORMAL;
11564 if (region->cont)
11565 {
11566 gcc_assert (EDGE_COUNT (region->cont->succs) == 2);
11567 BRANCH_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11568 FALLTHRU_EDGE (region->cont)->flags &= ~EDGE_ABNORMAL;
11569 }
11570 else
11571 /* If there isn't a continue then this is a degerate case where
11572 the introduction of abnormal edges during lowering will prevent
11573 original loops from being detected. Fix that up. */
11574 loops_state_set (LOOPS_NEED_FIXUP);
11575
11576 if (gimple_omp_for_kind (fd.for_stmt) & GF_OMP_FOR_SIMD)
11577 expand_omp_simd (region, &fd);
11578 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
11579 expand_cilk_for (region, &fd);
11580 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_OACC_LOOP)
11581 {
11582 gcc_assert (!inner_stmt);
11583 expand_oacc_for (region, &fd);
11584 }
11585 else if (gimple_omp_for_kind (fd.for_stmt) == GF_OMP_FOR_KIND_TASKLOOP)
11586 {
11587 if (gimple_omp_for_combined_into_p (fd.for_stmt))
11588 expand_omp_taskloop_for_inner (region, &fd, inner_stmt);
11589 else
11590 expand_omp_taskloop_for_outer (region, &fd, inner_stmt);
11591 }
11592 else if (fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
11593 && !fd.have_ordered)
11594 {
11595 if (fd.chunk_size == NULL)
11596 expand_omp_for_static_nochunk (region, &fd, inner_stmt);
11597 else
11598 expand_omp_for_static_chunk (region, &fd, inner_stmt);
11599 }
11600 else
11601 {
11602 int fn_index, start_ix, next_ix;
11603
11604 gcc_assert (gimple_omp_for_kind (fd.for_stmt)
11605 == GF_OMP_FOR_KIND_FOR);
11606 if (fd.chunk_size == NULL
11607 && fd.sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
11608 fd.chunk_size = integer_zero_node;
11609 gcc_assert (fd.sched_kind != OMP_CLAUSE_SCHEDULE_AUTO);
11610 switch (fd.sched_kind)
11611 {
11612 case OMP_CLAUSE_SCHEDULE_RUNTIME:
11613 fn_index = 3;
11614 break;
11615 case OMP_CLAUSE_SCHEDULE_DYNAMIC:
11616 case OMP_CLAUSE_SCHEDULE_GUIDED:
11617 if ((fd.sched_modifiers & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)
11618 && !fd.ordered
11619 && !fd.have_ordered)
11620 {
11621 fn_index = 3 + fd.sched_kind;
11622 break;
11623 }
11624 /* FALLTHRU */
11625 default:
11626 fn_index = fd.sched_kind;
11627 break;
11628 }
11629 if (!fd.ordered)
11630 fn_index += fd.have_ordered * 6;
11631 if (fd.ordered)
11632 start_ix = ((int)BUILT_IN_GOMP_LOOP_DOACROSS_STATIC_START) + fn_index;
11633 else
11634 start_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_START) + fn_index;
11635 next_ix = ((int)BUILT_IN_GOMP_LOOP_STATIC_NEXT) + fn_index;
11636 if (fd.iter_type == long_long_unsigned_type_node)
11637 {
11638 start_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_START
11639 - (int)BUILT_IN_GOMP_LOOP_STATIC_START);
11640 next_ix += ((int)BUILT_IN_GOMP_LOOP_ULL_STATIC_NEXT
11641 - (int)BUILT_IN_GOMP_LOOP_STATIC_NEXT);
11642 }
11643 expand_omp_for_generic (region, &fd, (enum built_in_function) start_ix,
11644 (enum built_in_function) next_ix, inner_stmt);
11645 }
11646
11647 if (gimple_in_ssa_p (cfun))
11648 update_ssa (TODO_update_ssa_only_virtuals);
11649 }
11650
11651
11652 /* Expand code for an OpenMP sections directive. In pseudo code, we generate
11653
11654 v = GOMP_sections_start (n);
11655 L0:
11656 switch (v)
11657 {
11658 case 0:
11659 goto L2;
11660 case 1:
11661 section 1;
11662 goto L1;
11663 case 2:
11664 ...
11665 case n:
11666 ...
11667 default:
11668 abort ();
11669 }
11670 L1:
11671 v = GOMP_sections_next ();
11672 goto L0;
11673 L2:
11674 reduction;
11675
11676 If this is a combined parallel sections, replace the call to
11677 GOMP_sections_start with call to GOMP_sections_next. */
11678
11679 static void
11680 expand_omp_sections (struct omp_region *region)
11681 {
11682 tree t, u, vin = NULL, vmain, vnext, l2;
11683 unsigned len;
11684 basic_block entry_bb, l0_bb, l1_bb, l2_bb, default_bb;
11685 gimple_stmt_iterator si, switch_si;
11686 gomp_sections *sections_stmt;
11687 gimple *stmt;
11688 gomp_continue *cont;
11689 edge_iterator ei;
11690 edge e;
11691 struct omp_region *inner;
11692 unsigned i, casei;
11693 bool exit_reachable = region->cont != NULL;
11694
11695 gcc_assert (region->exit != NULL);
11696 entry_bb = region->entry;
11697 l0_bb = single_succ (entry_bb);
11698 l1_bb = region->cont;
11699 l2_bb = region->exit;
11700 if (single_pred_p (l2_bb) && single_pred (l2_bb) == l0_bb)
11701 l2 = gimple_block_label (l2_bb);
11702 else
11703 {
11704 /* This can happen if there are reductions. */
11705 len = EDGE_COUNT (l0_bb->succs);
11706 gcc_assert (len > 0);
11707 e = EDGE_SUCC (l0_bb, len - 1);
11708 si = gsi_last_bb (e->dest);
11709 l2 = NULL_TREE;
11710 if (gsi_end_p (si)
11711 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11712 l2 = gimple_block_label (e->dest);
11713 else
11714 FOR_EACH_EDGE (e, ei, l0_bb->succs)
11715 {
11716 si = gsi_last_bb (e->dest);
11717 if (gsi_end_p (si)
11718 || gimple_code (gsi_stmt (si)) != GIMPLE_OMP_SECTION)
11719 {
11720 l2 = gimple_block_label (e->dest);
11721 break;
11722 }
11723 }
11724 }
11725 if (exit_reachable)
11726 default_bb = create_empty_bb (l1_bb->prev_bb);
11727 else
11728 default_bb = create_empty_bb (l0_bb);
11729
11730 /* We will build a switch() with enough cases for all the
11731 GIMPLE_OMP_SECTION regions, a '0' case to handle the end of more work
11732 and a default case to abort if something goes wrong. */
11733 len = EDGE_COUNT (l0_bb->succs);
11734
11735 /* Use vec::quick_push on label_vec throughout, since we know the size
11736 in advance. */
11737 auto_vec<tree> label_vec (len);
11738
11739 /* The call to GOMP_sections_start goes in ENTRY_BB, replacing the
11740 GIMPLE_OMP_SECTIONS statement. */
11741 si = gsi_last_bb (entry_bb);
11742 sections_stmt = as_a <gomp_sections *> (gsi_stmt (si));
11743 gcc_assert (gimple_code (sections_stmt) == GIMPLE_OMP_SECTIONS);
11744 vin = gimple_omp_sections_control (sections_stmt);
11745 if (!is_combined_parallel (region))
11746 {
11747 /* If we are not inside a combined parallel+sections region,
11748 call GOMP_sections_start. */
11749 t = build_int_cst (unsigned_type_node, len - 1);
11750 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_START);
11751 stmt = gimple_build_call (u, 1, t);
11752 }
11753 else
11754 {
11755 /* Otherwise, call GOMP_sections_next. */
11756 u = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11757 stmt = gimple_build_call (u, 0);
11758 }
11759 gimple_call_set_lhs (stmt, vin);
11760 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11761 gsi_remove (&si, true);
11762
11763 /* The switch() statement replacing GIMPLE_OMP_SECTIONS_SWITCH goes in
11764 L0_BB. */
11765 switch_si = gsi_last_bb (l0_bb);
11766 gcc_assert (gimple_code (gsi_stmt (switch_si)) == GIMPLE_OMP_SECTIONS_SWITCH);
11767 if (exit_reachable)
11768 {
11769 cont = as_a <gomp_continue *> (last_stmt (l1_bb));
11770 gcc_assert (gimple_code (cont) == GIMPLE_OMP_CONTINUE);
11771 vmain = gimple_omp_continue_control_use (cont);
11772 vnext = gimple_omp_continue_control_def (cont);
11773 }
11774 else
11775 {
11776 vmain = vin;
11777 vnext = NULL_TREE;
11778 }
11779
11780 t = build_case_label (build_int_cst (unsigned_type_node, 0), NULL, l2);
11781 label_vec.quick_push (t);
11782 i = 1;
11783
11784 /* Convert each GIMPLE_OMP_SECTION into a CASE_LABEL_EXPR. */
11785 for (inner = region->inner, casei = 1;
11786 inner;
11787 inner = inner->next, i++, casei++)
11788 {
11789 basic_block s_entry_bb, s_exit_bb;
11790
11791 /* Skip optional reduction region. */
11792 if (inner->type == GIMPLE_OMP_ATOMIC_LOAD)
11793 {
11794 --i;
11795 --casei;
11796 continue;
11797 }
11798
11799 s_entry_bb = inner->entry;
11800 s_exit_bb = inner->exit;
11801
11802 t = gimple_block_label (s_entry_bb);
11803 u = build_int_cst (unsigned_type_node, casei);
11804 u = build_case_label (u, NULL, t);
11805 label_vec.quick_push (u);
11806
11807 si = gsi_last_bb (s_entry_bb);
11808 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SECTION);
11809 gcc_assert (i < len || gimple_omp_section_last_p (gsi_stmt (si)));
11810 gsi_remove (&si, true);
11811 single_succ_edge (s_entry_bb)->flags = EDGE_FALLTHRU;
11812
11813 if (s_exit_bb == NULL)
11814 continue;
11815
11816 si = gsi_last_bb (s_exit_bb);
11817 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11818 gsi_remove (&si, true);
11819
11820 single_succ_edge (s_exit_bb)->flags = EDGE_FALLTHRU;
11821 }
11822
11823 /* Error handling code goes in DEFAULT_BB. */
11824 t = gimple_block_label (default_bb);
11825 u = build_case_label (NULL, NULL, t);
11826 make_edge (l0_bb, default_bb, 0);
11827 add_bb_to_loop (default_bb, current_loops->tree_root);
11828
11829 stmt = gimple_build_switch (vmain, u, label_vec);
11830 gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT);
11831 gsi_remove (&switch_si, true);
11832
11833 si = gsi_start_bb (default_bb);
11834 stmt = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
11835 gsi_insert_after (&si, stmt, GSI_CONTINUE_LINKING);
11836
11837 if (exit_reachable)
11838 {
11839 tree bfn_decl;
11840
11841 /* Code to get the next section goes in L1_BB. */
11842 si = gsi_last_bb (l1_bb);
11843 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CONTINUE);
11844
11845 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_NEXT);
11846 stmt = gimple_build_call (bfn_decl, 0);
11847 gimple_call_set_lhs (stmt, vnext);
11848 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11849 gsi_remove (&si, true);
11850
11851 single_succ_edge (l1_bb)->flags = EDGE_FALLTHRU;
11852 }
11853
11854 /* Cleanup function replaces GIMPLE_OMP_RETURN in EXIT_BB. */
11855 si = gsi_last_bb (l2_bb);
11856 if (gimple_omp_return_nowait_p (gsi_stmt (si)))
11857 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_NOWAIT);
11858 else if (gimple_omp_return_lhs (gsi_stmt (si)))
11859 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END_CANCEL);
11860 else
11861 t = builtin_decl_explicit (BUILT_IN_GOMP_SECTIONS_END);
11862 stmt = gimple_build_call (t, 0);
11863 if (gimple_omp_return_lhs (gsi_stmt (si)))
11864 gimple_call_set_lhs (stmt, gimple_omp_return_lhs (gsi_stmt (si)));
11865 gsi_insert_after (&si, stmt, GSI_SAME_STMT);
11866 gsi_remove (&si, true);
11867
11868 set_immediate_dominator (CDI_DOMINATORS, default_bb, l0_bb);
11869 }
11870
11871
11872 /* Expand code for an OpenMP single directive. We've already expanded
11873 much of the code, here we simply place the GOMP_barrier call. */
11874
11875 static void
11876 expand_omp_single (struct omp_region *region)
11877 {
11878 basic_block entry_bb, exit_bb;
11879 gimple_stmt_iterator si;
11880
11881 entry_bb = region->entry;
11882 exit_bb = region->exit;
11883
11884 si = gsi_last_bb (entry_bb);
11885 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE);
11886 gsi_remove (&si, true);
11887 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11888
11889 si = gsi_last_bb (exit_bb);
11890 if (!gimple_omp_return_nowait_p (gsi_stmt (si)))
11891 {
11892 tree t = gimple_omp_return_lhs (gsi_stmt (si));
11893 gsi_insert_after (&si, build_omp_barrier (t), GSI_SAME_STMT);
11894 }
11895 gsi_remove (&si, true);
11896 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11897 }
11898
11899
11900 /* Generic expansion for OpenMP synchronization directives: master,
11901 ordered and critical. All we need to do here is remove the entry
11902 and exit markers for REGION. */
11903
11904 static void
11905 expand_omp_synch (struct omp_region *region)
11906 {
11907 basic_block entry_bb, exit_bb;
11908 gimple_stmt_iterator si;
11909
11910 entry_bb = region->entry;
11911 exit_bb = region->exit;
11912
11913 si = gsi_last_bb (entry_bb);
11914 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_SINGLE
11915 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_MASTER
11916 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TASKGROUP
11917 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ORDERED
11918 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_CRITICAL
11919 || gimple_code (gsi_stmt (si)) == GIMPLE_OMP_TEAMS);
11920 gsi_remove (&si, true);
11921 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
11922
11923 if (exit_bb)
11924 {
11925 si = gsi_last_bb (exit_bb);
11926 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_RETURN);
11927 gsi_remove (&si, true);
11928 single_succ_edge (exit_bb)->flags = EDGE_FALLTHRU;
11929 }
11930 }
11931
11932 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11933 operation as a normal volatile load. */
11934
11935 static bool
11936 expand_omp_atomic_load (basic_block load_bb, tree addr,
11937 tree loaded_val, int index)
11938 {
11939 enum built_in_function tmpbase;
11940 gimple_stmt_iterator gsi;
11941 basic_block store_bb;
11942 location_t loc;
11943 gimple *stmt;
11944 tree decl, call, type, itype;
11945
11946 gsi = gsi_last_bb (load_bb);
11947 stmt = gsi_stmt (gsi);
11948 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
11949 loc = gimple_location (stmt);
11950
11951 /* ??? If the target does not implement atomic_load_optab[mode], and mode
11952 is smaller than word size, then expand_atomic_load assumes that the load
11953 is atomic. We could avoid the builtin entirely in this case. */
11954
11955 tmpbase = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
11956 decl = builtin_decl_explicit (tmpbase);
11957 if (decl == NULL_TREE)
11958 return false;
11959
11960 type = TREE_TYPE (loaded_val);
11961 itype = TREE_TYPE (TREE_TYPE (decl));
11962
11963 call = build_call_expr_loc (loc, decl, 2, addr,
11964 build_int_cst (NULL,
11965 gimple_omp_atomic_seq_cst_p (stmt)
11966 ? MEMMODEL_SEQ_CST
11967 : MEMMODEL_RELAXED));
11968 if (!useless_type_conversion_p (type, itype))
11969 call = fold_build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
11970 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
11971
11972 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
11973 gsi_remove (&gsi, true);
11974
11975 store_bb = single_succ (load_bb);
11976 gsi = gsi_last_bb (store_bb);
11977 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
11978 gsi_remove (&gsi, true);
11979
11980 if (gimple_in_ssa_p (cfun))
11981 update_ssa (TODO_update_ssa_no_phi);
11982
11983 return true;
11984 }
11985
11986 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
11987 operation as a normal volatile store. */
11988
11989 static bool
11990 expand_omp_atomic_store (basic_block load_bb, tree addr,
11991 tree loaded_val, tree stored_val, int index)
11992 {
11993 enum built_in_function tmpbase;
11994 gimple_stmt_iterator gsi;
11995 basic_block store_bb = single_succ (load_bb);
11996 location_t loc;
11997 gimple *stmt;
11998 tree decl, call, type, itype;
11999 machine_mode imode;
12000 bool exchange;
12001
12002 gsi = gsi_last_bb (load_bb);
12003 stmt = gsi_stmt (gsi);
12004 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_LOAD);
12005
12006 /* If the load value is needed, then this isn't a store but an exchange. */
12007 exchange = gimple_omp_atomic_need_value_p (stmt);
12008
12009 gsi = gsi_last_bb (store_bb);
12010 stmt = gsi_stmt (gsi);
12011 gcc_assert (gimple_code (stmt) == GIMPLE_OMP_ATOMIC_STORE);
12012 loc = gimple_location (stmt);
12013
12014 /* ??? If the target does not implement atomic_store_optab[mode], and mode
12015 is smaller than word size, then expand_atomic_store assumes that the store
12016 is atomic. We could avoid the builtin entirely in this case. */
12017
12018 tmpbase = (exchange ? BUILT_IN_ATOMIC_EXCHANGE_N : BUILT_IN_ATOMIC_STORE_N);
12019 tmpbase = (enum built_in_function) ((int) tmpbase + index + 1);
12020 decl = builtin_decl_explicit (tmpbase);
12021 if (decl == NULL_TREE)
12022 return false;
12023
12024 type = TREE_TYPE (stored_val);
12025
12026 /* Dig out the type of the function's second argument. */
12027 itype = TREE_TYPE (decl);
12028 itype = TYPE_ARG_TYPES (itype);
12029 itype = TREE_CHAIN (itype);
12030 itype = TREE_VALUE (itype);
12031 imode = TYPE_MODE (itype);
12032
12033 if (exchange && !can_atomic_exchange_p (imode, true))
12034 return false;
12035
12036 if (!useless_type_conversion_p (itype, type))
12037 stored_val = fold_build1_loc (loc, VIEW_CONVERT_EXPR, itype, stored_val);
12038 call = build_call_expr_loc (loc, decl, 3, addr, stored_val,
12039 build_int_cst (NULL,
12040 gimple_omp_atomic_seq_cst_p (stmt)
12041 ? MEMMODEL_SEQ_CST
12042 : MEMMODEL_RELAXED));
12043 if (exchange)
12044 {
12045 if (!useless_type_conversion_p (type, itype))
12046 call = build1_loc (loc, VIEW_CONVERT_EXPR, type, call);
12047 call = build2_loc (loc, MODIFY_EXPR, void_type_node, loaded_val, call);
12048 }
12049
12050 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12051 gsi_remove (&gsi, true);
12052
12053 /* Remove the GIMPLE_OMP_ATOMIC_LOAD that we verified above. */
12054 gsi = gsi_last_bb (load_bb);
12055 gsi_remove (&gsi, true);
12056
12057 if (gimple_in_ssa_p (cfun))
12058 update_ssa (TODO_update_ssa_no_phi);
12059
12060 return true;
12061 }
12062
12063 /* A subroutine of expand_omp_atomic. Attempt to implement the atomic
12064 operation as a __atomic_fetch_op builtin. INDEX is log2 of the
12065 size of the data type, and thus usable to find the index of the builtin
12066 decl. Returns false if the expression is not of the proper form. */
12067
12068 static bool
12069 expand_omp_atomic_fetch_op (basic_block load_bb,
12070 tree addr, tree loaded_val,
12071 tree stored_val, int index)
12072 {
12073 enum built_in_function oldbase, newbase, tmpbase;
12074 tree decl, itype, call;
12075 tree lhs, rhs;
12076 basic_block store_bb = single_succ (load_bb);
12077 gimple_stmt_iterator gsi;
12078 gimple *stmt;
12079 location_t loc;
12080 enum tree_code code;
12081 bool need_old, need_new;
12082 machine_mode imode;
12083 bool seq_cst;
12084
12085 /* We expect to find the following sequences:
12086
12087 load_bb:
12088 GIMPLE_OMP_ATOMIC_LOAD (tmp, mem)
12089
12090 store_bb:
12091 val = tmp OP something; (or: something OP tmp)
12092 GIMPLE_OMP_STORE (val)
12093
12094 ???FIXME: Allow a more flexible sequence.
12095 Perhaps use data flow to pick the statements.
12096
12097 */
12098
12099 gsi = gsi_after_labels (store_bb);
12100 stmt = gsi_stmt (gsi);
12101 loc = gimple_location (stmt);
12102 if (!is_gimple_assign (stmt))
12103 return false;
12104 gsi_next (&gsi);
12105 if (gimple_code (gsi_stmt (gsi)) != GIMPLE_OMP_ATOMIC_STORE)
12106 return false;
12107 need_new = gimple_omp_atomic_need_value_p (gsi_stmt (gsi));
12108 need_old = gimple_omp_atomic_need_value_p (last_stmt (load_bb));
12109 seq_cst = gimple_omp_atomic_seq_cst_p (last_stmt (load_bb));
12110 gcc_checking_assert (!need_old || !need_new);
12111
12112 if (!operand_equal_p (gimple_assign_lhs (stmt), stored_val, 0))
12113 return false;
12114
12115 /* Check for one of the supported fetch-op operations. */
12116 code = gimple_assign_rhs_code (stmt);
12117 switch (code)
12118 {
12119 case PLUS_EXPR:
12120 case POINTER_PLUS_EXPR:
12121 oldbase = BUILT_IN_ATOMIC_FETCH_ADD_N;
12122 newbase = BUILT_IN_ATOMIC_ADD_FETCH_N;
12123 break;
12124 case MINUS_EXPR:
12125 oldbase = BUILT_IN_ATOMIC_FETCH_SUB_N;
12126 newbase = BUILT_IN_ATOMIC_SUB_FETCH_N;
12127 break;
12128 case BIT_AND_EXPR:
12129 oldbase = BUILT_IN_ATOMIC_FETCH_AND_N;
12130 newbase = BUILT_IN_ATOMIC_AND_FETCH_N;
12131 break;
12132 case BIT_IOR_EXPR:
12133 oldbase = BUILT_IN_ATOMIC_FETCH_OR_N;
12134 newbase = BUILT_IN_ATOMIC_OR_FETCH_N;
12135 break;
12136 case BIT_XOR_EXPR:
12137 oldbase = BUILT_IN_ATOMIC_FETCH_XOR_N;
12138 newbase = BUILT_IN_ATOMIC_XOR_FETCH_N;
12139 break;
12140 default:
12141 return false;
12142 }
12143
12144 /* Make sure the expression is of the proper form. */
12145 if (operand_equal_p (gimple_assign_rhs1 (stmt), loaded_val, 0))
12146 rhs = gimple_assign_rhs2 (stmt);
12147 else if (commutative_tree_code (gimple_assign_rhs_code (stmt))
12148 && operand_equal_p (gimple_assign_rhs2 (stmt), loaded_val, 0))
12149 rhs = gimple_assign_rhs1 (stmt);
12150 else
12151 return false;
12152
12153 tmpbase = ((enum built_in_function)
12154 ((need_new ? newbase : oldbase) + index + 1));
12155 decl = builtin_decl_explicit (tmpbase);
12156 if (decl == NULL_TREE)
12157 return false;
12158 itype = TREE_TYPE (TREE_TYPE (decl));
12159 imode = TYPE_MODE (itype);
12160
12161 /* We could test all of the various optabs involved, but the fact of the
12162 matter is that (with the exception of i486 vs i586 and xadd) all targets
12163 that support any atomic operaton optab also implements compare-and-swap.
12164 Let optabs.c take care of expanding any compare-and-swap loop. */
12165 if (!can_compare_and_swap_p (imode, true))
12166 return false;
12167
12168 gsi = gsi_last_bb (load_bb);
12169 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_LOAD);
12170
12171 /* OpenMP does not imply any barrier-like semantics on its atomic ops.
12172 It only requires that the operation happen atomically. Thus we can
12173 use the RELAXED memory model. */
12174 call = build_call_expr_loc (loc, decl, 3, addr,
12175 fold_convert_loc (loc, itype, rhs),
12176 build_int_cst (NULL,
12177 seq_cst ? MEMMODEL_SEQ_CST
12178 : MEMMODEL_RELAXED));
12179
12180 if (need_old || need_new)
12181 {
12182 lhs = need_old ? loaded_val : stored_val;
12183 call = fold_convert_loc (loc, TREE_TYPE (lhs), call);
12184 call = build2_loc (loc, MODIFY_EXPR, void_type_node, lhs, call);
12185 }
12186 else
12187 call = fold_convert_loc (loc, void_type_node, call);
12188 force_gimple_operand_gsi (&gsi, call, true, NULL_TREE, true, GSI_SAME_STMT);
12189 gsi_remove (&gsi, true);
12190
12191 gsi = gsi_last_bb (store_bb);
12192 gcc_assert (gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_ATOMIC_STORE);
12193 gsi_remove (&gsi, true);
12194 gsi = gsi_last_bb (store_bb);
12195 stmt = gsi_stmt (gsi);
12196 gsi_remove (&gsi, true);
12197
12198 if (gimple_in_ssa_p (cfun))
12199 {
12200 release_defs (stmt);
12201 update_ssa (TODO_update_ssa_no_phi);
12202 }
12203
12204 return true;
12205 }
12206
12207 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12208
12209 oldval = *addr;
12210 repeat:
12211 newval = rhs; // with oldval replacing *addr in rhs
12212 oldval = __sync_val_compare_and_swap (addr, oldval, newval);
12213 if (oldval != newval)
12214 goto repeat;
12215
12216 INDEX is log2 of the size of the data type, and thus usable to find the
12217 index of the builtin decl. */
12218
12219 static bool
12220 expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
12221 tree addr, tree loaded_val, tree stored_val,
12222 int index)
12223 {
12224 tree loadedi, storedi, initial, new_storedi, old_vali;
12225 tree type, itype, cmpxchg, iaddr;
12226 gimple_stmt_iterator si;
12227 basic_block loop_header = single_succ (load_bb);
12228 gimple *phi, *stmt;
12229 edge e;
12230 enum built_in_function fncode;
12231
12232 /* ??? We need a non-pointer interface to __atomic_compare_exchange in
12233 order to use the RELAXED memory model effectively. */
12234 fncode = (enum built_in_function)((int)BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N
12235 + index + 1);
12236 cmpxchg = builtin_decl_explicit (fncode);
12237 if (cmpxchg == NULL_TREE)
12238 return false;
12239 type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12240 itype = TREE_TYPE (TREE_TYPE (cmpxchg));
12241
12242 if (!can_compare_and_swap_p (TYPE_MODE (itype), true))
12243 return false;
12244
12245 /* Load the initial value, replacing the GIMPLE_OMP_ATOMIC_LOAD. */
12246 si = gsi_last_bb (load_bb);
12247 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12248
12249 /* For floating-point values, we'll need to view-convert them to integers
12250 so that we can perform the atomic compare and swap. Simplify the
12251 following code by always setting up the "i"ntegral variables. */
12252 if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
12253 {
12254 tree iaddr_val;
12255
12256 iaddr = create_tmp_reg (build_pointer_type_for_mode (itype, ptr_mode,
12257 true));
12258 iaddr_val
12259 = force_gimple_operand_gsi (&si,
12260 fold_convert (TREE_TYPE (iaddr), addr),
12261 false, NULL_TREE, true, GSI_SAME_STMT);
12262 stmt = gimple_build_assign (iaddr, iaddr_val);
12263 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12264 loadedi = create_tmp_var (itype);
12265 if (gimple_in_ssa_p (cfun))
12266 loadedi = make_ssa_name (loadedi);
12267 }
12268 else
12269 {
12270 iaddr = addr;
12271 loadedi = loaded_val;
12272 }
12273
12274 fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1);
12275 tree loaddecl = builtin_decl_explicit (fncode);
12276 if (loaddecl)
12277 initial
12278 = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)),
12279 build_call_expr (loaddecl, 2, iaddr,
12280 build_int_cst (NULL_TREE,
12281 MEMMODEL_RELAXED)));
12282 else
12283 initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr,
12284 build_int_cst (TREE_TYPE (iaddr), 0));
12285
12286 initial
12287 = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true,
12288 GSI_SAME_STMT);
12289
12290 /* Move the value to the LOADEDI temporary. */
12291 if (gimple_in_ssa_p (cfun))
12292 {
12293 gcc_assert (gimple_seq_empty_p (phi_nodes (loop_header)));
12294 phi = create_phi_node (loadedi, loop_header);
12295 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, single_succ_edge (load_bb)),
12296 initial);
12297 }
12298 else
12299 gsi_insert_before (&si,
12300 gimple_build_assign (loadedi, initial),
12301 GSI_SAME_STMT);
12302 if (loadedi != loaded_val)
12303 {
12304 gimple_stmt_iterator gsi2;
12305 tree x;
12306
12307 x = build1 (VIEW_CONVERT_EXPR, type, loadedi);
12308 gsi2 = gsi_start_bb (loop_header);
12309 if (gimple_in_ssa_p (cfun))
12310 {
12311 gassign *stmt;
12312 x = force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12313 true, GSI_SAME_STMT);
12314 stmt = gimple_build_assign (loaded_val, x);
12315 gsi_insert_before (&gsi2, stmt, GSI_SAME_STMT);
12316 }
12317 else
12318 {
12319 x = build2 (MODIFY_EXPR, TREE_TYPE (loaded_val), loaded_val, x);
12320 force_gimple_operand_gsi (&gsi2, x, true, NULL_TREE,
12321 true, GSI_SAME_STMT);
12322 }
12323 }
12324 gsi_remove (&si, true);
12325
12326 si = gsi_last_bb (store_bb);
12327 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12328
12329 if (iaddr == addr)
12330 storedi = stored_val;
12331 else
12332 storedi =
12333 force_gimple_operand_gsi (&si,
12334 build1 (VIEW_CONVERT_EXPR, itype,
12335 stored_val), true, NULL_TREE, true,
12336 GSI_SAME_STMT);
12337
12338 /* Build the compare&swap statement. */
12339 new_storedi = build_call_expr (cmpxchg, 3, iaddr, loadedi, storedi);
12340 new_storedi = force_gimple_operand_gsi (&si,
12341 fold_convert (TREE_TYPE (loadedi),
12342 new_storedi),
12343 true, NULL_TREE,
12344 true, GSI_SAME_STMT);
12345
12346 if (gimple_in_ssa_p (cfun))
12347 old_vali = loadedi;
12348 else
12349 {
12350 old_vali = create_tmp_var (TREE_TYPE (loadedi));
12351 stmt = gimple_build_assign (old_vali, loadedi);
12352 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12353
12354 stmt = gimple_build_assign (loadedi, new_storedi);
12355 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12356 }
12357
12358 /* Note that we always perform the comparison as an integer, even for
12359 floating point. This allows the atomic operation to properly
12360 succeed even with NaNs and -0.0. */
12361 stmt = gimple_build_cond_empty
12362 (build2 (NE_EXPR, boolean_type_node,
12363 new_storedi, old_vali));
12364 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12365
12366 /* Update cfg. */
12367 e = single_succ_edge (store_bb);
12368 e->flags &= ~EDGE_FALLTHRU;
12369 e->flags |= EDGE_FALSE_VALUE;
12370
12371 e = make_edge (store_bb, loop_header, EDGE_TRUE_VALUE);
12372
12373 /* Copy the new value to loadedi (we already did that before the condition
12374 if we are not in SSA). */
12375 if (gimple_in_ssa_p (cfun))
12376 {
12377 phi = gimple_seq_first_stmt (phi_nodes (loop_header));
12378 SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e), new_storedi);
12379 }
12380
12381 /* Remove GIMPLE_OMP_ATOMIC_STORE. */
12382 gsi_remove (&si, true);
12383
12384 struct loop *loop = alloc_loop ();
12385 loop->header = loop_header;
12386 loop->latch = store_bb;
12387 add_loop (loop, loop_header->loop_father);
12388
12389 if (gimple_in_ssa_p (cfun))
12390 update_ssa (TODO_update_ssa_no_phi);
12391
12392 return true;
12393 }
12394
12395 /* A subroutine of expand_omp_atomic. Implement the atomic operation as:
12396
12397 GOMP_atomic_start ();
12398 *addr = rhs;
12399 GOMP_atomic_end ();
12400
12401 The result is not globally atomic, but works so long as all parallel
12402 references are within #pragma omp atomic directives. According to
12403 responses received from omp@openmp.org, appears to be within spec.
12404 Which makes sense, since that's how several other compilers handle
12405 this situation as well.
12406 LOADED_VAL and ADDR are the operands of GIMPLE_OMP_ATOMIC_LOAD we're
12407 expanding. STORED_VAL is the operand of the matching
12408 GIMPLE_OMP_ATOMIC_STORE.
12409
12410 We replace
12411 GIMPLE_OMP_ATOMIC_LOAD (loaded_val, addr) with
12412 loaded_val = *addr;
12413
12414 and replace
12415 GIMPLE_OMP_ATOMIC_STORE (stored_val) with
12416 *addr = stored_val;
12417 */
12418
12419 static bool
12420 expand_omp_atomic_mutex (basic_block load_bb, basic_block store_bb,
12421 tree addr, tree loaded_val, tree stored_val)
12422 {
12423 gimple_stmt_iterator si;
12424 gassign *stmt;
12425 tree t;
12426
12427 si = gsi_last_bb (load_bb);
12428 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_LOAD);
12429
12430 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_START);
12431 t = build_call_expr (t, 0);
12432 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12433
12434 stmt = gimple_build_assign (loaded_val, build_simple_mem_ref (addr));
12435 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12436 gsi_remove (&si, true);
12437
12438 si = gsi_last_bb (store_bb);
12439 gcc_assert (gimple_code (gsi_stmt (si)) == GIMPLE_OMP_ATOMIC_STORE);
12440
12441 stmt = gimple_build_assign (build_simple_mem_ref (unshare_expr (addr)),
12442 stored_val);
12443 gsi_insert_before (&si, stmt, GSI_SAME_STMT);
12444
12445 t = builtin_decl_explicit (BUILT_IN_GOMP_ATOMIC_END);
12446 t = build_call_expr (t, 0);
12447 force_gimple_operand_gsi (&si, t, true, NULL_TREE, true, GSI_SAME_STMT);
12448 gsi_remove (&si, true);
12449
12450 if (gimple_in_ssa_p (cfun))
12451 update_ssa (TODO_update_ssa_no_phi);
12452 return true;
12453 }
12454
12455 /* Expand an GIMPLE_OMP_ATOMIC statement. We try to expand
12456 using expand_omp_atomic_fetch_op. If it failed, we try to
12457 call expand_omp_atomic_pipeline, and if it fails too, the
12458 ultimate fallback is wrapping the operation in a mutex
12459 (expand_omp_atomic_mutex). REGION is the atomic region built
12460 by build_omp_regions_1(). */
12461
12462 static void
12463 expand_omp_atomic (struct omp_region *region)
12464 {
12465 basic_block load_bb = region->entry, store_bb = region->exit;
12466 gomp_atomic_load *load = as_a <gomp_atomic_load *> (last_stmt (load_bb));
12467 gomp_atomic_store *store = as_a <gomp_atomic_store *> (last_stmt (store_bb));
12468 tree loaded_val = gimple_omp_atomic_load_lhs (load);
12469 tree addr = gimple_omp_atomic_load_rhs (load);
12470 tree stored_val = gimple_omp_atomic_store_val (store);
12471 tree type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (addr)));
12472 HOST_WIDE_INT index;
12473
12474 /* Make sure the type is one of the supported sizes. */
12475 index = tree_to_uhwi (TYPE_SIZE_UNIT (type));
12476 index = exact_log2 (index);
12477 if (index >= 0 && index <= 4)
12478 {
12479 unsigned int align = TYPE_ALIGN_UNIT (type);
12480
12481 /* __sync builtins require strict data alignment. */
12482 if (exact_log2 (align) >= index)
12483 {
12484 /* Atomic load. */
12485 if (loaded_val == stored_val
12486 && (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12487 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12488 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12489 && expand_omp_atomic_load (load_bb, addr, loaded_val, index))
12490 return;
12491
12492 /* Atomic store. */
12493 if ((GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT
12494 || GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT)
12495 && GET_MODE_BITSIZE (TYPE_MODE (type)) <= BITS_PER_WORD
12496 && store_bb == single_succ (load_bb)
12497 && first_stmt (store_bb) == store
12498 && expand_omp_atomic_store (load_bb, addr, loaded_val,
12499 stored_val, index))
12500 return;
12501
12502 /* When possible, use specialized atomic update functions. */
12503 if ((INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type))
12504 && store_bb == single_succ (load_bb)
12505 && expand_omp_atomic_fetch_op (load_bb, addr,
12506 loaded_val, stored_val, index))
12507 return;
12508
12509 /* If we don't have specialized __sync builtins, try and implement
12510 as a compare and swap loop. */
12511 if (expand_omp_atomic_pipeline (load_bb, store_bb, addr,
12512 loaded_val, stored_val, index))
12513 return;
12514 }
12515 }
12516
12517 /* The ultimate fallback is wrapping the operation in a mutex. */
12518 expand_omp_atomic_mutex (load_bb, store_bb, addr, loaded_val, stored_val);
12519 }
12520
12521
12522 /* Encode an oacc launch argument. This matches the GOMP_LAUNCH_PACK
12523 macro on gomp-constants.h. We do not check for overflow. */
12524
12525 static tree
12526 oacc_launch_pack (unsigned code, tree device, unsigned op)
12527 {
12528 tree res;
12529
12530 res = build_int_cst (unsigned_type_node, GOMP_LAUNCH_PACK (code, 0, op));
12531 if (device)
12532 {
12533 device = fold_build2 (LSHIFT_EXPR, unsigned_type_node,
12534 device, build_int_cst (unsigned_type_node,
12535 GOMP_LAUNCH_DEVICE_SHIFT));
12536 res = fold_build2 (BIT_IOR_EXPR, unsigned_type_node, res, device);
12537 }
12538 return res;
12539 }
12540
12541 /* Look for compute grid dimension clauses and convert to an attribute
12542 attached to FN. This permits the target-side code to (a) massage
12543 the dimensions, (b) emit that data and (c) optimize. Non-constant
12544 dimensions are pushed onto ARGS.
12545
12546 The attribute value is a TREE_LIST. A set of dimensions is
12547 represented as a list of INTEGER_CST. Those that are runtime
12548 exprs are represented as an INTEGER_CST of zero.
12549
12550 TOOO. Normally the attribute will just contain a single such list. If
12551 however it contains a list of lists, this will represent the use of
12552 device_type. Each member of the outer list is an assoc list of
12553 dimensions, keyed by the device type. The first entry will be the
12554 default. Well, that's the plan. */
12555
12556 #define OACC_FN_ATTRIB "oacc function"
12557
12558 /* Replace any existing oacc fn attribute with updated dimensions. */
12559
12560 void
12561 replace_oacc_fn_attrib (tree fn, tree dims)
12562 {
12563 tree ident = get_identifier (OACC_FN_ATTRIB);
12564 tree attribs = DECL_ATTRIBUTES (fn);
12565
12566 /* If we happen to be present as the first attrib, drop it. */
12567 if (attribs && TREE_PURPOSE (attribs) == ident)
12568 attribs = TREE_CHAIN (attribs);
12569 DECL_ATTRIBUTES (fn) = tree_cons (ident, dims, attribs);
12570 }
12571
12572 /* Scan CLAUSES for launch dimensions and attach them to the oacc
12573 function attribute. Push any that are non-constant onto the ARGS
12574 list, along with an appropriate GOMP_LAUNCH_DIM tag. IS_KERNEL is
12575 true, if these are for a kernels region offload function. */
12576
12577 void
12578 set_oacc_fn_attrib (tree fn, tree clauses, bool is_kernel, vec<tree> *args)
12579 {
12580 /* Must match GOMP_DIM ordering. */
12581 static const omp_clause_code ids[]
12582 = { OMP_CLAUSE_NUM_GANGS, OMP_CLAUSE_NUM_WORKERS,
12583 OMP_CLAUSE_VECTOR_LENGTH };
12584 unsigned ix;
12585 tree dims[GOMP_DIM_MAX];
12586 tree attr = NULL_TREE;
12587 unsigned non_const = 0;
12588
12589 for (ix = GOMP_DIM_MAX; ix--;)
12590 {
12591 tree clause = find_omp_clause (clauses, ids[ix]);
12592 tree dim = NULL_TREE;
12593
12594 if (clause)
12595 dim = OMP_CLAUSE_EXPR (clause, ids[ix]);
12596 dims[ix] = dim;
12597 if (dim && TREE_CODE (dim) != INTEGER_CST)
12598 {
12599 dim = integer_zero_node;
12600 non_const |= GOMP_DIM_MASK (ix);
12601 }
12602 attr = tree_cons (NULL_TREE, dim, attr);
12603 /* Note kernelness with TREE_PUBLIC. */
12604 if (is_kernel)
12605 TREE_PUBLIC (attr) = 1;
12606 }
12607
12608 replace_oacc_fn_attrib (fn, attr);
12609
12610 if (non_const)
12611 {
12612 /* Push a dynamic argument set. */
12613 args->safe_push (oacc_launch_pack (GOMP_LAUNCH_DIM,
12614 NULL_TREE, non_const));
12615 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
12616 if (non_const & GOMP_DIM_MASK (ix))
12617 args->safe_push (dims[ix]);
12618 }
12619 }
12620
12621 /* Process the routine's dimension clauess to generate an attribute
12622 value. Issue diagnostics as appropriate. We default to SEQ
12623 (OpenACC 2.5 clarifies this). All dimensions have a size of zero
12624 (dynamic). TREE_PURPOSE is set to indicate whether that dimension
12625 can have a loop partitioned on it. non-zero indicates
12626 yes, zero indicates no. By construction once a non-zero has been
12627 reached, further inner dimensions must also be non-zero. We set
12628 TREE_VALUE to zero for the dimensions that may be partitioned and
12629 1 for the other ones -- if a loop is (erroneously) spawned at
12630 an outer level, we don't want to try and partition it. */
12631
12632 tree
12633 build_oacc_routine_dims (tree clauses)
12634 {
12635 /* Must match GOMP_DIM ordering. */
12636 static const omp_clause_code ids[] =
12637 {OMP_CLAUSE_GANG, OMP_CLAUSE_WORKER, OMP_CLAUSE_VECTOR, OMP_CLAUSE_SEQ};
12638 int ix;
12639 int level = -1;
12640
12641 for (; clauses; clauses = OMP_CLAUSE_CHAIN (clauses))
12642 for (ix = GOMP_DIM_MAX + 1; ix--;)
12643 if (OMP_CLAUSE_CODE (clauses) == ids[ix])
12644 {
12645 if (level >= 0)
12646 error_at (OMP_CLAUSE_LOCATION (clauses),
12647 "multiple loop axes specified for routine");
12648 level = ix;
12649 break;
12650 }
12651
12652 /* Default to SEQ. */
12653 if (level < 0)
12654 level = GOMP_DIM_MAX;
12655
12656 tree dims = NULL_TREE;
12657
12658 for (ix = GOMP_DIM_MAX; ix--;)
12659 dims = tree_cons (build_int_cst (boolean_type_node, ix >= level),
12660 build_int_cst (integer_type_node, ix < level), dims);
12661
12662 return dims;
12663 }
12664
12665 /* Retrieve the oacc function attrib and return it. Non-oacc
12666 functions will return NULL. */
12667
12668 tree
12669 get_oacc_fn_attrib (tree fn)
12670 {
12671 return lookup_attribute (OACC_FN_ATTRIB, DECL_ATTRIBUTES (fn));
12672 }
12673
12674 /* Return true if this oacc fn attrib is for a kernels offload
12675 region. We use the TREE_PUBLIC flag of each dimension -- only
12676 need to check the first one. */
12677
12678 bool
12679 oacc_fn_attrib_kernels_p (tree attr)
12680 {
12681 return TREE_PUBLIC (TREE_VALUE (attr));
12682 }
12683
12684 /* Return level at which oacc routine may spawn a partitioned loop, or
12685 -1 if it is not a routine (i.e. is an offload fn). */
12686
12687 static int
12688 oacc_fn_attrib_level (tree attr)
12689 {
12690 tree pos = TREE_VALUE (attr);
12691
12692 if (!TREE_PURPOSE (pos))
12693 return -1;
12694
12695 int ix = 0;
12696 for (ix = 0; ix != GOMP_DIM_MAX;
12697 ix++, pos = TREE_CHAIN (pos))
12698 if (!integer_zerop (TREE_PURPOSE (pos)))
12699 break;
12700
12701 return ix;
12702 }
12703
12704 /* Extract an oacc execution dimension from FN. FN must be an
12705 offloaded function or routine that has already had its execution
12706 dimensions lowered to the target-specific values. */
12707
12708 int
12709 get_oacc_fn_dim_size (tree fn, int axis)
12710 {
12711 tree attrs = get_oacc_fn_attrib (fn);
12712
12713 gcc_assert (axis < GOMP_DIM_MAX);
12714
12715 tree dims = TREE_VALUE (attrs);
12716 while (axis--)
12717 dims = TREE_CHAIN (dims);
12718
12719 int size = TREE_INT_CST_LOW (TREE_VALUE (dims));
12720
12721 return size;
12722 }
12723
12724 /* Extract the dimension axis from an IFN_GOACC_DIM_POS or
12725 IFN_GOACC_DIM_SIZE call. */
12726
12727 int
12728 get_oacc_ifn_dim_arg (const gimple *stmt)
12729 {
12730 gcc_checking_assert (gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_SIZE
12731 || gimple_call_internal_fn (stmt) == IFN_GOACC_DIM_POS);
12732 tree arg = gimple_call_arg (stmt, 0);
12733 HOST_WIDE_INT axis = TREE_INT_CST_LOW (arg);
12734
12735 gcc_checking_assert (axis >= 0 && axis < GOMP_DIM_MAX);
12736 return (int) axis;
12737 }
12738
12739 /* Mark the loops inside the kernels region starting at REGION_ENTRY and ending
12740 at REGION_EXIT. */
12741
12742 static void
12743 mark_loops_in_oacc_kernels_region (basic_block region_entry,
12744 basic_block region_exit)
12745 {
12746 struct loop *outer = region_entry->loop_father;
12747 gcc_assert (region_exit == NULL || outer == region_exit->loop_father);
12748
12749 /* Don't parallelize the kernels region if it contains more than one outer
12750 loop. */
12751 unsigned int nr_outer_loops = 0;
12752 struct loop *single_outer = NULL;
12753 for (struct loop *loop = outer->inner; loop != NULL; loop = loop->next)
12754 {
12755 gcc_assert (loop_outer (loop) == outer);
12756
12757 if (!dominated_by_p (CDI_DOMINATORS, loop->header, region_entry))
12758 continue;
12759
12760 if (region_exit != NULL
12761 && dominated_by_p (CDI_DOMINATORS, loop->header, region_exit))
12762 continue;
12763
12764 nr_outer_loops++;
12765 single_outer = loop;
12766 }
12767 if (nr_outer_loops != 1)
12768 return;
12769
12770 for (struct loop *loop = single_outer->inner; loop != NULL; loop = loop->inner)
12771 if (loop->next)
12772 return;
12773
12774 /* Mark the loops in the region. */
12775 for (struct loop *loop = single_outer; loop != NULL; loop = loop->inner)
12776 loop->in_oacc_kernels_region = true;
12777 }
12778
12779 /* Types used to pass grid and wortkgroup sizes to kernel invocation. */
12780
12781 struct GTY(()) grid_launch_attributes_trees
12782 {
12783 tree kernel_dim_array_type;
12784 tree kernel_lattrs_dimnum_decl;
12785 tree kernel_lattrs_grid_decl;
12786 tree kernel_lattrs_group_decl;
12787 tree kernel_launch_attributes_type;
12788 };
12789
12790 static GTY(()) struct grid_launch_attributes_trees *grid_attr_trees;
12791
12792 /* Create types used to pass kernel launch attributes to target. */
12793
12794 static void
12795 grid_create_kernel_launch_attr_types (void)
12796 {
12797 if (grid_attr_trees)
12798 return;
12799 grid_attr_trees = ggc_alloc <grid_launch_attributes_trees> ();
12800
12801 tree dim_arr_index_type
12802 = build_index_type (build_int_cst (integer_type_node, 2));
12803 grid_attr_trees->kernel_dim_array_type
12804 = build_array_type (uint32_type_node, dim_arr_index_type);
12805
12806 grid_attr_trees->kernel_launch_attributes_type = make_node (RECORD_TYPE);
12807 grid_attr_trees->kernel_lattrs_dimnum_decl
12808 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("ndim"),
12809 uint32_type_node);
12810 DECL_CHAIN (grid_attr_trees->kernel_lattrs_dimnum_decl) = NULL_TREE;
12811
12812 grid_attr_trees->kernel_lattrs_grid_decl
12813 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("grid_size"),
12814 grid_attr_trees->kernel_dim_array_type);
12815 DECL_CHAIN (grid_attr_trees->kernel_lattrs_grid_decl)
12816 = grid_attr_trees->kernel_lattrs_dimnum_decl;
12817 grid_attr_trees->kernel_lattrs_group_decl
12818 = build_decl (BUILTINS_LOCATION, FIELD_DECL, get_identifier ("group_size"),
12819 grid_attr_trees->kernel_dim_array_type);
12820 DECL_CHAIN (grid_attr_trees->kernel_lattrs_group_decl)
12821 = grid_attr_trees->kernel_lattrs_grid_decl;
12822 finish_builtin_struct (grid_attr_trees->kernel_launch_attributes_type,
12823 "__gomp_kernel_launch_attributes",
12824 grid_attr_trees->kernel_lattrs_group_decl, NULL_TREE);
12825 }
12826
12827 /* Insert before the current statement in GSI a store of VALUE to INDEX of
12828 array (of type kernel_dim_array_type) FLD_DECL of RANGE_VAR. VALUE must be
12829 of type uint32_type_node. */
12830
12831 static void
12832 grid_insert_store_range_dim (gimple_stmt_iterator *gsi, tree range_var,
12833 tree fld_decl, int index, tree value)
12834 {
12835 tree ref = build4 (ARRAY_REF, uint32_type_node,
12836 build3 (COMPONENT_REF,
12837 grid_attr_trees->kernel_dim_array_type,
12838 range_var, fld_decl, NULL_TREE),
12839 build_int_cst (integer_type_node, index),
12840 NULL_TREE, NULL_TREE);
12841 gsi_insert_before (gsi, gimple_build_assign (ref, value), GSI_SAME_STMT);
12842 }
12843
12844 /* Return a tree representation of a pointer to a structure with grid and
12845 work-group size information. Statements filling that information will be
12846 inserted before GSI, TGT_STMT is the target statement which has the
12847 necessary information in it. */
12848
12849 static tree
12850 grid_get_kernel_launch_attributes (gimple_stmt_iterator *gsi,
12851 gomp_target *tgt_stmt)
12852 {
12853 grid_create_kernel_launch_attr_types ();
12854 tree u32_one = build_one_cst (uint32_type_node);
12855 tree lattrs = create_tmp_var (grid_attr_trees->kernel_launch_attributes_type,
12856 "__kernel_launch_attrs");
12857
12858 unsigned max_dim = 0;
12859 for (tree clause = gimple_omp_target_clauses (tgt_stmt);
12860 clause;
12861 clause = OMP_CLAUSE_CHAIN (clause))
12862 {
12863 if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE__GRIDDIM_)
12864 continue;
12865
12866 unsigned dim = OMP_CLAUSE__GRIDDIM__DIMENSION (clause);
12867 max_dim = MAX (dim, max_dim);
12868
12869 grid_insert_store_range_dim (gsi, lattrs,
12870 grid_attr_trees->kernel_lattrs_grid_decl,
12871 dim, OMP_CLAUSE__GRIDDIM__SIZE (clause));
12872 grid_insert_store_range_dim (gsi, lattrs,
12873 grid_attr_trees->kernel_lattrs_group_decl,
12874 dim, OMP_CLAUSE__GRIDDIM__GROUP (clause));
12875 }
12876
12877 tree dimref = build3 (COMPONENT_REF, uint32_type_node, lattrs,
12878 grid_attr_trees->kernel_lattrs_dimnum_decl, NULL_TREE);
12879 /* At this moment we cannot gridify a loop with a collapse clause. */
12880 /* TODO: Adjust when we support bigger collapse. */
12881 gcc_assert (max_dim == 0);
12882 gsi_insert_before (gsi, gimple_build_assign (dimref, u32_one), GSI_SAME_STMT);
12883 TREE_ADDRESSABLE (lattrs) = 1;
12884 return build_fold_addr_expr (lattrs);
12885 }
12886
12887 /* Build target argument identifier from the DEVICE identifier, value
12888 identifier ID and whether the element also has a SUBSEQUENT_PARAM. */
12889
12890 static tree
12891 get_target_argument_identifier_1 (int device, bool subseqent_param, int id)
12892 {
12893 tree t = build_int_cst (integer_type_node, device);
12894 if (subseqent_param)
12895 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12896 build_int_cst (integer_type_node,
12897 GOMP_TARGET_ARG_SUBSEQUENT_PARAM));
12898 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12899 build_int_cst (integer_type_node, id));
12900 return t;
12901 }
12902
12903 /* Like above but return it in type that can be directly stored as an element
12904 of the argument array. */
12905
12906 static tree
12907 get_target_argument_identifier (int device, bool subseqent_param, int id)
12908 {
12909 tree t = get_target_argument_identifier_1 (device, subseqent_param, id);
12910 return fold_convert (ptr_type_node, t);
12911 }
12912
12913 /* Return a target argument consisting of DEVICE identifier, value identifier
12914 ID, and the actual VALUE. */
12915
12916 static tree
12917 get_target_argument_value (gimple_stmt_iterator *gsi, int device, int id,
12918 tree value)
12919 {
12920 tree t = fold_build2 (LSHIFT_EXPR, integer_type_node,
12921 fold_convert (integer_type_node, value),
12922 build_int_cst (unsigned_type_node,
12923 GOMP_TARGET_ARG_VALUE_SHIFT));
12924 t = fold_build2 (BIT_IOR_EXPR, integer_type_node, t,
12925 get_target_argument_identifier_1 (device, false, id));
12926 t = fold_convert (ptr_type_node, t);
12927 return force_gimple_operand_gsi (gsi, t, true, NULL, true, GSI_SAME_STMT);
12928 }
12929
12930 /* If VALUE is an integer constant greater than -2^15 and smaller than 2^15,
12931 push one argument to ARGS with both the DEVICE, ID and VALUE embedded in it,
12932 otherwise push an identifier (with DEVICE and ID) and the VALUE in two
12933 arguments. */
12934
12935 static void
12936 push_target_argument_according_to_value (gimple_stmt_iterator *gsi, int device,
12937 int id, tree value, vec <tree> *args)
12938 {
12939 if (tree_fits_shwi_p (value)
12940 && tree_to_shwi (value) > -(1 << 15)
12941 && tree_to_shwi (value) < (1 << 15))
12942 args->quick_push (get_target_argument_value (gsi, device, id, value));
12943 else
12944 {
12945 args->quick_push (get_target_argument_identifier (device, true, id));
12946 value = fold_convert (ptr_type_node, value);
12947 value = force_gimple_operand_gsi (gsi, value, true, NULL, true,
12948 GSI_SAME_STMT);
12949 args->quick_push (value);
12950 }
12951 }
12952
12953 /* Create an array of arguments that is then passed to GOMP_target. */
12954
12955 static tree
12956 get_target_arguments (gimple_stmt_iterator *gsi, gomp_target *tgt_stmt)
12957 {
12958 auto_vec <tree, 6> args;
12959 tree clauses = gimple_omp_target_clauses (tgt_stmt);
12960 tree t, c = find_omp_clause (clauses, OMP_CLAUSE_NUM_TEAMS);
12961 if (c)
12962 t = OMP_CLAUSE_NUM_TEAMS_EXPR (c);
12963 else
12964 t = integer_minus_one_node;
12965 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12966 GOMP_TARGET_ARG_NUM_TEAMS, t, &args);
12967
12968 c = find_omp_clause (clauses, OMP_CLAUSE_THREAD_LIMIT);
12969 if (c)
12970 t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c);
12971 else
12972 t = integer_minus_one_node;
12973 push_target_argument_according_to_value (gsi, GOMP_TARGET_ARG_DEVICE_ALL,
12974 GOMP_TARGET_ARG_THREAD_LIMIT, t,
12975 &args);
12976
12977 /* Add HSA-specific grid sizes, if available. */
12978 if (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
12979 OMP_CLAUSE__GRIDDIM_))
12980 {
12981 t = get_target_argument_identifier (GOMP_DEVICE_HSA, true,
12982 GOMP_TARGET_ARG_HSA_KERNEL_ATTRIBUTES);
12983 args.quick_push (t);
12984 args.quick_push (grid_get_kernel_launch_attributes (gsi, tgt_stmt));
12985 }
12986
12987 /* Produce more, perhaps device specific, arguments here. */
12988
12989 tree argarray = create_tmp_var (build_array_type_nelts (ptr_type_node,
12990 args.length () + 1),
12991 ".omp_target_args");
12992 for (unsigned i = 0; i < args.length (); i++)
12993 {
12994 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
12995 build_int_cst (integer_type_node, i),
12996 NULL_TREE, NULL_TREE);
12997 gsi_insert_before (gsi, gimple_build_assign (ref, args[i]),
12998 GSI_SAME_STMT);
12999 }
13000 tree ref = build4 (ARRAY_REF, ptr_type_node, argarray,
13001 build_int_cst (integer_type_node, args.length ()),
13002 NULL_TREE, NULL_TREE);
13003 gsi_insert_before (gsi, gimple_build_assign (ref, null_pointer_node),
13004 GSI_SAME_STMT);
13005 TREE_ADDRESSABLE (argarray) = 1;
13006 return build_fold_addr_expr (argarray);
13007 }
13008
13009 /* Expand the GIMPLE_OMP_TARGET starting at REGION. */
13010
13011 static void
13012 expand_omp_target (struct omp_region *region)
13013 {
13014 basic_block entry_bb, exit_bb, new_bb;
13015 struct function *child_cfun;
13016 tree child_fn, block, t;
13017 gimple_stmt_iterator gsi;
13018 gomp_target *entry_stmt;
13019 gimple *stmt;
13020 edge e;
13021 bool offloaded, data_region;
13022
13023 entry_stmt = as_a <gomp_target *> (last_stmt (region->entry));
13024 new_bb = region->entry;
13025
13026 offloaded = is_gimple_omp_offloaded (entry_stmt);
13027 switch (gimple_omp_target_kind (entry_stmt))
13028 {
13029 case GF_OMP_TARGET_KIND_REGION:
13030 case GF_OMP_TARGET_KIND_UPDATE:
13031 case GF_OMP_TARGET_KIND_ENTER_DATA:
13032 case GF_OMP_TARGET_KIND_EXIT_DATA:
13033 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13034 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13035 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13036 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13037 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13038 data_region = false;
13039 break;
13040 case GF_OMP_TARGET_KIND_DATA:
13041 case GF_OMP_TARGET_KIND_OACC_DATA:
13042 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13043 data_region = true;
13044 break;
13045 default:
13046 gcc_unreachable ();
13047 }
13048
13049 child_fn = NULL_TREE;
13050 child_cfun = NULL;
13051 if (offloaded)
13052 {
13053 child_fn = gimple_omp_target_child_fn (entry_stmt);
13054 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
13055 }
13056
13057 /* Supported by expand_omp_taskreg, but not here. */
13058 if (child_cfun != NULL)
13059 gcc_checking_assert (!child_cfun->cfg);
13060 gcc_checking_assert (!gimple_in_ssa_p (cfun));
13061
13062 entry_bb = region->entry;
13063 exit_bb = region->exit;
13064
13065 if (gimple_omp_target_kind (entry_stmt) == GF_OMP_TARGET_KIND_OACC_KERNELS)
13066 mark_loops_in_oacc_kernels_region (region->entry, region->exit);
13067
13068 if (offloaded)
13069 {
13070 unsigned srcidx, dstidx, num;
13071
13072 /* If the offloading region needs data sent from the parent
13073 function, then the very first statement (except possible
13074 tree profile counter updates) of the offloading body
13075 is a copy assignment .OMP_DATA_I = &.OMP_DATA_O. Since
13076 &.OMP_DATA_O is passed as an argument to the child function,
13077 we need to replace it with the argument as seen by the child
13078 function.
13079
13080 In most cases, this will end up being the identity assignment
13081 .OMP_DATA_I = .OMP_DATA_I. However, if the offloading body had
13082 a function call that has been inlined, the original PARM_DECL
13083 .OMP_DATA_I may have been converted into a different local
13084 variable. In which case, we need to keep the assignment. */
13085 tree data_arg = gimple_omp_target_data_arg (entry_stmt);
13086 if (data_arg)
13087 {
13088 basic_block entry_succ_bb = single_succ (entry_bb);
13089 gimple_stmt_iterator gsi;
13090 tree arg;
13091 gimple *tgtcopy_stmt = NULL;
13092 tree sender = TREE_VEC_ELT (data_arg, 0);
13093
13094 for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi))
13095 {
13096 gcc_assert (!gsi_end_p (gsi));
13097 stmt = gsi_stmt (gsi);
13098 if (gimple_code (stmt) != GIMPLE_ASSIGN)
13099 continue;
13100
13101 if (gimple_num_ops (stmt) == 2)
13102 {
13103 tree arg = gimple_assign_rhs1 (stmt);
13104
13105 /* We're ignoring the subcode because we're
13106 effectively doing a STRIP_NOPS. */
13107
13108 if (TREE_CODE (arg) == ADDR_EXPR
13109 && TREE_OPERAND (arg, 0) == sender)
13110 {
13111 tgtcopy_stmt = stmt;
13112 break;
13113 }
13114 }
13115 }
13116
13117 gcc_assert (tgtcopy_stmt != NULL);
13118 arg = DECL_ARGUMENTS (child_fn);
13119
13120 gcc_assert (gimple_assign_lhs (tgtcopy_stmt) == arg);
13121 gsi_remove (&gsi, true);
13122 }
13123
13124 /* Declare local variables needed in CHILD_CFUN. */
13125 block = DECL_INITIAL (child_fn);
13126 BLOCK_VARS (block) = vec2chain (child_cfun->local_decls);
13127 /* The gimplifier could record temporaries in the offloading block
13128 rather than in containing function's local_decls chain,
13129 which would mean cgraph missed finalizing them. Do it now. */
13130 for (t = BLOCK_VARS (block); t; t = DECL_CHAIN (t))
13131 if (VAR_P (t) && TREE_STATIC (t) && !DECL_EXTERNAL (t))
13132 varpool_node::finalize_decl (t);
13133 DECL_SAVED_TREE (child_fn) = NULL;
13134 /* We'll create a CFG for child_fn, so no gimple body is needed. */
13135 gimple_set_body (child_fn, NULL);
13136 TREE_USED (block) = 1;
13137
13138 /* Reset DECL_CONTEXT on function arguments. */
13139 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
13140 DECL_CONTEXT (t) = child_fn;
13141
13142 /* Split ENTRY_BB at GIMPLE_*,
13143 so that it can be moved to the child function. */
13144 gsi = gsi_last_bb (entry_bb);
13145 stmt = gsi_stmt (gsi);
13146 gcc_assert (stmt
13147 && gimple_code (stmt) == gimple_code (entry_stmt));
13148 e = split_block (entry_bb, stmt);
13149 gsi_remove (&gsi, true);
13150 entry_bb = e->dest;
13151 single_succ_edge (entry_bb)->flags = EDGE_FALLTHRU;
13152
13153 /* Convert GIMPLE_OMP_RETURN into a RETURN_EXPR. */
13154 if (exit_bb)
13155 {
13156 gsi = gsi_last_bb (exit_bb);
13157 gcc_assert (!gsi_end_p (gsi)
13158 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13159 stmt = gimple_build_return (NULL);
13160 gsi_insert_after (&gsi, stmt, GSI_SAME_STMT);
13161 gsi_remove (&gsi, true);
13162 }
13163
13164 /* Move the offloading region into CHILD_CFUN. */
13165
13166 block = gimple_block (entry_stmt);
13167
13168 new_bb = move_sese_region_to_fn (child_cfun, entry_bb, exit_bb, block);
13169 if (exit_bb)
13170 single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
13171 /* When the OMP expansion process cannot guarantee an up-to-date
13172 loop tree arrange for the child function to fixup loops. */
13173 if (loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13174 child_cfun->x_current_loops->state |= LOOPS_NEED_FIXUP;
13175
13176 /* Remove non-local VAR_DECLs from child_cfun->local_decls list. */
13177 num = vec_safe_length (child_cfun->local_decls);
13178 for (srcidx = 0, dstidx = 0; srcidx < num; srcidx++)
13179 {
13180 t = (*child_cfun->local_decls)[srcidx];
13181 if (DECL_CONTEXT (t) == cfun->decl)
13182 continue;
13183 if (srcidx != dstidx)
13184 (*child_cfun->local_decls)[dstidx] = t;
13185 dstidx++;
13186 }
13187 if (dstidx != num)
13188 vec_safe_truncate (child_cfun->local_decls, dstidx);
13189
13190 /* Inform the callgraph about the new function. */
13191 child_cfun->curr_properties = cfun->curr_properties;
13192 child_cfun->has_simduid_loops |= cfun->has_simduid_loops;
13193 child_cfun->has_force_vectorize_loops |= cfun->has_force_vectorize_loops;
13194 cgraph_node *node = cgraph_node::get_create (child_fn);
13195 node->parallelized_function = 1;
13196 cgraph_node::add_new_function (child_fn, true);
13197
13198 /* Add the new function to the offload table. */
13199 if (ENABLE_OFFLOADING)
13200 vec_safe_push (offload_funcs, child_fn);
13201
13202 bool need_asm = DECL_ASSEMBLER_NAME_SET_P (current_function_decl)
13203 && !DECL_ASSEMBLER_NAME_SET_P (child_fn);
13204
13205 /* Fix the callgraph edges for child_cfun. Those for cfun will be
13206 fixed in a following pass. */
13207 push_cfun (child_cfun);
13208 if (need_asm)
13209 assign_assembler_name_if_neeeded (child_fn);
13210 cgraph_edge::rebuild_edges ();
13211
13212 /* Some EH regions might become dead, see PR34608. If
13213 pass_cleanup_cfg isn't the first pass to happen with the
13214 new child, these dead EH edges might cause problems.
13215 Clean them up now. */
13216 if (flag_exceptions)
13217 {
13218 basic_block bb;
13219 bool changed = false;
13220
13221 FOR_EACH_BB_FN (bb, cfun)
13222 changed |= gimple_purge_dead_eh_edges (bb);
13223 if (changed)
13224 cleanup_tree_cfg ();
13225 }
13226 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
13227 verify_loop_structure ();
13228 pop_cfun ();
13229
13230 if (dump_file && !gimple_in_ssa_p (cfun))
13231 {
13232 omp_any_child_fn_dumped = true;
13233 dump_function_header (dump_file, child_fn, dump_flags);
13234 dump_function_to_file (child_fn, dump_file, dump_flags);
13235 }
13236 }
13237
13238 /* Emit a library call to launch the offloading region, or do data
13239 transfers. */
13240 tree t1, t2, t3, t4, device, cond, depend, c, clauses;
13241 enum built_in_function start_ix;
13242 location_t clause_loc;
13243 unsigned int flags_i = 0;
13244 bool oacc_kernels_p = false;
13245
13246 switch (gimple_omp_target_kind (entry_stmt))
13247 {
13248 case GF_OMP_TARGET_KIND_REGION:
13249 start_ix = BUILT_IN_GOMP_TARGET;
13250 break;
13251 case GF_OMP_TARGET_KIND_DATA:
13252 start_ix = BUILT_IN_GOMP_TARGET_DATA;
13253 break;
13254 case GF_OMP_TARGET_KIND_UPDATE:
13255 start_ix = BUILT_IN_GOMP_TARGET_UPDATE;
13256 break;
13257 case GF_OMP_TARGET_KIND_ENTER_DATA:
13258 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13259 break;
13260 case GF_OMP_TARGET_KIND_EXIT_DATA:
13261 start_ix = BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA;
13262 flags_i |= GOMP_TARGET_FLAG_EXIT_DATA;
13263 break;
13264 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13265 oacc_kernels_p = true;
13266 /* FALLTHROUGH */
13267 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13268 start_ix = BUILT_IN_GOACC_PARALLEL;
13269 break;
13270 case GF_OMP_TARGET_KIND_OACC_DATA:
13271 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13272 start_ix = BUILT_IN_GOACC_DATA_START;
13273 break;
13274 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13275 start_ix = BUILT_IN_GOACC_UPDATE;
13276 break;
13277 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13278 start_ix = BUILT_IN_GOACC_ENTER_EXIT_DATA;
13279 break;
13280 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13281 start_ix = BUILT_IN_GOACC_DECLARE;
13282 break;
13283 default:
13284 gcc_unreachable ();
13285 }
13286
13287 clauses = gimple_omp_target_clauses (entry_stmt);
13288
13289 /* By default, the value of DEVICE is GOMP_DEVICE_ICV (let runtime
13290 library choose) and there is no conditional. */
13291 cond = NULL_TREE;
13292 device = build_int_cst (integer_type_node, GOMP_DEVICE_ICV);
13293
13294 c = find_omp_clause (clauses, OMP_CLAUSE_IF);
13295 if (c)
13296 cond = OMP_CLAUSE_IF_EXPR (c);
13297
13298 c = find_omp_clause (clauses, OMP_CLAUSE_DEVICE);
13299 if (c)
13300 {
13301 /* Even if we pass it to all library function calls, it is currently only
13302 defined/used for the OpenMP target ones. */
13303 gcc_checking_assert (start_ix == BUILT_IN_GOMP_TARGET
13304 || start_ix == BUILT_IN_GOMP_TARGET_DATA
13305 || start_ix == BUILT_IN_GOMP_TARGET_UPDATE
13306 || start_ix == BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA);
13307
13308 device = OMP_CLAUSE_DEVICE_ID (c);
13309 clause_loc = OMP_CLAUSE_LOCATION (c);
13310 }
13311 else
13312 clause_loc = gimple_location (entry_stmt);
13313
13314 c = find_omp_clause (clauses, OMP_CLAUSE_NOWAIT);
13315 if (c)
13316 flags_i |= GOMP_TARGET_FLAG_NOWAIT;
13317
13318 /* Ensure 'device' is of the correct type. */
13319 device = fold_convert_loc (clause_loc, integer_type_node, device);
13320
13321 /* If we found the clause 'if (cond)', build
13322 (cond ? device : GOMP_DEVICE_HOST_FALLBACK). */
13323 if (cond)
13324 {
13325 cond = gimple_boolify (cond);
13326
13327 basic_block cond_bb, then_bb, else_bb;
13328 edge e;
13329 tree tmp_var;
13330
13331 tmp_var = create_tmp_var (TREE_TYPE (device));
13332 if (offloaded)
13333 e = split_block_after_labels (new_bb);
13334 else
13335 {
13336 gsi = gsi_last_bb (new_bb);
13337 gsi_prev (&gsi);
13338 e = split_block (new_bb, gsi_stmt (gsi));
13339 }
13340 cond_bb = e->src;
13341 new_bb = e->dest;
13342 remove_edge (e);
13343
13344 then_bb = create_empty_bb (cond_bb);
13345 else_bb = create_empty_bb (then_bb);
13346 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
13347 set_immediate_dominator (CDI_DOMINATORS, else_bb, cond_bb);
13348
13349 stmt = gimple_build_cond_empty (cond);
13350 gsi = gsi_last_bb (cond_bb);
13351 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13352
13353 gsi = gsi_start_bb (then_bb);
13354 stmt = gimple_build_assign (tmp_var, device);
13355 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13356
13357 gsi = gsi_start_bb (else_bb);
13358 stmt = gimple_build_assign (tmp_var,
13359 build_int_cst (integer_type_node,
13360 GOMP_DEVICE_HOST_FALLBACK));
13361 gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
13362
13363 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
13364 make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE);
13365 add_bb_to_loop (then_bb, cond_bb->loop_father);
13366 add_bb_to_loop (else_bb, cond_bb->loop_father);
13367 make_edge (then_bb, new_bb, EDGE_FALLTHRU);
13368 make_edge (else_bb, new_bb, EDGE_FALLTHRU);
13369
13370 device = tmp_var;
13371 gsi = gsi_last_bb (new_bb);
13372 }
13373 else
13374 {
13375 gsi = gsi_last_bb (new_bb);
13376 device = force_gimple_operand_gsi (&gsi, device, true, NULL_TREE,
13377 true, GSI_SAME_STMT);
13378 }
13379
13380 t = gimple_omp_target_data_arg (entry_stmt);
13381 if (t == NULL)
13382 {
13383 t1 = size_zero_node;
13384 t2 = build_zero_cst (ptr_type_node);
13385 t3 = t2;
13386 t4 = t2;
13387 }
13388 else
13389 {
13390 t1 = TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (TREE_VEC_ELT (t, 1))));
13391 t1 = size_binop (PLUS_EXPR, t1, size_int (1));
13392 t2 = build_fold_addr_expr (TREE_VEC_ELT (t, 0));
13393 t3 = build_fold_addr_expr (TREE_VEC_ELT (t, 1));
13394 t4 = build_fold_addr_expr (TREE_VEC_ELT (t, 2));
13395 }
13396
13397 gimple *g;
13398 bool tagging = false;
13399 /* The maximum number used by any start_ix, without varargs. */
13400 auto_vec<tree, 11> args;
13401 args.quick_push (device);
13402 if (offloaded)
13403 args.quick_push (build_fold_addr_expr (child_fn));
13404 args.quick_push (t1);
13405 args.quick_push (t2);
13406 args.quick_push (t3);
13407 args.quick_push (t4);
13408 switch (start_ix)
13409 {
13410 case BUILT_IN_GOACC_DATA_START:
13411 case BUILT_IN_GOACC_DECLARE:
13412 case BUILT_IN_GOMP_TARGET_DATA:
13413 break;
13414 case BUILT_IN_GOMP_TARGET:
13415 case BUILT_IN_GOMP_TARGET_UPDATE:
13416 case BUILT_IN_GOMP_TARGET_ENTER_EXIT_DATA:
13417 args.quick_push (build_int_cst (unsigned_type_node, flags_i));
13418 c = find_omp_clause (clauses, OMP_CLAUSE_DEPEND);
13419 if (c)
13420 depend = OMP_CLAUSE_DECL (c);
13421 else
13422 depend = build_int_cst (ptr_type_node, 0);
13423 args.quick_push (depend);
13424 if (start_ix == BUILT_IN_GOMP_TARGET)
13425 args.quick_push (get_target_arguments (&gsi, entry_stmt));
13426 break;
13427 case BUILT_IN_GOACC_PARALLEL:
13428 {
13429 set_oacc_fn_attrib (child_fn, clauses, oacc_kernels_p, &args);
13430 tagging = true;
13431 }
13432 /* FALLTHRU */
13433 case BUILT_IN_GOACC_ENTER_EXIT_DATA:
13434 case BUILT_IN_GOACC_UPDATE:
13435 {
13436 tree t_async = NULL_TREE;
13437
13438 /* If present, use the value specified by the respective
13439 clause, making sure that is of the correct type. */
13440 c = find_omp_clause (clauses, OMP_CLAUSE_ASYNC);
13441 if (c)
13442 t_async = fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13443 integer_type_node,
13444 OMP_CLAUSE_ASYNC_EXPR (c));
13445 else if (!tagging)
13446 /* Default values for t_async. */
13447 t_async = fold_convert_loc (gimple_location (entry_stmt),
13448 integer_type_node,
13449 build_int_cst (integer_type_node,
13450 GOMP_ASYNC_SYNC));
13451 if (tagging && t_async)
13452 {
13453 unsigned HOST_WIDE_INT i_async = GOMP_LAUNCH_OP_MAX;
13454
13455 if (TREE_CODE (t_async) == INTEGER_CST)
13456 {
13457 /* See if we can pack the async arg in to the tag's
13458 operand. */
13459 i_async = TREE_INT_CST_LOW (t_async);
13460 if (i_async < GOMP_LAUNCH_OP_MAX)
13461 t_async = NULL_TREE;
13462 else
13463 i_async = GOMP_LAUNCH_OP_MAX;
13464 }
13465 args.safe_push (oacc_launch_pack (GOMP_LAUNCH_ASYNC, NULL_TREE,
13466 i_async));
13467 }
13468 if (t_async)
13469 args.safe_push (t_async);
13470
13471 /* Save the argument index, and ... */
13472 unsigned t_wait_idx = args.length ();
13473 unsigned num_waits = 0;
13474 c = find_omp_clause (clauses, OMP_CLAUSE_WAIT);
13475 if (!tagging || c)
13476 /* ... push a placeholder. */
13477 args.safe_push (integer_zero_node);
13478
13479 for (; c; c = OMP_CLAUSE_CHAIN (c))
13480 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_WAIT)
13481 {
13482 args.safe_push (fold_convert_loc (OMP_CLAUSE_LOCATION (c),
13483 integer_type_node,
13484 OMP_CLAUSE_WAIT_EXPR (c)));
13485 num_waits++;
13486 }
13487
13488 if (!tagging || num_waits)
13489 {
13490 tree len;
13491
13492 /* Now that we know the number, update the placeholder. */
13493 if (tagging)
13494 len = oacc_launch_pack (GOMP_LAUNCH_WAIT, NULL_TREE, num_waits);
13495 else
13496 len = build_int_cst (integer_type_node, num_waits);
13497 len = fold_convert_loc (gimple_location (entry_stmt),
13498 unsigned_type_node, len);
13499 args[t_wait_idx] = len;
13500 }
13501 }
13502 break;
13503 default:
13504 gcc_unreachable ();
13505 }
13506 if (tagging)
13507 /* Push terminal marker - zero. */
13508 args.safe_push (oacc_launch_pack (0, NULL_TREE, 0));
13509
13510 g = gimple_build_call_vec (builtin_decl_explicit (start_ix), args);
13511 gimple_set_location (g, gimple_location (entry_stmt));
13512 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
13513 if (!offloaded)
13514 {
13515 g = gsi_stmt (gsi);
13516 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_TARGET);
13517 gsi_remove (&gsi, true);
13518 }
13519 if (data_region && region->exit)
13520 {
13521 gsi = gsi_last_bb (region->exit);
13522 g = gsi_stmt (gsi);
13523 gcc_assert (g && gimple_code (g) == GIMPLE_OMP_RETURN);
13524 gsi_remove (&gsi, true);
13525 }
13526 }
13527
13528 /* Expand KFOR loop as a GPGPU kernel, i.e. as a body only with iteration
13529 variable derived from the thread number. */
13530
13531 static void
13532 grid_expand_omp_for_loop (struct omp_region *kfor)
13533 {
13534 tree t, threadid;
13535 tree type, itype;
13536 gimple_stmt_iterator gsi;
13537 tree n1, step;
13538 struct omp_for_data fd;
13539
13540 gomp_for *for_stmt = as_a <gomp_for *> (last_stmt (kfor->entry));
13541 gcc_checking_assert (gimple_omp_for_kind (for_stmt)
13542 == GF_OMP_FOR_KIND_GRID_LOOP);
13543 basic_block body_bb = FALLTHRU_EDGE (kfor->entry)->dest;
13544
13545 gcc_assert (gimple_omp_for_collapse (for_stmt) == 1);
13546 gcc_assert (kfor->cont);
13547 extract_omp_for_data (for_stmt, &fd, NULL);
13548
13549 itype = type = TREE_TYPE (fd.loop.v);
13550 if (POINTER_TYPE_P (type))
13551 itype = signed_type_for (type);
13552
13553 gsi = gsi_start_bb (body_bb);
13554
13555 n1 = fd.loop.n1;
13556 step = fd.loop.step;
13557 n1 = force_gimple_operand_gsi (&gsi, fold_convert (type, n1),
13558 true, NULL_TREE, true, GSI_SAME_STMT);
13559 step = force_gimple_operand_gsi (&gsi, fold_convert (itype, step),
13560 true, NULL_TREE, true, GSI_SAME_STMT);
13561 threadid = build_call_expr (builtin_decl_explicit
13562 (BUILT_IN_OMP_GET_THREAD_NUM), 0);
13563 threadid = fold_convert (itype, threadid);
13564 threadid = force_gimple_operand_gsi (&gsi, threadid, true, NULL_TREE,
13565 true, GSI_SAME_STMT);
13566
13567 tree startvar = fd.loop.v;
13568 t = fold_build2 (MULT_EXPR, itype, threadid, step);
13569 if (POINTER_TYPE_P (type))
13570 t = fold_build_pointer_plus (n1, t);
13571 else
13572 t = fold_build2 (PLUS_EXPR, type, t, n1);
13573 t = fold_convert (type, t);
13574 t = force_gimple_operand_gsi (&gsi, t,
13575 DECL_P (startvar)
13576 && TREE_ADDRESSABLE (startvar),
13577 NULL_TREE, true, GSI_SAME_STMT);
13578 gassign *assign_stmt = gimple_build_assign (startvar, t);
13579 gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT);
13580
13581 /* Remove the omp for statement */
13582 gsi = gsi_last_bb (kfor->entry);
13583 gsi_remove (&gsi, true);
13584
13585 /* Remove the GIMPLE_OMP_CONTINUE statement. */
13586 gsi = gsi_last_bb (kfor->cont);
13587 gcc_assert (!gsi_end_p (gsi)
13588 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_CONTINUE);
13589 gsi_remove (&gsi, true);
13590
13591 /* Replace the GIMPLE_OMP_RETURN with a real return. */
13592 gsi = gsi_last_bb (kfor->exit);
13593 gcc_assert (!gsi_end_p (gsi)
13594 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13595 gsi_remove (&gsi, true);
13596
13597 /* Fixup the much simpler CFG. */
13598 remove_edge (find_edge (kfor->cont, body_bb));
13599
13600 if (kfor->cont != body_bb)
13601 set_immediate_dominator (CDI_DOMINATORS, kfor->cont, body_bb);
13602 set_immediate_dominator (CDI_DOMINATORS, kfor->exit, kfor->cont);
13603 }
13604
13605 /* Structure passed to grid_remap_kernel_arg_accesses so that it can remap
13606 argument_decls. */
13607
13608 struct grid_arg_decl_map
13609 {
13610 tree old_arg;
13611 tree new_arg;
13612 };
13613
13614 /* Invoked through walk_gimple_op, will remap all PARM_DECLs to the ones
13615 pertaining to kernel function. */
13616
13617 static tree
13618 grid_remap_kernel_arg_accesses (tree *tp, int *walk_subtrees, void *data)
13619 {
13620 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
13621 struct grid_arg_decl_map *adm = (struct grid_arg_decl_map *) wi->info;
13622 tree t = *tp;
13623
13624 if (t == adm->old_arg)
13625 *tp = adm->new_arg;
13626 *walk_subtrees = !TYPE_P (t) && !DECL_P (t);
13627 return NULL_TREE;
13628 }
13629
13630 static void expand_omp (struct omp_region *region);
13631
13632 /* If TARGET region contains a kernel body for loop, remove its region from the
13633 TARGET and expand it in GPGPU kernel fashion. */
13634
13635 static void
13636 grid_expand_target_grid_body (struct omp_region *target)
13637 {
13638 if (!hsa_gen_requested_p ())
13639 return;
13640
13641 gomp_target *tgt_stmt = as_a <gomp_target *> (last_stmt (target->entry));
13642 struct omp_region **pp;
13643
13644 for (pp = &target->inner; *pp; pp = &(*pp)->next)
13645 if ((*pp)->type == GIMPLE_OMP_GRID_BODY)
13646 break;
13647
13648 struct omp_region *gpukernel = *pp;
13649
13650 tree orig_child_fndecl = gimple_omp_target_child_fn (tgt_stmt);
13651 if (!gpukernel)
13652 {
13653 /* HSA cannot handle OACC stuff. */
13654 if (gimple_omp_target_kind (tgt_stmt) != GF_OMP_TARGET_KIND_REGION)
13655 return;
13656 gcc_checking_assert (orig_child_fndecl);
13657 gcc_assert (!find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13658 OMP_CLAUSE__GRIDDIM_));
13659 cgraph_node *n = cgraph_node::get (orig_child_fndecl);
13660
13661 hsa_register_kernel (n);
13662 return;
13663 }
13664
13665 gcc_assert (find_omp_clause (gimple_omp_target_clauses (tgt_stmt),
13666 OMP_CLAUSE__GRIDDIM_));
13667 tree inside_block = gimple_block (first_stmt (single_succ (gpukernel->entry)));
13668 *pp = gpukernel->next;
13669 for (pp = &gpukernel->inner; *pp; pp = &(*pp)->next)
13670 if ((*pp)->type == GIMPLE_OMP_FOR)
13671 break;
13672
13673 struct omp_region *kfor = *pp;
13674 gcc_assert (kfor);
13675 gcc_assert (gimple_omp_for_kind (last_stmt ((kfor)->entry))
13676 == GF_OMP_FOR_KIND_GRID_LOOP);
13677 *pp = kfor->next;
13678 if (kfor->inner)
13679 expand_omp (kfor->inner);
13680 if (gpukernel->inner)
13681 expand_omp (gpukernel->inner);
13682
13683 tree kern_fndecl = copy_node (orig_child_fndecl);
13684 DECL_NAME (kern_fndecl) = clone_function_name (kern_fndecl, "kernel");
13685 SET_DECL_ASSEMBLER_NAME (kern_fndecl, DECL_NAME (kern_fndecl));
13686 tree tgtblock = gimple_block (tgt_stmt);
13687 tree fniniblock = make_node (BLOCK);
13688 BLOCK_ABSTRACT_ORIGIN (fniniblock) = tgtblock;
13689 BLOCK_SOURCE_LOCATION (fniniblock) = BLOCK_SOURCE_LOCATION (tgtblock);
13690 BLOCK_SOURCE_END_LOCATION (fniniblock) = BLOCK_SOURCE_END_LOCATION (tgtblock);
13691 BLOCK_SUPERCONTEXT (fniniblock) = kern_fndecl;
13692 DECL_INITIAL (kern_fndecl) = fniniblock;
13693 push_struct_function (kern_fndecl);
13694 cfun->function_end_locus = gimple_location (tgt_stmt);
13695 init_tree_ssa (cfun);
13696 pop_cfun ();
13697
13698 tree old_parm_decl = DECL_ARGUMENTS (kern_fndecl);
13699 gcc_assert (!DECL_CHAIN (old_parm_decl));
13700 tree new_parm_decl = copy_node (DECL_ARGUMENTS (kern_fndecl));
13701 DECL_CONTEXT (new_parm_decl) = kern_fndecl;
13702 DECL_ARGUMENTS (kern_fndecl) = new_parm_decl;
13703 gcc_assert (VOID_TYPE_P (TREE_TYPE (DECL_RESULT (kern_fndecl))));
13704 DECL_RESULT (kern_fndecl) = copy_node (DECL_RESULT (kern_fndecl));
13705 DECL_CONTEXT (DECL_RESULT (kern_fndecl)) = kern_fndecl;
13706 struct function *kern_cfun = DECL_STRUCT_FUNCTION (kern_fndecl);
13707 kern_cfun->curr_properties = cfun->curr_properties;
13708
13709 remove_edge (BRANCH_EDGE (kfor->entry));
13710 grid_expand_omp_for_loop (kfor);
13711
13712 /* Remove the omp for statement */
13713 gimple_stmt_iterator gsi = gsi_last_bb (gpukernel->entry);
13714 gsi_remove (&gsi, true);
13715 /* Replace the GIMPLE_OMP_RETURN at the end of the kernel region with a real
13716 return. */
13717 gsi = gsi_last_bb (gpukernel->exit);
13718 gcc_assert (!gsi_end_p (gsi)
13719 && gimple_code (gsi_stmt (gsi)) == GIMPLE_OMP_RETURN);
13720 gimple *ret_stmt = gimple_build_return (NULL);
13721 gsi_insert_after (&gsi, ret_stmt, GSI_SAME_STMT);
13722 gsi_remove (&gsi, true);
13723
13724 /* Statements in the first BB in the target construct have been produced by
13725 target lowering and must be copied inside the GPUKERNEL, with the two
13726 exceptions of the first OMP statement and the OMP_DATA assignment
13727 statement. */
13728 gsi = gsi_start_bb (single_succ (gpukernel->entry));
13729 tree data_arg = gimple_omp_target_data_arg (tgt_stmt);
13730 tree sender = data_arg ? TREE_VEC_ELT (data_arg, 0) : NULL;
13731 for (gimple_stmt_iterator tsi = gsi_start_bb (single_succ (target->entry));
13732 !gsi_end_p (tsi); gsi_next (&tsi))
13733 {
13734 gimple *stmt = gsi_stmt (tsi);
13735 if (is_gimple_omp (stmt))
13736 break;
13737 if (sender
13738 && is_gimple_assign (stmt)
13739 && TREE_CODE (gimple_assign_rhs1 (stmt)) == ADDR_EXPR
13740 && TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) == sender)
13741 continue;
13742 gimple *copy = gimple_copy (stmt);
13743 gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
13744 gimple_set_block (copy, fniniblock);
13745 }
13746
13747 move_sese_region_to_fn (kern_cfun, single_succ (gpukernel->entry),
13748 gpukernel->exit, inside_block);
13749
13750 cgraph_node *kcn = cgraph_node::get_create (kern_fndecl);
13751 kcn->mark_force_output ();
13752 cgraph_node *orig_child = cgraph_node::get (orig_child_fndecl);
13753
13754 hsa_register_kernel (kcn, orig_child);
13755
13756 cgraph_node::add_new_function (kern_fndecl, true);
13757 push_cfun (kern_cfun);
13758 cgraph_edge::rebuild_edges ();
13759
13760 /* Re-map any mention of the PARM_DECL of the original function to the
13761 PARM_DECL of the new one.
13762
13763 TODO: It would be great if lowering produced references into the GPU
13764 kernel decl straight away and we did not have to do this. */
13765 struct grid_arg_decl_map adm;
13766 adm.old_arg = old_parm_decl;
13767 adm.new_arg = new_parm_decl;
13768 basic_block bb;
13769 FOR_EACH_BB_FN (bb, kern_cfun)
13770 {
13771 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
13772 {
13773 gimple *stmt = gsi_stmt (gsi);
13774 struct walk_stmt_info wi;
13775 memset (&wi, 0, sizeof (wi));
13776 wi.info = &adm;
13777 walk_gimple_op (stmt, grid_remap_kernel_arg_accesses, &wi);
13778 }
13779 }
13780 pop_cfun ();
13781
13782 return;
13783 }
13784
13785 /* Expand the parallel region tree rooted at REGION. Expansion
13786 proceeds in depth-first order. Innermost regions are expanded
13787 first. This way, parallel regions that require a new function to
13788 be created (e.g., GIMPLE_OMP_PARALLEL) can be expanded without having any
13789 internal dependencies in their body. */
13790
13791 static void
13792 expand_omp (struct omp_region *region)
13793 {
13794 omp_any_child_fn_dumped = false;
13795 while (region)
13796 {
13797 location_t saved_location;
13798 gimple *inner_stmt = NULL;
13799
13800 /* First, determine whether this is a combined parallel+workshare
13801 region. */
13802 if (region->type == GIMPLE_OMP_PARALLEL)
13803 determine_parallel_type (region);
13804 else if (region->type == GIMPLE_OMP_TARGET)
13805 grid_expand_target_grid_body (region);
13806
13807 if (region->type == GIMPLE_OMP_FOR
13808 && gimple_omp_for_combined_p (last_stmt (region->entry)))
13809 inner_stmt = last_stmt (region->inner->entry);
13810
13811 if (region->inner)
13812 expand_omp (region->inner);
13813
13814 saved_location = input_location;
13815 if (gimple_has_location (last_stmt (region->entry)))
13816 input_location = gimple_location (last_stmt (region->entry));
13817
13818 switch (region->type)
13819 {
13820 case GIMPLE_OMP_PARALLEL:
13821 case GIMPLE_OMP_TASK:
13822 expand_omp_taskreg (region);
13823 break;
13824
13825 case GIMPLE_OMP_FOR:
13826 expand_omp_for (region, inner_stmt);
13827 break;
13828
13829 case GIMPLE_OMP_SECTIONS:
13830 expand_omp_sections (region);
13831 break;
13832
13833 case GIMPLE_OMP_SECTION:
13834 /* Individual omp sections are handled together with their
13835 parent GIMPLE_OMP_SECTIONS region. */
13836 break;
13837
13838 case GIMPLE_OMP_SINGLE:
13839 expand_omp_single (region);
13840 break;
13841
13842 case GIMPLE_OMP_ORDERED:
13843 {
13844 gomp_ordered *ord_stmt
13845 = as_a <gomp_ordered *> (last_stmt (region->entry));
13846 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
13847 OMP_CLAUSE_DEPEND))
13848 {
13849 /* We'll expand these when expanding corresponding
13850 worksharing region with ordered(n) clause. */
13851 gcc_assert (region->outer
13852 && region->outer->type == GIMPLE_OMP_FOR);
13853 region->ord_stmt = ord_stmt;
13854 break;
13855 }
13856 }
13857 /* FALLTHRU */
13858 case GIMPLE_OMP_MASTER:
13859 case GIMPLE_OMP_TASKGROUP:
13860 case GIMPLE_OMP_CRITICAL:
13861 case GIMPLE_OMP_TEAMS:
13862 expand_omp_synch (region);
13863 break;
13864
13865 case GIMPLE_OMP_ATOMIC_LOAD:
13866 expand_omp_atomic (region);
13867 break;
13868
13869 case GIMPLE_OMP_TARGET:
13870 expand_omp_target (region);
13871 break;
13872
13873 default:
13874 gcc_unreachable ();
13875 }
13876
13877 input_location = saved_location;
13878 region = region->next;
13879 }
13880 if (omp_any_child_fn_dumped)
13881 {
13882 if (dump_file)
13883 dump_function_header (dump_file, current_function_decl, dump_flags);
13884 omp_any_child_fn_dumped = false;
13885 }
13886 }
13887
13888
13889 /* Helper for build_omp_regions. Scan the dominator tree starting at
13890 block BB. PARENT is the region that contains BB. If SINGLE_TREE is
13891 true, the function ends once a single tree is built (otherwise, whole
13892 forest of OMP constructs may be built). */
13893
13894 static void
13895 build_omp_regions_1 (basic_block bb, struct omp_region *parent,
13896 bool single_tree)
13897 {
13898 gimple_stmt_iterator gsi;
13899 gimple *stmt;
13900 basic_block son;
13901
13902 gsi = gsi_last_bb (bb);
13903 if (!gsi_end_p (gsi) && is_gimple_omp (gsi_stmt (gsi)))
13904 {
13905 struct omp_region *region;
13906 enum gimple_code code;
13907
13908 stmt = gsi_stmt (gsi);
13909 code = gimple_code (stmt);
13910 if (code == GIMPLE_OMP_RETURN)
13911 {
13912 /* STMT is the return point out of region PARENT. Mark it
13913 as the exit point and make PARENT the immediately
13914 enclosing region. */
13915 gcc_assert (parent);
13916 region = parent;
13917 region->exit = bb;
13918 parent = parent->outer;
13919 }
13920 else if (code == GIMPLE_OMP_ATOMIC_STORE)
13921 {
13922 /* GIMPLE_OMP_ATOMIC_STORE is analoguous to
13923 GIMPLE_OMP_RETURN, but matches with
13924 GIMPLE_OMP_ATOMIC_LOAD. */
13925 gcc_assert (parent);
13926 gcc_assert (parent->type == GIMPLE_OMP_ATOMIC_LOAD);
13927 region = parent;
13928 region->exit = bb;
13929 parent = parent->outer;
13930 }
13931 else if (code == GIMPLE_OMP_CONTINUE)
13932 {
13933 gcc_assert (parent);
13934 parent->cont = bb;
13935 }
13936 else if (code == GIMPLE_OMP_SECTIONS_SWITCH)
13937 {
13938 /* GIMPLE_OMP_SECTIONS_SWITCH is part of
13939 GIMPLE_OMP_SECTIONS, and we do nothing for it. */
13940 }
13941 else
13942 {
13943 region = new_omp_region (bb, code, parent);
13944 /* Otherwise... */
13945 if (code == GIMPLE_OMP_TARGET)
13946 {
13947 switch (gimple_omp_target_kind (stmt))
13948 {
13949 case GF_OMP_TARGET_KIND_REGION:
13950 case GF_OMP_TARGET_KIND_DATA:
13951 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
13952 case GF_OMP_TARGET_KIND_OACC_KERNELS:
13953 case GF_OMP_TARGET_KIND_OACC_DATA:
13954 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
13955 break;
13956 case GF_OMP_TARGET_KIND_UPDATE:
13957 case GF_OMP_TARGET_KIND_ENTER_DATA:
13958 case GF_OMP_TARGET_KIND_EXIT_DATA:
13959 case GF_OMP_TARGET_KIND_OACC_UPDATE:
13960 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
13961 case GF_OMP_TARGET_KIND_OACC_DECLARE:
13962 /* ..., other than for those stand-alone directives... */
13963 region = NULL;
13964 break;
13965 default:
13966 gcc_unreachable ();
13967 }
13968 }
13969 else if (code == GIMPLE_OMP_ORDERED
13970 && find_omp_clause (gimple_omp_ordered_clauses
13971 (as_a <gomp_ordered *> (stmt)),
13972 OMP_CLAUSE_DEPEND))
13973 /* #pragma omp ordered depend is also just a stand-alone
13974 directive. */
13975 region = NULL;
13976 /* ..., this directive becomes the parent for a new region. */
13977 if (region)
13978 parent = region;
13979 }
13980 }
13981
13982 if (single_tree && !parent)
13983 return;
13984
13985 for (son = first_dom_son (CDI_DOMINATORS, bb);
13986 son;
13987 son = next_dom_son (CDI_DOMINATORS, son))
13988 build_omp_regions_1 (son, parent, single_tree);
13989 }
13990
13991 /* Builds the tree of OMP regions rooted at ROOT, storing it to
13992 root_omp_region. */
13993
13994 static void
13995 build_omp_regions_root (basic_block root)
13996 {
13997 gcc_assert (root_omp_region == NULL);
13998 build_omp_regions_1 (root, NULL, true);
13999 gcc_assert (root_omp_region != NULL);
14000 }
14001
14002 /* Expands omp construct (and its subconstructs) starting in HEAD. */
14003
14004 void
14005 omp_expand_local (basic_block head)
14006 {
14007 build_omp_regions_root (head);
14008 if (dump_file && (dump_flags & TDF_DETAILS))
14009 {
14010 fprintf (dump_file, "\nOMP region tree\n\n");
14011 dump_omp_region (dump_file, root_omp_region, 0);
14012 fprintf (dump_file, "\n");
14013 }
14014
14015 remove_exit_barriers (root_omp_region);
14016 expand_omp (root_omp_region);
14017
14018 free_omp_regions ();
14019 }
14020
14021 /* Scan the CFG and build a tree of OMP regions. Return the root of
14022 the OMP region tree. */
14023
14024 static void
14025 build_omp_regions (void)
14026 {
14027 gcc_assert (root_omp_region == NULL);
14028 calculate_dominance_info (CDI_DOMINATORS);
14029 build_omp_regions_1 (ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, false);
14030 }
14031
14032 /* Main entry point for expanding OMP-GIMPLE into runtime calls. */
14033
14034 static unsigned int
14035 execute_expand_omp (void)
14036 {
14037 build_omp_regions ();
14038
14039 if (!root_omp_region)
14040 return 0;
14041
14042 if (dump_file)
14043 {
14044 fprintf (dump_file, "\nOMP region tree\n\n");
14045 dump_omp_region (dump_file, root_omp_region, 0);
14046 fprintf (dump_file, "\n");
14047 }
14048
14049 remove_exit_barriers (root_omp_region);
14050
14051 expand_omp (root_omp_region);
14052
14053 if (flag_checking && !loops_state_satisfies_p (LOOPS_NEED_FIXUP))
14054 verify_loop_structure ();
14055 cleanup_tree_cfg ();
14056
14057 free_omp_regions ();
14058
14059 return 0;
14060 }
14061
14062 /* OMP expansion -- the default pass, run before creation of SSA form. */
14063
14064 namespace {
14065
14066 const pass_data pass_data_expand_omp =
14067 {
14068 GIMPLE_PASS, /* type */
14069 "ompexp", /* name */
14070 OPTGROUP_NONE, /* optinfo_flags */
14071 TV_NONE, /* tv_id */
14072 PROP_gimple_any, /* properties_required */
14073 PROP_gimple_eomp, /* properties_provided */
14074 0, /* properties_destroyed */
14075 0, /* todo_flags_start */
14076 0, /* todo_flags_finish */
14077 };
14078
14079 class pass_expand_omp : public gimple_opt_pass
14080 {
14081 public:
14082 pass_expand_omp (gcc::context *ctxt)
14083 : gimple_opt_pass (pass_data_expand_omp, ctxt)
14084 {}
14085
14086 /* opt_pass methods: */
14087 virtual unsigned int execute (function *)
14088 {
14089 bool gate = ((flag_cilkplus != 0 || flag_openacc != 0 || flag_openmp != 0
14090 || flag_openmp_simd != 0)
14091 && !seen_error ());
14092
14093 /* This pass always runs, to provide PROP_gimple_eomp.
14094 But often, there is nothing to do. */
14095 if (!gate)
14096 return 0;
14097
14098 return execute_expand_omp ();
14099 }
14100
14101 }; // class pass_expand_omp
14102
14103 } // anon namespace
14104
14105 gimple_opt_pass *
14106 make_pass_expand_omp (gcc::context *ctxt)
14107 {
14108 return new pass_expand_omp (ctxt);
14109 }
14110
14111 namespace {
14112
14113 const pass_data pass_data_expand_omp_ssa =
14114 {
14115 GIMPLE_PASS, /* type */
14116 "ompexpssa", /* name */
14117 OPTGROUP_NONE, /* optinfo_flags */
14118 TV_NONE, /* tv_id */
14119 PROP_cfg | PROP_ssa, /* properties_required */
14120 PROP_gimple_eomp, /* properties_provided */
14121 0, /* properties_destroyed */
14122 0, /* todo_flags_start */
14123 TODO_cleanup_cfg | TODO_rebuild_alias, /* todo_flags_finish */
14124 };
14125
14126 class pass_expand_omp_ssa : public gimple_opt_pass
14127 {
14128 public:
14129 pass_expand_omp_ssa (gcc::context *ctxt)
14130 : gimple_opt_pass (pass_data_expand_omp_ssa, ctxt)
14131 {}
14132
14133 /* opt_pass methods: */
14134 virtual bool gate (function *fun)
14135 {
14136 return !(fun->curr_properties & PROP_gimple_eomp);
14137 }
14138 virtual unsigned int execute (function *) { return execute_expand_omp (); }
14139 opt_pass * clone () { return new pass_expand_omp_ssa (m_ctxt); }
14140
14141 }; // class pass_expand_omp_ssa
14142
14143 } // anon namespace
14144
14145 gimple_opt_pass *
14146 make_pass_expand_omp_ssa (gcc::context *ctxt)
14147 {
14148 return new pass_expand_omp_ssa (ctxt);
14149 }
14150 \f
14151 /* Routines to lower OMP directives into OMP-GIMPLE. */
14152
14153 /* If ctx is a worksharing context inside of a cancellable parallel
14154 region and it isn't nowait, add lhs to its GIMPLE_OMP_RETURN
14155 and conditional branch to parallel's cancel_label to handle
14156 cancellation in the implicit barrier. */
14157
14158 static void
14159 maybe_add_implicit_barrier_cancel (omp_context *ctx, gimple_seq *body)
14160 {
14161 gimple *omp_return = gimple_seq_last_stmt (*body);
14162 gcc_assert (gimple_code (omp_return) == GIMPLE_OMP_RETURN);
14163 if (gimple_omp_return_nowait_p (omp_return))
14164 return;
14165 if (ctx->outer
14166 && gimple_code (ctx->outer->stmt) == GIMPLE_OMP_PARALLEL
14167 && ctx->outer->cancellable)
14168 {
14169 tree fndecl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
14170 tree c_bool_type = TREE_TYPE (TREE_TYPE (fndecl));
14171 tree lhs = create_tmp_var (c_bool_type);
14172 gimple_omp_return_set_lhs (omp_return, lhs);
14173 tree fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
14174 gimple *g = gimple_build_cond (NE_EXPR, lhs,
14175 fold_convert (c_bool_type,
14176 boolean_false_node),
14177 ctx->outer->cancel_label, fallthru_label);
14178 gimple_seq_add_stmt (body, g);
14179 gimple_seq_add_stmt (body, gimple_build_label (fallthru_label));
14180 }
14181 }
14182
14183 /* Lower the OpenMP sections directive in the current statement in GSI_P.
14184 CTX is the enclosing OMP context for the current statement. */
14185
14186 static void
14187 lower_omp_sections (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14188 {
14189 tree block, control;
14190 gimple_stmt_iterator tgsi;
14191 gomp_sections *stmt;
14192 gimple *t;
14193 gbind *new_stmt, *bind;
14194 gimple_seq ilist, dlist, olist, new_body;
14195
14196 stmt = as_a <gomp_sections *> (gsi_stmt (*gsi_p));
14197
14198 push_gimplify_context ();
14199
14200 dlist = NULL;
14201 ilist = NULL;
14202 lower_rec_input_clauses (gimple_omp_sections_clauses (stmt),
14203 &ilist, &dlist, ctx, NULL);
14204
14205 new_body = gimple_omp_body (stmt);
14206 gimple_omp_set_body (stmt, NULL);
14207 tgsi = gsi_start (new_body);
14208 for (; !gsi_end_p (tgsi); gsi_next (&tgsi))
14209 {
14210 omp_context *sctx;
14211 gimple *sec_start;
14212
14213 sec_start = gsi_stmt (tgsi);
14214 sctx = maybe_lookup_ctx (sec_start);
14215 gcc_assert (sctx);
14216
14217 lower_omp (gimple_omp_body_ptr (sec_start), sctx);
14218 gsi_insert_seq_after (&tgsi, gimple_omp_body (sec_start),
14219 GSI_CONTINUE_LINKING);
14220 gimple_omp_set_body (sec_start, NULL);
14221
14222 if (gsi_one_before_end_p (tgsi))
14223 {
14224 gimple_seq l = NULL;
14225 lower_lastprivate_clauses (gimple_omp_sections_clauses (stmt), NULL,
14226 &l, ctx);
14227 gsi_insert_seq_after (&tgsi, l, GSI_CONTINUE_LINKING);
14228 gimple_omp_section_set_last (sec_start);
14229 }
14230
14231 gsi_insert_after (&tgsi, gimple_build_omp_return (false),
14232 GSI_CONTINUE_LINKING);
14233 }
14234
14235 block = make_node (BLOCK);
14236 bind = gimple_build_bind (NULL, new_body, block);
14237
14238 olist = NULL;
14239 lower_reduction_clauses (gimple_omp_sections_clauses (stmt), &olist, ctx);
14240
14241 block = make_node (BLOCK);
14242 new_stmt = gimple_build_bind (NULL, NULL, block);
14243 gsi_replace (gsi_p, new_stmt, true);
14244
14245 pop_gimplify_context (new_stmt);
14246 gimple_bind_append_vars (new_stmt, ctx->block_vars);
14247 BLOCK_VARS (block) = gimple_bind_vars (bind);
14248 if (BLOCK_VARS (block))
14249 TREE_USED (block) = 1;
14250
14251 new_body = NULL;
14252 gimple_seq_add_seq (&new_body, ilist);
14253 gimple_seq_add_stmt (&new_body, stmt);
14254 gimple_seq_add_stmt (&new_body, gimple_build_omp_sections_switch ());
14255 gimple_seq_add_stmt (&new_body, bind);
14256
14257 control = create_tmp_var (unsigned_type_node, ".section");
14258 t = gimple_build_omp_continue (control, control);
14259 gimple_omp_sections_set_control (stmt, control);
14260 gimple_seq_add_stmt (&new_body, t);
14261
14262 gimple_seq_add_seq (&new_body, olist);
14263 if (ctx->cancellable)
14264 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
14265 gimple_seq_add_seq (&new_body, dlist);
14266
14267 new_body = maybe_catch_exception (new_body);
14268
14269 t = gimple_build_omp_return
14270 (!!find_omp_clause (gimple_omp_sections_clauses (stmt),
14271 OMP_CLAUSE_NOWAIT));
14272 gimple_seq_add_stmt (&new_body, t);
14273 maybe_add_implicit_barrier_cancel (ctx, &new_body);
14274
14275 gimple_bind_set_body (new_stmt, new_body);
14276 }
14277
14278
14279 /* A subroutine of lower_omp_single. Expand the simple form of
14280 a GIMPLE_OMP_SINGLE, without a copyprivate clause:
14281
14282 if (GOMP_single_start ())
14283 BODY;
14284 [ GOMP_barrier (); ] -> unless 'nowait' is present.
14285
14286 FIXME. It may be better to delay expanding the logic of this until
14287 pass_expand_omp. The expanded logic may make the job more difficult
14288 to a synchronization analysis pass. */
14289
14290 static void
14291 lower_omp_single_simple (gomp_single *single_stmt, gimple_seq *pre_p)
14292 {
14293 location_t loc = gimple_location (single_stmt);
14294 tree tlabel = create_artificial_label (loc);
14295 tree flabel = create_artificial_label (loc);
14296 gimple *call, *cond;
14297 tree lhs, decl;
14298
14299 decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_START);
14300 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (decl)));
14301 call = gimple_build_call (decl, 0);
14302 gimple_call_set_lhs (call, lhs);
14303 gimple_seq_add_stmt (pre_p, call);
14304
14305 cond = gimple_build_cond (EQ_EXPR, lhs,
14306 fold_convert_loc (loc, TREE_TYPE (lhs),
14307 boolean_true_node),
14308 tlabel, flabel);
14309 gimple_seq_add_stmt (pre_p, cond);
14310 gimple_seq_add_stmt (pre_p, gimple_build_label (tlabel));
14311 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14312 gimple_seq_add_stmt (pre_p, gimple_build_label (flabel));
14313 }
14314
14315
14316 /* A subroutine of lower_omp_single. Expand the simple form of
14317 a GIMPLE_OMP_SINGLE, with a copyprivate clause:
14318
14319 #pragma omp single copyprivate (a, b, c)
14320
14321 Create a new structure to hold copies of 'a', 'b' and 'c' and emit:
14322
14323 {
14324 if ((copyout_p = GOMP_single_copy_start ()) == NULL)
14325 {
14326 BODY;
14327 copyout.a = a;
14328 copyout.b = b;
14329 copyout.c = c;
14330 GOMP_single_copy_end (&copyout);
14331 }
14332 else
14333 {
14334 a = copyout_p->a;
14335 b = copyout_p->b;
14336 c = copyout_p->c;
14337 }
14338 GOMP_barrier ();
14339 }
14340
14341 FIXME. It may be better to delay expanding the logic of this until
14342 pass_expand_omp. The expanded logic may make the job more difficult
14343 to a synchronization analysis pass. */
14344
14345 static void
14346 lower_omp_single_copy (gomp_single *single_stmt, gimple_seq *pre_p,
14347 omp_context *ctx)
14348 {
14349 tree ptr_type, t, l0, l1, l2, bfn_decl;
14350 gimple_seq copyin_seq;
14351 location_t loc = gimple_location (single_stmt);
14352
14353 ctx->sender_decl = create_tmp_var (ctx->record_type, ".omp_copy_o");
14354
14355 ptr_type = build_pointer_type (ctx->record_type);
14356 ctx->receiver_decl = create_tmp_var (ptr_type, ".omp_copy_i");
14357
14358 l0 = create_artificial_label (loc);
14359 l1 = create_artificial_label (loc);
14360 l2 = create_artificial_label (loc);
14361
14362 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_START);
14363 t = build_call_expr_loc (loc, bfn_decl, 0);
14364 t = fold_convert_loc (loc, ptr_type, t);
14365 gimplify_assign (ctx->receiver_decl, t, pre_p);
14366
14367 t = build2 (EQ_EXPR, boolean_type_node, ctx->receiver_decl,
14368 build_int_cst (ptr_type, 0));
14369 t = build3 (COND_EXPR, void_type_node, t,
14370 build_and_jump (&l0), build_and_jump (&l1));
14371 gimplify_and_add (t, pre_p);
14372
14373 gimple_seq_add_stmt (pre_p, gimple_build_label (l0));
14374
14375 gimple_seq_add_seq (pre_p, gimple_omp_body (single_stmt));
14376
14377 copyin_seq = NULL;
14378 lower_copyprivate_clauses (gimple_omp_single_clauses (single_stmt), pre_p,
14379 &copyin_seq, ctx);
14380
14381 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
14382 bfn_decl = builtin_decl_explicit (BUILT_IN_GOMP_SINGLE_COPY_END);
14383 t = build_call_expr_loc (loc, bfn_decl, 1, t);
14384 gimplify_and_add (t, pre_p);
14385
14386 t = build_and_jump (&l2);
14387 gimplify_and_add (t, pre_p);
14388
14389 gimple_seq_add_stmt (pre_p, gimple_build_label (l1));
14390
14391 gimple_seq_add_seq (pre_p, copyin_seq);
14392
14393 gimple_seq_add_stmt (pre_p, gimple_build_label (l2));
14394 }
14395
14396
14397 /* Expand code for an OpenMP single directive. */
14398
14399 static void
14400 lower_omp_single (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14401 {
14402 tree block;
14403 gimple *t;
14404 gomp_single *single_stmt = as_a <gomp_single *> (gsi_stmt (*gsi_p));
14405 gbind *bind;
14406 gimple_seq bind_body, bind_body_tail = NULL, dlist;
14407
14408 push_gimplify_context ();
14409
14410 block = make_node (BLOCK);
14411 bind = gimple_build_bind (NULL, NULL, block);
14412 gsi_replace (gsi_p, bind, true);
14413 bind_body = NULL;
14414 dlist = NULL;
14415 lower_rec_input_clauses (gimple_omp_single_clauses (single_stmt),
14416 &bind_body, &dlist, ctx, NULL);
14417 lower_omp (gimple_omp_body_ptr (single_stmt), ctx);
14418
14419 gimple_seq_add_stmt (&bind_body, single_stmt);
14420
14421 if (ctx->record_type)
14422 lower_omp_single_copy (single_stmt, &bind_body, ctx);
14423 else
14424 lower_omp_single_simple (single_stmt, &bind_body);
14425
14426 gimple_omp_set_body (single_stmt, NULL);
14427
14428 gimple_seq_add_seq (&bind_body, dlist);
14429
14430 bind_body = maybe_catch_exception (bind_body);
14431
14432 t = gimple_build_omp_return
14433 (!!find_omp_clause (gimple_omp_single_clauses (single_stmt),
14434 OMP_CLAUSE_NOWAIT));
14435 gimple_seq_add_stmt (&bind_body_tail, t);
14436 maybe_add_implicit_barrier_cancel (ctx, &bind_body_tail);
14437 if (ctx->record_type)
14438 {
14439 gimple_stmt_iterator gsi = gsi_start (bind_body_tail);
14440 tree clobber = build_constructor (ctx->record_type, NULL);
14441 TREE_THIS_VOLATILE (clobber) = 1;
14442 gsi_insert_after (&gsi, gimple_build_assign (ctx->sender_decl,
14443 clobber), GSI_SAME_STMT);
14444 }
14445 gimple_seq_add_seq (&bind_body, bind_body_tail);
14446 gimple_bind_set_body (bind, bind_body);
14447
14448 pop_gimplify_context (bind);
14449
14450 gimple_bind_append_vars (bind, ctx->block_vars);
14451 BLOCK_VARS (block) = ctx->block_vars;
14452 if (BLOCK_VARS (block))
14453 TREE_USED (block) = 1;
14454 }
14455
14456
14457 /* Expand code for an OpenMP master directive. */
14458
14459 static void
14460 lower_omp_master (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14461 {
14462 tree block, lab = NULL, x, bfn_decl;
14463 gimple *stmt = gsi_stmt (*gsi_p);
14464 gbind *bind;
14465 location_t loc = gimple_location (stmt);
14466 gimple_seq tseq;
14467
14468 push_gimplify_context ();
14469
14470 block = make_node (BLOCK);
14471 bind = gimple_build_bind (NULL, NULL, block);
14472 gsi_replace (gsi_p, bind, true);
14473 gimple_bind_add_stmt (bind, stmt);
14474
14475 bfn_decl = builtin_decl_explicit (BUILT_IN_OMP_GET_THREAD_NUM);
14476 x = build_call_expr_loc (loc, bfn_decl, 0);
14477 x = build2 (EQ_EXPR, boolean_type_node, x, integer_zero_node);
14478 x = build3 (COND_EXPR, void_type_node, x, NULL, build_and_jump (&lab));
14479 tseq = NULL;
14480 gimplify_and_add (x, &tseq);
14481 gimple_bind_add_seq (bind, tseq);
14482
14483 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14484 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14485 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14486 gimple_omp_set_body (stmt, NULL);
14487
14488 gimple_bind_add_stmt (bind, gimple_build_label (lab));
14489
14490 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14491
14492 pop_gimplify_context (bind);
14493
14494 gimple_bind_append_vars (bind, ctx->block_vars);
14495 BLOCK_VARS (block) = ctx->block_vars;
14496 }
14497
14498
14499 /* Expand code for an OpenMP taskgroup directive. */
14500
14501 static void
14502 lower_omp_taskgroup (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14503 {
14504 gimple *stmt = gsi_stmt (*gsi_p);
14505 gcall *x;
14506 gbind *bind;
14507 tree block = make_node (BLOCK);
14508
14509 bind = gimple_build_bind (NULL, NULL, block);
14510 gsi_replace (gsi_p, bind, true);
14511 gimple_bind_add_stmt (bind, stmt);
14512
14513 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_TASKGROUP_START),
14514 0);
14515 gimple_bind_add_stmt (bind, x);
14516
14517 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14518 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14519 gimple_omp_set_body (stmt, NULL);
14520
14521 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14522
14523 gimple_bind_append_vars (bind, ctx->block_vars);
14524 BLOCK_VARS (block) = ctx->block_vars;
14525 }
14526
14527
14528 /* Fold the OMP_ORDERED_CLAUSES for the OMP_ORDERED in STMT if possible. */
14529
14530 static void
14531 lower_omp_ordered_clauses (gimple_stmt_iterator *gsi_p, gomp_ordered *ord_stmt,
14532 omp_context *ctx)
14533 {
14534 struct omp_for_data fd;
14535 if (!ctx->outer || gimple_code (ctx->outer->stmt) != GIMPLE_OMP_FOR)
14536 return;
14537
14538 unsigned int len = gimple_omp_for_collapse (ctx->outer->stmt);
14539 struct omp_for_data_loop *loops = XALLOCAVEC (struct omp_for_data_loop, len);
14540 extract_omp_for_data (as_a <gomp_for *> (ctx->outer->stmt), &fd, loops);
14541 if (!fd.ordered)
14542 return;
14543
14544 tree *list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14545 tree c = gimple_omp_ordered_clauses (ord_stmt);
14546 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
14547 && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK)
14548 {
14549 /* Merge depend clauses from multiple adjacent
14550 #pragma omp ordered depend(sink:...) constructs
14551 into one #pragma omp ordered depend(sink:...), so that
14552 we can optimize them together. */
14553 gimple_stmt_iterator gsi = *gsi_p;
14554 gsi_next (&gsi);
14555 while (!gsi_end_p (gsi))
14556 {
14557 gimple *stmt = gsi_stmt (gsi);
14558 if (is_gimple_debug (stmt)
14559 || gimple_code (stmt) == GIMPLE_NOP)
14560 {
14561 gsi_next (&gsi);
14562 continue;
14563 }
14564 if (gimple_code (stmt) != GIMPLE_OMP_ORDERED)
14565 break;
14566 gomp_ordered *ord_stmt2 = as_a <gomp_ordered *> (stmt);
14567 c = gimple_omp_ordered_clauses (ord_stmt2);
14568 if (c == NULL_TREE
14569 || OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND
14570 || OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14571 break;
14572 while (*list_p)
14573 list_p = &OMP_CLAUSE_CHAIN (*list_p);
14574 *list_p = c;
14575 gsi_remove (&gsi, true);
14576 }
14577 }
14578
14579 /* Canonicalize sink dependence clauses into one folded clause if
14580 possible.
14581
14582 The basic algorithm is to create a sink vector whose first
14583 element is the GCD of all the first elements, and whose remaining
14584 elements are the minimum of the subsequent columns.
14585
14586 We ignore dependence vectors whose first element is zero because
14587 such dependencies are known to be executed by the same thread.
14588
14589 We take into account the direction of the loop, so a minimum
14590 becomes a maximum if the loop is iterating forwards. We also
14591 ignore sink clauses where the loop direction is unknown, or where
14592 the offsets are clearly invalid because they are not a multiple
14593 of the loop increment.
14594
14595 For example:
14596
14597 #pragma omp for ordered(2)
14598 for (i=0; i < N; ++i)
14599 for (j=0; j < M; ++j)
14600 {
14601 #pragma omp ordered \
14602 depend(sink:i-8,j-2) \
14603 depend(sink:i,j-1) \ // Completely ignored because i+0.
14604 depend(sink:i-4,j-3) \
14605 depend(sink:i-6,j-4)
14606 #pragma omp ordered depend(source)
14607 }
14608
14609 Folded clause is:
14610
14611 depend(sink:-gcd(8,4,6),-min(2,3,4))
14612 -or-
14613 depend(sink:-2,-2)
14614 */
14615
14616 /* FIXME: Computing GCD's where the first element is zero is
14617 non-trivial in the presence of collapsed loops. Do this later. */
14618 if (fd.collapse > 1)
14619 return;
14620
14621 wide_int *folded_deps = XALLOCAVEC (wide_int, 2 * len - 1);
14622 memset (folded_deps, 0, sizeof (*folded_deps) * (2 * len - 1));
14623 tree folded_dep = NULL_TREE;
14624 /* TRUE if the first dimension's offset is negative. */
14625 bool neg_offset_p = false;
14626
14627 list_p = gimple_omp_ordered_clauses_ptr (ord_stmt);
14628 unsigned int i;
14629 while ((c = *list_p) != NULL)
14630 {
14631 bool remove = false;
14632
14633 gcc_assert (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND);
14634 if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_SINK)
14635 goto next_ordered_clause;
14636
14637 tree vec;
14638 for (vec = OMP_CLAUSE_DECL (c), i = 0;
14639 vec && TREE_CODE (vec) == TREE_LIST;
14640 vec = TREE_CHAIN (vec), ++i)
14641 {
14642 gcc_assert (i < len);
14643
14644 /* extract_omp_for_data has canonicalized the condition. */
14645 gcc_assert (fd.loops[i].cond_code == LT_EXPR
14646 || fd.loops[i].cond_code == GT_EXPR);
14647 bool forward = fd.loops[i].cond_code == LT_EXPR;
14648 bool maybe_lexically_later = true;
14649
14650 /* While the committee makes up its mind, bail if we have any
14651 non-constant steps. */
14652 if (TREE_CODE (fd.loops[i].step) != INTEGER_CST)
14653 goto lower_omp_ordered_ret;
14654
14655 tree itype = TREE_TYPE (TREE_VALUE (vec));
14656 if (POINTER_TYPE_P (itype))
14657 itype = sizetype;
14658 wide_int offset = wide_int::from (TREE_PURPOSE (vec),
14659 TYPE_PRECISION (itype),
14660 TYPE_SIGN (itype));
14661
14662 /* Ignore invalid offsets that are not multiples of the step. */
14663 if (!wi::multiple_of_p
14664 (wi::abs (offset), wi::abs ((wide_int) fd.loops[i].step),
14665 UNSIGNED))
14666 {
14667 warning_at (OMP_CLAUSE_LOCATION (c), 0,
14668 "ignoring sink clause with offset that is not "
14669 "a multiple of the loop step");
14670 remove = true;
14671 goto next_ordered_clause;
14672 }
14673
14674 /* Calculate the first dimension. The first dimension of
14675 the folded dependency vector is the GCD of the first
14676 elements, while ignoring any first elements whose offset
14677 is 0. */
14678 if (i == 0)
14679 {
14680 /* Ignore dependence vectors whose first dimension is 0. */
14681 if (offset == 0)
14682 {
14683 remove = true;
14684 goto next_ordered_clause;
14685 }
14686 else
14687 {
14688 if (!TYPE_UNSIGNED (itype) && (forward ^ wi::neg_p (offset)))
14689 {
14690 error_at (OMP_CLAUSE_LOCATION (c),
14691 "first offset must be in opposite direction "
14692 "of loop iterations");
14693 goto lower_omp_ordered_ret;
14694 }
14695 if (forward)
14696 offset = -offset;
14697 neg_offset_p = forward;
14698 /* Initialize the first time around. */
14699 if (folded_dep == NULL_TREE)
14700 {
14701 folded_dep = c;
14702 folded_deps[0] = offset;
14703 }
14704 else
14705 folded_deps[0] = wi::gcd (folded_deps[0],
14706 offset, UNSIGNED);
14707 }
14708 }
14709 /* Calculate minimum for the remaining dimensions. */
14710 else
14711 {
14712 folded_deps[len + i - 1] = offset;
14713 if (folded_dep == c)
14714 folded_deps[i] = offset;
14715 else if (maybe_lexically_later
14716 && !wi::eq_p (folded_deps[i], offset))
14717 {
14718 if (forward ^ wi::gts_p (folded_deps[i], offset))
14719 {
14720 unsigned int j;
14721 folded_dep = c;
14722 for (j = 1; j <= i; j++)
14723 folded_deps[j] = folded_deps[len + j - 1];
14724 }
14725 else
14726 maybe_lexically_later = false;
14727 }
14728 }
14729 }
14730 gcc_assert (i == len);
14731
14732 remove = true;
14733
14734 next_ordered_clause:
14735 if (remove)
14736 *list_p = OMP_CLAUSE_CHAIN (c);
14737 else
14738 list_p = &OMP_CLAUSE_CHAIN (c);
14739 }
14740
14741 if (folded_dep)
14742 {
14743 if (neg_offset_p)
14744 folded_deps[0] = -folded_deps[0];
14745
14746 tree itype = TREE_TYPE (TREE_VALUE (OMP_CLAUSE_DECL (folded_dep)));
14747 if (POINTER_TYPE_P (itype))
14748 itype = sizetype;
14749
14750 TREE_PURPOSE (OMP_CLAUSE_DECL (folded_dep))
14751 = wide_int_to_tree (itype, folded_deps[0]);
14752 OMP_CLAUSE_CHAIN (folded_dep) = gimple_omp_ordered_clauses (ord_stmt);
14753 *gimple_omp_ordered_clauses_ptr (ord_stmt) = folded_dep;
14754 }
14755
14756 lower_omp_ordered_ret:
14757
14758 /* Ordered without clauses is #pragma omp threads, while we want
14759 a nop instead if we remove all clauses. */
14760 if (gimple_omp_ordered_clauses (ord_stmt) == NULL_TREE)
14761 gsi_replace (gsi_p, gimple_build_nop (), true);
14762 }
14763
14764
14765 /* Expand code for an OpenMP ordered directive. */
14766
14767 static void
14768 lower_omp_ordered (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14769 {
14770 tree block;
14771 gimple *stmt = gsi_stmt (*gsi_p);
14772 gomp_ordered *ord_stmt = as_a <gomp_ordered *> (stmt);
14773 gcall *x;
14774 gbind *bind;
14775 bool simd = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14776 OMP_CLAUSE_SIMD);
14777 bool threads = find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14778 OMP_CLAUSE_THREADS);
14779
14780 if (find_omp_clause (gimple_omp_ordered_clauses (ord_stmt),
14781 OMP_CLAUSE_DEPEND))
14782 {
14783 /* FIXME: This is needs to be moved to the expansion to verify various
14784 conditions only testable on cfg with dominators computed, and also
14785 all the depend clauses to be merged still might need to be available
14786 for the runtime checks. */
14787 if (0)
14788 lower_omp_ordered_clauses (gsi_p, ord_stmt, ctx);
14789 return;
14790 }
14791
14792 push_gimplify_context ();
14793
14794 block = make_node (BLOCK);
14795 bind = gimple_build_bind (NULL, NULL, block);
14796 gsi_replace (gsi_p, bind, true);
14797 gimple_bind_add_stmt (bind, stmt);
14798
14799 if (simd)
14800 {
14801 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_START, 1,
14802 build_int_cst (NULL_TREE, threads));
14803 cfun->has_simduid_loops = true;
14804 }
14805 else
14806 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_START),
14807 0);
14808 gimple_bind_add_stmt (bind, x);
14809
14810 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14811 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14812 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14813 gimple_omp_set_body (stmt, NULL);
14814
14815 if (simd)
14816 x = gimple_build_call_internal (IFN_GOMP_SIMD_ORDERED_END, 1,
14817 build_int_cst (NULL_TREE, threads));
14818 else
14819 x = gimple_build_call (builtin_decl_explicit (BUILT_IN_GOMP_ORDERED_END),
14820 0);
14821 gimple_bind_add_stmt (bind, x);
14822
14823 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14824
14825 pop_gimplify_context (bind);
14826
14827 gimple_bind_append_vars (bind, ctx->block_vars);
14828 BLOCK_VARS (block) = gimple_bind_vars (bind);
14829 }
14830
14831
14832 /* Gimplify a GIMPLE_OMP_CRITICAL statement. This is a relatively simple
14833 substitution of a couple of function calls. But in the NAMED case,
14834 requires that languages coordinate a symbol name. It is therefore
14835 best put here in common code. */
14836
14837 static GTY(()) hash_map<tree, tree> *critical_name_mutexes;
14838
14839 static void
14840 lower_omp_critical (gimple_stmt_iterator *gsi_p, omp_context *ctx)
14841 {
14842 tree block;
14843 tree name, lock, unlock;
14844 gomp_critical *stmt = as_a <gomp_critical *> (gsi_stmt (*gsi_p));
14845 gbind *bind;
14846 location_t loc = gimple_location (stmt);
14847 gimple_seq tbody;
14848
14849 name = gimple_omp_critical_name (stmt);
14850 if (name)
14851 {
14852 tree decl;
14853
14854 if (!critical_name_mutexes)
14855 critical_name_mutexes = hash_map<tree, tree>::create_ggc (10);
14856
14857 tree *n = critical_name_mutexes->get (name);
14858 if (n == NULL)
14859 {
14860 char *new_str;
14861
14862 decl = create_tmp_var_raw (ptr_type_node);
14863
14864 new_str = ACONCAT ((".gomp_critical_user_",
14865 IDENTIFIER_POINTER (name), NULL));
14866 DECL_NAME (decl) = get_identifier (new_str);
14867 TREE_PUBLIC (decl) = 1;
14868 TREE_STATIC (decl) = 1;
14869 DECL_COMMON (decl) = 1;
14870 DECL_ARTIFICIAL (decl) = 1;
14871 DECL_IGNORED_P (decl) = 1;
14872
14873 varpool_node::finalize_decl (decl);
14874
14875 critical_name_mutexes->put (name, decl);
14876 }
14877 else
14878 decl = *n;
14879
14880 /* If '#pragma omp critical' is inside offloaded region or
14881 inside function marked as offloadable, the symbol must be
14882 marked as offloadable too. */
14883 omp_context *octx;
14884 if (cgraph_node::get (current_function_decl)->offloadable)
14885 varpool_node::get_create (decl)->offloadable = 1;
14886 else
14887 for (octx = ctx->outer; octx; octx = octx->outer)
14888 if (is_gimple_omp_offloaded (octx->stmt))
14889 {
14890 varpool_node::get_create (decl)->offloadable = 1;
14891 break;
14892 }
14893
14894 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_START);
14895 lock = build_call_expr_loc (loc, lock, 1, build_fold_addr_expr_loc (loc, decl));
14896
14897 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_NAME_END);
14898 unlock = build_call_expr_loc (loc, unlock, 1,
14899 build_fold_addr_expr_loc (loc, decl));
14900 }
14901 else
14902 {
14903 lock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_START);
14904 lock = build_call_expr_loc (loc, lock, 0);
14905
14906 unlock = builtin_decl_explicit (BUILT_IN_GOMP_CRITICAL_END);
14907 unlock = build_call_expr_loc (loc, unlock, 0);
14908 }
14909
14910 push_gimplify_context ();
14911
14912 block = make_node (BLOCK);
14913 bind = gimple_build_bind (NULL, NULL, block);
14914 gsi_replace (gsi_p, bind, true);
14915 gimple_bind_add_stmt (bind, stmt);
14916
14917 tbody = gimple_bind_body (bind);
14918 gimplify_and_add (lock, &tbody);
14919 gimple_bind_set_body (bind, tbody);
14920
14921 lower_omp (gimple_omp_body_ptr (stmt), ctx);
14922 gimple_omp_set_body (stmt, maybe_catch_exception (gimple_omp_body (stmt)));
14923 gimple_bind_add_seq (bind, gimple_omp_body (stmt));
14924 gimple_omp_set_body (stmt, NULL);
14925
14926 tbody = gimple_bind_body (bind);
14927 gimplify_and_add (unlock, &tbody);
14928 gimple_bind_set_body (bind, tbody);
14929
14930 gimple_bind_add_stmt (bind, gimple_build_omp_return (true));
14931
14932 pop_gimplify_context (bind);
14933 gimple_bind_append_vars (bind, ctx->block_vars);
14934 BLOCK_VARS (block) = gimple_bind_vars (bind);
14935 }
14936
14937
14938 /* A subroutine of lower_omp_for. Generate code to emit the predicate
14939 for a lastprivate clause. Given a loop control predicate of (V
14940 cond N2), we gate the clause on (!(V cond N2)). The lowered form
14941 is appended to *DLIST, iterator initialization is appended to
14942 *BODY_P. */
14943
14944 static void
14945 lower_omp_for_lastprivate (struct omp_for_data *fd, gimple_seq *body_p,
14946 gimple_seq *dlist, struct omp_context *ctx)
14947 {
14948 tree clauses, cond, vinit;
14949 enum tree_code cond_code;
14950 gimple_seq stmts;
14951
14952 cond_code = fd->loop.cond_code;
14953 cond_code = cond_code == LT_EXPR ? GE_EXPR : LE_EXPR;
14954
14955 /* When possible, use a strict equality expression. This can let VRP
14956 type optimizations deduce the value and remove a copy. */
14957 if (tree_fits_shwi_p (fd->loop.step))
14958 {
14959 HOST_WIDE_INT step = tree_to_shwi (fd->loop.step);
14960 if (step == 1 || step == -1)
14961 cond_code = EQ_EXPR;
14962 }
14963
14964 tree n2 = fd->loop.n2;
14965 if (fd->collapse > 1
14966 && TREE_CODE (n2) != INTEGER_CST
14967 && gimple_omp_for_combined_into_p (fd->for_stmt))
14968 {
14969 struct omp_context *taskreg_ctx = NULL;
14970 if (gimple_code (ctx->outer->stmt) == GIMPLE_OMP_FOR)
14971 {
14972 gomp_for *gfor = as_a <gomp_for *> (ctx->outer->stmt);
14973 if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_FOR
14974 || gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_DISTRIBUTE)
14975 {
14976 if (gimple_omp_for_combined_into_p (gfor))
14977 {
14978 gcc_assert (ctx->outer->outer
14979 && is_parallel_ctx (ctx->outer->outer));
14980 taskreg_ctx = ctx->outer->outer;
14981 }
14982 else
14983 {
14984 struct omp_for_data outer_fd;
14985 extract_omp_for_data (gfor, &outer_fd, NULL);
14986 n2 = fold_convert (TREE_TYPE (n2), outer_fd.loop.n2);
14987 }
14988 }
14989 else if (gimple_omp_for_kind (gfor) == GF_OMP_FOR_KIND_TASKLOOP)
14990 taskreg_ctx = ctx->outer->outer;
14991 }
14992 else if (is_taskreg_ctx (ctx->outer))
14993 taskreg_ctx = ctx->outer;
14994 if (taskreg_ctx)
14995 {
14996 int i;
14997 tree innerc
14998 = find_omp_clause (gimple_omp_taskreg_clauses (taskreg_ctx->stmt),
14999 OMP_CLAUSE__LOOPTEMP_);
15000 gcc_assert (innerc);
15001 for (i = 0; i < fd->collapse; i++)
15002 {
15003 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
15004 OMP_CLAUSE__LOOPTEMP_);
15005 gcc_assert (innerc);
15006 }
15007 innerc = find_omp_clause (OMP_CLAUSE_CHAIN (innerc),
15008 OMP_CLAUSE__LOOPTEMP_);
15009 if (innerc)
15010 n2 = fold_convert (TREE_TYPE (n2),
15011 lookup_decl (OMP_CLAUSE_DECL (innerc),
15012 taskreg_ctx));
15013 }
15014 }
15015 cond = build2 (cond_code, boolean_type_node, fd->loop.v, n2);
15016
15017 clauses = gimple_omp_for_clauses (fd->for_stmt);
15018 stmts = NULL;
15019 lower_lastprivate_clauses (clauses, cond, &stmts, ctx);
15020 if (!gimple_seq_empty_p (stmts))
15021 {
15022 gimple_seq_add_seq (&stmts, *dlist);
15023 *dlist = stmts;
15024
15025 /* Optimize: v = 0; is usually cheaper than v = some_other_constant. */
15026 vinit = fd->loop.n1;
15027 if (cond_code == EQ_EXPR
15028 && tree_fits_shwi_p (fd->loop.n2)
15029 && ! integer_zerop (fd->loop.n2))
15030 vinit = build_int_cst (TREE_TYPE (fd->loop.v), 0);
15031 else
15032 vinit = unshare_expr (vinit);
15033
15034 /* Initialize the iterator variable, so that threads that don't execute
15035 any iterations don't execute the lastprivate clauses by accident. */
15036 gimplify_assign (fd->loop.v, vinit, body_p);
15037 }
15038 }
15039
15040
15041 /* Lower code for an OMP loop directive. */
15042
15043 static void
15044 lower_omp_for (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15045 {
15046 tree *rhs_p, block;
15047 struct omp_for_data fd, *fdp = NULL;
15048 gomp_for *stmt = as_a <gomp_for *> (gsi_stmt (*gsi_p));
15049 gbind *new_stmt;
15050 gimple_seq omp_for_body, body, dlist;
15051 gimple_seq oacc_head = NULL, oacc_tail = NULL;
15052 size_t i;
15053
15054 push_gimplify_context ();
15055
15056 lower_omp (gimple_omp_for_pre_body_ptr (stmt), ctx);
15057
15058 block = make_node (BLOCK);
15059 new_stmt = gimple_build_bind (NULL, NULL, block);
15060 /* Replace at gsi right away, so that 'stmt' is no member
15061 of a sequence anymore as we're going to add to a different
15062 one below. */
15063 gsi_replace (gsi_p, new_stmt, true);
15064
15065 /* Move declaration of temporaries in the loop body before we make
15066 it go away. */
15067 omp_for_body = gimple_omp_body (stmt);
15068 if (!gimple_seq_empty_p (omp_for_body)
15069 && gimple_code (gimple_seq_first_stmt (omp_for_body)) == GIMPLE_BIND)
15070 {
15071 gbind *inner_bind
15072 = as_a <gbind *> (gimple_seq_first_stmt (omp_for_body));
15073 tree vars = gimple_bind_vars (inner_bind);
15074 gimple_bind_append_vars (new_stmt, vars);
15075 /* bind_vars/BLOCK_VARS are being moved to new_stmt/block, don't
15076 keep them on the inner_bind and it's block. */
15077 gimple_bind_set_vars (inner_bind, NULL_TREE);
15078 if (gimple_bind_block (inner_bind))
15079 BLOCK_VARS (gimple_bind_block (inner_bind)) = NULL_TREE;
15080 }
15081
15082 if (gimple_omp_for_combined_into_p (stmt))
15083 {
15084 extract_omp_for_data (stmt, &fd, NULL);
15085 fdp = &fd;
15086
15087 /* We need two temporaries with fd.loop.v type (istart/iend)
15088 and then (fd.collapse - 1) temporaries with the same
15089 type for count2 ... countN-1 vars if not constant. */
15090 size_t count = 2;
15091 tree type = fd.iter_type;
15092 if (fd.collapse > 1
15093 && TREE_CODE (fd.loop.n2) != INTEGER_CST)
15094 count += fd.collapse - 1;
15095 bool taskreg_for
15096 = (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR
15097 || gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_TASKLOOP);
15098 tree outerc = NULL, *pc = gimple_omp_for_clauses_ptr (stmt);
15099 tree clauses = *pc;
15100 if (taskreg_for)
15101 outerc
15102 = find_omp_clause (gimple_omp_taskreg_clauses (ctx->outer->stmt),
15103 OMP_CLAUSE__LOOPTEMP_);
15104 for (i = 0; i < count; i++)
15105 {
15106 tree temp;
15107 if (taskreg_for)
15108 {
15109 gcc_assert (outerc);
15110 temp = lookup_decl (OMP_CLAUSE_DECL (outerc), ctx->outer);
15111 outerc = find_omp_clause (OMP_CLAUSE_CHAIN (outerc),
15112 OMP_CLAUSE__LOOPTEMP_);
15113 }
15114 else
15115 {
15116 temp = create_tmp_var (type);
15117 insert_decl_map (&ctx->outer->cb, temp, temp);
15118 }
15119 *pc = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__LOOPTEMP_);
15120 OMP_CLAUSE_DECL (*pc) = temp;
15121 pc = &OMP_CLAUSE_CHAIN (*pc);
15122 }
15123 *pc = clauses;
15124 }
15125
15126 /* The pre-body and input clauses go before the lowered GIMPLE_OMP_FOR. */
15127 dlist = NULL;
15128 body = NULL;
15129 lower_rec_input_clauses (gimple_omp_for_clauses (stmt), &body, &dlist, ctx,
15130 fdp);
15131 gimple_seq_add_seq (&body, gimple_omp_for_pre_body (stmt));
15132
15133 lower_omp (gimple_omp_body_ptr (stmt), ctx);
15134
15135 /* Lower the header expressions. At this point, we can assume that
15136 the header is of the form:
15137
15138 #pragma omp for (V = VAL1; V {<|>|<=|>=} VAL2; V = V [+-] VAL3)
15139
15140 We just need to make sure that VAL1, VAL2 and VAL3 are lowered
15141 using the .omp_data_s mapping, if needed. */
15142 for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
15143 {
15144 rhs_p = gimple_omp_for_initial_ptr (stmt, i);
15145 if (!is_gimple_min_invariant (*rhs_p))
15146 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15147
15148 rhs_p = gimple_omp_for_final_ptr (stmt, i);
15149 if (!is_gimple_min_invariant (*rhs_p))
15150 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15151
15152 rhs_p = &TREE_OPERAND (gimple_omp_for_incr (stmt, i), 1);
15153 if (!is_gimple_min_invariant (*rhs_p))
15154 *rhs_p = get_formal_tmp_var (*rhs_p, &body);
15155 }
15156
15157 /* Once lowered, extract the bounds and clauses. */
15158 extract_omp_for_data (stmt, &fd, NULL);
15159
15160 if (is_gimple_omp_oacc (ctx->stmt)
15161 && !ctx_in_oacc_kernels_region (ctx))
15162 lower_oacc_head_tail (gimple_location (stmt),
15163 gimple_omp_for_clauses (stmt),
15164 &oacc_head, &oacc_tail, ctx);
15165
15166 /* Add OpenACC partitioning and reduction markers just before the loop */
15167 if (oacc_head)
15168 gimple_seq_add_seq (&body, oacc_head);
15169
15170 lower_omp_for_lastprivate (&fd, &body, &dlist, ctx);
15171
15172 if (gimple_omp_for_kind (stmt) == GF_OMP_FOR_KIND_FOR)
15173 for (tree c = gimple_omp_for_clauses (stmt); c; c = OMP_CLAUSE_CHAIN (c))
15174 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
15175 && !OMP_CLAUSE_LINEAR_NO_COPYIN (c))
15176 {
15177 OMP_CLAUSE_DECL (c) = lookup_decl (OMP_CLAUSE_DECL (c), ctx);
15178 if (DECL_P (OMP_CLAUSE_LINEAR_STEP (c)))
15179 OMP_CLAUSE_LINEAR_STEP (c)
15180 = maybe_lookup_decl_in_outer_ctx (OMP_CLAUSE_LINEAR_STEP (c),
15181 ctx);
15182 }
15183
15184 if (!gimple_omp_for_grid_phony (stmt))
15185 gimple_seq_add_stmt (&body, stmt);
15186 gimple_seq_add_seq (&body, gimple_omp_body (stmt));
15187
15188 if (!gimple_omp_for_grid_phony (stmt))
15189 gimple_seq_add_stmt (&body, gimple_build_omp_continue (fd.loop.v,
15190 fd.loop.v));
15191
15192 /* After the loop, add exit clauses. */
15193 lower_reduction_clauses (gimple_omp_for_clauses (stmt), &body, ctx);
15194
15195 if (ctx->cancellable)
15196 gimple_seq_add_stmt (&body, gimple_build_label (ctx->cancel_label));
15197
15198 gimple_seq_add_seq (&body, dlist);
15199
15200 body = maybe_catch_exception (body);
15201
15202 if (!gimple_omp_for_grid_phony (stmt))
15203 {
15204 /* Region exit marker goes at the end of the loop body. */
15205 gimple_seq_add_stmt (&body, gimple_build_omp_return (fd.have_nowait));
15206 maybe_add_implicit_barrier_cancel (ctx, &body);
15207 }
15208
15209 /* Add OpenACC joining and reduction markers just after the loop. */
15210 if (oacc_tail)
15211 gimple_seq_add_seq (&body, oacc_tail);
15212
15213 pop_gimplify_context (new_stmt);
15214
15215 gimple_bind_append_vars (new_stmt, ctx->block_vars);
15216 BLOCK_VARS (block) = gimple_bind_vars (new_stmt);
15217 if (BLOCK_VARS (block))
15218 TREE_USED (block) = 1;
15219
15220 gimple_bind_set_body (new_stmt, body);
15221 gimple_omp_set_body (stmt, NULL);
15222 gimple_omp_for_set_pre_body (stmt, NULL);
15223 }
15224
15225 /* Callback for walk_stmts. Check if the current statement only contains
15226 GIMPLE_OMP_FOR or GIMPLE_OMP_SECTIONS. */
15227
15228 static tree
15229 check_combined_parallel (gimple_stmt_iterator *gsi_p,
15230 bool *handled_ops_p,
15231 struct walk_stmt_info *wi)
15232 {
15233 int *info = (int *) wi->info;
15234 gimple *stmt = gsi_stmt (*gsi_p);
15235
15236 *handled_ops_p = true;
15237 switch (gimple_code (stmt))
15238 {
15239 WALK_SUBSTMTS;
15240
15241 case GIMPLE_OMP_FOR:
15242 case GIMPLE_OMP_SECTIONS:
15243 *info = *info == 0 ? 1 : -1;
15244 break;
15245 default:
15246 *info = -1;
15247 break;
15248 }
15249 return NULL;
15250 }
15251
15252 struct omp_taskcopy_context
15253 {
15254 /* This field must be at the beginning, as we do "inheritance": Some
15255 callback functions for tree-inline.c (e.g., omp_copy_decl)
15256 receive a copy_body_data pointer that is up-casted to an
15257 omp_context pointer. */
15258 copy_body_data cb;
15259 omp_context *ctx;
15260 };
15261
15262 static tree
15263 task_copyfn_copy_decl (tree var, copy_body_data *cb)
15264 {
15265 struct omp_taskcopy_context *tcctx = (struct omp_taskcopy_context *) cb;
15266
15267 if (splay_tree_lookup (tcctx->ctx->sfield_map, (splay_tree_key) var))
15268 return create_tmp_var (TREE_TYPE (var));
15269
15270 return var;
15271 }
15272
15273 static tree
15274 task_copyfn_remap_type (struct omp_taskcopy_context *tcctx, tree orig_type)
15275 {
15276 tree name, new_fields = NULL, type, f;
15277
15278 type = lang_hooks.types.make_type (RECORD_TYPE);
15279 name = DECL_NAME (TYPE_NAME (orig_type));
15280 name = build_decl (gimple_location (tcctx->ctx->stmt),
15281 TYPE_DECL, name, type);
15282 TYPE_NAME (type) = name;
15283
15284 for (f = TYPE_FIELDS (orig_type); f ; f = TREE_CHAIN (f))
15285 {
15286 tree new_f = copy_node (f);
15287 DECL_CONTEXT (new_f) = type;
15288 TREE_TYPE (new_f) = remap_type (TREE_TYPE (f), &tcctx->cb);
15289 TREE_CHAIN (new_f) = new_fields;
15290 walk_tree (&DECL_SIZE (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15291 walk_tree (&DECL_SIZE_UNIT (new_f), copy_tree_body_r, &tcctx->cb, NULL);
15292 walk_tree (&DECL_FIELD_OFFSET (new_f), copy_tree_body_r,
15293 &tcctx->cb, NULL);
15294 new_fields = new_f;
15295 tcctx->cb.decl_map->put (f, new_f);
15296 }
15297 TYPE_FIELDS (type) = nreverse (new_fields);
15298 layout_type (type);
15299 return type;
15300 }
15301
15302 /* Create task copyfn. */
15303
15304 static void
15305 create_task_copyfn (gomp_task *task_stmt, omp_context *ctx)
15306 {
15307 struct function *child_cfun;
15308 tree child_fn, t, c, src, dst, f, sf, arg, sarg, decl;
15309 tree record_type, srecord_type, bind, list;
15310 bool record_needs_remap = false, srecord_needs_remap = false;
15311 splay_tree_node n;
15312 struct omp_taskcopy_context tcctx;
15313 location_t loc = gimple_location (task_stmt);
15314
15315 child_fn = gimple_omp_task_copy_fn (task_stmt);
15316 child_cfun = DECL_STRUCT_FUNCTION (child_fn);
15317 gcc_assert (child_cfun->cfg == NULL);
15318 DECL_SAVED_TREE (child_fn) = alloc_stmt_list ();
15319
15320 /* Reset DECL_CONTEXT on function arguments. */
15321 for (t = DECL_ARGUMENTS (child_fn); t; t = DECL_CHAIN (t))
15322 DECL_CONTEXT (t) = child_fn;
15323
15324 /* Populate the function. */
15325 push_gimplify_context ();
15326 push_cfun (child_cfun);
15327
15328 bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
15329 TREE_SIDE_EFFECTS (bind) = 1;
15330 list = NULL;
15331 DECL_SAVED_TREE (child_fn) = bind;
15332 DECL_SOURCE_LOCATION (child_fn) = gimple_location (task_stmt);
15333
15334 /* Remap src and dst argument types if needed. */
15335 record_type = ctx->record_type;
15336 srecord_type = ctx->srecord_type;
15337 for (f = TYPE_FIELDS (record_type); f ; f = DECL_CHAIN (f))
15338 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15339 {
15340 record_needs_remap = true;
15341 break;
15342 }
15343 for (f = TYPE_FIELDS (srecord_type); f ; f = DECL_CHAIN (f))
15344 if (variably_modified_type_p (TREE_TYPE (f), ctx->cb.src_fn))
15345 {
15346 srecord_needs_remap = true;
15347 break;
15348 }
15349
15350 if (record_needs_remap || srecord_needs_remap)
15351 {
15352 memset (&tcctx, '\0', sizeof (tcctx));
15353 tcctx.cb.src_fn = ctx->cb.src_fn;
15354 tcctx.cb.dst_fn = child_fn;
15355 tcctx.cb.src_node = cgraph_node::get (tcctx.cb.src_fn);
15356 gcc_checking_assert (tcctx.cb.src_node);
15357 tcctx.cb.dst_node = tcctx.cb.src_node;
15358 tcctx.cb.src_cfun = ctx->cb.src_cfun;
15359 tcctx.cb.copy_decl = task_copyfn_copy_decl;
15360 tcctx.cb.eh_lp_nr = 0;
15361 tcctx.cb.transform_call_graph_edges = CB_CGE_MOVE;
15362 tcctx.cb.decl_map = new hash_map<tree, tree>;
15363 tcctx.ctx = ctx;
15364
15365 if (record_needs_remap)
15366 record_type = task_copyfn_remap_type (&tcctx, record_type);
15367 if (srecord_needs_remap)
15368 srecord_type = task_copyfn_remap_type (&tcctx, srecord_type);
15369 }
15370 else
15371 tcctx.cb.decl_map = NULL;
15372
15373 arg = DECL_ARGUMENTS (child_fn);
15374 TREE_TYPE (arg) = build_pointer_type (record_type);
15375 sarg = DECL_CHAIN (arg);
15376 TREE_TYPE (sarg) = build_pointer_type (srecord_type);
15377
15378 /* First pass: initialize temporaries used in record_type and srecord_type
15379 sizes and field offsets. */
15380 if (tcctx.cb.decl_map)
15381 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15382 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15383 {
15384 tree *p;
15385
15386 decl = OMP_CLAUSE_DECL (c);
15387 p = tcctx.cb.decl_map->get (decl);
15388 if (p == NULL)
15389 continue;
15390 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15391 sf = (tree) n->value;
15392 sf = *tcctx.cb.decl_map->get (sf);
15393 src = build_simple_mem_ref_loc (loc, sarg);
15394 src = omp_build_component_ref (src, sf);
15395 t = build2 (MODIFY_EXPR, TREE_TYPE (*p), *p, src);
15396 append_to_statement_list (t, &list);
15397 }
15398
15399 /* Second pass: copy shared var pointers and copy construct non-VLA
15400 firstprivate vars. */
15401 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15402 switch (OMP_CLAUSE_CODE (c))
15403 {
15404 splay_tree_key key;
15405 case OMP_CLAUSE_SHARED:
15406 decl = OMP_CLAUSE_DECL (c);
15407 key = (splay_tree_key) decl;
15408 if (OMP_CLAUSE_SHARED_FIRSTPRIVATE (c))
15409 key = (splay_tree_key) &DECL_UID (decl);
15410 n = splay_tree_lookup (ctx->field_map, key);
15411 if (n == NULL)
15412 break;
15413 f = (tree) n->value;
15414 if (tcctx.cb.decl_map)
15415 f = *tcctx.cb.decl_map->get (f);
15416 n = splay_tree_lookup (ctx->sfield_map, key);
15417 sf = (tree) n->value;
15418 if (tcctx.cb.decl_map)
15419 sf = *tcctx.cb.decl_map->get (sf);
15420 src = build_simple_mem_ref_loc (loc, sarg);
15421 src = omp_build_component_ref (src, sf);
15422 dst = build_simple_mem_ref_loc (loc, arg);
15423 dst = omp_build_component_ref (dst, f);
15424 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15425 append_to_statement_list (t, &list);
15426 break;
15427 case OMP_CLAUSE_FIRSTPRIVATE:
15428 decl = OMP_CLAUSE_DECL (c);
15429 if (is_variable_sized (decl))
15430 break;
15431 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15432 if (n == NULL)
15433 break;
15434 f = (tree) n->value;
15435 if (tcctx.cb.decl_map)
15436 f = *tcctx.cb.decl_map->get (f);
15437 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15438 if (n != NULL)
15439 {
15440 sf = (tree) n->value;
15441 if (tcctx.cb.decl_map)
15442 sf = *tcctx.cb.decl_map->get (sf);
15443 src = build_simple_mem_ref_loc (loc, sarg);
15444 src = omp_build_component_ref (src, sf);
15445 if (use_pointer_for_field (decl, NULL) || is_reference (decl))
15446 src = build_simple_mem_ref_loc (loc, src);
15447 }
15448 else
15449 src = decl;
15450 dst = build_simple_mem_ref_loc (loc, arg);
15451 dst = omp_build_component_ref (dst, f);
15452 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15453 append_to_statement_list (t, &list);
15454 break;
15455 case OMP_CLAUSE_PRIVATE:
15456 if (! OMP_CLAUSE_PRIVATE_OUTER_REF (c))
15457 break;
15458 decl = OMP_CLAUSE_DECL (c);
15459 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15460 f = (tree) n->value;
15461 if (tcctx.cb.decl_map)
15462 f = *tcctx.cb.decl_map->get (f);
15463 n = splay_tree_lookup (ctx->sfield_map, (splay_tree_key) decl);
15464 if (n != NULL)
15465 {
15466 sf = (tree) n->value;
15467 if (tcctx.cb.decl_map)
15468 sf = *tcctx.cb.decl_map->get (sf);
15469 src = build_simple_mem_ref_loc (loc, sarg);
15470 src = omp_build_component_ref (src, sf);
15471 if (use_pointer_for_field (decl, NULL))
15472 src = build_simple_mem_ref_loc (loc, src);
15473 }
15474 else
15475 src = decl;
15476 dst = build_simple_mem_ref_loc (loc, arg);
15477 dst = omp_build_component_ref (dst, f);
15478 t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
15479 append_to_statement_list (t, &list);
15480 break;
15481 default:
15482 break;
15483 }
15484
15485 /* Last pass: handle VLA firstprivates. */
15486 if (tcctx.cb.decl_map)
15487 for (c = gimple_omp_task_clauses (task_stmt); c; c = OMP_CLAUSE_CHAIN (c))
15488 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15489 {
15490 tree ind, ptr, df;
15491
15492 decl = OMP_CLAUSE_DECL (c);
15493 if (!is_variable_sized (decl))
15494 continue;
15495 n = splay_tree_lookup (ctx->field_map, (splay_tree_key) decl);
15496 if (n == NULL)
15497 continue;
15498 f = (tree) n->value;
15499 f = *tcctx.cb.decl_map->get (f);
15500 gcc_assert (DECL_HAS_VALUE_EXPR_P (decl));
15501 ind = DECL_VALUE_EXPR (decl);
15502 gcc_assert (TREE_CODE (ind) == INDIRECT_REF);
15503 gcc_assert (DECL_P (TREE_OPERAND (ind, 0)));
15504 n = splay_tree_lookup (ctx->sfield_map,
15505 (splay_tree_key) TREE_OPERAND (ind, 0));
15506 sf = (tree) n->value;
15507 sf = *tcctx.cb.decl_map->get (sf);
15508 src = build_simple_mem_ref_loc (loc, sarg);
15509 src = omp_build_component_ref (src, sf);
15510 src = build_simple_mem_ref_loc (loc, src);
15511 dst = build_simple_mem_ref_loc (loc, arg);
15512 dst = omp_build_component_ref (dst, f);
15513 t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src);
15514 append_to_statement_list (t, &list);
15515 n = splay_tree_lookup (ctx->field_map,
15516 (splay_tree_key) TREE_OPERAND (ind, 0));
15517 df = (tree) n->value;
15518 df = *tcctx.cb.decl_map->get (df);
15519 ptr = build_simple_mem_ref_loc (loc, arg);
15520 ptr = omp_build_component_ref (ptr, df);
15521 t = build2 (MODIFY_EXPR, TREE_TYPE (ptr), ptr,
15522 build_fold_addr_expr_loc (loc, dst));
15523 append_to_statement_list (t, &list);
15524 }
15525
15526 t = build1 (RETURN_EXPR, void_type_node, NULL);
15527 append_to_statement_list (t, &list);
15528
15529 if (tcctx.cb.decl_map)
15530 delete tcctx.cb.decl_map;
15531 pop_gimplify_context (NULL);
15532 BIND_EXPR_BODY (bind) = list;
15533 pop_cfun ();
15534 }
15535
15536 static void
15537 lower_depend_clauses (tree *pclauses, gimple_seq *iseq, gimple_seq *oseq)
15538 {
15539 tree c, clauses;
15540 gimple *g;
15541 size_t n_in = 0, n_out = 0, idx = 2, i;
15542
15543 clauses = find_omp_clause (*pclauses, OMP_CLAUSE_DEPEND);
15544 gcc_assert (clauses);
15545 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15546 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND)
15547 switch (OMP_CLAUSE_DEPEND_KIND (c))
15548 {
15549 case OMP_CLAUSE_DEPEND_IN:
15550 n_in++;
15551 break;
15552 case OMP_CLAUSE_DEPEND_OUT:
15553 case OMP_CLAUSE_DEPEND_INOUT:
15554 n_out++;
15555 break;
15556 case OMP_CLAUSE_DEPEND_SOURCE:
15557 case OMP_CLAUSE_DEPEND_SINK:
15558 /* FALLTHRU */
15559 default:
15560 gcc_unreachable ();
15561 }
15562 tree type = build_array_type_nelts (ptr_type_node, n_in + n_out + 2);
15563 tree array = create_tmp_var (type);
15564 TREE_ADDRESSABLE (array) = 1;
15565 tree r = build4 (ARRAY_REF, ptr_type_node, array, size_int (0), NULL_TREE,
15566 NULL_TREE);
15567 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_in + n_out));
15568 gimple_seq_add_stmt (iseq, g);
15569 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (1), NULL_TREE,
15570 NULL_TREE);
15571 g = gimple_build_assign (r, build_int_cst (ptr_type_node, n_out));
15572 gimple_seq_add_stmt (iseq, g);
15573 for (i = 0; i < 2; i++)
15574 {
15575 if ((i ? n_in : n_out) == 0)
15576 continue;
15577 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
15578 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
15579 && ((OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_IN) ^ i))
15580 {
15581 tree t = OMP_CLAUSE_DECL (c);
15582 t = fold_convert (ptr_type_node, t);
15583 gimplify_expr (&t, iseq, NULL, is_gimple_val, fb_rvalue);
15584 r = build4 (ARRAY_REF, ptr_type_node, array, size_int (idx++),
15585 NULL_TREE, NULL_TREE);
15586 g = gimple_build_assign (r, t);
15587 gimple_seq_add_stmt (iseq, g);
15588 }
15589 }
15590 c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEPEND);
15591 OMP_CLAUSE_DECL (c) = build_fold_addr_expr (array);
15592 OMP_CLAUSE_CHAIN (c) = *pclauses;
15593 *pclauses = c;
15594 tree clobber = build_constructor (type, NULL);
15595 TREE_THIS_VOLATILE (clobber) = 1;
15596 g = gimple_build_assign (array, clobber);
15597 gimple_seq_add_stmt (oseq, g);
15598 }
15599
15600 /* Lower the OpenMP parallel or task directive in the current statement
15601 in GSI_P. CTX holds context information for the directive. */
15602
15603 static void
15604 lower_omp_taskreg (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15605 {
15606 tree clauses;
15607 tree child_fn, t;
15608 gimple *stmt = gsi_stmt (*gsi_p);
15609 gbind *par_bind, *bind, *dep_bind = NULL;
15610 gimple_seq par_body, olist, ilist, par_olist, par_rlist, par_ilist, new_body;
15611 location_t loc = gimple_location (stmt);
15612
15613 clauses = gimple_omp_taskreg_clauses (stmt);
15614 par_bind
15615 = as_a <gbind *> (gimple_seq_first_stmt (gimple_omp_body (stmt)));
15616 par_body = gimple_bind_body (par_bind);
15617 child_fn = ctx->cb.dst_fn;
15618 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15619 && !gimple_omp_parallel_combined_p (stmt))
15620 {
15621 struct walk_stmt_info wi;
15622 int ws_num = 0;
15623
15624 memset (&wi, 0, sizeof (wi));
15625 wi.info = &ws_num;
15626 wi.val_only = true;
15627 walk_gimple_seq (par_body, check_combined_parallel, NULL, &wi);
15628 if (ws_num == 1)
15629 gimple_omp_parallel_set_combined_p (stmt, true);
15630 }
15631 gimple_seq dep_ilist = NULL;
15632 gimple_seq dep_olist = NULL;
15633 if (gimple_code (stmt) == GIMPLE_OMP_TASK
15634 && find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15635 {
15636 push_gimplify_context ();
15637 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15638 lower_depend_clauses (gimple_omp_task_clauses_ptr (stmt),
15639 &dep_ilist, &dep_olist);
15640 }
15641
15642 if (ctx->srecord_type)
15643 create_task_copyfn (as_a <gomp_task *> (stmt), ctx);
15644
15645 push_gimplify_context ();
15646
15647 par_olist = NULL;
15648 par_ilist = NULL;
15649 par_rlist = NULL;
15650 bool phony_construct = gimple_code (stmt) == GIMPLE_OMP_PARALLEL
15651 && gimple_omp_parallel_grid_phony (as_a <gomp_parallel *> (stmt));
15652 if (phony_construct && ctx->record_type)
15653 {
15654 gcc_checking_assert (!ctx->receiver_decl);
15655 ctx->receiver_decl = create_tmp_var
15656 (build_reference_type (ctx->record_type), ".omp_rec");
15657 }
15658 lower_rec_input_clauses (clauses, &par_ilist, &par_olist, ctx, NULL);
15659 lower_omp (&par_body, ctx);
15660 if (gimple_code (stmt) == GIMPLE_OMP_PARALLEL)
15661 lower_reduction_clauses (clauses, &par_rlist, ctx);
15662
15663 /* Declare all the variables created by mapping and the variables
15664 declared in the scope of the parallel body. */
15665 record_vars_into (ctx->block_vars, child_fn);
15666 record_vars_into (gimple_bind_vars (par_bind), child_fn);
15667
15668 if (ctx->record_type)
15669 {
15670 ctx->sender_decl
15671 = create_tmp_var (ctx->srecord_type ? ctx->srecord_type
15672 : ctx->record_type, ".omp_data_o");
15673 DECL_NAMELESS (ctx->sender_decl) = 1;
15674 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
15675 gimple_omp_taskreg_set_data_arg (stmt, ctx->sender_decl);
15676 }
15677
15678 olist = NULL;
15679 ilist = NULL;
15680 lower_send_clauses (clauses, &ilist, &olist, ctx);
15681 lower_send_shared_vars (&ilist, &olist, ctx);
15682
15683 if (ctx->record_type)
15684 {
15685 tree clobber = build_constructor (TREE_TYPE (ctx->sender_decl), NULL);
15686 TREE_THIS_VOLATILE (clobber) = 1;
15687 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
15688 clobber));
15689 }
15690
15691 /* Once all the expansions are done, sequence all the different
15692 fragments inside gimple_omp_body. */
15693
15694 new_body = NULL;
15695
15696 if (ctx->record_type)
15697 {
15698 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
15699 /* fixup_child_record_type might have changed receiver_decl's type. */
15700 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
15701 gimple_seq_add_stmt (&new_body,
15702 gimple_build_assign (ctx->receiver_decl, t));
15703 }
15704
15705 gimple_seq_add_seq (&new_body, par_ilist);
15706 gimple_seq_add_seq (&new_body, par_body);
15707 gimple_seq_add_seq (&new_body, par_rlist);
15708 if (ctx->cancellable)
15709 gimple_seq_add_stmt (&new_body, gimple_build_label (ctx->cancel_label));
15710 gimple_seq_add_seq (&new_body, par_olist);
15711 new_body = maybe_catch_exception (new_body);
15712 if (gimple_code (stmt) == GIMPLE_OMP_TASK)
15713 gimple_seq_add_stmt (&new_body,
15714 gimple_build_omp_continue (integer_zero_node,
15715 integer_zero_node));
15716 if (!phony_construct)
15717 {
15718 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
15719 gimple_omp_set_body (stmt, new_body);
15720 }
15721
15722 bind = gimple_build_bind (NULL, NULL, gimple_bind_block (par_bind));
15723 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
15724 gimple_bind_add_seq (bind, ilist);
15725 if (!phony_construct)
15726 gimple_bind_add_stmt (bind, stmt);
15727 else
15728 gimple_bind_add_seq (bind, new_body);
15729 gimple_bind_add_seq (bind, olist);
15730
15731 pop_gimplify_context (NULL);
15732
15733 if (dep_bind)
15734 {
15735 gimple_bind_add_seq (dep_bind, dep_ilist);
15736 gimple_bind_add_stmt (dep_bind, bind);
15737 gimple_bind_add_seq (dep_bind, dep_olist);
15738 pop_gimplify_context (dep_bind);
15739 }
15740 }
15741
15742 /* Lower the GIMPLE_OMP_TARGET in the current statement
15743 in GSI_P. CTX holds context information for the directive. */
15744
15745 static void
15746 lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx)
15747 {
15748 tree clauses;
15749 tree child_fn, t, c;
15750 gomp_target *stmt = as_a <gomp_target *> (gsi_stmt (*gsi_p));
15751 gbind *tgt_bind, *bind, *dep_bind = NULL;
15752 gimple_seq tgt_body, olist, ilist, fplist, new_body;
15753 location_t loc = gimple_location (stmt);
15754 bool offloaded, data_region;
15755 unsigned int map_cnt = 0;
15756
15757 offloaded = is_gimple_omp_offloaded (stmt);
15758 switch (gimple_omp_target_kind (stmt))
15759 {
15760 case GF_OMP_TARGET_KIND_REGION:
15761 case GF_OMP_TARGET_KIND_UPDATE:
15762 case GF_OMP_TARGET_KIND_ENTER_DATA:
15763 case GF_OMP_TARGET_KIND_EXIT_DATA:
15764 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
15765 case GF_OMP_TARGET_KIND_OACC_KERNELS:
15766 case GF_OMP_TARGET_KIND_OACC_UPDATE:
15767 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
15768 case GF_OMP_TARGET_KIND_OACC_DECLARE:
15769 data_region = false;
15770 break;
15771 case GF_OMP_TARGET_KIND_DATA:
15772 case GF_OMP_TARGET_KIND_OACC_DATA:
15773 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
15774 data_region = true;
15775 break;
15776 default:
15777 gcc_unreachable ();
15778 }
15779
15780 clauses = gimple_omp_target_clauses (stmt);
15781
15782 gimple_seq dep_ilist = NULL;
15783 gimple_seq dep_olist = NULL;
15784 if (find_omp_clause (clauses, OMP_CLAUSE_DEPEND))
15785 {
15786 push_gimplify_context ();
15787 dep_bind = gimple_build_bind (NULL, NULL, make_node (BLOCK));
15788 lower_depend_clauses (gimple_omp_target_clauses_ptr (stmt),
15789 &dep_ilist, &dep_olist);
15790 }
15791
15792 tgt_bind = NULL;
15793 tgt_body = NULL;
15794 if (offloaded)
15795 {
15796 tgt_bind = gimple_seq_first_stmt_as_a_bind (gimple_omp_body (stmt));
15797 tgt_body = gimple_bind_body (tgt_bind);
15798 }
15799 else if (data_region)
15800 tgt_body = gimple_omp_body (stmt);
15801 child_fn = ctx->cb.dst_fn;
15802
15803 push_gimplify_context ();
15804 fplist = NULL;
15805
15806 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
15807 switch (OMP_CLAUSE_CODE (c))
15808 {
15809 tree var, x;
15810
15811 default:
15812 break;
15813 case OMP_CLAUSE_MAP:
15814 #if CHECKING_P
15815 /* First check what we're prepared to handle in the following. */
15816 switch (OMP_CLAUSE_MAP_KIND (c))
15817 {
15818 case GOMP_MAP_ALLOC:
15819 case GOMP_MAP_TO:
15820 case GOMP_MAP_FROM:
15821 case GOMP_MAP_TOFROM:
15822 case GOMP_MAP_POINTER:
15823 case GOMP_MAP_TO_PSET:
15824 case GOMP_MAP_DELETE:
15825 case GOMP_MAP_RELEASE:
15826 case GOMP_MAP_ALWAYS_TO:
15827 case GOMP_MAP_ALWAYS_FROM:
15828 case GOMP_MAP_ALWAYS_TOFROM:
15829 case GOMP_MAP_FIRSTPRIVATE_POINTER:
15830 case GOMP_MAP_FIRSTPRIVATE_REFERENCE:
15831 case GOMP_MAP_STRUCT:
15832 case GOMP_MAP_ALWAYS_POINTER:
15833 break;
15834 case GOMP_MAP_FORCE_ALLOC:
15835 case GOMP_MAP_FORCE_TO:
15836 case GOMP_MAP_FORCE_FROM:
15837 case GOMP_MAP_FORCE_TOFROM:
15838 case GOMP_MAP_FORCE_PRESENT:
15839 case GOMP_MAP_FORCE_DEVICEPTR:
15840 case GOMP_MAP_DEVICE_RESIDENT:
15841 case GOMP_MAP_LINK:
15842 gcc_assert (is_gimple_omp_oacc (stmt));
15843 break;
15844 default:
15845 gcc_unreachable ();
15846 }
15847 #endif
15848 /* FALLTHRU */
15849 case OMP_CLAUSE_TO:
15850 case OMP_CLAUSE_FROM:
15851 oacc_firstprivate:
15852 var = OMP_CLAUSE_DECL (c);
15853 if (!DECL_P (var))
15854 {
15855 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP
15856 || (!OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15857 && (OMP_CLAUSE_MAP_KIND (c)
15858 != GOMP_MAP_FIRSTPRIVATE_POINTER)))
15859 map_cnt++;
15860 continue;
15861 }
15862
15863 if (DECL_SIZE (var)
15864 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
15865 {
15866 tree var2 = DECL_VALUE_EXPR (var);
15867 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
15868 var2 = TREE_OPERAND (var2, 0);
15869 gcc_assert (DECL_P (var2));
15870 var = var2;
15871 }
15872
15873 if (offloaded
15874 && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15875 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
15876 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE))
15877 {
15878 if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15879 {
15880 if (is_global_var (maybe_lookup_decl_in_outer_ctx (var, ctx))
15881 && varpool_node::get_create (var)->offloadable)
15882 continue;
15883
15884 tree type = build_pointer_type (TREE_TYPE (var));
15885 tree new_var = lookup_decl (var, ctx);
15886 x = create_tmp_var_raw (type, get_name (new_var));
15887 gimple_add_tmp_var (x);
15888 x = build_simple_mem_ref (x);
15889 SET_DECL_VALUE_EXPR (new_var, x);
15890 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15891 }
15892 continue;
15893 }
15894
15895 if (!maybe_lookup_field (var, ctx))
15896 continue;
15897
15898 /* Don't remap oacc parallel reduction variables, because the
15899 intermediate result must be local to each gang. */
15900 if (offloaded && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15901 && OMP_CLAUSE_MAP_IN_REDUCTION (c)))
15902 {
15903 x = build_receiver_ref (var, true, ctx);
15904 tree new_var = lookup_decl (var, ctx);
15905
15906 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
15907 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
15908 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
15909 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
15910 x = build_simple_mem_ref (x);
15911 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
15912 {
15913 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
15914 if (is_reference (new_var))
15915 {
15916 /* Create a local object to hold the instance
15917 value. */
15918 tree type = TREE_TYPE (TREE_TYPE (new_var));
15919 const char *id = IDENTIFIER_POINTER (DECL_NAME (new_var));
15920 tree inst = create_tmp_var (type, id);
15921 gimplify_assign (inst, fold_indirect_ref (x), &fplist);
15922 x = build_fold_addr_expr (inst);
15923 }
15924 gimplify_assign (new_var, x, &fplist);
15925 }
15926 else if (DECL_P (new_var))
15927 {
15928 SET_DECL_VALUE_EXPR (new_var, x);
15929 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15930 }
15931 else
15932 gcc_unreachable ();
15933 }
15934 map_cnt++;
15935 break;
15936
15937 case OMP_CLAUSE_FIRSTPRIVATE:
15938 if (is_oacc_parallel (ctx))
15939 goto oacc_firstprivate;
15940 map_cnt++;
15941 var = OMP_CLAUSE_DECL (c);
15942 if (!is_reference (var)
15943 && !is_gimple_reg_type (TREE_TYPE (var)))
15944 {
15945 tree new_var = lookup_decl (var, ctx);
15946 if (is_variable_sized (var))
15947 {
15948 tree pvar = DECL_VALUE_EXPR (var);
15949 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15950 pvar = TREE_OPERAND (pvar, 0);
15951 gcc_assert (DECL_P (pvar));
15952 tree new_pvar = lookup_decl (pvar, ctx);
15953 x = build_fold_indirect_ref (new_pvar);
15954 TREE_THIS_NOTRAP (x) = 1;
15955 }
15956 else
15957 x = build_receiver_ref (var, true, ctx);
15958 SET_DECL_VALUE_EXPR (new_var, x);
15959 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15960 }
15961 break;
15962
15963 case OMP_CLAUSE_PRIVATE:
15964 if (is_gimple_omp_oacc (ctx->stmt))
15965 break;
15966 var = OMP_CLAUSE_DECL (c);
15967 if (is_variable_sized (var))
15968 {
15969 tree new_var = lookup_decl (var, ctx);
15970 tree pvar = DECL_VALUE_EXPR (var);
15971 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15972 pvar = TREE_OPERAND (pvar, 0);
15973 gcc_assert (DECL_P (pvar));
15974 tree new_pvar = lookup_decl (pvar, ctx);
15975 x = build_fold_indirect_ref (new_pvar);
15976 TREE_THIS_NOTRAP (x) = 1;
15977 SET_DECL_VALUE_EXPR (new_var, x);
15978 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15979 }
15980 break;
15981
15982 case OMP_CLAUSE_USE_DEVICE_PTR:
15983 case OMP_CLAUSE_IS_DEVICE_PTR:
15984 var = OMP_CLAUSE_DECL (c);
15985 map_cnt++;
15986 if (is_variable_sized (var))
15987 {
15988 tree new_var = lookup_decl (var, ctx);
15989 tree pvar = DECL_VALUE_EXPR (var);
15990 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
15991 pvar = TREE_OPERAND (pvar, 0);
15992 gcc_assert (DECL_P (pvar));
15993 tree new_pvar = lookup_decl (pvar, ctx);
15994 x = build_fold_indirect_ref (new_pvar);
15995 TREE_THIS_NOTRAP (x) = 1;
15996 SET_DECL_VALUE_EXPR (new_var, x);
15997 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
15998 }
15999 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16000 {
16001 tree new_var = lookup_decl (var, ctx);
16002 tree type = build_pointer_type (TREE_TYPE (var));
16003 x = create_tmp_var_raw (type, get_name (new_var));
16004 gimple_add_tmp_var (x);
16005 x = build_simple_mem_ref (x);
16006 SET_DECL_VALUE_EXPR (new_var, x);
16007 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
16008 }
16009 else
16010 {
16011 tree new_var = lookup_decl (var, ctx);
16012 x = create_tmp_var_raw (TREE_TYPE (new_var), get_name (new_var));
16013 gimple_add_tmp_var (x);
16014 SET_DECL_VALUE_EXPR (new_var, x);
16015 DECL_HAS_VALUE_EXPR_P (new_var) = 1;
16016 }
16017 break;
16018 }
16019
16020 if (offloaded)
16021 {
16022 target_nesting_level++;
16023 lower_omp (&tgt_body, ctx);
16024 target_nesting_level--;
16025 }
16026 else if (data_region)
16027 lower_omp (&tgt_body, ctx);
16028
16029 if (offloaded)
16030 {
16031 /* Declare all the variables created by mapping and the variables
16032 declared in the scope of the target body. */
16033 record_vars_into (ctx->block_vars, child_fn);
16034 record_vars_into (gimple_bind_vars (tgt_bind), child_fn);
16035 }
16036
16037 olist = NULL;
16038 ilist = NULL;
16039 if (ctx->record_type)
16040 {
16041 ctx->sender_decl
16042 = create_tmp_var (ctx->record_type, ".omp_data_arr");
16043 DECL_NAMELESS (ctx->sender_decl) = 1;
16044 TREE_ADDRESSABLE (ctx->sender_decl) = 1;
16045 t = make_tree_vec (3);
16046 TREE_VEC_ELT (t, 0) = ctx->sender_decl;
16047 TREE_VEC_ELT (t, 1)
16048 = create_tmp_var (build_array_type_nelts (size_type_node, map_cnt),
16049 ".omp_data_sizes");
16050 DECL_NAMELESS (TREE_VEC_ELT (t, 1)) = 1;
16051 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 1)) = 1;
16052 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 1;
16053 tree tkind_type = short_unsigned_type_node;
16054 int talign_shift = 8;
16055 TREE_VEC_ELT (t, 2)
16056 = create_tmp_var (build_array_type_nelts (tkind_type, map_cnt),
16057 ".omp_data_kinds");
16058 DECL_NAMELESS (TREE_VEC_ELT (t, 2)) = 1;
16059 TREE_ADDRESSABLE (TREE_VEC_ELT (t, 2)) = 1;
16060 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 1;
16061 gimple_omp_target_set_data_arg (stmt, t);
16062
16063 vec<constructor_elt, va_gc> *vsize;
16064 vec<constructor_elt, va_gc> *vkind;
16065 vec_alloc (vsize, map_cnt);
16066 vec_alloc (vkind, map_cnt);
16067 unsigned int map_idx = 0;
16068
16069 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16070 switch (OMP_CLAUSE_CODE (c))
16071 {
16072 tree ovar, nc, s, purpose, var, x, type;
16073 unsigned int talign;
16074
16075 default:
16076 break;
16077
16078 case OMP_CLAUSE_MAP:
16079 case OMP_CLAUSE_TO:
16080 case OMP_CLAUSE_FROM:
16081 oacc_firstprivate_map:
16082 nc = c;
16083 ovar = OMP_CLAUSE_DECL (c);
16084 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16085 && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16086 || (OMP_CLAUSE_MAP_KIND (c)
16087 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16088 break;
16089 if (!DECL_P (ovar))
16090 {
16091 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16092 && OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c))
16093 {
16094 gcc_checking_assert (OMP_CLAUSE_DECL (OMP_CLAUSE_CHAIN (c))
16095 == get_base_address (ovar));
16096 nc = OMP_CLAUSE_CHAIN (c);
16097 ovar = OMP_CLAUSE_DECL (nc);
16098 }
16099 else
16100 {
16101 tree x = build_sender_ref (ovar, ctx);
16102 tree v
16103 = build_fold_addr_expr_with_type (ovar, ptr_type_node);
16104 gimplify_assign (x, v, &ilist);
16105 nc = NULL_TREE;
16106 }
16107 }
16108 else
16109 {
16110 if (DECL_SIZE (ovar)
16111 && TREE_CODE (DECL_SIZE (ovar)) != INTEGER_CST)
16112 {
16113 tree ovar2 = DECL_VALUE_EXPR (ovar);
16114 gcc_assert (TREE_CODE (ovar2) == INDIRECT_REF);
16115 ovar2 = TREE_OPERAND (ovar2, 0);
16116 gcc_assert (DECL_P (ovar2));
16117 ovar = ovar2;
16118 }
16119 if (!maybe_lookup_field (ovar, ctx))
16120 continue;
16121 }
16122
16123 talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar));
16124 if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign)
16125 talign = DECL_ALIGN_UNIT (ovar);
16126 if (nc)
16127 {
16128 var = lookup_decl_in_outer_ctx (ovar, ctx);
16129 x = build_sender_ref (ovar, ctx);
16130
16131 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
16132 && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER
16133 && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)
16134 && TREE_CODE (TREE_TYPE (ovar)) == ARRAY_TYPE)
16135 {
16136 gcc_assert (offloaded);
16137 tree avar
16138 = create_tmp_var (TREE_TYPE (TREE_TYPE (x)));
16139 mark_addressable (avar);
16140 gimplify_assign (avar, build_fold_addr_expr (var), &ilist);
16141 talign = DECL_ALIGN_UNIT (avar);
16142 avar = build_fold_addr_expr (avar);
16143 gimplify_assign (x, avar, &ilist);
16144 }
16145 else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16146 {
16147 gcc_assert (is_gimple_omp_oacc (ctx->stmt));
16148 if (!is_reference (var))
16149 {
16150 if (is_gimple_reg (var)
16151 && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16152 TREE_NO_WARNING (var) = 1;
16153 var = build_fold_addr_expr (var);
16154 }
16155 else
16156 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16157 gimplify_assign (x, var, &ilist);
16158 }
16159 else if (is_gimple_reg (var))
16160 {
16161 gcc_assert (offloaded);
16162 tree avar = create_tmp_var (TREE_TYPE (var));
16163 mark_addressable (avar);
16164 enum gomp_map_kind map_kind = OMP_CLAUSE_MAP_KIND (c);
16165 if (GOMP_MAP_COPY_TO_P (map_kind)
16166 || map_kind == GOMP_MAP_POINTER
16167 || map_kind == GOMP_MAP_TO_PSET
16168 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16169 {
16170 /* If we need to initialize a temporary
16171 with VAR because it is not addressable, and
16172 the variable hasn't been initialized yet, then
16173 we'll get a warning for the store to avar.
16174 Don't warn in that case, the mapping might
16175 be implicit. */
16176 TREE_NO_WARNING (var) = 1;
16177 gimplify_assign (avar, var, &ilist);
16178 }
16179 avar = build_fold_addr_expr (avar);
16180 gimplify_assign (x, avar, &ilist);
16181 if ((GOMP_MAP_COPY_FROM_P (map_kind)
16182 || map_kind == GOMP_MAP_FORCE_DEVICEPTR)
16183 && !TYPE_READONLY (TREE_TYPE (var)))
16184 {
16185 x = unshare_expr (x);
16186 x = build_simple_mem_ref (x);
16187 gimplify_assign (var, x, &olist);
16188 }
16189 }
16190 else
16191 {
16192 var = build_fold_addr_expr (var);
16193 gimplify_assign (x, var, &ilist);
16194 }
16195 }
16196 s = NULL_TREE;
16197 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE)
16198 {
16199 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16200 s = TREE_TYPE (ovar);
16201 if (TREE_CODE (s) == REFERENCE_TYPE)
16202 s = TREE_TYPE (s);
16203 s = TYPE_SIZE_UNIT (s);
16204 }
16205 else
16206 s = OMP_CLAUSE_SIZE (c);
16207 if (s == NULL_TREE)
16208 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16209 s = fold_convert (size_type_node, s);
16210 purpose = size_int (map_idx++);
16211 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16212 if (TREE_CODE (s) != INTEGER_CST)
16213 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16214
16215 unsigned HOST_WIDE_INT tkind, tkind_zero;
16216 switch (OMP_CLAUSE_CODE (c))
16217 {
16218 case OMP_CLAUSE_MAP:
16219 tkind = OMP_CLAUSE_MAP_KIND (c);
16220 tkind_zero = tkind;
16221 if (OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c))
16222 switch (tkind)
16223 {
16224 case GOMP_MAP_ALLOC:
16225 case GOMP_MAP_TO:
16226 case GOMP_MAP_FROM:
16227 case GOMP_MAP_TOFROM:
16228 case GOMP_MAP_ALWAYS_TO:
16229 case GOMP_MAP_ALWAYS_FROM:
16230 case GOMP_MAP_ALWAYS_TOFROM:
16231 case GOMP_MAP_RELEASE:
16232 case GOMP_MAP_FORCE_TO:
16233 case GOMP_MAP_FORCE_FROM:
16234 case GOMP_MAP_FORCE_TOFROM:
16235 case GOMP_MAP_FORCE_PRESENT:
16236 tkind_zero = GOMP_MAP_ZERO_LEN_ARRAY_SECTION;
16237 break;
16238 case GOMP_MAP_DELETE:
16239 tkind_zero = GOMP_MAP_DELETE_ZERO_LEN_ARRAY_SECTION;
16240 default:
16241 break;
16242 }
16243 if (tkind_zero != tkind)
16244 {
16245 if (integer_zerop (s))
16246 tkind = tkind_zero;
16247 else if (integer_nonzerop (s))
16248 tkind_zero = tkind;
16249 }
16250 break;
16251 case OMP_CLAUSE_FIRSTPRIVATE:
16252 gcc_checking_assert (is_gimple_omp_oacc (ctx->stmt));
16253 tkind = GOMP_MAP_TO;
16254 tkind_zero = tkind;
16255 break;
16256 case OMP_CLAUSE_TO:
16257 tkind = GOMP_MAP_TO;
16258 tkind_zero = tkind;
16259 break;
16260 case OMP_CLAUSE_FROM:
16261 tkind = GOMP_MAP_FROM;
16262 tkind_zero = tkind;
16263 break;
16264 default:
16265 gcc_unreachable ();
16266 }
16267 gcc_checking_assert (tkind
16268 < (HOST_WIDE_INT_C (1U) << talign_shift));
16269 gcc_checking_assert (tkind_zero
16270 < (HOST_WIDE_INT_C (1U) << talign_shift));
16271 talign = ceil_log2 (talign);
16272 tkind |= talign << talign_shift;
16273 tkind_zero |= talign << talign_shift;
16274 gcc_checking_assert (tkind
16275 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16276 gcc_checking_assert (tkind_zero
16277 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16278 if (tkind == tkind_zero)
16279 x = build_int_cstu (tkind_type, tkind);
16280 else
16281 {
16282 TREE_STATIC (TREE_VEC_ELT (t, 2)) = 0;
16283 x = build3 (COND_EXPR, tkind_type,
16284 fold_build2 (EQ_EXPR, boolean_type_node,
16285 unshare_expr (s), size_zero_node),
16286 build_int_cstu (tkind_type, tkind_zero),
16287 build_int_cstu (tkind_type, tkind));
16288 }
16289 CONSTRUCTOR_APPEND_ELT (vkind, purpose, x);
16290 if (nc && nc != c)
16291 c = nc;
16292 break;
16293
16294 case OMP_CLAUSE_FIRSTPRIVATE:
16295 if (is_oacc_parallel (ctx))
16296 goto oacc_firstprivate_map;
16297 ovar = OMP_CLAUSE_DECL (c);
16298 if (is_reference (ovar))
16299 talign = TYPE_ALIGN_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16300 else
16301 talign = DECL_ALIGN_UNIT (ovar);
16302 var = lookup_decl_in_outer_ctx (ovar, ctx);
16303 x = build_sender_ref (ovar, ctx);
16304 tkind = GOMP_MAP_FIRSTPRIVATE;
16305 type = TREE_TYPE (ovar);
16306 if (is_reference (ovar))
16307 type = TREE_TYPE (type);
16308 if ((INTEGRAL_TYPE_P (type)
16309 && TYPE_PRECISION (type) <= POINTER_SIZE)
16310 || TREE_CODE (type) == POINTER_TYPE)
16311 {
16312 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16313 tree t = var;
16314 if (is_reference (var))
16315 t = build_simple_mem_ref (var);
16316 else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16317 TREE_NO_WARNING (var) = 1;
16318 if (TREE_CODE (type) != POINTER_TYPE)
16319 t = fold_convert (pointer_sized_int_node, t);
16320 t = fold_convert (TREE_TYPE (x), t);
16321 gimplify_assign (x, t, &ilist);
16322 }
16323 else if (is_reference (var))
16324 gimplify_assign (x, var, &ilist);
16325 else if (is_gimple_reg (var))
16326 {
16327 tree avar = create_tmp_var (TREE_TYPE (var));
16328 mark_addressable (avar);
16329 if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c))
16330 TREE_NO_WARNING (var) = 1;
16331 gimplify_assign (avar, var, &ilist);
16332 avar = build_fold_addr_expr (avar);
16333 gimplify_assign (x, avar, &ilist);
16334 }
16335 else
16336 {
16337 var = build_fold_addr_expr (var);
16338 gimplify_assign (x, var, &ilist);
16339 }
16340 if (tkind == GOMP_MAP_FIRSTPRIVATE_INT)
16341 s = size_int (0);
16342 else if (is_reference (var))
16343 s = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ovar)));
16344 else
16345 s = TYPE_SIZE_UNIT (TREE_TYPE (ovar));
16346 s = fold_convert (size_type_node, s);
16347 purpose = size_int (map_idx++);
16348 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16349 if (TREE_CODE (s) != INTEGER_CST)
16350 TREE_STATIC (TREE_VEC_ELT (t, 1)) = 0;
16351
16352 gcc_checking_assert (tkind
16353 < (HOST_WIDE_INT_C (1U) << talign_shift));
16354 talign = ceil_log2 (talign);
16355 tkind |= talign << talign_shift;
16356 gcc_checking_assert (tkind
16357 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16358 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16359 build_int_cstu (tkind_type, tkind));
16360 break;
16361
16362 case OMP_CLAUSE_USE_DEVICE_PTR:
16363 case OMP_CLAUSE_IS_DEVICE_PTR:
16364 ovar = OMP_CLAUSE_DECL (c);
16365 var = lookup_decl_in_outer_ctx (ovar, ctx);
16366 x = build_sender_ref (ovar, ctx);
16367 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16368 tkind = GOMP_MAP_USE_DEVICE_PTR;
16369 else
16370 tkind = GOMP_MAP_FIRSTPRIVATE_INT;
16371 type = TREE_TYPE (ovar);
16372 if (TREE_CODE (type) == ARRAY_TYPE)
16373 var = build_fold_addr_expr (var);
16374 else
16375 {
16376 if (is_reference (ovar))
16377 {
16378 type = TREE_TYPE (type);
16379 if (TREE_CODE (type) != ARRAY_TYPE)
16380 var = build_simple_mem_ref (var);
16381 var = fold_convert (TREE_TYPE (x), var);
16382 }
16383 }
16384 gimplify_assign (x, var, &ilist);
16385 s = size_int (0);
16386 purpose = size_int (map_idx++);
16387 CONSTRUCTOR_APPEND_ELT (vsize, purpose, s);
16388 gcc_checking_assert (tkind
16389 < (HOST_WIDE_INT_C (1U) << talign_shift));
16390 gcc_checking_assert (tkind
16391 <= tree_to_uhwi (TYPE_MAX_VALUE (tkind_type)));
16392 CONSTRUCTOR_APPEND_ELT (vkind, purpose,
16393 build_int_cstu (tkind_type, tkind));
16394 break;
16395 }
16396
16397 gcc_assert (map_idx == map_cnt);
16398
16399 DECL_INITIAL (TREE_VEC_ELT (t, 1))
16400 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 1)), vsize);
16401 DECL_INITIAL (TREE_VEC_ELT (t, 2))
16402 = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, 2)), vkind);
16403 for (int i = 1; i <= 2; i++)
16404 if (!TREE_STATIC (TREE_VEC_ELT (t, i)))
16405 {
16406 gimple_seq initlist = NULL;
16407 force_gimple_operand (build1 (DECL_EXPR, void_type_node,
16408 TREE_VEC_ELT (t, i)),
16409 &initlist, true, NULL_TREE);
16410 gimple_seq_add_seq (&ilist, initlist);
16411
16412 tree clobber = build_constructor (TREE_TYPE (TREE_VEC_ELT (t, i)),
16413 NULL);
16414 TREE_THIS_VOLATILE (clobber) = 1;
16415 gimple_seq_add_stmt (&olist,
16416 gimple_build_assign (TREE_VEC_ELT (t, i),
16417 clobber));
16418 }
16419
16420 tree clobber = build_constructor (ctx->record_type, NULL);
16421 TREE_THIS_VOLATILE (clobber) = 1;
16422 gimple_seq_add_stmt (&olist, gimple_build_assign (ctx->sender_decl,
16423 clobber));
16424 }
16425
16426 /* Once all the expansions are done, sequence all the different
16427 fragments inside gimple_omp_body. */
16428
16429 new_body = NULL;
16430
16431 if (offloaded
16432 && ctx->record_type)
16433 {
16434 t = build_fold_addr_expr_loc (loc, ctx->sender_decl);
16435 /* fixup_child_record_type might have changed receiver_decl's type. */
16436 t = fold_convert_loc (loc, TREE_TYPE (ctx->receiver_decl), t);
16437 gimple_seq_add_stmt (&new_body,
16438 gimple_build_assign (ctx->receiver_decl, t));
16439 }
16440 gimple_seq_add_seq (&new_body, fplist);
16441
16442 if (offloaded || data_region)
16443 {
16444 tree prev = NULL_TREE;
16445 for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
16446 switch (OMP_CLAUSE_CODE (c))
16447 {
16448 tree var, x;
16449 default:
16450 break;
16451 case OMP_CLAUSE_FIRSTPRIVATE:
16452 if (is_gimple_omp_oacc (ctx->stmt))
16453 break;
16454 var = OMP_CLAUSE_DECL (c);
16455 if (is_reference (var)
16456 || is_gimple_reg_type (TREE_TYPE (var)))
16457 {
16458 tree new_var = lookup_decl (var, ctx);
16459 tree type;
16460 type = TREE_TYPE (var);
16461 if (is_reference (var))
16462 type = TREE_TYPE (type);
16463 if ((INTEGRAL_TYPE_P (type)
16464 && TYPE_PRECISION (type) <= POINTER_SIZE)
16465 || TREE_CODE (type) == POINTER_TYPE)
16466 {
16467 x = build_receiver_ref (var, false, ctx);
16468 if (TREE_CODE (type) != POINTER_TYPE)
16469 x = fold_convert (pointer_sized_int_node, x);
16470 x = fold_convert (type, x);
16471 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16472 fb_rvalue);
16473 if (is_reference (var))
16474 {
16475 tree v = create_tmp_var_raw (type, get_name (var));
16476 gimple_add_tmp_var (v);
16477 TREE_ADDRESSABLE (v) = 1;
16478 gimple_seq_add_stmt (&new_body,
16479 gimple_build_assign (v, x));
16480 x = build_fold_addr_expr (v);
16481 }
16482 gimple_seq_add_stmt (&new_body,
16483 gimple_build_assign (new_var, x));
16484 }
16485 else
16486 {
16487 x = build_receiver_ref (var, !is_reference (var), ctx);
16488 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16489 fb_rvalue);
16490 gimple_seq_add_stmt (&new_body,
16491 gimple_build_assign (new_var, x));
16492 }
16493 }
16494 else if (is_variable_sized (var))
16495 {
16496 tree pvar = DECL_VALUE_EXPR (var);
16497 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16498 pvar = TREE_OPERAND (pvar, 0);
16499 gcc_assert (DECL_P (pvar));
16500 tree new_var = lookup_decl (pvar, ctx);
16501 x = build_receiver_ref (var, false, ctx);
16502 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16503 gimple_seq_add_stmt (&new_body,
16504 gimple_build_assign (new_var, x));
16505 }
16506 break;
16507 case OMP_CLAUSE_PRIVATE:
16508 if (is_gimple_omp_oacc (ctx->stmt))
16509 break;
16510 var = OMP_CLAUSE_DECL (c);
16511 if (is_reference (var))
16512 {
16513 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16514 tree new_var = lookup_decl (var, ctx);
16515 x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16516 if (TREE_CONSTANT (x))
16517 {
16518 x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)),
16519 get_name (var));
16520 gimple_add_tmp_var (x);
16521 TREE_ADDRESSABLE (x) = 1;
16522 x = build_fold_addr_expr_loc (clause_loc, x);
16523 }
16524 else
16525 break;
16526
16527 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16528 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16529 gimple_seq_add_stmt (&new_body,
16530 gimple_build_assign (new_var, x));
16531 }
16532 break;
16533 case OMP_CLAUSE_USE_DEVICE_PTR:
16534 case OMP_CLAUSE_IS_DEVICE_PTR:
16535 var = OMP_CLAUSE_DECL (c);
16536 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR)
16537 x = build_sender_ref (var, ctx);
16538 else
16539 x = build_receiver_ref (var, false, ctx);
16540 if (is_variable_sized (var))
16541 {
16542 tree pvar = DECL_VALUE_EXPR (var);
16543 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16544 pvar = TREE_OPERAND (pvar, 0);
16545 gcc_assert (DECL_P (pvar));
16546 tree new_var = lookup_decl (pvar, ctx);
16547 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16548 gimple_seq_add_stmt (&new_body,
16549 gimple_build_assign (new_var, x));
16550 }
16551 else if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
16552 {
16553 tree new_var = lookup_decl (var, ctx);
16554 new_var = DECL_VALUE_EXPR (new_var);
16555 gcc_assert (TREE_CODE (new_var) == MEM_REF);
16556 new_var = TREE_OPERAND (new_var, 0);
16557 gcc_assert (DECL_P (new_var));
16558 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16559 gimple_seq_add_stmt (&new_body,
16560 gimple_build_assign (new_var, x));
16561 }
16562 else
16563 {
16564 tree type = TREE_TYPE (var);
16565 tree new_var = lookup_decl (var, ctx);
16566 if (is_reference (var))
16567 {
16568 type = TREE_TYPE (type);
16569 if (TREE_CODE (type) != ARRAY_TYPE)
16570 {
16571 tree v = create_tmp_var_raw (type, get_name (var));
16572 gimple_add_tmp_var (v);
16573 TREE_ADDRESSABLE (v) = 1;
16574 x = fold_convert (type, x);
16575 gimplify_expr (&x, &new_body, NULL, is_gimple_val,
16576 fb_rvalue);
16577 gimple_seq_add_stmt (&new_body,
16578 gimple_build_assign (v, x));
16579 x = build_fold_addr_expr (v);
16580 }
16581 }
16582 new_var = DECL_VALUE_EXPR (new_var);
16583 x = fold_convert (TREE_TYPE (new_var), x);
16584 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16585 gimple_seq_add_stmt (&new_body,
16586 gimple_build_assign (new_var, x));
16587 }
16588 break;
16589 }
16590 /* Handle GOMP_MAP_FIRSTPRIVATE_{POINTER,REFERENCE} in second pass,
16591 so that firstprivate vars holding OMP_CLAUSE_SIZE if needed
16592 are already handled. Similarly OMP_CLAUSE_PRIVATE for VLAs
16593 or references to VLAs. */
16594 for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
16595 switch (OMP_CLAUSE_CODE (c))
16596 {
16597 tree var;
16598 default:
16599 break;
16600 case OMP_CLAUSE_MAP:
16601 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER
16602 || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16603 {
16604 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16605 HOST_WIDE_INT offset = 0;
16606 gcc_assert (prev);
16607 var = OMP_CLAUSE_DECL (c);
16608 if (DECL_P (var)
16609 && TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE
16610 && is_global_var (maybe_lookup_decl_in_outer_ctx (var,
16611 ctx))
16612 && varpool_node::get_create (var)->offloadable)
16613 break;
16614 if (TREE_CODE (var) == INDIRECT_REF
16615 && TREE_CODE (TREE_OPERAND (var, 0)) == COMPONENT_REF)
16616 var = TREE_OPERAND (var, 0);
16617 if (TREE_CODE (var) == COMPONENT_REF)
16618 {
16619 var = get_addr_base_and_unit_offset (var, &offset);
16620 gcc_assert (var != NULL_TREE && DECL_P (var));
16621 }
16622 else if (DECL_SIZE (var)
16623 && TREE_CODE (DECL_SIZE (var)) != INTEGER_CST)
16624 {
16625 tree var2 = DECL_VALUE_EXPR (var);
16626 gcc_assert (TREE_CODE (var2) == INDIRECT_REF);
16627 var2 = TREE_OPERAND (var2, 0);
16628 gcc_assert (DECL_P (var2));
16629 var = var2;
16630 }
16631 tree new_var = lookup_decl (var, ctx), x;
16632 tree type = TREE_TYPE (new_var);
16633 bool is_ref;
16634 if (TREE_CODE (OMP_CLAUSE_DECL (c)) == INDIRECT_REF
16635 && (TREE_CODE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0))
16636 == COMPONENT_REF))
16637 {
16638 type = TREE_TYPE (TREE_OPERAND (OMP_CLAUSE_DECL (c), 0));
16639 is_ref = true;
16640 new_var = build2 (MEM_REF, type,
16641 build_fold_addr_expr (new_var),
16642 build_int_cst (build_pointer_type (type),
16643 offset));
16644 }
16645 else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == COMPONENT_REF)
16646 {
16647 type = TREE_TYPE (OMP_CLAUSE_DECL (c));
16648 is_ref = TREE_CODE (type) == REFERENCE_TYPE;
16649 new_var = build2 (MEM_REF, type,
16650 build_fold_addr_expr (new_var),
16651 build_int_cst (build_pointer_type (type),
16652 offset));
16653 }
16654 else
16655 is_ref = is_reference (var);
16656 if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_REFERENCE)
16657 is_ref = false;
16658 bool ref_to_array = false;
16659 if (is_ref)
16660 {
16661 type = TREE_TYPE (type);
16662 if (TREE_CODE (type) == ARRAY_TYPE)
16663 {
16664 type = build_pointer_type (type);
16665 ref_to_array = true;
16666 }
16667 }
16668 else if (TREE_CODE (type) == ARRAY_TYPE)
16669 {
16670 tree decl2 = DECL_VALUE_EXPR (new_var);
16671 gcc_assert (TREE_CODE (decl2) == MEM_REF);
16672 decl2 = TREE_OPERAND (decl2, 0);
16673 gcc_assert (DECL_P (decl2));
16674 new_var = decl2;
16675 type = TREE_TYPE (new_var);
16676 }
16677 x = build_receiver_ref (OMP_CLAUSE_DECL (prev), false, ctx);
16678 x = fold_convert_loc (clause_loc, type, x);
16679 if (!integer_zerop (OMP_CLAUSE_SIZE (c)))
16680 {
16681 tree bias = OMP_CLAUSE_SIZE (c);
16682 if (DECL_P (bias))
16683 bias = lookup_decl (bias, ctx);
16684 bias = fold_convert_loc (clause_loc, sizetype, bias);
16685 bias = fold_build1_loc (clause_loc, NEGATE_EXPR, sizetype,
16686 bias);
16687 x = fold_build2_loc (clause_loc, POINTER_PLUS_EXPR,
16688 TREE_TYPE (x), x, bias);
16689 }
16690 if (ref_to_array)
16691 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16692 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16693 if (is_ref && !ref_to_array)
16694 {
16695 tree t = create_tmp_var_raw (type, get_name (var));
16696 gimple_add_tmp_var (t);
16697 TREE_ADDRESSABLE (t) = 1;
16698 gimple_seq_add_stmt (&new_body,
16699 gimple_build_assign (t, x));
16700 x = build_fold_addr_expr_loc (clause_loc, t);
16701 }
16702 gimple_seq_add_stmt (&new_body,
16703 gimple_build_assign (new_var, x));
16704 prev = NULL_TREE;
16705 }
16706 else if (OMP_CLAUSE_CHAIN (c)
16707 && OMP_CLAUSE_CODE (OMP_CLAUSE_CHAIN (c))
16708 == OMP_CLAUSE_MAP
16709 && (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16710 == GOMP_MAP_FIRSTPRIVATE_POINTER
16711 || (OMP_CLAUSE_MAP_KIND (OMP_CLAUSE_CHAIN (c))
16712 == GOMP_MAP_FIRSTPRIVATE_REFERENCE)))
16713 prev = c;
16714 break;
16715 case OMP_CLAUSE_PRIVATE:
16716 var = OMP_CLAUSE_DECL (c);
16717 if (is_variable_sized (var))
16718 {
16719 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16720 tree new_var = lookup_decl (var, ctx);
16721 tree pvar = DECL_VALUE_EXPR (var);
16722 gcc_assert (TREE_CODE (pvar) == INDIRECT_REF);
16723 pvar = TREE_OPERAND (pvar, 0);
16724 gcc_assert (DECL_P (pvar));
16725 tree new_pvar = lookup_decl (pvar, ctx);
16726 tree atmp = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16727 tree al = size_int (DECL_ALIGN (var));
16728 tree x = TYPE_SIZE_UNIT (TREE_TYPE (new_var));
16729 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16730 x = fold_convert_loc (clause_loc, TREE_TYPE (new_pvar), x);
16731 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16732 gimple_seq_add_stmt (&new_body,
16733 gimple_build_assign (new_pvar, x));
16734 }
16735 else if (is_reference (var) && !is_gimple_omp_oacc (ctx->stmt))
16736 {
16737 location_t clause_loc = OMP_CLAUSE_LOCATION (c);
16738 tree new_var = lookup_decl (var, ctx);
16739 tree x = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_var)));
16740 if (TREE_CONSTANT (x))
16741 break;
16742 else
16743 {
16744 tree atmp
16745 = builtin_decl_explicit (BUILT_IN_ALLOCA_WITH_ALIGN);
16746 tree rtype = TREE_TYPE (TREE_TYPE (new_var));
16747 tree al = size_int (TYPE_ALIGN (rtype));
16748 x = build_call_expr_loc (clause_loc, atmp, 2, x, al);
16749 }
16750
16751 x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x);
16752 gimplify_expr (&x, &new_body, NULL, is_gimple_val, fb_rvalue);
16753 gimple_seq_add_stmt (&new_body,
16754 gimple_build_assign (new_var, x));
16755 }
16756 break;
16757 }
16758
16759 gimple_seq fork_seq = NULL;
16760 gimple_seq join_seq = NULL;
16761
16762 if (is_oacc_parallel (ctx))
16763 {
16764 /* If there are reductions on the offloaded region itself, treat
16765 them as a dummy GANG loop. */
16766 tree level = build_int_cst (integer_type_node, GOMP_DIM_GANG);
16767
16768 lower_oacc_reductions (gimple_location (ctx->stmt), clauses, level,
16769 false, NULL, NULL, &fork_seq, &join_seq, ctx);
16770 }
16771
16772 gimple_seq_add_seq (&new_body, fork_seq);
16773 gimple_seq_add_seq (&new_body, tgt_body);
16774 gimple_seq_add_seq (&new_body, join_seq);
16775
16776 if (offloaded)
16777 new_body = maybe_catch_exception (new_body);
16778
16779 gimple_seq_add_stmt (&new_body, gimple_build_omp_return (false));
16780 gimple_omp_set_body (stmt, new_body);
16781 }
16782
16783 bind = gimple_build_bind (NULL, NULL,
16784 tgt_bind ? gimple_bind_block (tgt_bind)
16785 : NULL_TREE);
16786 gsi_replace (gsi_p, dep_bind ? dep_bind : bind, true);
16787 gimple_bind_add_seq (bind, ilist);
16788 gimple_bind_add_stmt (bind, stmt);
16789 gimple_bind_add_seq (bind, olist);
16790
16791 pop_gimplify_context (NULL);
16792
16793 if (dep_bind)
16794 {
16795 gimple_bind_add_seq (dep_bind, dep_ilist);
16796 gimple_bind_add_stmt (dep_bind, bind);
16797 gimple_bind_add_seq (dep_bind, dep_olist);
16798 pop_gimplify_context (dep_bind);
16799 }
16800 }
16801
16802 /* Expand code for an OpenMP teams directive. */
16803
16804 static void
16805 lower_omp_teams (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16806 {
16807 gomp_teams *teams_stmt = as_a <gomp_teams *> (gsi_stmt (*gsi_p));
16808 push_gimplify_context ();
16809
16810 tree block = make_node (BLOCK);
16811 gbind *bind = gimple_build_bind (NULL, NULL, block);
16812 gsi_replace (gsi_p, bind, true);
16813 gimple_seq bind_body = NULL;
16814 gimple_seq dlist = NULL;
16815 gimple_seq olist = NULL;
16816
16817 tree num_teams = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16818 OMP_CLAUSE_NUM_TEAMS);
16819 if (num_teams == NULL_TREE)
16820 num_teams = build_int_cst (unsigned_type_node, 0);
16821 else
16822 {
16823 num_teams = OMP_CLAUSE_NUM_TEAMS_EXPR (num_teams);
16824 num_teams = fold_convert (unsigned_type_node, num_teams);
16825 gimplify_expr (&num_teams, &bind_body, NULL, is_gimple_val, fb_rvalue);
16826 }
16827 tree thread_limit = find_omp_clause (gimple_omp_teams_clauses (teams_stmt),
16828 OMP_CLAUSE_THREAD_LIMIT);
16829 if (thread_limit == NULL_TREE)
16830 thread_limit = build_int_cst (unsigned_type_node, 0);
16831 else
16832 {
16833 thread_limit = OMP_CLAUSE_THREAD_LIMIT_EXPR (thread_limit);
16834 thread_limit = fold_convert (unsigned_type_node, thread_limit);
16835 gimplify_expr (&thread_limit, &bind_body, NULL, is_gimple_val,
16836 fb_rvalue);
16837 }
16838
16839 lower_rec_input_clauses (gimple_omp_teams_clauses (teams_stmt),
16840 &bind_body, &dlist, ctx, NULL);
16841 lower_omp (gimple_omp_body_ptr (teams_stmt), ctx);
16842 lower_reduction_clauses (gimple_omp_teams_clauses (teams_stmt), &olist, ctx);
16843 if (!gimple_omp_teams_grid_phony (teams_stmt))
16844 {
16845 gimple_seq_add_stmt (&bind_body, teams_stmt);
16846 location_t loc = gimple_location (teams_stmt);
16847 tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TEAMS);
16848 gimple *call = gimple_build_call (decl, 2, num_teams, thread_limit);
16849 gimple_set_location (call, loc);
16850 gimple_seq_add_stmt (&bind_body, call);
16851 }
16852
16853 gimple_seq_add_seq (&bind_body, gimple_omp_body (teams_stmt));
16854 gimple_omp_set_body (teams_stmt, NULL);
16855 gimple_seq_add_seq (&bind_body, olist);
16856 gimple_seq_add_seq (&bind_body, dlist);
16857 if (!gimple_omp_teams_grid_phony (teams_stmt))
16858 gimple_seq_add_stmt (&bind_body, gimple_build_omp_return (true));
16859 gimple_bind_set_body (bind, bind_body);
16860
16861 pop_gimplify_context (bind);
16862
16863 gimple_bind_append_vars (bind, ctx->block_vars);
16864 BLOCK_VARS (block) = ctx->block_vars;
16865 if (BLOCK_VARS (block))
16866 TREE_USED (block) = 1;
16867 }
16868
16869 /* Expand code within an artificial GIMPLE_OMP_GRID_BODY OMP construct. */
16870
16871 static void
16872 lower_omp_grid_body (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16873 {
16874 gimple *stmt = gsi_stmt (*gsi_p);
16875 lower_omp (gimple_omp_body_ptr (stmt), ctx);
16876 gimple_seq_add_stmt (gimple_omp_body_ptr (stmt),
16877 gimple_build_omp_return (false));
16878 }
16879
16880
16881 /* Callback for lower_omp_1. Return non-NULL if *tp needs to be
16882 regimplified. If DATA is non-NULL, lower_omp_1 is outside
16883 of OMP context, but with task_shared_vars set. */
16884
16885 static tree
16886 lower_omp_regimplify_p (tree *tp, int *walk_subtrees,
16887 void *data)
16888 {
16889 tree t = *tp;
16890
16891 /* Any variable with DECL_VALUE_EXPR needs to be regimplified. */
16892 if (VAR_P (t) && data == NULL && DECL_HAS_VALUE_EXPR_P (t))
16893 return t;
16894
16895 if (task_shared_vars
16896 && DECL_P (t)
16897 && bitmap_bit_p (task_shared_vars, DECL_UID (t)))
16898 return t;
16899
16900 /* If a global variable has been privatized, TREE_CONSTANT on
16901 ADDR_EXPR might be wrong. */
16902 if (data == NULL && TREE_CODE (t) == ADDR_EXPR)
16903 recompute_tree_invariant_for_addr_expr (t);
16904
16905 *walk_subtrees = !IS_TYPE_OR_DECL_P (t);
16906 return NULL_TREE;
16907 }
16908
16909 /* Data to be communicated between lower_omp_regimplify_operands and
16910 lower_omp_regimplify_operands_p. */
16911
16912 struct lower_omp_regimplify_operands_data
16913 {
16914 omp_context *ctx;
16915 vec<tree> *decls;
16916 };
16917
16918 /* Helper function for lower_omp_regimplify_operands. Find
16919 omp_member_access_dummy_var vars and adjust temporarily their
16920 DECL_VALUE_EXPRs if needed. */
16921
16922 static tree
16923 lower_omp_regimplify_operands_p (tree *tp, int *walk_subtrees,
16924 void *data)
16925 {
16926 tree t = omp_member_access_dummy_var (*tp);
16927 if (t)
16928 {
16929 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
16930 lower_omp_regimplify_operands_data *ldata
16931 = (lower_omp_regimplify_operands_data *) wi->info;
16932 tree o = maybe_lookup_decl (t, ldata->ctx);
16933 if (o != t)
16934 {
16935 ldata->decls->safe_push (DECL_VALUE_EXPR (*tp));
16936 ldata->decls->safe_push (*tp);
16937 tree v = unshare_and_remap (DECL_VALUE_EXPR (*tp), t, o);
16938 SET_DECL_VALUE_EXPR (*tp, v);
16939 }
16940 }
16941 *walk_subtrees = !IS_TYPE_OR_DECL_P (*tp);
16942 return NULL_TREE;
16943 }
16944
16945 /* Wrapper around gimple_regimplify_operands that adjusts DECL_VALUE_EXPRs
16946 of omp_member_access_dummy_var vars during regimplification. */
16947
16948 static void
16949 lower_omp_regimplify_operands (omp_context *ctx, gimple *stmt,
16950 gimple_stmt_iterator *gsi_p)
16951 {
16952 auto_vec<tree, 10> decls;
16953 if (ctx)
16954 {
16955 struct walk_stmt_info wi;
16956 memset (&wi, '\0', sizeof (wi));
16957 struct lower_omp_regimplify_operands_data data;
16958 data.ctx = ctx;
16959 data.decls = &decls;
16960 wi.info = &data;
16961 walk_gimple_op (stmt, lower_omp_regimplify_operands_p, &wi);
16962 }
16963 gimple_regimplify_operands (stmt, gsi_p);
16964 while (!decls.is_empty ())
16965 {
16966 tree t = decls.pop ();
16967 tree v = decls.pop ();
16968 SET_DECL_VALUE_EXPR (t, v);
16969 }
16970 }
16971
16972 static void
16973 lower_omp_1 (gimple_stmt_iterator *gsi_p, omp_context *ctx)
16974 {
16975 gimple *stmt = gsi_stmt (*gsi_p);
16976 struct walk_stmt_info wi;
16977 gcall *call_stmt;
16978
16979 if (gimple_has_location (stmt))
16980 input_location = gimple_location (stmt);
16981
16982 if (task_shared_vars)
16983 memset (&wi, '\0', sizeof (wi));
16984
16985 /* If we have issued syntax errors, avoid doing any heavy lifting.
16986 Just replace the OMP directives with a NOP to avoid
16987 confusing RTL expansion. */
16988 if (seen_error () && is_gimple_omp (stmt))
16989 {
16990 gsi_replace (gsi_p, gimple_build_nop (), true);
16991 return;
16992 }
16993
16994 switch (gimple_code (stmt))
16995 {
16996 case GIMPLE_COND:
16997 {
16998 gcond *cond_stmt = as_a <gcond *> (stmt);
16999 if ((ctx || task_shared_vars)
17000 && (walk_tree (gimple_cond_lhs_ptr (cond_stmt),
17001 lower_omp_regimplify_p,
17002 ctx ? NULL : &wi, NULL)
17003 || walk_tree (gimple_cond_rhs_ptr (cond_stmt),
17004 lower_omp_regimplify_p,
17005 ctx ? NULL : &wi, NULL)))
17006 lower_omp_regimplify_operands (ctx, cond_stmt, gsi_p);
17007 }
17008 break;
17009 case GIMPLE_CATCH:
17010 lower_omp (gimple_catch_handler_ptr (as_a <gcatch *> (stmt)), ctx);
17011 break;
17012 case GIMPLE_EH_FILTER:
17013 lower_omp (gimple_eh_filter_failure_ptr (stmt), ctx);
17014 break;
17015 case GIMPLE_TRY:
17016 lower_omp (gimple_try_eval_ptr (stmt), ctx);
17017 lower_omp (gimple_try_cleanup_ptr (stmt), ctx);
17018 break;
17019 case GIMPLE_TRANSACTION:
17020 lower_omp (gimple_transaction_body_ptr (
17021 as_a <gtransaction *> (stmt)),
17022 ctx);
17023 break;
17024 case GIMPLE_BIND:
17025 lower_omp (gimple_bind_body_ptr (as_a <gbind *> (stmt)), ctx);
17026 break;
17027 case GIMPLE_OMP_PARALLEL:
17028 case GIMPLE_OMP_TASK:
17029 ctx = maybe_lookup_ctx (stmt);
17030 gcc_assert (ctx);
17031 if (ctx->cancellable)
17032 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17033 lower_omp_taskreg (gsi_p, ctx);
17034 break;
17035 case GIMPLE_OMP_FOR:
17036 ctx = maybe_lookup_ctx (stmt);
17037 gcc_assert (ctx);
17038 if (ctx->cancellable)
17039 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17040 lower_omp_for (gsi_p, ctx);
17041 break;
17042 case GIMPLE_OMP_SECTIONS:
17043 ctx = maybe_lookup_ctx (stmt);
17044 gcc_assert (ctx);
17045 if (ctx->cancellable)
17046 ctx->cancel_label = create_artificial_label (UNKNOWN_LOCATION);
17047 lower_omp_sections (gsi_p, ctx);
17048 break;
17049 case GIMPLE_OMP_SINGLE:
17050 ctx = maybe_lookup_ctx (stmt);
17051 gcc_assert (ctx);
17052 lower_omp_single (gsi_p, ctx);
17053 break;
17054 case GIMPLE_OMP_MASTER:
17055 ctx = maybe_lookup_ctx (stmt);
17056 gcc_assert (ctx);
17057 lower_omp_master (gsi_p, ctx);
17058 break;
17059 case GIMPLE_OMP_TASKGROUP:
17060 ctx = maybe_lookup_ctx (stmt);
17061 gcc_assert (ctx);
17062 lower_omp_taskgroup (gsi_p, ctx);
17063 break;
17064 case GIMPLE_OMP_ORDERED:
17065 ctx = maybe_lookup_ctx (stmt);
17066 gcc_assert (ctx);
17067 lower_omp_ordered (gsi_p, ctx);
17068 break;
17069 case GIMPLE_OMP_CRITICAL:
17070 ctx = maybe_lookup_ctx (stmt);
17071 gcc_assert (ctx);
17072 lower_omp_critical (gsi_p, ctx);
17073 break;
17074 case GIMPLE_OMP_ATOMIC_LOAD:
17075 if ((ctx || task_shared_vars)
17076 && walk_tree (gimple_omp_atomic_load_rhs_ptr (
17077 as_a <gomp_atomic_load *> (stmt)),
17078 lower_omp_regimplify_p, ctx ? NULL : &wi, NULL))
17079 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17080 break;
17081 case GIMPLE_OMP_TARGET:
17082 ctx = maybe_lookup_ctx (stmt);
17083 gcc_assert (ctx);
17084 lower_omp_target (gsi_p, ctx);
17085 break;
17086 case GIMPLE_OMP_TEAMS:
17087 ctx = maybe_lookup_ctx (stmt);
17088 gcc_assert (ctx);
17089 lower_omp_teams (gsi_p, ctx);
17090 break;
17091 case GIMPLE_OMP_GRID_BODY:
17092 ctx = maybe_lookup_ctx (stmt);
17093 gcc_assert (ctx);
17094 lower_omp_grid_body (gsi_p, ctx);
17095 break;
17096 case GIMPLE_CALL:
17097 tree fndecl;
17098 call_stmt = as_a <gcall *> (stmt);
17099 fndecl = gimple_call_fndecl (call_stmt);
17100 if (fndecl
17101 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
17102 switch (DECL_FUNCTION_CODE (fndecl))
17103 {
17104 case BUILT_IN_GOMP_BARRIER:
17105 if (ctx == NULL)
17106 break;
17107 /* FALLTHRU */
17108 case BUILT_IN_GOMP_CANCEL:
17109 case BUILT_IN_GOMP_CANCELLATION_POINT:
17110 omp_context *cctx;
17111 cctx = ctx;
17112 if (gimple_code (cctx->stmt) == GIMPLE_OMP_SECTION)
17113 cctx = cctx->outer;
17114 gcc_assert (gimple_call_lhs (call_stmt) == NULL_TREE);
17115 if (!cctx->cancellable)
17116 {
17117 if (DECL_FUNCTION_CODE (fndecl)
17118 == BUILT_IN_GOMP_CANCELLATION_POINT)
17119 {
17120 stmt = gimple_build_nop ();
17121 gsi_replace (gsi_p, stmt, false);
17122 }
17123 break;
17124 }
17125 if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_GOMP_BARRIER)
17126 {
17127 fndecl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER_CANCEL);
17128 gimple_call_set_fndecl (call_stmt, fndecl);
17129 gimple_call_set_fntype (call_stmt, TREE_TYPE (fndecl));
17130 }
17131 tree lhs;
17132 lhs = create_tmp_var (TREE_TYPE (TREE_TYPE (fndecl)));
17133 gimple_call_set_lhs (call_stmt, lhs);
17134 tree fallthru_label;
17135 fallthru_label = create_artificial_label (UNKNOWN_LOCATION);
17136 gimple *g;
17137 g = gimple_build_label (fallthru_label);
17138 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17139 g = gimple_build_cond (NE_EXPR, lhs,
17140 fold_convert (TREE_TYPE (lhs),
17141 boolean_false_node),
17142 cctx->cancel_label, fallthru_label);
17143 gsi_insert_after (gsi_p, g, GSI_SAME_STMT);
17144 break;
17145 default:
17146 break;
17147 }
17148 /* FALLTHRU */
17149 default:
17150 if ((ctx || task_shared_vars)
17151 && walk_gimple_op (stmt, lower_omp_regimplify_p,
17152 ctx ? NULL : &wi))
17153 {
17154 /* Just remove clobbers, this should happen only if we have
17155 "privatized" local addressable variables in SIMD regions,
17156 the clobber isn't needed in that case and gimplifying address
17157 of the ARRAY_REF into a pointer and creating MEM_REF based
17158 clobber would create worse code than we get with the clobber
17159 dropped. */
17160 if (gimple_clobber_p (stmt))
17161 {
17162 gsi_replace (gsi_p, gimple_build_nop (), true);
17163 break;
17164 }
17165 lower_omp_regimplify_operands (ctx, stmt, gsi_p);
17166 }
17167 break;
17168 }
17169 }
17170
17171 static void
17172 lower_omp (gimple_seq *body, omp_context *ctx)
17173 {
17174 location_t saved_location = input_location;
17175 gimple_stmt_iterator gsi;
17176 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17177 lower_omp_1 (&gsi, ctx);
17178 /* During gimplification, we haven't folded statments inside offloading
17179 or taskreg regions (gimplify.c:maybe_fold_stmt); do that now. */
17180 if (target_nesting_level || taskreg_nesting_level)
17181 for (gsi = gsi_start (*body); !gsi_end_p (gsi); gsi_next (&gsi))
17182 fold_stmt (&gsi);
17183 input_location = saved_location;
17184 }
17185
17186 /* Returen true if STMT is an assignment of a register-type into a local
17187 VAR_DECL. */
17188
17189 static bool
17190 grid_reg_assignment_to_local_var_p (gimple *stmt)
17191 {
17192 gassign *assign = dyn_cast <gassign *> (stmt);
17193 if (!assign)
17194 return false;
17195 tree lhs = gimple_assign_lhs (assign);
17196 if (!VAR_P (lhs)
17197 || !is_gimple_reg_type (TREE_TYPE (lhs))
17198 || is_global_var (lhs))
17199 return false;
17200 return true;
17201 }
17202
17203 /* Return true if all statements in SEQ are assignments to local register-type
17204 variables. */
17205
17206 static bool
17207 grid_seq_only_contains_local_assignments (gimple_seq seq)
17208 {
17209 if (!seq)
17210 return true;
17211
17212 gimple_stmt_iterator gsi;
17213 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17214 if (!grid_reg_assignment_to_local_var_p (gsi_stmt (gsi)))
17215 return false;
17216 return true;
17217 }
17218
17219 /* Scan statements in SEQ and call itself recursively on any bind. If during
17220 whole search only assignments to register-type local variables and one
17221 single OMP statement is encountered, return true, otherwise return false.
17222 RET is where we store any OMP statement encountered. TARGET_LOC and NAME
17223 are used for dumping a note about a failure. */
17224
17225 static bool
17226 grid_find_single_omp_among_assignments_1 (gimple_seq seq, location_t target_loc,
17227 const char *name, gimple **ret)
17228 {
17229 gimple_stmt_iterator gsi;
17230 for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
17231 {
17232 gimple *stmt = gsi_stmt (gsi);
17233
17234 if (grid_reg_assignment_to_local_var_p (stmt))
17235 continue;
17236 if (gbind *bind = dyn_cast <gbind *> (stmt))
17237 {
17238 if (!grid_find_single_omp_among_assignments_1 (gimple_bind_body (bind),
17239 target_loc, name, ret))
17240 return false;
17241 }
17242 else if (is_gimple_omp (stmt))
17243 {
17244 if (*ret)
17245 {
17246 if (dump_enabled_p ())
17247 dump_printf_loc (MSG_NOTE, target_loc,
17248 "Will not turn target construct into a simple "
17249 "GPGPU kernel because %s construct contains "
17250 "multiple OpenMP constructs\n", name);
17251 return false;
17252 }
17253 *ret = stmt;
17254 }
17255 else
17256 {
17257 if (dump_enabled_p ())
17258 dump_printf_loc (MSG_NOTE, target_loc,
17259 "Will not turn target construct into a simple "
17260 "GPGPU kernel because %s construct contains "
17261 "a complex statement\n", name);
17262 return false;
17263 }
17264 }
17265 return true;
17266 }
17267
17268 /* Scan statements in SEQ and make sure that it and any binds in it contain
17269 only assignments to local register-type variables and one OMP construct. If
17270 so, return that construct, otherwise return NULL. If dumping is enabled and
17271 function fails, use TARGET_LOC and NAME to dump a note with the reason for
17272 failure. */
17273
17274 static gimple *
17275 grid_find_single_omp_among_assignments (gimple_seq seq, location_t target_loc,
17276 const char *name)
17277 {
17278 if (!seq)
17279 {
17280 if (dump_enabled_p ())
17281 dump_printf_loc (MSG_NOTE, target_loc,
17282 "Will not turn target construct into a simple "
17283 "GPGPU kernel because %s construct has empty "
17284 "body\n",
17285 name);
17286 return NULL;
17287 }
17288
17289 gimple *ret = NULL;
17290 if (grid_find_single_omp_among_assignments_1 (seq, target_loc, name, &ret))
17291 {
17292 if (!ret && dump_enabled_p ())
17293 dump_printf_loc (MSG_NOTE, target_loc,
17294 "Will not turn target construct into a simple "
17295 "GPGPU kernel because %s construct does not contain"
17296 "any other OpenMP construct\n", name);
17297 return ret;
17298 }
17299 else
17300 return NULL;
17301 }
17302
17303 /* Walker function looking for statements there is no point gridifying (and for
17304 noreturn function calls which we cannot do). Return non-NULL if such a
17305 function is found. */
17306
17307 static tree
17308 grid_find_ungridifiable_statement (gimple_stmt_iterator *gsi,
17309 bool *handled_ops_p,
17310 struct walk_stmt_info *wi)
17311 {
17312 *handled_ops_p = false;
17313 gimple *stmt = gsi_stmt (*gsi);
17314 switch (gimple_code (stmt))
17315 {
17316 case GIMPLE_CALL:
17317 if (gimple_call_noreturn_p (as_a <gcall *> (stmt)))
17318 {
17319 *handled_ops_p = true;
17320 wi->info = stmt;
17321 return error_mark_node;
17322 }
17323 break;
17324
17325 /* We may reduce the following list if we find a way to implement the
17326 clauses, but now there is no point trying further. */
17327 case GIMPLE_OMP_CRITICAL:
17328 case GIMPLE_OMP_TASKGROUP:
17329 case GIMPLE_OMP_TASK:
17330 case GIMPLE_OMP_SECTION:
17331 case GIMPLE_OMP_SECTIONS:
17332 case GIMPLE_OMP_SECTIONS_SWITCH:
17333 case GIMPLE_OMP_TARGET:
17334 case GIMPLE_OMP_ORDERED:
17335 *handled_ops_p = true;
17336 wi->info = stmt;
17337 return error_mark_node;
17338
17339 case GIMPLE_OMP_FOR:
17340 if ((gimple_omp_for_kind (stmt) & GF_OMP_FOR_SIMD)
17341 && gimple_omp_for_combined_into_p (stmt))
17342 {
17343 *handled_ops_p = true;
17344 wi->info = stmt;
17345 return error_mark_node;
17346 }
17347 break;
17348
17349 default:
17350 break;
17351 }
17352 return NULL;
17353 }
17354
17355
17356 /* If TARGET follows a pattern that can be turned into a gridified GPGPU
17357 kernel, return true, otherwise return false. In the case of success, also
17358 fill in GROUP_SIZE_P with the requested group size or NULL if there is
17359 none. */
17360
17361 static bool
17362 grid_target_follows_gridifiable_pattern (gomp_target *target, tree *group_size_p)
17363 {
17364 if (gimple_omp_target_kind (target) != GF_OMP_TARGET_KIND_REGION)
17365 return false;
17366
17367 location_t tloc = gimple_location (target);
17368 gimple *stmt
17369 = grid_find_single_omp_among_assignments (gimple_omp_body (target),
17370 tloc, "target");
17371 if (!stmt)
17372 return false;
17373 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17374 tree group_size = NULL;
17375 if (!teams)
17376 {
17377 dump_printf_loc (MSG_NOTE, tloc,
17378 "Will not turn target construct into a simple "
17379 "GPGPU kernel because it does not have a sole teams "
17380 "construct in it.\n");
17381 return false;
17382 }
17383
17384 tree clauses = gimple_omp_teams_clauses (teams);
17385 while (clauses)
17386 {
17387 switch (OMP_CLAUSE_CODE (clauses))
17388 {
17389 case OMP_CLAUSE_NUM_TEAMS:
17390 if (dump_enabled_p ())
17391 dump_printf_loc (MSG_NOTE, tloc,
17392 "Will not turn target construct into a "
17393 "gridified GPGPU kernel because we cannot "
17394 "handle num_teams clause of teams "
17395 "construct\n ");
17396 return false;
17397
17398 case OMP_CLAUSE_REDUCTION:
17399 if (dump_enabled_p ())
17400 dump_printf_loc (MSG_NOTE, tloc,
17401 "Will not turn target construct into a "
17402 "gridified GPGPU kernel because a reduction "
17403 "clause is present\n ");
17404 return false;
17405
17406 case OMP_CLAUSE_LASTPRIVATE:
17407 if (dump_enabled_p ())
17408 dump_printf_loc (MSG_NOTE, tloc,
17409 "Will not turn target construct into a "
17410 "gridified GPGPU kernel because a lastprivate "
17411 "clause is present\n ");
17412 return false;
17413
17414 case OMP_CLAUSE_THREAD_LIMIT:
17415 group_size = OMP_CLAUSE_OPERAND (clauses, 0);
17416 break;
17417
17418 default:
17419 break;
17420 }
17421 clauses = OMP_CLAUSE_CHAIN (clauses);
17422 }
17423
17424 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (teams), tloc,
17425 "teams");
17426 if (!stmt)
17427 return false;
17428 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17429 if (!dist)
17430 {
17431 dump_printf_loc (MSG_NOTE, tloc,
17432 "Will not turn target construct into a simple "
17433 "GPGPU kernel because the teams construct does not have "
17434 "a sole distribute construct in it.\n");
17435 return false;
17436 }
17437
17438 gcc_assert (gimple_omp_for_kind (dist) == GF_OMP_FOR_KIND_DISTRIBUTE);
17439 if (!gimple_omp_for_combined_p (dist))
17440 {
17441 if (dump_enabled_p ())
17442 dump_printf_loc (MSG_NOTE, tloc,
17443 "Will not turn target construct into a gridified GPGPU "
17444 "kernel because we cannot handle a standalone "
17445 "distribute construct\n ");
17446 return false;
17447 }
17448 if (dist->collapse > 1)
17449 {
17450 if (dump_enabled_p ())
17451 dump_printf_loc (MSG_NOTE, tloc,
17452 "Will not turn target construct into a gridified GPGPU "
17453 "kernel because the distribute construct contains "
17454 "collapse clause\n");
17455 return false;
17456 }
17457 struct omp_for_data fd;
17458 extract_omp_for_data (dist, &fd, NULL);
17459 if (fd.chunk_size)
17460 {
17461 if (group_size && !operand_equal_p (group_size, fd.chunk_size, 0))
17462 {
17463 if (dump_enabled_p ())
17464 dump_printf_loc (MSG_NOTE, tloc,
17465 "Will not turn target construct into a "
17466 "gridified GPGPU kernel because the teams "
17467 "thread limit is different from distribute "
17468 "schedule chunk\n");
17469 return false;
17470 }
17471 group_size = fd.chunk_size;
17472 }
17473 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (dist), tloc,
17474 "distribute");
17475 gomp_parallel *par;
17476 if (!stmt || !(par = dyn_cast <gomp_parallel *> (stmt)))
17477 return false;
17478
17479 clauses = gimple_omp_parallel_clauses (par);
17480 while (clauses)
17481 {
17482 switch (OMP_CLAUSE_CODE (clauses))
17483 {
17484 case OMP_CLAUSE_NUM_THREADS:
17485 if (dump_enabled_p ())
17486 dump_printf_loc (MSG_NOTE, tloc,
17487 "Will not turn target construct into a gridified"
17488 "GPGPU kernel because there is a num_threads "
17489 "clause of the parallel construct\n");
17490 return false;
17491
17492 case OMP_CLAUSE_REDUCTION:
17493 if (dump_enabled_p ())
17494 dump_printf_loc (MSG_NOTE, tloc,
17495 "Will not turn target construct into a "
17496 "gridified GPGPU kernel because a reduction "
17497 "clause is present\n ");
17498 return false;
17499
17500 case OMP_CLAUSE_LASTPRIVATE:
17501 if (dump_enabled_p ())
17502 dump_printf_loc (MSG_NOTE, tloc,
17503 "Will not turn target construct into a "
17504 "gridified GPGPU kernel because a lastprivate "
17505 "clause is present\n ");
17506 return false;
17507
17508 default:
17509 break;
17510 }
17511 clauses = OMP_CLAUSE_CHAIN (clauses);
17512 }
17513
17514 stmt = grid_find_single_omp_among_assignments (gimple_omp_body (par), tloc,
17515 "parallel");
17516 gomp_for *gfor;
17517 if (!stmt || !(gfor = dyn_cast <gomp_for *> (stmt)))
17518 return false;
17519
17520 if (gimple_omp_for_kind (gfor) != GF_OMP_FOR_KIND_FOR)
17521 {
17522 if (dump_enabled_p ())
17523 dump_printf_loc (MSG_NOTE, tloc,
17524 "Will not turn target construct into a gridified GPGPU "
17525 "kernel because the inner loop is not a simple for "
17526 "loop\n");
17527 return false;
17528 }
17529 if (gfor->collapse > 1)
17530 {
17531 if (dump_enabled_p ())
17532 dump_printf_loc (MSG_NOTE, tloc,
17533 "Will not turn target construct into a gridified GPGPU "
17534 "kernel because the inner loop contains collapse "
17535 "clause\n");
17536 return false;
17537 }
17538
17539 if (!grid_seq_only_contains_local_assignments (gimple_omp_for_pre_body (gfor)))
17540 {
17541 if (dump_enabled_p ())
17542 dump_printf_loc (MSG_NOTE, tloc,
17543 "Will not turn target construct into a gridified GPGPU "
17544 "kernel because the inner loop pre_body contains"
17545 "a complex instruction\n");
17546 return false;
17547 }
17548
17549 clauses = gimple_omp_for_clauses (gfor);
17550 while (clauses)
17551 {
17552 switch (OMP_CLAUSE_CODE (clauses))
17553 {
17554 case OMP_CLAUSE_SCHEDULE:
17555 if (OMP_CLAUSE_SCHEDULE_KIND (clauses) != OMP_CLAUSE_SCHEDULE_AUTO)
17556 {
17557 if (dump_enabled_p ())
17558 dump_printf_loc (MSG_NOTE, tloc,
17559 "Will not turn target construct into a "
17560 "gridified GPGPU kernel because the inner "
17561 "loop has a non-automatic scheduling clause\n");
17562 return false;
17563 }
17564 break;
17565
17566 case OMP_CLAUSE_REDUCTION:
17567 if (dump_enabled_p ())
17568 dump_printf_loc (MSG_NOTE, tloc,
17569 "Will not turn target construct into a "
17570 "gridified GPGPU kernel because a reduction "
17571 "clause is present\n ");
17572 return false;
17573
17574 case OMP_CLAUSE_LASTPRIVATE:
17575 if (dump_enabled_p ())
17576 dump_printf_loc (MSG_NOTE, tloc,
17577 "Will not turn target construct into a "
17578 "gridified GPGPU kernel because a lastprivate "
17579 "clause is present\n ");
17580 return false;
17581
17582 default:
17583 break;
17584 }
17585 clauses = OMP_CLAUSE_CHAIN (clauses);
17586 }
17587
17588 struct walk_stmt_info wi;
17589 memset (&wi, 0, sizeof (wi));
17590 if (walk_gimple_seq (gimple_omp_body (gfor),
17591 grid_find_ungridifiable_statement,
17592 NULL, &wi))
17593 {
17594 gimple *bad = (gimple *) wi.info;
17595 if (dump_enabled_p ())
17596 {
17597 if (is_gimple_call (bad))
17598 dump_printf_loc (MSG_NOTE, tloc,
17599 "Will not turn target construct into a gridified "
17600 " GPGPU kernel because the inner loop contains "
17601 "call to a noreturn function\n");
17602 if (gimple_code (bad) == GIMPLE_OMP_FOR)
17603 dump_printf_loc (MSG_NOTE, tloc,
17604 "Will not turn target construct into a gridified "
17605 " GPGPU kernel because the inner loop contains "
17606 "a simd construct\n");
17607 else
17608 dump_printf_loc (MSG_NOTE, tloc,
17609 "Will not turn target construct into a gridified "
17610 "GPGPU kernel because the inner loop contains "
17611 "statement %s which cannot be transformed\n",
17612 gimple_code_name[(int) gimple_code (bad)]);
17613 }
17614 return false;
17615 }
17616
17617 *group_size_p = group_size;
17618 return true;
17619 }
17620
17621 /* Operand walker, used to remap pre-body declarations according to a hash map
17622 provided in DATA. */
17623
17624 static tree
17625 grid_remap_prebody_decls (tree *tp, int *walk_subtrees, void *data)
17626 {
17627 tree t = *tp;
17628
17629 if (DECL_P (t) || TYPE_P (t))
17630 *walk_subtrees = 0;
17631 else
17632 *walk_subtrees = 1;
17633
17634 if (VAR_P (t))
17635 {
17636 struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
17637 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17638 tree *repl = declmap->get (t);
17639 if (repl)
17640 *tp = *repl;
17641 }
17642 return NULL_TREE;
17643 }
17644
17645 /* Copy leading register-type assignments to local variables in SRC to just
17646 before DST, Creating temporaries, adjusting mapping of operands in WI and
17647 remapping operands as necessary. Add any new temporaries to TGT_BIND.
17648 Return the first statement that does not conform to
17649 grid_reg_assignment_to_local_var_p or NULL. */
17650
17651 static gimple *
17652 grid_copy_leading_local_assignments (gimple_seq src, gimple_stmt_iterator *dst,
17653 gbind *tgt_bind, struct walk_stmt_info *wi)
17654 {
17655 hash_map<tree, tree> *declmap = (hash_map<tree, tree> *) wi->info;
17656 gimple_stmt_iterator gsi;
17657 for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
17658 {
17659 gimple *stmt = gsi_stmt (gsi);
17660 if (gbind *bind = dyn_cast <gbind *> (stmt))
17661 {
17662 gimple *r = grid_copy_leading_local_assignments
17663 (gimple_bind_body (bind), dst, tgt_bind, wi);
17664 if (r)
17665 return r;
17666 else
17667 continue;
17668 }
17669 if (!grid_reg_assignment_to_local_var_p (stmt))
17670 return stmt;
17671 tree lhs = gimple_assign_lhs (as_a <gassign *> (stmt));
17672 tree repl = copy_var_decl (lhs, create_tmp_var_name (NULL),
17673 TREE_TYPE (lhs));
17674 DECL_CONTEXT (repl) = current_function_decl;
17675 gimple_bind_append_vars (tgt_bind, repl);
17676
17677 declmap->put (lhs, repl);
17678 gassign *copy = as_a <gassign *> (gimple_copy (stmt));
17679 walk_gimple_op (copy, grid_remap_prebody_decls, wi);
17680 gsi_insert_before (dst, copy, GSI_SAME_STMT);
17681 }
17682 return NULL;
17683 }
17684
17685 /* Given freshly copied top level kernel SEQ, identify the individual OMP
17686 components, mark them as part of kernel and return the inner loop, and copy
17687 assignment leading to them just before DST, remapping them using WI and
17688 adding new temporaries to TGT_BIND. */
17689
17690 static gomp_for *
17691 grid_process_kernel_body_copy (gimple_seq seq, gimple_stmt_iterator *dst,
17692 gbind *tgt_bind, struct walk_stmt_info *wi)
17693 {
17694 gimple *stmt = grid_copy_leading_local_assignments (seq, dst, tgt_bind, wi);
17695 gomp_teams *teams = dyn_cast <gomp_teams *> (stmt);
17696 gcc_assert (teams);
17697 gimple_omp_teams_set_grid_phony (teams, true);
17698 stmt = grid_copy_leading_local_assignments (gimple_omp_body (teams), dst,
17699 tgt_bind, wi);
17700 gcc_checking_assert (stmt);
17701 gomp_for *dist = dyn_cast <gomp_for *> (stmt);
17702 gcc_assert (dist);
17703 gimple_seq prebody = gimple_omp_for_pre_body (dist);
17704 if (prebody)
17705 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17706 gimple_omp_for_set_grid_phony (dist, true);
17707 stmt = grid_copy_leading_local_assignments (gimple_omp_body (dist), dst,
17708 tgt_bind, wi);
17709 gcc_checking_assert (stmt);
17710
17711 gomp_parallel *parallel = as_a <gomp_parallel *> (stmt);
17712 gimple_omp_parallel_set_grid_phony (parallel, true);
17713 stmt = grid_copy_leading_local_assignments (gimple_omp_body (parallel), dst,
17714 tgt_bind, wi);
17715 gomp_for *inner_loop = as_a <gomp_for *> (stmt);
17716 gimple_omp_for_set_kind (inner_loop, GF_OMP_FOR_KIND_GRID_LOOP);
17717 prebody = gimple_omp_for_pre_body (inner_loop);
17718 if (prebody)
17719 grid_copy_leading_local_assignments (prebody, dst, tgt_bind, wi);
17720
17721 return inner_loop;
17722 }
17723
17724 /* If TARGET points to a GOMP_TARGET which follows a gridifiable pattern,
17725 create a GPU kernel for it. GSI must point to the same statement, TGT_BIND
17726 is the bind into which temporaries inserted before TARGET should be
17727 added. */
17728
17729 static void
17730 grid_attempt_target_gridification (gomp_target *target,
17731 gimple_stmt_iterator *gsi,
17732 gbind *tgt_bind)
17733 {
17734 tree group_size;
17735 if (!target || !grid_target_follows_gridifiable_pattern (target, &group_size))
17736 return;
17737
17738 location_t loc = gimple_location (target);
17739 if (dump_enabled_p ())
17740 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
17741 "Target construct will be turned into a gridified GPGPU "
17742 "kernel\n");
17743
17744 /* Copy target body to a GPUKERNEL construct: */
17745 gimple_seq kernel_seq = copy_gimple_seq_and_replace_locals
17746 (gimple_omp_body (target));
17747
17748 hash_map<tree, tree> *declmap = new hash_map<tree, tree>;
17749 struct walk_stmt_info wi;
17750 memset (&wi, 0, sizeof (struct walk_stmt_info));
17751 wi.info = declmap;
17752
17753 /* Copy assignments in between OMP statements before target, mark OMP
17754 statements within copy appropriatly. */
17755 gomp_for *inner_loop = grid_process_kernel_body_copy (kernel_seq, gsi,
17756 tgt_bind, &wi);
17757
17758 gbind *old_bind = as_a <gbind *> (gimple_seq_first (gimple_omp_body (target)));
17759 gbind *new_bind = as_a <gbind *> (gimple_seq_first (kernel_seq));
17760 tree new_block = gimple_bind_block (new_bind);
17761 tree enc_block = BLOCK_SUPERCONTEXT (gimple_bind_block (old_bind));
17762 BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (enc_block);
17763 BLOCK_SUBBLOCKS (enc_block) = new_block;
17764 BLOCK_SUPERCONTEXT (new_block) = enc_block;
17765 gimple *gpukernel = gimple_build_omp_grid_body (kernel_seq);
17766 gimple_seq_add_stmt
17767 (gimple_bind_body_ptr (as_a <gbind *> (gimple_omp_body (target))),
17768 gpukernel);
17769
17770 walk_tree (&group_size, grid_remap_prebody_decls, &wi, NULL);
17771 push_gimplify_context ();
17772 size_t collapse = gimple_omp_for_collapse (inner_loop);
17773 for (size_t i = 0; i < collapse; i++)
17774 {
17775 tree itype, type = TREE_TYPE (gimple_omp_for_index (inner_loop, i));
17776 if (POINTER_TYPE_P (type))
17777 itype = signed_type_for (type);
17778 else
17779 itype = type;
17780
17781 enum tree_code cond_code = gimple_omp_for_cond (inner_loop, i);
17782 tree n1 = unshare_expr (gimple_omp_for_initial (inner_loop, i));
17783 walk_tree (&n1, grid_remap_prebody_decls, &wi, NULL);
17784 tree n2 = unshare_expr (gimple_omp_for_final (inner_loop, i));
17785 walk_tree (&n2, grid_remap_prebody_decls, &wi, NULL);
17786 adjust_for_condition (loc, &cond_code, &n2);
17787 tree step;
17788 step = get_omp_for_step_from_incr (loc,
17789 gimple_omp_for_incr (inner_loop, i));
17790 gimple_seq tmpseq = NULL;
17791 n1 = fold_convert (itype, n1);
17792 n2 = fold_convert (itype, n2);
17793 tree t = build_int_cst (itype, (cond_code == LT_EXPR ? -1 : 1));
17794 t = fold_build2 (PLUS_EXPR, itype, step, t);
17795 t = fold_build2 (PLUS_EXPR, itype, t, n2);
17796 t = fold_build2 (MINUS_EXPR, itype, t, n1);
17797 if (TYPE_UNSIGNED (itype) && cond_code == GT_EXPR)
17798 t = fold_build2 (TRUNC_DIV_EXPR, itype,
17799 fold_build1 (NEGATE_EXPR, itype, t),
17800 fold_build1 (NEGATE_EXPR, itype, step));
17801 else
17802 t = fold_build2 (TRUNC_DIV_EXPR, itype, t, step);
17803 tree gs = fold_convert (uint32_type_node, t);
17804 gimplify_expr (&gs, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17805 if (!gimple_seq_empty_p (tmpseq))
17806 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17807
17808 tree ws;
17809 if (i == 0 && group_size)
17810 {
17811 ws = fold_convert (uint32_type_node, group_size);
17812 tmpseq = NULL;
17813 gimplify_expr (&ws, &tmpseq, NULL, is_gimple_val, fb_rvalue);
17814 if (!gimple_seq_empty_p (tmpseq))
17815 gsi_insert_seq_before (gsi, tmpseq, GSI_SAME_STMT);
17816 }
17817 else
17818 ws = build_zero_cst (uint32_type_node);
17819
17820 tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE__GRIDDIM_);
17821 OMP_CLAUSE__GRIDDIM__DIMENSION (c) = i;
17822 OMP_CLAUSE__GRIDDIM__SIZE (c) = gs;
17823 OMP_CLAUSE__GRIDDIM__GROUP (c) = ws;
17824 OMP_CLAUSE_CHAIN (c) = gimple_omp_target_clauses (target);
17825 gimple_omp_target_set_clauses (target, c);
17826 }
17827 pop_gimplify_context (tgt_bind);
17828 delete declmap;
17829 return;
17830 }
17831
17832 /* Walker function doing all the work for create_target_kernels. */
17833
17834 static tree
17835 grid_gridify_all_targets_stmt (gimple_stmt_iterator *gsi,
17836 bool *handled_ops_p,
17837 struct walk_stmt_info *incoming)
17838 {
17839 *handled_ops_p = false;
17840
17841 gimple *stmt = gsi_stmt (*gsi);
17842 gomp_target *target = dyn_cast <gomp_target *> (stmt);
17843 if (target)
17844 {
17845 gbind *tgt_bind = (gbind *) incoming->info;
17846 gcc_checking_assert (tgt_bind);
17847 grid_attempt_target_gridification (target, gsi, tgt_bind);
17848 return NULL_TREE;
17849 }
17850 gbind *bind = dyn_cast <gbind *> (stmt);
17851 if (bind)
17852 {
17853 *handled_ops_p = true;
17854 struct walk_stmt_info wi;
17855 memset (&wi, 0, sizeof (wi));
17856 wi.info = bind;
17857 walk_gimple_seq_mod (gimple_bind_body_ptr (bind),
17858 grid_gridify_all_targets_stmt, NULL, &wi);
17859 }
17860 return NULL_TREE;
17861 }
17862
17863 /* Attempt to gridify all target constructs in BODY_P. All such targets will
17864 have their bodies duplicated, with the new copy being put into a
17865 gimple_omp_grid_body statement. All kernel-related construct within the
17866 grid_body will be marked with phony flags or kernel kinds. Moreover, some
17867 re-structuring is often needed, such as copying pre-bodies before the target
17868 construct so that kernel grid sizes can be computed. */
17869
17870 static void
17871 grid_gridify_all_targets (gimple_seq *body_p)
17872 {
17873 struct walk_stmt_info wi;
17874 memset (&wi, 0, sizeof (wi));
17875 walk_gimple_seq_mod (body_p, grid_gridify_all_targets_stmt, NULL, &wi);
17876 }
17877 \f
17878
17879 /* Main entry point. */
17880
17881 static unsigned int
17882 execute_lower_omp (void)
17883 {
17884 gimple_seq body;
17885 int i;
17886 omp_context *ctx;
17887
17888 /* This pass always runs, to provide PROP_gimple_lomp.
17889 But often, there is nothing to do. */
17890 if (flag_cilkplus == 0 && flag_openacc == 0 && flag_openmp == 0
17891 && flag_openmp_simd == 0)
17892 return 0;
17893
17894 all_contexts = splay_tree_new (splay_tree_compare_pointers, 0,
17895 delete_omp_context);
17896
17897 body = gimple_body (current_function_decl);
17898
17899 if (hsa_gen_requested_p ())
17900 grid_gridify_all_targets (&body);
17901
17902 scan_omp (&body, NULL);
17903 gcc_assert (taskreg_nesting_level == 0);
17904 FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx)
17905 finish_taskreg_scan (ctx);
17906 taskreg_contexts.release ();
17907
17908 if (all_contexts->root)
17909 {
17910 if (task_shared_vars)
17911 push_gimplify_context ();
17912 lower_omp (&body, NULL);
17913 if (task_shared_vars)
17914 pop_gimplify_context (NULL);
17915 }
17916
17917 if (all_contexts)
17918 {
17919 splay_tree_delete (all_contexts);
17920 all_contexts = NULL;
17921 }
17922 BITMAP_FREE (task_shared_vars);
17923 return 0;
17924 }
17925
17926 namespace {
17927
17928 const pass_data pass_data_lower_omp =
17929 {
17930 GIMPLE_PASS, /* type */
17931 "omplower", /* name */
17932 OPTGROUP_NONE, /* optinfo_flags */
17933 TV_NONE, /* tv_id */
17934 PROP_gimple_any, /* properties_required */
17935 PROP_gimple_lomp, /* properties_provided */
17936 0, /* properties_destroyed */
17937 0, /* todo_flags_start */
17938 0, /* todo_flags_finish */
17939 };
17940
17941 class pass_lower_omp : public gimple_opt_pass
17942 {
17943 public:
17944 pass_lower_omp (gcc::context *ctxt)
17945 : gimple_opt_pass (pass_data_lower_omp, ctxt)
17946 {}
17947
17948 /* opt_pass methods: */
17949 virtual unsigned int execute (function *) { return execute_lower_omp (); }
17950
17951 }; // class pass_lower_omp
17952
17953 } // anon namespace
17954
17955 gimple_opt_pass *
17956 make_pass_lower_omp (gcc::context *ctxt)
17957 {
17958 return new pass_lower_omp (ctxt);
17959 }
17960 \f
17961 /* The following is a utility to diagnose structured block violations.
17962 It is not part of the "omplower" pass, as that's invoked too late. It
17963 should be invoked by the respective front ends after gimplification. */
17964
17965 static splay_tree all_labels;
17966
17967 /* Check for mismatched contexts and generate an error if needed. Return
17968 true if an error is detected. */
17969
17970 static bool
17971 diagnose_sb_0 (gimple_stmt_iterator *gsi_p,
17972 gimple *branch_ctx, gimple *label_ctx)
17973 {
17974 gcc_checking_assert (!branch_ctx || is_gimple_omp (branch_ctx));
17975 gcc_checking_assert (!label_ctx || is_gimple_omp (label_ctx));
17976
17977 if (label_ctx == branch_ctx)
17978 return false;
17979
17980 const char* kind = NULL;
17981
17982 if (flag_cilkplus)
17983 {
17984 if ((branch_ctx
17985 && gimple_code (branch_ctx) == GIMPLE_OMP_FOR
17986 && gimple_omp_for_kind (branch_ctx) == GF_OMP_FOR_KIND_CILKSIMD)
17987 || (label_ctx
17988 && gimple_code (label_ctx) == GIMPLE_OMP_FOR
17989 && gimple_omp_for_kind (label_ctx) == GF_OMP_FOR_KIND_CILKSIMD))
17990 kind = "Cilk Plus";
17991 }
17992 if (flag_openacc)
17993 {
17994 if ((branch_ctx && is_gimple_omp_oacc (branch_ctx))
17995 || (label_ctx && is_gimple_omp_oacc (label_ctx)))
17996 {
17997 gcc_checking_assert (kind == NULL);
17998 kind = "OpenACC";
17999 }
18000 }
18001 if (kind == NULL)
18002 {
18003 gcc_checking_assert (flag_openmp);
18004 kind = "OpenMP";
18005 }
18006
18007 /*
18008 Previously we kept track of the label's entire context in diagnose_sb_[12]
18009 so we could traverse it and issue a correct "exit" or "enter" error
18010 message upon a structured block violation.
18011
18012 We built the context by building a list with tree_cons'ing, but there is
18013 no easy counterpart in gimple tuples. It seems like far too much work
18014 for issuing exit/enter error messages. If someone really misses the
18015 distinct error message... patches welcome.
18016 */
18017
18018 #if 0
18019 /* Try to avoid confusing the user by producing and error message
18020 with correct "exit" or "enter" verbiage. We prefer "exit"
18021 unless we can show that LABEL_CTX is nested within BRANCH_CTX. */
18022 if (branch_ctx == NULL)
18023 exit_p = false;
18024 else
18025 {
18026 while (label_ctx)
18027 {
18028 if (TREE_VALUE (label_ctx) == branch_ctx)
18029 {
18030 exit_p = false;
18031 break;
18032 }
18033 label_ctx = TREE_CHAIN (label_ctx);
18034 }
18035 }
18036
18037 if (exit_p)
18038 error ("invalid exit from %s structured block", kind);
18039 else
18040 error ("invalid entry to %s structured block", kind);
18041 #endif
18042
18043 /* If it's obvious we have an invalid entry, be specific about the error. */
18044 if (branch_ctx == NULL)
18045 error ("invalid entry to %s structured block", kind);
18046 else
18047 {
18048 /* Otherwise, be vague and lazy, but efficient. */
18049 error ("invalid branch to/from %s structured block", kind);
18050 }
18051
18052 gsi_replace (gsi_p, gimple_build_nop (), false);
18053 return true;
18054 }
18055
18056 /* Pass 1: Create a minimal tree of structured blocks, and record
18057 where each label is found. */
18058
18059 static tree
18060 diagnose_sb_1 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18061 struct walk_stmt_info *wi)
18062 {
18063 gimple *context = (gimple *) wi->info;
18064 gimple *inner_context;
18065 gimple *stmt = gsi_stmt (*gsi_p);
18066
18067 *handled_ops_p = true;
18068
18069 switch (gimple_code (stmt))
18070 {
18071 WALK_SUBSTMTS;
18072
18073 case GIMPLE_OMP_PARALLEL:
18074 case GIMPLE_OMP_TASK:
18075 case GIMPLE_OMP_SECTIONS:
18076 case GIMPLE_OMP_SINGLE:
18077 case GIMPLE_OMP_SECTION:
18078 case GIMPLE_OMP_MASTER:
18079 case GIMPLE_OMP_ORDERED:
18080 case GIMPLE_OMP_CRITICAL:
18081 case GIMPLE_OMP_TARGET:
18082 case GIMPLE_OMP_TEAMS:
18083 case GIMPLE_OMP_TASKGROUP:
18084 /* The minimal context here is just the current OMP construct. */
18085 inner_context = stmt;
18086 wi->info = inner_context;
18087 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18088 wi->info = context;
18089 break;
18090
18091 case GIMPLE_OMP_FOR:
18092 inner_context = stmt;
18093 wi->info = inner_context;
18094 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18095 walk them. */
18096 walk_gimple_seq (gimple_omp_for_pre_body (stmt),
18097 diagnose_sb_1, NULL, wi);
18098 walk_gimple_seq (gimple_omp_body (stmt), diagnose_sb_1, NULL, wi);
18099 wi->info = context;
18100 break;
18101
18102 case GIMPLE_LABEL:
18103 splay_tree_insert (all_labels,
18104 (splay_tree_key) gimple_label_label (
18105 as_a <glabel *> (stmt)),
18106 (splay_tree_value) context);
18107 break;
18108
18109 default:
18110 break;
18111 }
18112
18113 return NULL_TREE;
18114 }
18115
18116 /* Pass 2: Check each branch and see if its context differs from that of
18117 the destination label's context. */
18118
18119 static tree
18120 diagnose_sb_2 (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
18121 struct walk_stmt_info *wi)
18122 {
18123 gimple *context = (gimple *) wi->info;
18124 splay_tree_node n;
18125 gimple *stmt = gsi_stmt (*gsi_p);
18126
18127 *handled_ops_p = true;
18128
18129 switch (gimple_code (stmt))
18130 {
18131 WALK_SUBSTMTS;
18132
18133 case GIMPLE_OMP_PARALLEL:
18134 case GIMPLE_OMP_TASK:
18135 case GIMPLE_OMP_SECTIONS:
18136 case GIMPLE_OMP_SINGLE:
18137 case GIMPLE_OMP_SECTION:
18138 case GIMPLE_OMP_MASTER:
18139 case GIMPLE_OMP_ORDERED:
18140 case GIMPLE_OMP_CRITICAL:
18141 case GIMPLE_OMP_TARGET:
18142 case GIMPLE_OMP_TEAMS:
18143 case GIMPLE_OMP_TASKGROUP:
18144 wi->info = stmt;
18145 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18146 wi->info = context;
18147 break;
18148
18149 case GIMPLE_OMP_FOR:
18150 wi->info = stmt;
18151 /* gimple_omp_for_{index,initial,final} are all DECLs; no need to
18152 walk them. */
18153 walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt),
18154 diagnose_sb_2, NULL, wi);
18155 walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), diagnose_sb_2, NULL, wi);
18156 wi->info = context;
18157 break;
18158
18159 case GIMPLE_COND:
18160 {
18161 gcond *cond_stmt = as_a <gcond *> (stmt);
18162 tree lab = gimple_cond_true_label (cond_stmt);
18163 if (lab)
18164 {
18165 n = splay_tree_lookup (all_labels,
18166 (splay_tree_key) lab);
18167 diagnose_sb_0 (gsi_p, context,
18168 n ? (gimple *) n->value : NULL);
18169 }
18170 lab = gimple_cond_false_label (cond_stmt);
18171 if (lab)
18172 {
18173 n = splay_tree_lookup (all_labels,
18174 (splay_tree_key) lab);
18175 diagnose_sb_0 (gsi_p, context,
18176 n ? (gimple *) n->value : NULL);
18177 }
18178 }
18179 break;
18180
18181 case GIMPLE_GOTO:
18182 {
18183 tree lab = gimple_goto_dest (stmt);
18184 if (TREE_CODE (lab) != LABEL_DECL)
18185 break;
18186
18187 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18188 diagnose_sb_0 (gsi_p, context, n ? (gimple *) n->value : NULL);
18189 }
18190 break;
18191
18192 case GIMPLE_SWITCH:
18193 {
18194 gswitch *switch_stmt = as_a <gswitch *> (stmt);
18195 unsigned int i;
18196 for (i = 0; i < gimple_switch_num_labels (switch_stmt); ++i)
18197 {
18198 tree lab = CASE_LABEL (gimple_switch_label (switch_stmt, i));
18199 n = splay_tree_lookup (all_labels, (splay_tree_key) lab);
18200 if (n && diagnose_sb_0 (gsi_p, context, (gimple *) n->value))
18201 break;
18202 }
18203 }
18204 break;
18205
18206 case GIMPLE_RETURN:
18207 diagnose_sb_0 (gsi_p, context, NULL);
18208 break;
18209
18210 default:
18211 break;
18212 }
18213
18214 return NULL_TREE;
18215 }
18216
18217 /* Called from tree-cfg.c::make_edges to create cfg edges for all relevant
18218 GIMPLE_* codes. */
18219 bool
18220 make_gimple_omp_edges (basic_block bb, struct omp_region **region,
18221 int *region_idx)
18222 {
18223 gimple *last = last_stmt (bb);
18224 enum gimple_code code = gimple_code (last);
18225 struct omp_region *cur_region = *region;
18226 bool fallthru = false;
18227
18228 switch (code)
18229 {
18230 case GIMPLE_OMP_PARALLEL:
18231 case GIMPLE_OMP_TASK:
18232 case GIMPLE_OMP_FOR:
18233 case GIMPLE_OMP_SINGLE:
18234 case GIMPLE_OMP_TEAMS:
18235 case GIMPLE_OMP_MASTER:
18236 case GIMPLE_OMP_TASKGROUP:
18237 case GIMPLE_OMP_CRITICAL:
18238 case GIMPLE_OMP_SECTION:
18239 case GIMPLE_OMP_GRID_BODY:
18240 cur_region = new_omp_region (bb, code, cur_region);
18241 fallthru = true;
18242 break;
18243
18244 case GIMPLE_OMP_ORDERED:
18245 cur_region = new_omp_region (bb, code, cur_region);
18246 fallthru = true;
18247 if (find_omp_clause (gimple_omp_ordered_clauses
18248 (as_a <gomp_ordered *> (last)),
18249 OMP_CLAUSE_DEPEND))
18250 cur_region = cur_region->outer;
18251 break;
18252
18253 case GIMPLE_OMP_TARGET:
18254 cur_region = new_omp_region (bb, code, cur_region);
18255 fallthru = true;
18256 switch (gimple_omp_target_kind (last))
18257 {
18258 case GF_OMP_TARGET_KIND_REGION:
18259 case GF_OMP_TARGET_KIND_DATA:
18260 case GF_OMP_TARGET_KIND_OACC_PARALLEL:
18261 case GF_OMP_TARGET_KIND_OACC_KERNELS:
18262 case GF_OMP_TARGET_KIND_OACC_DATA:
18263 case GF_OMP_TARGET_KIND_OACC_HOST_DATA:
18264 break;
18265 case GF_OMP_TARGET_KIND_UPDATE:
18266 case GF_OMP_TARGET_KIND_ENTER_DATA:
18267 case GF_OMP_TARGET_KIND_EXIT_DATA:
18268 case GF_OMP_TARGET_KIND_OACC_UPDATE:
18269 case GF_OMP_TARGET_KIND_OACC_ENTER_EXIT_DATA:
18270 case GF_OMP_TARGET_KIND_OACC_DECLARE:
18271 cur_region = cur_region->outer;
18272 break;
18273 default:
18274 gcc_unreachable ();
18275 }
18276 break;
18277
18278 case GIMPLE_OMP_SECTIONS:
18279 cur_region = new_omp_region (bb, code, cur_region);
18280 fallthru = true;
18281 break;
18282
18283 case GIMPLE_OMP_SECTIONS_SWITCH:
18284 fallthru = false;
18285 break;
18286
18287 case GIMPLE_OMP_ATOMIC_LOAD:
18288 case GIMPLE_OMP_ATOMIC_STORE:
18289 fallthru = true;
18290 break;
18291
18292 case GIMPLE_OMP_RETURN:
18293 /* In the case of a GIMPLE_OMP_SECTION, the edge will go
18294 somewhere other than the next block. This will be
18295 created later. */
18296 cur_region->exit = bb;
18297 if (cur_region->type == GIMPLE_OMP_TASK)
18298 /* Add an edge corresponding to not scheduling the task
18299 immediately. */
18300 make_edge (cur_region->entry, bb, EDGE_ABNORMAL);
18301 fallthru = cur_region->type != GIMPLE_OMP_SECTION;
18302 cur_region = cur_region->outer;
18303 break;
18304
18305 case GIMPLE_OMP_CONTINUE:
18306 cur_region->cont = bb;
18307 switch (cur_region->type)
18308 {
18309 case GIMPLE_OMP_FOR:
18310 /* Mark all GIMPLE_OMP_FOR and GIMPLE_OMP_CONTINUE
18311 succs edges as abnormal to prevent splitting
18312 them. */
18313 single_succ_edge (cur_region->entry)->flags |= EDGE_ABNORMAL;
18314 /* Make the loopback edge. */
18315 make_edge (bb, single_succ (cur_region->entry),
18316 EDGE_ABNORMAL);
18317
18318 /* Create an edge from GIMPLE_OMP_FOR to exit, which
18319 corresponds to the case that the body of the loop
18320 is not executed at all. */
18321 make_edge (cur_region->entry, bb->next_bb, EDGE_ABNORMAL);
18322 make_edge (bb, bb->next_bb, EDGE_FALLTHRU | EDGE_ABNORMAL);
18323 fallthru = false;
18324 break;
18325
18326 case GIMPLE_OMP_SECTIONS:
18327 /* Wire up the edges into and out of the nested sections. */
18328 {
18329 basic_block switch_bb = single_succ (cur_region->entry);
18330
18331 struct omp_region *i;
18332 for (i = cur_region->inner; i ; i = i->next)
18333 {
18334 gcc_assert (i->type == GIMPLE_OMP_SECTION);
18335 make_edge (switch_bb, i->entry, 0);
18336 make_edge (i->exit, bb, EDGE_FALLTHRU);
18337 }
18338
18339 /* Make the loopback edge to the block with
18340 GIMPLE_OMP_SECTIONS_SWITCH. */
18341 make_edge (bb, switch_bb, 0);
18342
18343 /* Make the edge from the switch to exit. */
18344 make_edge (switch_bb, bb->next_bb, 0);
18345 fallthru = false;
18346 }
18347 break;
18348
18349 case GIMPLE_OMP_TASK:
18350 fallthru = true;
18351 break;
18352
18353 default:
18354 gcc_unreachable ();
18355 }
18356 break;
18357
18358 default:
18359 gcc_unreachable ();
18360 }
18361
18362 if (*region != cur_region)
18363 {
18364 *region = cur_region;
18365 if (cur_region)
18366 *region_idx = cur_region->entry->index;
18367 else
18368 *region_idx = 0;
18369 }
18370
18371 return fallthru;
18372 }
18373
18374 static unsigned int
18375 diagnose_omp_structured_block_errors (void)
18376 {
18377 struct walk_stmt_info wi;
18378 gimple_seq body = gimple_body (current_function_decl);
18379
18380 all_labels = splay_tree_new (splay_tree_compare_pointers, 0, 0);
18381
18382 memset (&wi, 0, sizeof (wi));
18383 walk_gimple_seq (body, diagnose_sb_1, NULL, &wi);
18384
18385 memset (&wi, 0, sizeof (wi));
18386 wi.want_locations = true;
18387 walk_gimple_seq_mod (&body, diagnose_sb_2, NULL, &wi);
18388
18389 gimple_set_body (current_function_decl, body);
18390
18391 splay_tree_delete (all_labels);
18392 all_labels = NULL;
18393
18394 return 0;
18395 }
18396
18397 namespace {
18398
18399 const pass_data pass_data_diagnose_omp_blocks =
18400 {
18401 GIMPLE_PASS, /* type */
18402 "*diagnose_omp_blocks", /* name */
18403 OPTGROUP_NONE, /* optinfo_flags */
18404 TV_NONE, /* tv_id */
18405 PROP_gimple_any, /* properties_required */
18406 0, /* properties_provided */
18407 0, /* properties_destroyed */
18408 0, /* todo_flags_start */
18409 0, /* todo_flags_finish */
18410 };
18411
18412 class pass_diagnose_omp_blocks : public gimple_opt_pass
18413 {
18414 public:
18415 pass_diagnose_omp_blocks (gcc::context *ctxt)
18416 : gimple_opt_pass (pass_data_diagnose_omp_blocks, ctxt)
18417 {}
18418
18419 /* opt_pass methods: */
18420 virtual bool gate (function *)
18421 {
18422 return flag_cilkplus || flag_openacc || flag_openmp;
18423 }
18424 virtual unsigned int execute (function *)
18425 {
18426 return diagnose_omp_structured_block_errors ();
18427 }
18428
18429 }; // class pass_diagnose_omp_blocks
18430
18431 } // anon namespace
18432
18433 gimple_opt_pass *
18434 make_pass_diagnose_omp_blocks (gcc::context *ctxt)
18435 {
18436 return new pass_diagnose_omp_blocks (ctxt);
18437 }
18438 \f
18439 /* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
18440 adds their addresses and sizes to constructor-vector V_CTOR. */
18441 static void
18442 add_decls_addresses_to_decl_constructor (vec<tree, va_gc> *v_decls,
18443 vec<constructor_elt, va_gc> *v_ctor)
18444 {
18445 unsigned len = vec_safe_length (v_decls);
18446 for (unsigned i = 0; i < len; i++)
18447 {
18448 tree it = (*v_decls)[i];
18449 bool is_var = VAR_P (it);
18450 bool is_link_var
18451 = is_var
18452 #ifdef ACCEL_COMPILER
18453 && DECL_HAS_VALUE_EXPR_P (it)
18454 #endif
18455 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (it));
18456
18457 tree size = NULL_TREE;
18458 if (is_var)
18459 size = fold_convert (const_ptr_type_node, DECL_SIZE_UNIT (it));
18460
18461 tree addr;
18462 if (!is_link_var)
18463 addr = build_fold_addr_expr (it);
18464 else
18465 {
18466 #ifdef ACCEL_COMPILER
18467 /* For "omp declare target link" vars add address of the pointer to
18468 the target table, instead of address of the var. */
18469 tree value_expr = DECL_VALUE_EXPR (it);
18470 tree link_ptr_decl = TREE_OPERAND (value_expr, 0);
18471 varpool_node::finalize_decl (link_ptr_decl);
18472 addr = build_fold_addr_expr (link_ptr_decl);
18473 #else
18474 addr = build_fold_addr_expr (it);
18475 #endif
18476
18477 /* Most significant bit of the size marks "omp declare target link"
18478 vars in host and target tables. */
18479 unsigned HOST_WIDE_INT isize = tree_to_uhwi (size);
18480 isize |= 1ULL << (int_size_in_bytes (const_ptr_type_node)
18481 * BITS_PER_UNIT - 1);
18482 size = wide_int_to_tree (const_ptr_type_node, isize);
18483 }
18484
18485 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, addr);
18486 if (is_var)
18487 CONSTRUCTOR_APPEND_ELT (v_ctor, NULL_TREE, size);
18488 }
18489 }
18490
18491 /* Create new symbols containing (address, size) pairs for global variables,
18492 marked with "omp declare target" attribute, as well as addresses for the
18493 functions, which are outlined offloading regions. */
18494 void
18495 omp_finish_file (void)
18496 {
18497 unsigned num_funcs = vec_safe_length (offload_funcs);
18498 unsigned num_vars = vec_safe_length (offload_vars);
18499
18500 if (num_funcs == 0 && num_vars == 0)
18501 return;
18502
18503 if (targetm_common.have_named_sections)
18504 {
18505 vec<constructor_elt, va_gc> *v_f, *v_v;
18506 vec_alloc (v_f, num_funcs);
18507 vec_alloc (v_v, num_vars * 2);
18508
18509 add_decls_addresses_to_decl_constructor (offload_funcs, v_f);
18510 add_decls_addresses_to_decl_constructor (offload_vars, v_v);
18511
18512 tree vars_decl_type = build_array_type_nelts (pointer_sized_int_node,
18513 num_vars * 2);
18514 tree funcs_decl_type = build_array_type_nelts (pointer_sized_int_node,
18515 num_funcs);
18516 SET_TYPE_ALIGN (vars_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18517 SET_TYPE_ALIGN (funcs_decl_type, TYPE_ALIGN (pointer_sized_int_node));
18518 tree ctor_v = build_constructor (vars_decl_type, v_v);
18519 tree ctor_f = build_constructor (funcs_decl_type, v_f);
18520 TREE_CONSTANT (ctor_v) = TREE_CONSTANT (ctor_f) = 1;
18521 TREE_STATIC (ctor_v) = TREE_STATIC (ctor_f) = 1;
18522 tree funcs_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18523 get_identifier (".offload_func_table"),
18524 funcs_decl_type);
18525 tree vars_decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
18526 get_identifier (".offload_var_table"),
18527 vars_decl_type);
18528 TREE_STATIC (funcs_decl) = TREE_STATIC (vars_decl) = 1;
18529 /* Do not align tables more than TYPE_ALIGN (pointer_sized_int_node),
18530 otherwise a joint table in a binary will contain padding between
18531 tables from multiple object files. */
18532 DECL_USER_ALIGN (funcs_decl) = DECL_USER_ALIGN (vars_decl) = 1;
18533 SET_DECL_ALIGN (funcs_decl, TYPE_ALIGN (funcs_decl_type));
18534 SET_DECL_ALIGN (vars_decl, TYPE_ALIGN (vars_decl_type));
18535 DECL_INITIAL (funcs_decl) = ctor_f;
18536 DECL_INITIAL (vars_decl) = ctor_v;
18537 set_decl_section_name (funcs_decl, OFFLOAD_FUNC_TABLE_SECTION_NAME);
18538 set_decl_section_name (vars_decl, OFFLOAD_VAR_TABLE_SECTION_NAME);
18539
18540 varpool_node::finalize_decl (vars_decl);
18541 varpool_node::finalize_decl (funcs_decl);
18542 }
18543 else
18544 {
18545 for (unsigned i = 0; i < num_funcs; i++)
18546 {
18547 tree it = (*offload_funcs)[i];
18548 targetm.record_offload_symbol (it);
18549 }
18550 for (unsigned i = 0; i < num_vars; i++)
18551 {
18552 tree it = (*offload_vars)[i];
18553 targetm.record_offload_symbol (it);
18554 }
18555 }
18556 }
18557
18558 /* Find the number of threads (POS = false), or thread number (POS =
18559 true) for an OpenACC region partitioned as MASK. Setup code
18560 required for the calculation is added to SEQ. */
18561
18562 static tree
18563 oacc_thread_numbers (bool pos, int mask, gimple_seq *seq)
18564 {
18565 tree res = pos ? NULL_TREE : build_int_cst (unsigned_type_node, 1);
18566 unsigned ix;
18567
18568 /* Start at gang level, and examine relevant dimension indices. */
18569 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
18570 if (GOMP_DIM_MASK (ix) & mask)
18571 {
18572 tree arg = build_int_cst (unsigned_type_node, ix);
18573
18574 if (res)
18575 {
18576 /* We had an outer index, so scale that by the size of
18577 this dimension. */
18578 tree n = create_tmp_var (integer_type_node);
18579 gimple *call
18580 = gimple_build_call_internal (IFN_GOACC_DIM_SIZE, 1, arg);
18581
18582 gimple_call_set_lhs (call, n);
18583 gimple_seq_add_stmt (seq, call);
18584 res = fold_build2 (MULT_EXPR, integer_type_node, res, n);
18585 }
18586 if (pos)
18587 {
18588 /* Determine index in this dimension. */
18589 tree id = create_tmp_var (integer_type_node);
18590 gimple *call = gimple_build_call_internal
18591 (IFN_GOACC_DIM_POS, 1, arg);
18592
18593 gimple_call_set_lhs (call, id);
18594 gimple_seq_add_stmt (seq, call);
18595 if (res)
18596 res = fold_build2 (PLUS_EXPR, integer_type_node, res, id);
18597 else
18598 res = id;
18599 }
18600 }
18601
18602 if (res == NULL_TREE)
18603 res = integer_zero_node;
18604
18605 return res;
18606 }
18607
18608 /* Transform IFN_GOACC_LOOP calls to actual code. See
18609 expand_oacc_for for where these are generated. At the vector
18610 level, we stride loops, such that each member of a warp will
18611 operate on adjacent iterations. At the worker and gang level,
18612 each gang/warp executes a set of contiguous iterations. Chunking
18613 can override this such that each iteration engine executes a
18614 contiguous chunk, and then moves on to stride to the next chunk. */
18615
18616 static void
18617 oacc_xform_loop (gcall *call)
18618 {
18619 gimple_stmt_iterator gsi = gsi_for_stmt (call);
18620 enum ifn_goacc_loop_kind code
18621 = (enum ifn_goacc_loop_kind) TREE_INT_CST_LOW (gimple_call_arg (call, 0));
18622 tree dir = gimple_call_arg (call, 1);
18623 tree range = gimple_call_arg (call, 2);
18624 tree step = gimple_call_arg (call, 3);
18625 tree chunk_size = NULL_TREE;
18626 unsigned mask = (unsigned) TREE_INT_CST_LOW (gimple_call_arg (call, 5));
18627 tree lhs = gimple_call_lhs (call);
18628 tree type = TREE_TYPE (lhs);
18629 tree diff_type = TREE_TYPE (range);
18630 tree r = NULL_TREE;
18631 gimple_seq seq = NULL;
18632 bool chunking = false, striding = true;
18633 unsigned outer_mask = mask & (~mask + 1); // Outermost partitioning
18634 unsigned inner_mask = mask & ~outer_mask; // Inner partitioning (if any)
18635
18636 #ifdef ACCEL_COMPILER
18637 chunk_size = gimple_call_arg (call, 4);
18638 if (integer_minus_onep (chunk_size) /* Force static allocation. */
18639 || integer_zerop (chunk_size)) /* Default (also static). */
18640 {
18641 /* If we're at the gang level, we want each to execute a
18642 contiguous run of iterations. Otherwise we want each element
18643 to stride. */
18644 striding = !(outer_mask & GOMP_DIM_MASK (GOMP_DIM_GANG));
18645 chunking = false;
18646 }
18647 else
18648 {
18649 /* Chunk of size 1 is striding. */
18650 striding = integer_onep (chunk_size);
18651 chunking = !striding;
18652 }
18653 #endif
18654
18655 /* striding=true, chunking=true
18656 -> invalid.
18657 striding=true, chunking=false
18658 -> chunks=1
18659 striding=false,chunking=true
18660 -> chunks=ceil (range/(chunksize*threads*step))
18661 striding=false,chunking=false
18662 -> chunk_size=ceil(range/(threads*step)),chunks=1 */
18663 push_gimplify_context (true);
18664
18665 switch (code)
18666 {
18667 default: gcc_unreachable ();
18668
18669 case IFN_GOACC_LOOP_CHUNKS:
18670 if (!chunking)
18671 r = build_int_cst (type, 1);
18672 else
18673 {
18674 /* chunk_max
18675 = (range - dir) / (chunks * step * num_threads) + dir */
18676 tree per = oacc_thread_numbers (false, mask, &seq);
18677 per = fold_convert (type, per);
18678 chunk_size = fold_convert (type, chunk_size);
18679 per = fold_build2 (MULT_EXPR, type, per, chunk_size);
18680 per = fold_build2 (MULT_EXPR, type, per, step);
18681 r = build2 (MINUS_EXPR, type, range, dir);
18682 r = build2 (PLUS_EXPR, type, r, per);
18683 r = build2 (TRUNC_DIV_EXPR, type, r, per);
18684 }
18685 break;
18686
18687 case IFN_GOACC_LOOP_STEP:
18688 {
18689 /* If striding, step by the entire compute volume, otherwise
18690 step by the inner volume. */
18691 unsigned volume = striding ? mask : inner_mask;
18692
18693 r = oacc_thread_numbers (false, volume, &seq);
18694 r = build2 (MULT_EXPR, type, fold_convert (type, r), step);
18695 }
18696 break;
18697
18698 case IFN_GOACC_LOOP_OFFSET:
18699 if (striding)
18700 {
18701 r = oacc_thread_numbers (true, mask, &seq);
18702 r = fold_convert (diff_type, r);
18703 }
18704 else
18705 {
18706 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18707 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18708 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18709 inner_size, outer_size);
18710
18711 volume = fold_convert (diff_type, volume);
18712 if (chunking)
18713 chunk_size = fold_convert (diff_type, chunk_size);
18714 else
18715 {
18716 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18717
18718 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18719 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18720 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18721 }
18722
18723 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18724 fold_convert (diff_type, inner_size));
18725 r = oacc_thread_numbers (true, outer_mask, &seq);
18726 r = fold_convert (diff_type, r);
18727 r = build2 (MULT_EXPR, diff_type, r, span);
18728
18729 tree inner = oacc_thread_numbers (true, inner_mask, &seq);
18730 inner = fold_convert (diff_type, inner);
18731 r = fold_build2 (PLUS_EXPR, diff_type, r, inner);
18732
18733 if (chunking)
18734 {
18735 tree chunk = fold_convert (diff_type, gimple_call_arg (call, 6));
18736 tree per
18737 = fold_build2 (MULT_EXPR, diff_type, volume, chunk_size);
18738 per = build2 (MULT_EXPR, diff_type, per, chunk);
18739
18740 r = build2 (PLUS_EXPR, diff_type, r, per);
18741 }
18742 }
18743 r = fold_build2 (MULT_EXPR, diff_type, r, step);
18744 if (type != diff_type)
18745 r = fold_convert (type, r);
18746 break;
18747
18748 case IFN_GOACC_LOOP_BOUND:
18749 if (striding)
18750 r = range;
18751 else
18752 {
18753 tree inner_size = oacc_thread_numbers (false, inner_mask, &seq);
18754 tree outer_size = oacc_thread_numbers (false, outer_mask, &seq);
18755 tree volume = fold_build2 (MULT_EXPR, TREE_TYPE (inner_size),
18756 inner_size, outer_size);
18757
18758 volume = fold_convert (diff_type, volume);
18759 if (chunking)
18760 chunk_size = fold_convert (diff_type, chunk_size);
18761 else
18762 {
18763 tree per = fold_build2 (MULT_EXPR, diff_type, volume, step);
18764
18765 chunk_size = build2 (MINUS_EXPR, diff_type, range, dir);
18766 chunk_size = build2 (PLUS_EXPR, diff_type, chunk_size, per);
18767 chunk_size = build2 (TRUNC_DIV_EXPR, diff_type, chunk_size, per);
18768 }
18769
18770 tree span = build2 (MULT_EXPR, diff_type, chunk_size,
18771 fold_convert (diff_type, inner_size));
18772
18773 r = fold_build2 (MULT_EXPR, diff_type, span, step);
18774
18775 tree offset = gimple_call_arg (call, 6);
18776 r = build2 (PLUS_EXPR, diff_type, r,
18777 fold_convert (diff_type, offset));
18778 r = build2 (integer_onep (dir) ? MIN_EXPR : MAX_EXPR,
18779 diff_type, r, range);
18780 }
18781 if (diff_type != type)
18782 r = fold_convert (type, r);
18783 break;
18784 }
18785
18786 gimplify_assign (lhs, r, &seq);
18787
18788 pop_gimplify_context (NULL);
18789
18790 gsi_replace_with_seq (&gsi, seq, true);
18791 }
18792
18793 /* Default partitioned and minimum partitioned dimensions. */
18794
18795 static int oacc_default_dims[GOMP_DIM_MAX];
18796 static int oacc_min_dims[GOMP_DIM_MAX];
18797
18798 /* Parse the default dimension parameter. This is a set of
18799 :-separated optional compute dimensions. Each specified dimension
18800 is a positive integer. When device type support is added, it is
18801 planned to be a comma separated list of such compute dimensions,
18802 with all but the first prefixed by the colon-terminated device
18803 type. */
18804
18805 static void
18806 oacc_parse_default_dims (const char *dims)
18807 {
18808 int ix;
18809
18810 for (ix = GOMP_DIM_MAX; ix--;)
18811 {
18812 oacc_default_dims[ix] = -1;
18813 oacc_min_dims[ix] = 1;
18814 }
18815
18816 #ifndef ACCEL_COMPILER
18817 /* Cannot be overridden on the host. */
18818 dims = NULL;
18819 #endif
18820 if (dims)
18821 {
18822 const char *pos = dims;
18823
18824 for (ix = 0; *pos && ix != GOMP_DIM_MAX; ix++)
18825 {
18826 if (ix)
18827 {
18828 if (*pos != ':')
18829 goto malformed;
18830 pos++;
18831 }
18832
18833 if (*pos != ':')
18834 {
18835 long val;
18836 const char *eptr;
18837
18838 errno = 0;
18839 val = strtol (pos, CONST_CAST (char **, &eptr), 10);
18840 if (errno || val <= 0 || (int) val != val)
18841 goto malformed;
18842 pos = eptr;
18843 oacc_default_dims[ix] = (int) val;
18844 }
18845 }
18846 if (*pos)
18847 {
18848 malformed:
18849 error_at (UNKNOWN_LOCATION,
18850 "-fopenacc-dim operand is malformed at '%s'", pos);
18851 }
18852 }
18853
18854 /* Allow the backend to validate the dimensions. */
18855 targetm.goacc.validate_dims (NULL_TREE, oacc_default_dims, -1);
18856 targetm.goacc.validate_dims (NULL_TREE, oacc_min_dims, -2);
18857 }
18858
18859 /* Validate and update the dimensions for offloaded FN. ATTRS is the
18860 raw attribute. DIMS is an array of dimensions, which is filled in.
18861 LEVEL is the partitioning level of a routine, or -1 for an offload
18862 region itself. USED is the mask of partitioned execution in the
18863 function. */
18864
18865 static void
18866 oacc_validate_dims (tree fn, tree attrs, int *dims, int level, unsigned used)
18867 {
18868 tree purpose[GOMP_DIM_MAX];
18869 unsigned ix;
18870 tree pos = TREE_VALUE (attrs);
18871 bool is_kernel = oacc_fn_attrib_kernels_p (attrs);
18872
18873 /* Make sure the attribute creator attached the dimension
18874 information. */
18875 gcc_assert (pos);
18876
18877 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18878 {
18879 purpose[ix] = TREE_PURPOSE (pos);
18880 tree val = TREE_VALUE (pos);
18881 dims[ix] = val ? TREE_INT_CST_LOW (val) : -1;
18882 pos = TREE_CHAIN (pos);
18883 }
18884
18885 bool changed = targetm.goacc.validate_dims (fn, dims, level);
18886
18887 /* Default anything left to 1 or a partitioned default. */
18888 for (ix = 0; ix != GOMP_DIM_MAX; ix++)
18889 if (dims[ix] < 0)
18890 {
18891 /* The OpenACC spec says 'If the [num_gangs] clause is not
18892 specified, an implementation-defined default will be used;
18893 the default may depend on the code within the construct.'
18894 (2.5.6). Thus an implementation is free to choose
18895 non-unity default for a parallel region that doesn't have
18896 any gang-partitioned loops. However, it appears that there
18897 is a sufficient body of user code that expects non-gang
18898 partitioned regions to not execute in gang-redundant mode.
18899 So we (a) don't warn about the non-portability and (b) pick
18900 the minimum permissible dimension size when there is no
18901 partitioned execution. Otherwise we pick the global
18902 default for the dimension, which the user can control. The
18903 same wording and logic applies to num_workers and
18904 vector_length, however the worker- or vector- single
18905 execution doesn't have the same impact as gang-redundant
18906 execution. (If the minimum gang-level partioning is not 1,
18907 the target is probably too confusing.) */
18908 dims[ix] = (used & GOMP_DIM_MASK (ix)
18909 ? oacc_default_dims[ix] : oacc_min_dims[ix]);
18910 changed = true;
18911 }
18912
18913 if (changed)
18914 {
18915 /* Replace the attribute with new values. */
18916 pos = NULL_TREE;
18917 for (ix = GOMP_DIM_MAX; ix--;)
18918 {
18919 pos = tree_cons (purpose[ix],
18920 build_int_cst (integer_type_node, dims[ix]),
18921 pos);
18922 if (is_kernel)
18923 TREE_PUBLIC (pos) = 1;
18924 }
18925 replace_oacc_fn_attrib (fn, pos);
18926 }
18927 }
18928
18929 /* Create an empty OpenACC loop structure at LOC. */
18930
18931 static oacc_loop *
18932 new_oacc_loop_raw (oacc_loop *parent, location_t loc)
18933 {
18934 oacc_loop *loop = XCNEW (oacc_loop);
18935
18936 loop->parent = parent;
18937 loop->child = loop->sibling = NULL;
18938
18939 if (parent)
18940 {
18941 loop->sibling = parent->child;
18942 parent->child = loop;
18943 }
18944
18945 loop->loc = loc;
18946 loop->marker = NULL;
18947 memset (loop->heads, 0, sizeof (loop->heads));
18948 memset (loop->tails, 0, sizeof (loop->tails));
18949 loop->routine = NULL_TREE;
18950
18951 loop->mask = loop->flags = loop->inner = 0;
18952 loop->ifns = 0;
18953 loop->chunk_size = 0;
18954 loop->head_end = NULL;
18955
18956 return loop;
18957 }
18958
18959 /* Create an outermost, dummy OpenACC loop for offloaded function
18960 DECL. */
18961
18962 static oacc_loop *
18963 new_oacc_loop_outer (tree decl)
18964 {
18965 return new_oacc_loop_raw (NULL, DECL_SOURCE_LOCATION (decl));
18966 }
18967
18968 /* Start a new OpenACC loop structure beginning at head marker HEAD.
18969 Link into PARENT loop. Return the new loop. */
18970
18971 static oacc_loop *
18972 new_oacc_loop (oacc_loop *parent, gcall *marker)
18973 {
18974 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (marker));
18975
18976 loop->marker = marker;
18977
18978 /* TODO: This is where device_type flattening would occur for the loop
18979 flags. */
18980
18981 loop->flags = TREE_INT_CST_LOW (gimple_call_arg (marker, 3));
18982
18983 tree chunk_size = integer_zero_node;
18984 if (loop->flags & OLF_GANG_STATIC)
18985 chunk_size = gimple_call_arg (marker, 4);
18986 loop->chunk_size = chunk_size;
18987
18988 return loop;
18989 }
18990
18991 /* Create a dummy loop encompassing a call to a openACC routine.
18992 Extract the routine's partitioning requirements. */
18993
18994 static void
18995 new_oacc_loop_routine (oacc_loop *parent, gcall *call, tree decl, tree attrs)
18996 {
18997 oacc_loop *loop = new_oacc_loop_raw (parent, gimple_location (call));
18998 int level = oacc_fn_attrib_level (attrs);
18999
19000 gcc_assert (level >= 0);
19001
19002 loop->marker = call;
19003 loop->routine = decl;
19004 loop->mask = ((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1)
19005 ^ (GOMP_DIM_MASK (level) - 1));
19006 }
19007
19008 /* Finish off the current OpenACC loop ending at tail marker TAIL.
19009 Return the parent loop. */
19010
19011 static oacc_loop *
19012 finish_oacc_loop (oacc_loop *loop)
19013 {
19014 /* If the loop has been collapsed, don't partition it. */
19015 if (!loop->ifns)
19016 loop->mask = loop->flags = 0;
19017 return loop->parent;
19018 }
19019
19020 /* Free all OpenACC loop structures within LOOP (inclusive). */
19021
19022 static void
19023 free_oacc_loop (oacc_loop *loop)
19024 {
19025 if (loop->sibling)
19026 free_oacc_loop (loop->sibling);
19027 if (loop->child)
19028 free_oacc_loop (loop->child);
19029
19030 free (loop);
19031 }
19032
19033 /* Dump out the OpenACC loop head or tail beginning at FROM. */
19034
19035 static void
19036 dump_oacc_loop_part (FILE *file, gcall *from, int depth,
19037 const char *title, int level)
19038 {
19039 enum ifn_unique_kind kind
19040 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19041
19042 fprintf (file, "%*s%s-%d:\n", depth * 2, "", title, level);
19043 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19044 {
19045 gimple *stmt = gsi_stmt (gsi);
19046
19047 if (gimple_call_internal_p (stmt, IFN_UNIQUE))
19048 {
19049 enum ifn_unique_kind k
19050 = ((enum ifn_unique_kind) TREE_INT_CST_LOW
19051 (gimple_call_arg (stmt, 0)));
19052
19053 if (k == kind && stmt != from)
19054 break;
19055 }
19056 print_gimple_stmt (file, stmt, depth * 2 + 2, 0);
19057
19058 gsi_next (&gsi);
19059 while (gsi_end_p (gsi))
19060 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19061 }
19062 }
19063
19064 /* Dump OpenACC loops LOOP, its siblings and its children. */
19065
19066 static void
19067 dump_oacc_loop (FILE *file, oacc_loop *loop, int depth)
19068 {
19069 int ix;
19070
19071 fprintf (file, "%*sLoop %x(%x) %s:%u\n", depth * 2, "",
19072 loop->flags, loop->mask,
19073 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc));
19074
19075 if (loop->marker)
19076 print_gimple_stmt (file, loop->marker, depth * 2, 0);
19077
19078 if (loop->routine)
19079 fprintf (file, "%*sRoutine %s:%u:%s\n",
19080 depth * 2, "", DECL_SOURCE_FILE (loop->routine),
19081 DECL_SOURCE_LINE (loop->routine),
19082 IDENTIFIER_POINTER (DECL_NAME (loop->routine)));
19083
19084 for (ix = GOMP_DIM_GANG; ix != GOMP_DIM_MAX; ix++)
19085 if (loop->heads[ix])
19086 dump_oacc_loop_part (file, loop->heads[ix], depth, "Head", ix);
19087 for (ix = GOMP_DIM_MAX; ix--;)
19088 if (loop->tails[ix])
19089 dump_oacc_loop_part (file, loop->tails[ix], depth, "Tail", ix);
19090
19091 if (loop->child)
19092 dump_oacc_loop (file, loop->child, depth + 1);
19093 if (loop->sibling)
19094 dump_oacc_loop (file, loop->sibling, depth);
19095 }
19096
19097 void debug_oacc_loop (oacc_loop *);
19098
19099 /* Dump loops to stderr. */
19100
19101 DEBUG_FUNCTION void
19102 debug_oacc_loop (oacc_loop *loop)
19103 {
19104 dump_oacc_loop (stderr, loop, 0);
19105 }
19106
19107 /* DFS walk of basic blocks BB onwards, creating OpenACC loop
19108 structures as we go. By construction these loops are properly
19109 nested. */
19110
19111 static void
19112 oacc_loop_discover_walk (oacc_loop *loop, basic_block bb)
19113 {
19114 int marker = 0;
19115 int remaining = 0;
19116
19117 if (bb->flags & BB_VISITED)
19118 return;
19119
19120 follow:
19121 bb->flags |= BB_VISITED;
19122
19123 /* Scan for loop markers. */
19124 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
19125 gsi_next (&gsi))
19126 {
19127 gimple *stmt = gsi_stmt (gsi);
19128
19129 if (!is_gimple_call (stmt))
19130 continue;
19131
19132 gcall *call = as_a <gcall *> (stmt);
19133
19134 /* If this is a routine, make a dummy loop for it. */
19135 if (tree decl = gimple_call_fndecl (call))
19136 if (tree attrs = get_oacc_fn_attrib (decl))
19137 {
19138 gcc_assert (!marker);
19139 new_oacc_loop_routine (loop, call, decl, attrs);
19140 }
19141
19142 if (!gimple_call_internal_p (call))
19143 continue;
19144
19145 switch (gimple_call_internal_fn (call))
19146 {
19147 default:
19148 break;
19149
19150 case IFN_GOACC_LOOP:
19151 /* Count the goacc loop abstraction fns, to determine if the
19152 loop was collapsed already. */
19153 loop->ifns++;
19154 break;
19155
19156 case IFN_UNIQUE:
19157 enum ifn_unique_kind kind
19158 = (enum ifn_unique_kind) (TREE_INT_CST_LOW
19159 (gimple_call_arg (call, 0)));
19160 if (kind == IFN_UNIQUE_OACC_HEAD_MARK
19161 || kind == IFN_UNIQUE_OACC_TAIL_MARK)
19162 {
19163 if (gimple_call_num_args (call) == 2)
19164 {
19165 gcc_assert (marker && !remaining);
19166 marker = 0;
19167 if (kind == IFN_UNIQUE_OACC_TAIL_MARK)
19168 loop = finish_oacc_loop (loop);
19169 else
19170 loop->head_end = call;
19171 }
19172 else
19173 {
19174 int count = TREE_INT_CST_LOW (gimple_call_arg (call, 2));
19175
19176 if (!marker)
19177 {
19178 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19179 loop = new_oacc_loop (loop, call);
19180 remaining = count;
19181 }
19182 gcc_assert (count == remaining);
19183 if (remaining)
19184 {
19185 remaining--;
19186 if (kind == IFN_UNIQUE_OACC_HEAD_MARK)
19187 loop->heads[marker] = call;
19188 else
19189 loop->tails[remaining] = call;
19190 }
19191 marker++;
19192 }
19193 }
19194 }
19195 }
19196 if (remaining || marker)
19197 {
19198 bb = single_succ (bb);
19199 gcc_assert (single_pred_p (bb) && !(bb->flags & BB_VISITED));
19200 goto follow;
19201 }
19202
19203 /* Walk successor blocks. */
19204 edge e;
19205 edge_iterator ei;
19206
19207 FOR_EACH_EDGE (e, ei, bb->succs)
19208 oacc_loop_discover_walk (loop, e->dest);
19209 }
19210
19211 /* LOOP is the first sibling. Reverse the order in place and return
19212 the new first sibling. Recurse to child loops. */
19213
19214 static oacc_loop *
19215 oacc_loop_sibling_nreverse (oacc_loop *loop)
19216 {
19217 oacc_loop *last = NULL;
19218 do
19219 {
19220 if (loop->child)
19221 loop->child = oacc_loop_sibling_nreverse (loop->child);
19222
19223 oacc_loop *next = loop->sibling;
19224 loop->sibling = last;
19225 last = loop;
19226 loop = next;
19227 }
19228 while (loop);
19229
19230 return last;
19231 }
19232
19233 /* Discover the OpenACC loops marked up by HEAD and TAIL markers for
19234 the current function. */
19235
19236 static oacc_loop *
19237 oacc_loop_discovery ()
19238 {
19239 /* Clear basic block flags, in particular BB_VISITED which we're going to use
19240 in the following. */
19241 clear_bb_flags ();
19242
19243 oacc_loop *top = new_oacc_loop_outer (current_function_decl);
19244 oacc_loop_discover_walk (top, ENTRY_BLOCK_PTR_FOR_FN (cfun));
19245
19246 /* The siblings were constructed in reverse order, reverse them so
19247 that diagnostics come out in an unsurprising order. */
19248 top = oacc_loop_sibling_nreverse (top);
19249
19250 return top;
19251 }
19252
19253 /* Transform the abstract internal function markers starting at FROM
19254 to be for partitioning level LEVEL. Stop when we meet another HEAD
19255 or TAIL marker. */
19256
19257 static void
19258 oacc_loop_xform_head_tail (gcall *from, int level)
19259 {
19260 enum ifn_unique_kind kind
19261 = (enum ifn_unique_kind) TREE_INT_CST_LOW (gimple_call_arg (from, 0));
19262 tree replacement = build_int_cst (unsigned_type_node, level);
19263
19264 for (gimple_stmt_iterator gsi = gsi_for_stmt (from);;)
19265 {
19266 gimple *stmt = gsi_stmt (gsi);
19267
19268 if (gimple_call_internal_p (stmt, IFN_UNIQUE))
19269 {
19270 enum ifn_unique_kind k
19271 = ((enum ifn_unique_kind)
19272 TREE_INT_CST_LOW (gimple_call_arg (stmt, 0)));
19273
19274 if (k == IFN_UNIQUE_OACC_FORK || k == IFN_UNIQUE_OACC_JOIN)
19275 *gimple_call_arg_ptr (stmt, 2) = replacement;
19276 else if (k == kind && stmt != from)
19277 break;
19278 }
19279 else if (gimple_call_internal_p (stmt, IFN_GOACC_REDUCTION))
19280 *gimple_call_arg_ptr (stmt, 3) = replacement;
19281
19282 gsi_next (&gsi);
19283 while (gsi_end_p (gsi))
19284 gsi = gsi_start_bb (single_succ (gsi_bb (gsi)));
19285 }
19286 }
19287
19288 /* Transform the IFN_GOACC_LOOP internal functions by providing the
19289 determined partitioning mask and chunking argument. END_MARKER
19290 points at the end IFN_HEAD_TAIL call intgroducing the loop. IFNS
19291 is the number of IFN_GOACC_LOOP calls for the loop. MASK_ARG is
19292 the replacement partitioning mask and CHUNK_ARG is the replacement
19293 chunking arg. */
19294
19295 static void
19296 oacc_loop_xform_loop (gcall *end_marker, unsigned ifns,
19297 tree mask_arg, tree chunk_arg)
19298 {
19299 gimple_stmt_iterator gsi = gsi_for_stmt (end_marker);
19300
19301 gcc_checking_assert (ifns);
19302 for (;;)
19303 {
19304 for (; !gsi_end_p (gsi); gsi_next (&gsi))
19305 {
19306 gimple *stmt = gsi_stmt (gsi);
19307
19308 if (!is_gimple_call (stmt))
19309 continue;
19310
19311 gcall *call = as_a <gcall *> (stmt);
19312
19313 if (!gimple_call_internal_p (call))
19314 continue;
19315
19316 if (gimple_call_internal_fn (call) != IFN_GOACC_LOOP)
19317 continue;
19318
19319 *gimple_call_arg_ptr (call, 5) = mask_arg;
19320 *gimple_call_arg_ptr (call, 4) = chunk_arg;
19321 ifns--;
19322 if (!ifns)
19323 return;
19324 }
19325
19326 /* The LOOP_BOUND ifn could be in the single successor
19327 block. */
19328 basic_block bb = single_succ (gsi_bb (gsi));
19329 gsi = gsi_start_bb (bb);
19330 }
19331 }
19332
19333 /* Process the discovered OpenACC loops, setting the correct
19334 partitioning level etc. */
19335
19336 static void
19337 oacc_loop_process (oacc_loop *loop)
19338 {
19339 if (loop->child)
19340 oacc_loop_process (loop->child);
19341
19342 if (loop->mask && !loop->routine)
19343 {
19344 int ix;
19345 unsigned mask = loop->mask;
19346 unsigned dim = GOMP_DIM_GANG;
19347 tree mask_arg = build_int_cst (unsigned_type_node, mask);
19348 tree chunk_arg = loop->chunk_size;
19349
19350 oacc_loop_xform_loop (loop->head_end, loop->ifns, mask_arg, chunk_arg);
19351
19352 for (ix = 0; ix != GOMP_DIM_MAX && mask; ix++)
19353 {
19354 while (!(GOMP_DIM_MASK (dim) & mask))
19355 dim++;
19356
19357 oacc_loop_xform_head_tail (loop->heads[ix], dim);
19358 oacc_loop_xform_head_tail (loop->tails[ix], dim);
19359
19360 mask ^= GOMP_DIM_MASK (dim);
19361 }
19362 }
19363
19364 if (loop->sibling)
19365 oacc_loop_process (loop->sibling);
19366 }
19367
19368 /* Walk the OpenACC loop heirarchy checking and assigning the
19369 programmer-specified partitionings. OUTER_MASK is the partitioning
19370 this loop is contained within. Return mask of partitioning
19371 encountered. If any auto loops are discovered, set GOMP_DIM_MAX
19372 bit. */
19373
19374 static unsigned
19375 oacc_loop_fixed_partitions (oacc_loop *loop, unsigned outer_mask)
19376 {
19377 unsigned this_mask = loop->mask;
19378 unsigned mask_all = 0;
19379 bool noisy = true;
19380
19381 #ifdef ACCEL_COMPILER
19382 /* When device_type is supported, we want the device compiler to be
19383 noisy, if the loop parameters are device_type-specific. */
19384 noisy = false;
19385 #endif
19386
19387 if (!loop->routine)
19388 {
19389 bool auto_par = (loop->flags & OLF_AUTO) != 0;
19390 bool seq_par = (loop->flags & OLF_SEQ) != 0;
19391
19392 this_mask = ((loop->flags >> OLF_DIM_BASE)
19393 & (GOMP_DIM_MASK (GOMP_DIM_MAX) - 1));
19394
19395 if ((this_mask != 0) + auto_par + seq_par > 1)
19396 {
19397 if (noisy)
19398 error_at (loop->loc,
19399 seq_par
19400 ? "%<seq%> overrides other OpenACC loop specifiers"
19401 : "%<auto%> conflicts with other OpenACC loop specifiers");
19402 auto_par = false;
19403 loop->flags &= ~OLF_AUTO;
19404 if (seq_par)
19405 {
19406 loop->flags &=
19407 ~((GOMP_DIM_MASK (GOMP_DIM_MAX) - 1) << OLF_DIM_BASE);
19408 this_mask = 0;
19409 }
19410 }
19411 if (auto_par && (loop->flags & OLF_INDEPENDENT))
19412 mask_all |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19413 }
19414
19415 if (this_mask & outer_mask)
19416 {
19417 const oacc_loop *outer;
19418 for (outer = loop->parent; outer; outer = outer->parent)
19419 if (outer->mask & this_mask)
19420 break;
19421
19422 if (noisy)
19423 {
19424 if (outer)
19425 {
19426 error_at (loop->loc,
19427 "%s uses same OpenACC parallelism as containing loop",
19428 loop->routine ? "routine call" : "inner loop");
19429 inform (outer->loc, "containing loop here");
19430 }
19431 else
19432 error_at (loop->loc,
19433 "%s uses OpenACC parallelism disallowed by containing routine",
19434 loop->routine ? "routine call" : "loop");
19435
19436 if (loop->routine)
19437 inform (DECL_SOURCE_LOCATION (loop->routine),
19438 "routine %qD declared here", loop->routine);
19439 }
19440 this_mask &= ~outer_mask;
19441 }
19442 else
19443 {
19444 unsigned outermost = least_bit_hwi (this_mask);
19445
19446 if (outermost && outermost <= outer_mask)
19447 {
19448 if (noisy)
19449 {
19450 error_at (loop->loc,
19451 "incorrectly nested OpenACC loop parallelism");
19452
19453 const oacc_loop *outer;
19454 for (outer = loop->parent;
19455 outer->flags && outer->flags < outermost;
19456 outer = outer->parent)
19457 continue;
19458 inform (outer->loc, "containing loop here");
19459 }
19460
19461 this_mask &= ~outermost;
19462 }
19463 }
19464
19465 loop->mask = this_mask;
19466 mask_all |= this_mask;
19467
19468 if (loop->child)
19469 {
19470 loop->inner = oacc_loop_fixed_partitions (loop->child,
19471 outer_mask | this_mask);
19472 mask_all |= loop->inner;
19473 }
19474
19475 if (loop->sibling)
19476 mask_all |= oacc_loop_fixed_partitions (loop->sibling, outer_mask);
19477
19478 return mask_all;
19479 }
19480
19481 /* Walk the OpenACC loop heirarchy to assign auto-partitioned loops.
19482 OUTER_MASK is the partitioning this loop is contained within.
19483 Return the cumulative partitioning used by this loop, siblings and
19484 children. */
19485
19486 static unsigned
19487 oacc_loop_auto_partitions (oacc_loop *loop, unsigned outer_mask)
19488 {
19489 bool assign = (loop->flags & OLF_AUTO) && (loop->flags & OLF_INDEPENDENT);
19490 bool noisy = true;
19491
19492 #ifdef ACCEL_COMPILER
19493 /* When device_type is supported, we want the device compiler to be
19494 noisy, if the loop parameters are device_type-specific. */
19495 noisy = false;
19496 #endif
19497
19498 if (assign && outer_mask < GOMP_DIM_MASK (GOMP_DIM_MAX - 1))
19499 {
19500 /* Allocate the outermost loop at the outermost available
19501 level. */
19502 unsigned this_mask = outer_mask + 1;
19503
19504 if (!(this_mask & loop->inner))
19505 loop->mask = this_mask;
19506 }
19507
19508 if (loop->child)
19509 {
19510 unsigned child_mask = outer_mask | loop->mask;
19511
19512 if (loop->mask || assign)
19513 child_mask |= GOMP_DIM_MASK (GOMP_DIM_MAX);
19514
19515 loop->inner = oacc_loop_auto_partitions (loop->child, child_mask);
19516 }
19517
19518 if (assign && !loop->mask)
19519 {
19520 /* Allocate the loop at the innermost available level. */
19521 unsigned this_mask = 0;
19522
19523 /* Determine the outermost partitioning used within this loop. */
19524 this_mask = loop->inner | GOMP_DIM_MASK (GOMP_DIM_MAX);
19525 this_mask = least_bit_hwi (this_mask);
19526
19527 /* Pick the partitioning just inside that one. */
19528 this_mask >>= 1;
19529
19530 /* And avoid picking one use by an outer loop. */
19531 this_mask &= ~outer_mask;
19532
19533 if (!this_mask && noisy)
19534 warning_at (loop->loc, 0,
19535 "insufficient partitioning available to parallelize loop");
19536
19537 loop->mask = this_mask;
19538 }
19539
19540 if (assign && dump_file)
19541 fprintf (dump_file, "Auto loop %s:%d assigned %d\n",
19542 LOCATION_FILE (loop->loc), LOCATION_LINE (loop->loc),
19543 loop->mask);
19544
19545 unsigned inner_mask = 0;
19546
19547 if (loop->sibling)
19548 inner_mask |= oacc_loop_auto_partitions (loop->sibling, outer_mask);
19549
19550 inner_mask |= loop->inner | loop->mask;
19551
19552 return inner_mask;
19553 }
19554
19555 /* Walk the OpenACC loop heirarchy to check and assign partitioning
19556 axes. Return mask of partitioning. */
19557
19558 static unsigned
19559 oacc_loop_partition (oacc_loop *loop, unsigned outer_mask)
19560 {
19561 unsigned mask_all = oacc_loop_fixed_partitions (loop, outer_mask);
19562
19563 if (mask_all & GOMP_DIM_MASK (GOMP_DIM_MAX))
19564 {
19565 mask_all ^= GOMP_DIM_MASK (GOMP_DIM_MAX);
19566 mask_all |= oacc_loop_auto_partitions (loop, outer_mask);
19567 }
19568 return mask_all;
19569 }
19570
19571 /* Default fork/join early expander. Delete the function calls if
19572 there is no RTL expander. */
19573
19574 bool
19575 default_goacc_fork_join (gcall *ARG_UNUSED (call),
19576 const int *ARG_UNUSED (dims), bool is_fork)
19577 {
19578 if (is_fork)
19579 return targetm.have_oacc_fork ();
19580 else
19581 return targetm.have_oacc_join ();
19582 }
19583
19584 /* Default goacc.reduction early expander.
19585
19586 LHS-opt = IFN_REDUCTION (KIND, RES_PTR, VAR, LEVEL, OP, OFFSET)
19587 If RES_PTR is not integer-zerop:
19588 SETUP - emit 'LHS = *RES_PTR', LHS = NULL
19589 TEARDOWN - emit '*RES_PTR = VAR'
19590 If LHS is not NULL
19591 emit 'LHS = VAR' */
19592
19593 void
19594 default_goacc_reduction (gcall *call)
19595 {
19596 unsigned code = (unsigned)TREE_INT_CST_LOW (gimple_call_arg (call, 0));
19597 gimple_stmt_iterator gsi = gsi_for_stmt (call);
19598 tree lhs = gimple_call_lhs (call);
19599 tree var = gimple_call_arg (call, 2);
19600 gimple_seq seq = NULL;
19601
19602 if (code == IFN_GOACC_REDUCTION_SETUP
19603 || code == IFN_GOACC_REDUCTION_TEARDOWN)
19604 {
19605 /* Setup and Teardown need to copy from/to the receiver object,
19606 if there is one. */
19607 tree ref_to_res = gimple_call_arg (call, 1);
19608
19609 if (!integer_zerop (ref_to_res))
19610 {
19611 tree dst = build_simple_mem_ref (ref_to_res);
19612 tree src = var;
19613
19614 if (code == IFN_GOACC_REDUCTION_SETUP)
19615 {
19616 src = dst;
19617 dst = lhs;
19618 lhs = NULL;
19619 }
19620 gimple_seq_add_stmt (&seq, gimple_build_assign (dst, src));
19621 }
19622 }
19623
19624 /* Copy VAR to LHS, if there is an LHS. */
19625 if (lhs)
19626 gimple_seq_add_stmt (&seq, gimple_build_assign (lhs, var));
19627
19628 gsi_replace_with_seq (&gsi, seq, true);
19629 }
19630
19631 /* Main entry point for oacc transformations which run on the device
19632 compiler after LTO, so we know what the target device is at this
19633 point (including the host fallback). */
19634
19635 static unsigned int
19636 execute_oacc_device_lower ()
19637 {
19638 tree attrs = get_oacc_fn_attrib (current_function_decl);
19639
19640 if (!attrs)
19641 /* Not an offloaded function. */
19642 return 0;
19643
19644 /* Parse the default dim argument exactly once. */
19645 if ((const void *)flag_openacc_dims != &flag_openacc_dims)
19646 {
19647 oacc_parse_default_dims (flag_openacc_dims);
19648 flag_openacc_dims = (char *)&flag_openacc_dims;
19649 }
19650
19651 /* Discover, partition and process the loops. */
19652 oacc_loop *loops = oacc_loop_discovery ();
19653 int fn_level = oacc_fn_attrib_level (attrs);
19654
19655 if (dump_file)
19656 fprintf (dump_file, oacc_fn_attrib_kernels_p (attrs)
19657 ? "Function is kernels offload\n"
19658 : fn_level < 0 ? "Function is parallel offload\n"
19659 : "Function is routine level %d\n", fn_level);
19660
19661 unsigned outer_mask = fn_level >= 0 ? GOMP_DIM_MASK (fn_level) - 1 : 0;
19662 unsigned used_mask = oacc_loop_partition (loops, outer_mask);
19663 int dims[GOMP_DIM_MAX];
19664
19665 oacc_validate_dims (current_function_decl, attrs, dims, fn_level, used_mask);
19666
19667 if (dump_file)
19668 {
19669 const char *comma = "Compute dimensions [";
19670 for (int ix = 0; ix != GOMP_DIM_MAX; ix++, comma = ", ")
19671 fprintf (dump_file, "%s%d", comma, dims[ix]);
19672 fprintf (dump_file, "]\n");
19673 }
19674
19675 oacc_loop_process (loops);
19676 if (dump_file)
19677 {
19678 fprintf (dump_file, "OpenACC loops\n");
19679 dump_oacc_loop (dump_file, loops, 0);
19680 fprintf (dump_file, "\n");
19681 }
19682
19683 /* Offloaded targets may introduce new basic blocks, which require
19684 dominance information to update SSA. */
19685 calculate_dominance_info (CDI_DOMINATORS);
19686
19687 /* Now lower internal loop functions to target-specific code
19688 sequences. */
19689 basic_block bb;
19690 FOR_ALL_BB_FN (bb, cfun)
19691 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
19692 {
19693 gimple *stmt = gsi_stmt (gsi);
19694 if (!is_gimple_call (stmt))
19695 {
19696 gsi_next (&gsi);
19697 continue;
19698 }
19699
19700 gcall *call = as_a <gcall *> (stmt);
19701 if (!gimple_call_internal_p (call))
19702 {
19703 gsi_next (&gsi);
19704 continue;
19705 }
19706
19707 /* Rewind to allow rescan. */
19708 gsi_prev (&gsi);
19709 bool rescan = false, remove = false;
19710 enum internal_fn ifn_code = gimple_call_internal_fn (call);
19711
19712 switch (ifn_code)
19713 {
19714 default: break;
19715
19716 case IFN_GOACC_LOOP:
19717 oacc_xform_loop (call);
19718 rescan = true;
19719 break;
19720
19721 case IFN_GOACC_REDUCTION:
19722 /* Mark the function for SSA renaming. */
19723 mark_virtual_operands_for_renaming (cfun);
19724
19725 /* If the level is -1, this ended up being an unused
19726 axis. Handle as a default. */
19727 if (integer_minus_onep (gimple_call_arg (call, 3)))
19728 default_goacc_reduction (call);
19729 else
19730 targetm.goacc.reduction (call);
19731 rescan = true;
19732 break;
19733
19734 case IFN_UNIQUE:
19735 {
19736 enum ifn_unique_kind kind
19737 = ((enum ifn_unique_kind)
19738 TREE_INT_CST_LOW (gimple_call_arg (call, 0)));
19739
19740 switch (kind)
19741 {
19742 default:
19743 gcc_unreachable ();
19744
19745 case IFN_UNIQUE_OACC_FORK:
19746 case IFN_UNIQUE_OACC_JOIN:
19747 if (integer_minus_onep (gimple_call_arg (call, 2)))
19748 remove = true;
19749 else if (!targetm.goacc.fork_join
19750 (call, dims, kind == IFN_UNIQUE_OACC_FORK))
19751 remove = true;
19752 break;
19753
19754 case IFN_UNIQUE_OACC_HEAD_MARK:
19755 case IFN_UNIQUE_OACC_TAIL_MARK:
19756 remove = true;
19757 break;
19758 }
19759 break;
19760 }
19761 }
19762
19763 if (gsi_end_p (gsi))
19764 /* We rewound past the beginning of the BB. */
19765 gsi = gsi_start_bb (bb);
19766 else
19767 /* Undo the rewind. */
19768 gsi_next (&gsi);
19769
19770 if (remove)
19771 {
19772 if (gimple_vdef (call))
19773 replace_uses_by (gimple_vdef (call), gimple_vuse (call));
19774 if (gimple_call_lhs (call))
19775 {
19776 /* Propagate the data dependency var. */
19777 gimple *ass = gimple_build_assign (gimple_call_lhs (call),
19778 gimple_call_arg (call, 1));
19779 gsi_replace (&gsi, ass, false);
19780 }
19781 else
19782 gsi_remove (&gsi, true);
19783 }
19784 else if (!rescan)
19785 /* If not rescanning, advance over the call. */
19786 gsi_next (&gsi);
19787 }
19788
19789 free_oacc_loop (loops);
19790
19791 return 0;
19792 }
19793
19794 /* Default launch dimension validator. Force everything to 1. A
19795 backend that wants to provide larger dimensions must override this
19796 hook. */
19797
19798 bool
19799 default_goacc_validate_dims (tree ARG_UNUSED (decl), int *dims,
19800 int ARG_UNUSED (fn_level))
19801 {
19802 bool changed = false;
19803
19804 for (unsigned ix = 0; ix != GOMP_DIM_MAX; ix++)
19805 {
19806 if (dims[ix] != 1)
19807 {
19808 dims[ix] = 1;
19809 changed = true;
19810 }
19811 }
19812
19813 return changed;
19814 }
19815
19816 /* Default dimension bound is unknown on accelerator and 1 on host. */
19817
19818 int
19819 default_goacc_dim_limit (int ARG_UNUSED (axis))
19820 {
19821 #ifdef ACCEL_COMPILER
19822 return 0;
19823 #else
19824 return 1;
19825 #endif
19826 }
19827
19828 namespace {
19829
19830 const pass_data pass_data_oacc_device_lower =
19831 {
19832 GIMPLE_PASS, /* type */
19833 "oaccdevlow", /* name */
19834 OPTGROUP_NONE, /* optinfo_flags */
19835 TV_NONE, /* tv_id */
19836 PROP_cfg, /* properties_required */
19837 0 /* Possibly PROP_gimple_eomp. */, /* properties_provided */
19838 0, /* properties_destroyed */
19839 0, /* todo_flags_start */
19840 TODO_update_ssa | TODO_cleanup_cfg, /* todo_flags_finish */
19841 };
19842
19843 class pass_oacc_device_lower : public gimple_opt_pass
19844 {
19845 public:
19846 pass_oacc_device_lower (gcc::context *ctxt)
19847 : gimple_opt_pass (pass_data_oacc_device_lower, ctxt)
19848 {}
19849
19850 /* opt_pass methods: */
19851 virtual bool gate (function *) { return flag_openacc; };
19852
19853 virtual unsigned int execute (function *)
19854 {
19855 return execute_oacc_device_lower ();
19856 }
19857
19858 }; // class pass_oacc_device_lower
19859
19860 } // anon namespace
19861
19862 gimple_opt_pass *
19863 make_pass_oacc_device_lower (gcc::context *ctxt)
19864 {
19865 return new pass_oacc_device_lower (ctxt);
19866 }
19867
19868 /* "omp declare target link" handling pass. */
19869
19870 namespace {
19871
19872 const pass_data pass_data_omp_target_link =
19873 {
19874 GIMPLE_PASS, /* type */
19875 "omptargetlink", /* name */
19876 OPTGROUP_NONE, /* optinfo_flags */
19877 TV_NONE, /* tv_id */
19878 PROP_ssa, /* properties_required */
19879 0, /* properties_provided */
19880 0, /* properties_destroyed */
19881 0, /* todo_flags_start */
19882 TODO_update_ssa, /* todo_flags_finish */
19883 };
19884
19885 class pass_omp_target_link : public gimple_opt_pass
19886 {
19887 public:
19888 pass_omp_target_link (gcc::context *ctxt)
19889 : gimple_opt_pass (pass_data_omp_target_link, ctxt)
19890 {}
19891
19892 /* opt_pass methods: */
19893 virtual bool gate (function *fun)
19894 {
19895 #ifdef ACCEL_COMPILER
19896 tree attrs = DECL_ATTRIBUTES (fun->decl);
19897 return lookup_attribute ("omp declare target", attrs)
19898 || lookup_attribute ("omp target entrypoint", attrs);
19899 #else
19900 (void) fun;
19901 return false;
19902 #endif
19903 }
19904
19905 virtual unsigned execute (function *);
19906 };
19907
19908 /* Callback for walk_gimple_stmt used to scan for link var operands. */
19909
19910 static tree
19911 find_link_var_op (tree *tp, int *walk_subtrees, void *)
19912 {
19913 tree t = *tp;
19914
19915 if (VAR_P (t) && DECL_HAS_VALUE_EXPR_P (t)
19916 && lookup_attribute ("omp declare target link", DECL_ATTRIBUTES (t)))
19917 {
19918 *walk_subtrees = 0;
19919 return t;
19920 }
19921
19922 return NULL_TREE;
19923 }
19924
19925 unsigned
19926 pass_omp_target_link::execute (function *fun)
19927 {
19928 basic_block bb;
19929 FOR_EACH_BB_FN (bb, fun)
19930 {
19931 gimple_stmt_iterator gsi;
19932 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
19933 if (walk_gimple_stmt (&gsi, NULL, find_link_var_op, NULL))
19934 gimple_regimplify_operands (gsi_stmt (gsi), &gsi);
19935 }
19936
19937 return 0;
19938 }
19939
19940 } // anon namespace
19941
19942 gimple_opt_pass *
19943 make_pass_omp_target_link (gcc::context *ctxt)
19944 {
19945 return new pass_omp_target_link (ctxt);
19946 }
19947
19948 #include "gt-omp-low.h"